Trigger early announcement when a new peer is first seen

When the receive thread detects a genuinely new peer it sets
early_announce, causing the announce thread to break out of its
sleep and send immediately. The new node receives our announcement
within ~100ms rather than waiting up to interval_ms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 22:23:46 +00:00
parent e8f52e8fe6
commit d6e34ed95b

View File

@@ -40,6 +40,7 @@ struct Discovery {
pthread_t announce_thread; pthread_t announce_thread;
pthread_t receive_thread; pthread_t receive_thread;
atomic_int running; atomic_int running;
atomic_int early_announce; /* set when a new peer is seen */
pthread_mutex_t peers_mutex; pthread_mutex_t peers_mutex;
struct Peer_Entry peers[DISCOVERY_MAX_PEERS]; struct Peer_Entry peers[DISCOVERY_MAX_PEERS];
@@ -131,9 +132,11 @@ static void *announce_thread_fn(void *arg) {
send_announcement(d); send_announcement(d);
while (atomic_load(&d->running)) { while (atomic_load(&d->running)) {
/* sleep in 100 ms increments so destroy doesn't wait a full interval */ /* sleep in 100 ms increments; breaks early if a new peer is detected
* or if destroy is called */
uint32_t elapsed = 0; uint32_t elapsed = 0;
while (atomic_load(&d->running) && elapsed < d->config.interval_ms) { while (atomic_load(&d->running) && elapsed < d->config.interval_ms) {
if (atomic_load(&d->early_announce)) { break; }
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100 * 1000000L }; struct timespec ts = { .tv_sec = 0, .tv_nsec = 100 * 1000000L };
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
elapsed += 100; elapsed += 100;
@@ -141,6 +144,7 @@ static void *announce_thread_fn(void *arg) {
if (!atomic_load(&d->running)) { break; } if (!atomic_load(&d->running)) { break; }
atomic_store(&d->early_announce, 0);
send_announcement(d); send_announcement(d);
check_timeouts(d); check_timeouts(d);
} }
@@ -224,8 +228,11 @@ static void *receive_thread_fn(void *arg) {
pthread_mutex_unlock(&d->peers_mutex); pthread_mutex_unlock(&d->peers_mutex);
if (is_new && d->config.on_peer_found) { if (is_new) {
d->config.on_peer_found(&peer_copy, d->config.userdata); atomic_store(&d->early_announce, 1);
if (d->config.on_peer_found) {
d->config.on_peer_found(&peer_copy, d->config.userdata);
}
} }
} }
@@ -255,6 +262,7 @@ struct App_Error discovery_create(struct Discovery **out,
inet_pton(AF_INET, DISCOVERY_MULTICAST_GROUP, &d->mcast_addr.sin_addr); inet_pton(AF_INET, DISCOVERY_MULTICAST_GROUP, &d->mcast_addr.sin_addr);
atomic_init(&d->running, 0); atomic_init(&d->running, 0);
atomic_init(&d->early_announce, 0);
pthread_mutex_init(&d->peers_mutex, NULL); pthread_mutex_init(&d->peers_mutex, NULL);
*out = d; *out = d;