Discovery: reply unicast when responding to new/restarted peer
When we see a new peer or detect a restart (site_id change for known addr+port), send the announcement directly to that host via unicast instead of broadcasting to the multicast group. This avoids waking every other node on the subnet for a reply that is only relevant to one machine. The periodic multicast announcements continue unchanged for initial discovery. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -76,19 +76,14 @@ static int find_slot(struct Discovery *d) {
|
|||||||
|
|
||||||
/* -- send ------------------------------------------------------------------ */
|
/* -- send ------------------------------------------------------------------ */
|
||||||
|
|
||||||
static void send_announcement(struct Discovery *d) {
|
static size_t build_announcement(struct Discovery *d, uint8_t *buf) {
|
||||||
size_t name_len = strlen(d->config.name);
|
size_t name_len = strlen(d->config.name);
|
||||||
if (name_len > DISCOVERY_MAX_NAME_LEN) { name_len = DISCOVERY_MAX_NAME_LEN; }
|
if (name_len > DISCOVERY_MAX_NAME_LEN) { name_len = DISCOVERY_MAX_NAME_LEN; }
|
||||||
|
|
||||||
uint32_t payload_len = (uint32_t)(ANN_FIXED_SIZE + name_len);
|
uint32_t payload_len = (uint32_t)(ANN_FIXED_SIZE + name_len);
|
||||||
size_t total = TRANSPORT_FRAME_HEADER_SIZE + payload_len;
|
put_u16(buf, 0, 0x0010);
|
||||||
uint8_t buf[TRANSPORT_FRAME_HEADER_SIZE + ANN_FIXED_SIZE + DISCOVERY_MAX_NAME_LEN];
|
|
||||||
|
|
||||||
/* frame header */
|
|
||||||
put_u16(buf, 0, 0x0010); /* message_type: DISCOVERY_ANNOUNCE */
|
|
||||||
put_u32(buf, 2, payload_len);
|
put_u32(buf, 2, payload_len);
|
||||||
|
|
||||||
/* announcement payload */
|
|
||||||
uint8_t *p = buf + TRANSPORT_FRAME_HEADER_SIZE;
|
uint8_t *p = buf + TRANSPORT_FRAME_HEADER_SIZE;
|
||||||
put_u8 (p, ANN_PROTOCOL_VERSION, DISCOVERY_PROTOCOL_VERSION);
|
put_u8 (p, ANN_PROTOCOL_VERSION, DISCOVERY_PROTOCOL_VERSION);
|
||||||
put_u16(p, ANN_SITE_ID, d->config.site_id);
|
put_u16(p, ANN_SITE_ID, d->config.site_id);
|
||||||
@@ -97,10 +92,26 @@ static void send_announcement(struct Discovery *d) {
|
|||||||
put_u8 (p, ANN_NAME_LEN, (uint8_t)name_len);
|
put_u8 (p, ANN_NAME_LEN, (uint8_t)name_len);
|
||||||
memcpy(p + ANN_NAME, d->config.name, name_len);
|
memcpy(p + ANN_NAME, d->config.name, name_len);
|
||||||
|
|
||||||
|
return TRANSPORT_FRAME_HEADER_SIZE + payload_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_announcement(struct Discovery *d) {
|
||||||
|
uint8_t buf[TRANSPORT_FRAME_HEADER_SIZE + ANN_FIXED_SIZE + DISCOVERY_MAX_NAME_LEN];
|
||||||
|
size_t total = build_announcement(d, buf);
|
||||||
sendto(d->sock, buf, total, 0,
|
sendto(d->sock, buf, total, 0,
|
||||||
(struct sockaddr *)&d->mcast_addr, sizeof(d->mcast_addr));
|
(struct sockaddr *)&d->mcast_addr, sizeof(d->mcast_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_announcement_unicast(struct Discovery *d, uint32_t addr) {
|
||||||
|
uint8_t buf[TRANSPORT_FRAME_HEADER_SIZE + ANN_FIXED_SIZE + DISCOVERY_MAX_NAME_LEN];
|
||||||
|
size_t total = build_announcement(d, buf);
|
||||||
|
struct sockaddr_in dest = {0};
|
||||||
|
dest.sin_family = AF_INET;
|
||||||
|
dest.sin_port = htons(DISCOVERY_PORT);
|
||||||
|
dest.sin_addr.s_addr = addr;
|
||||||
|
sendto(d->sock, buf, total, 0, (struct sockaddr *)&dest, sizeof(dest));
|
||||||
|
}
|
||||||
|
|
||||||
/* -- timeout check --------------------------------------------------------- */
|
/* -- timeout check --------------------------------------------------------- */
|
||||||
|
|
||||||
static void check_timeouts(struct Discovery *d) {
|
static void check_timeouts(struct Discovery *d) {
|
||||||
@@ -237,11 +248,10 @@ static void *receive_thread_fn(void *arg) {
|
|||||||
pthread_mutex_unlock(&d->peers_mutex);
|
pthread_mutex_unlock(&d->peers_mutex);
|
||||||
|
|
||||||
if (is_new || reannounce) {
|
if (is_new || reannounce) {
|
||||||
/* new peer, or peer restarted (site_id changed) — announce ourselves
|
/* new peer, or peer restarted (site_id changed) — reply directly
|
||||||
* immediately so it learns about us without waiting up to interval_ms */
|
* to that host so it learns about us without waiting up to interval_ms.
|
||||||
pthread_mutex_lock(&d->announce_mutex);
|
* Use unicast rather than multicast to avoid disturbing other nodes. */
|
||||||
pthread_cond_signal(&d->announce_cond);
|
send_announcement_unicast(d, addr);
|
||||||
pthread_mutex_unlock(&d->announce_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_new && d->config.on_peer_found) {
|
if (is_new && d->config.on_peer_found) {
|
||||||
|
|||||||
Reference in New Issue
Block a user