aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c')
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
new file mode 100644
index 000000000..a8e97e8e0
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
@@ -0,0 +1,192 @@
+
+#ifdef _WIN32
+# define _CRT_SECURE_NO_WARNINGS 1
+#endif
+
+#include "mdns.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef _WIN32
+# define sleep(x) Sleep(x * 1000)
+#else
+# include <netdb.h>
+#endif
+
+static char addrbuffer[64];
+static char namebuffer[256];
+static mdns_record_txt_t txtbuffer[128];
+
+static mdns_string_t
+ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in),
+ host, NI_MAXHOST, service, NI_MAXSERV,
+ NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin_port != 0)
+ len = snprintf(buffer, capacity, "%s:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity)
+ len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
+}
+
+static mdns_string_t
+ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST, service, NI_MAXSERV,
+ NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin6_port != 0)
+ len = snprintf(buffer, capacity, "[%s]:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity)
+ len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
+}
+
+static mdns_string_t
+ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) {
+ if (addr->sa_family == AF_INET6)
+ return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr);
+ return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr);
+}
+
+static int
+callback(const struct sockaddr* from,
+ mdns_entry_type_t entry, uint16_t type,
+ uint16_t rclass, uint32_t ttl,
+ const void* data, size_t size, size_t offset, size_t length,
+ void* user_data) {
+ mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from);
+ const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" :
+ ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
+ if (type == MDNS_RECORDTYPE_PTR) {
+ mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length,
+ namebuffer, sizeof(namebuffer));
+ INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length);
+ }
+ else if (type == MDNS_RECORDTYPE_SRV) {
+ mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length,
+ namebuffer, sizeof(namebuffer));
+ INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
+ }
+ else if (type == MDNS_RECORDTYPE_A) {
+ struct sockaddr_in addr;
+ mdns_record_parse_a(data, size, offset, length, &addr);
+ mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr);
+ INFO("%.*s : %s A %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+ }
+ else if (type == MDNS_RECORDTYPE_AAAA) {
+ struct sockaddr_in6 addr;
+ mdns_record_parse_aaaa(data, size, offset, length, &addr);
+ mdns_string_t addrstr = ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr);
+ INFO("%.*s : %s AAAA %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+ }
+ else if (type == MDNS_RECORDTYPE_TXT) {
+ size_t parsed = mdns_record_parse_txt(data, size, offset, length,
+ txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
+ for (size_t itxt = 0; itxt < parsed; ++itxt) {
+ if (txtbuffer[itxt].value.length) {
+ INFO("%.*s : %s TXT %.*s = %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(txtbuffer[itxt].key),
+ MDNS_STRING_FORMAT(txtbuffer[itxt].value));
+ }
+ else {
+ INFO("%.*s : %s TXT %.*s\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(txtbuffer[itxt].key));
+ }
+ }
+ }
+ else {
+ INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ type, rclass, ttl, (int)length);
+ }
+ return 0;
+}
+
+int
+main() {
+ size_t capacity = 2048;
+ void* buffer = 0;
+ void* user_data = 0;
+ size_t records;
+
+#ifdef _WIN32
+ WORD versionWanted = MAKEWORD(1, 1);
+ WSADATA wsaData;
+ WSAStartup(versionWanted, &wsaData);
+#endif
+
+ int sock = mdns_socket_open_ipv4();
+ if (sock < 0) {
+ INFO("Failed to open socket: %s\n", strerror(errno));
+ return -1;
+ }
+ INFO("Opened IPv4 socket for mDNS/DNS-SD\n");
+ buffer = malloc(capacity);
+/*
+ INFO("Sending DNS-SD discovery\n");
+ if (mdns_discovery_send(sock)) {
+ INFO("Failed to send DNS-DS discovery: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ INFO("Reading DNS-SD replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_discovery_recv(sock, buffer, capacity, callback,
+ user_data);
+ sleep(1);
+ }
+ */
+
+ INFO("Sending mDNS query\n");
+ if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR,
+ MDNS_STRING_CONST("_hicn._udp.local."),
+ buffer, capacity)) {
+ INFO("Failed to send mDNS query: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ INFO("Reading mDNS replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1);
+ sleep(1);
+ }
+
+quit:
+ free(buffer);
+
+ mdns_socket_close(sock);
+ INFO("Closed socket\n");
+
+#ifdef _WIN32
+ WSACleanup();
+#endif
+
+ return 0;
+}