#include #include #include #include #include #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 [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; }