// session-daemon — one session channel, exposed on a local Unix socket.
//
// session-daemon --topic <seed> --bootstrap <host:port> --socket <path>
//
// The topic is BLAKE2b(seed) so a human can name a session without handling 32
// raw bytes. Omit --bootstrap to use the public DHT.
#include <cstdio>
#include <cstring>
#include <csignal>
#include <sodium.h>
#include "session_daemon.h"
static volatile sig_atomic_t g_stop = 0;
static void on_signal(int) { g_stop = 1; }
int main(int argc, char **argv) {
if (sodium_init() < 0) {
fprintf(stderr, "sodium_init failed\n");
return 1;
}
const char *seed = nullptr;
const char *bootstrap = nullptr;
const char *sock = nullptr;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--topic") && i + 1 < argc) seed = argv[++i];
else if (!strcmp(argv[i], "--bootstrap") && i + 1 < argc) bootstrap = argv[++i];
else if (!strcmp(argv[i], "--socket") && i + 1 < argc) sock = argv[++i];
}
if (!seed || !sock) {
fprintf(stderr, "usage: session-daemon --topic <seed> --socket <path> "
"[--bootstrap host:port]\n");
return 1;
}
uint8_t topic[32];
crypto_generichash(topic, sizeof(topic), (const uint8_t *)seed, strlen(seed),
nullptr, 0);
signal(SIGINT, on_signal);
signal(SIGTERM, on_signal);
session::SessionDaemon d;
if (!d.start(topic, bootstrap, sock)) {
fprintf(stderr, "failed to start (socket %s)\n", sock);
return 1;
}
printf("[session] listening on %s, topic %s\n", sock, seed);
fflush(stdout);
// ⛔ SAY WHETHER THE SWARM IS REACHABLE, not just whether we started.
// "joined" is a LOCAL fact — the socket bound and a client attached. It says
// nothing about the DHT, and two peers once sat on the same topic for ten
// minutes both reporting success while neither had ever bootstrapped. A
// daemon that cannot be asked "am I on the network?" turns every failure
// into a guess.
int ticks = 0;
int last_peers = -1;
bool last_boot = false;
while (!g_stop) {
d.poll(200);
const bool boot = d.dht_bootstrapped();
const int peers = d.peer_count();
// On change immediately, otherwise every ~5s so a log tail shows a pulse.
if (boot != last_boot || peers != last_peers || (ticks % 25) == 0) {
printf("[session] dht=%s peers=%d local=%d frames=%llu/%llu\n",
boot ? "up" : (d.dht_active() ? "connecting" : "starting"),
peers, d.local_client_count(),
(unsigned long long)d.frames_to_peers(),
(unsigned long long)d.frames_to_local());
fflush(stdout);
last_boot = boot;
last_peers = peers;
}
ticks++;
}
printf("[session] stopping\n");
d.stop();
return 0;
}