Files
video-setup/dev/cli/discovery_cli.c
mikael-lovqvists-claude-agent fe350e531e Add discovery module: UDP multicast announcements and peer tracking
Sends 6-byte framed announcements to 224.0.0.251:5353 on startup and
every interval_ms (default 5s). Receive thread maintains a peer table
(max 64 entries); fires on_peer_found for new peers, on_peer_lost when
a peer misses timeout_intervals (default 3) consecutive intervals.

Own announcements are filtered by name+site_id. SO_REUSEADDR+REUSEPORT
allows multiple processes on the same host for testing.

discovery_cli: announce <name> <tcp_port> [flags] — prints found/lost events.

Also notes future config module in planning.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 22:19:56 +00:00

109 lines
3.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include "discovery.h"
#include "error.h"
static void flags_str(uint16_t flags, char *buf, size_t len) {
buf[0] = '\0';
if (flags & DISCOVERY_FLAG_SOURCE) { strncat(buf, "source ", len - strlen(buf) - 1); }
if (flags & DISCOVERY_FLAG_RELAY) { strncat(buf, "relay ", len - strlen(buf) - 1); }
if (flags & DISCOVERY_FLAG_SINK) { strncat(buf, "sink ", len - strlen(buf) - 1); }
if (flags & DISCOVERY_FLAG_CONTROLLER) { strncat(buf, "controller ", len - strlen(buf) - 1); }
/* trim trailing space */
size_t l = strlen(buf);
if (l > 0 && buf[l - 1] == ' ') { buf[l - 1] = '\0'; }
}
static void on_peer_found(const struct Discovery_Peer *peer, void *userdata) {
(void)userdata;
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &peer->addr, addr, sizeof(addr));
char flags[64];
flags_str(peer->function_flags, flags, sizeof(flags));
printf("found %-30s %s:%u site=%u [%s]\n",
peer->name, addr, peer->tcp_port, peer->site_id, flags);
}
static void on_peer_lost(const struct Discovery_Peer *peer, void *userdata) {
(void)userdata;
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &peer->addr, addr, sizeof(addr));
printf("lost %-30s %s:%u\n", peer->name, addr, peer->tcp_port);
}
static void usage(void) {
fprintf(stderr,
"usage: discovery_cli <name> <tcp_port> [flags]\n"
"\n"
" name node name in namespace:instance form, e.g. v4l2:microscope\n"
" tcp_port port this node listens on for transport connections\n"
" flags comma-separated roles: source,relay,sink,controller\n"
" default: source\n"
"\n"
"Announces this node on the multicast group and prints peers as they\n"
"appear and disappear. Press Ctrl-C to exit.\n");
}
static uint16_t parse_flags(const char *s) {
uint16_t f = 0;
if (strstr(s, "source")) { f |= DISCOVERY_FLAG_SOURCE; }
if (strstr(s, "relay")) { f |= DISCOVERY_FLAG_RELAY; }
if (strstr(s, "sink")) { f |= DISCOVERY_FLAG_SINK; }
if (strstr(s, "controller")) { f |= DISCOVERY_FLAG_CONTROLLER; }
return f;
}
int main(int argc, char **argv) {
if (argc < 3) {
usage();
return 1;
}
const char *name = argv[1];
uint16_t tcp_port = (uint16_t)atoi(argv[2]);
uint16_t flags = argc >= 4 ? parse_flags(argv[3]) : DISCOVERY_FLAG_SOURCE;
if (strlen(name) == 0 || strlen(name) > DISCOVERY_MAX_NAME_LEN) {
fprintf(stderr, "name must be 1%d characters\n", DISCOVERY_MAX_NAME_LEN);
return 1;
}
struct Discovery_Config config = {
.site_id = 0,
.tcp_port = tcp_port,
.function_flags = flags,
.name = name,
.interval_ms = 0, /* use default */
.timeout_intervals = 0, /* use default */
.on_peer_found = on_peer_found,
.on_peer_lost = on_peer_lost,
.userdata = NULL,
};
struct Discovery *d;
struct App_Error err = discovery_create(&d, &config);
if (!APP_IS_OK(err)) {
fprintf(stderr, "discovery_create: errno %d\n", err.detail.syscall.err_no);
return 1;
}
err = discovery_start(d);
if (!APP_IS_OK(err)) {
fprintf(stderr, "discovery_start: errno %d\n", err.detail.syscall.err_no);
return 1;
}
char flags_buf[64];
flags_str(flags, flags_buf, sizeof(flags_buf));
printf("announcing %-30s port=%u [%s]\n", name, tcp_port, flags_buf);
printf("listening on %s:%d\n\n", DISCOVERY_MULTICAST_GROUP, DISCOVERY_PORT);
pause();
discovery_destroy(d);
return 0;
}