OverviewFilesCommitsIssuesDocsReleasesPeers

hyperswarm-peer / daemon / main.cpp

85 lines · cpp ref:
// 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;
}