feat(daemon): say what to do next on startup, and prove multiple clients agree

Starting the daemon printed 'ready' and nothing else, so the token and the
next step were both somewhere else. It now prints what other commands can do
from here, and when --bind is given, the token itself with the two config
commands a remote client needs. All on stderr, so stdout stays empty and
daemon still composes in a pipeline.

Adds the guarantee daemon mode is for as a test: eight clients connected at
once are each answered correctly, none has its replies crossed with another's,
and the daemon still counts all eight. Plus 250 connect-and-drop cycles, well
past the connection cap, to catch a per-connection resource that is not
released — the shape a daemon that works for a while and then refuses
everybody would take.

A connection the daemon drops before it can be served now logs why at warning
level. A client only ever sees 'the connection closed', so that line is the
only account of the reason.
This commit is contained in:
Michel de Graaf
2026-07-27 14:39:31 +02:00
parent 2a906df1b5
commit 01152d91f6
8 changed files with 226 additions and 66 deletions
+8 -2
View File
@@ -155,14 +155,20 @@ fn spawn_connection(stream: Stream, daemon: Arc<Daemon>) {
if open > MAX_CONNECTIONS {
daemon.open.fetch_sub(1, Ordering::Relaxed);
soulseek_rs::warn!(
"refusing a control connection: {MAX_CONNECTIONS} already open"
"refusing a control connection: {MAX_CONNECTIONS} already open. \
This is a leak unless you really have that many clients — please \
report it with `soulseek-rs daemon status`."
);
stream.shutdown();
return;
}
std::thread::spawn(move || {
if let Err(e) = handle(stream, daemon.as_ref()) {
soulseek_rs::debug!("control connection ended: {e}");
// Loud, not debug: a client sees only "the connection closed", so
// this line is the only account of why it did.
soulseek_rs::warn!(
"control connection dropped before it could be served: {e}"
);
}
daemon.open.fetch_sub(1, Ordering::Relaxed);
});