diff options
Diffstat (limited to 'ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h')
-rw-r--r-- | ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h | 950 |
1 files changed, 459 insertions, 491 deletions
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h index ff04b5d72..4b8e7a7f4 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h +++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h @@ -7,7 +7,8 @@ * * https://github.com/mjansson/mdns * - * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * This library is put in the public domain; you can redistribute it and/or + * modify it without any restrictions. * */ @@ -31,76 +32,73 @@ #define MDNS_INVALID_POS ((size_t)-1) -#define MDNS_STRING_CONST(s) (s), (sizeof((s))-1) +#define MDNS_STRING_CONST(s) (s), (sizeof((s)) - 1) #define MDNS_STRING_FORMAT(s) (int)((s).length), s.str enum mdns_record_type { - MDNS_RECORDTYPE_IGNORE = 0, - //Address - MDNS_RECORDTYPE_A = 1, - //Domain Name pointer - MDNS_RECORDTYPE_PTR = 12, - //Arbitrary text string - MDNS_RECORDTYPE_TXT = 16, - //IP6 Address [Thomson] - MDNS_RECORDTYPE_AAAA = 28, - //Server Selection [RFC2782] - MDNS_RECORDTYPE_SRV = 33 + MDNS_RECORDTYPE_IGNORE = 0, + // Address + MDNS_RECORDTYPE_A = 1, + // Domain Name pointer + MDNS_RECORDTYPE_PTR = 12, + // Arbitrary text string + MDNS_RECORDTYPE_TXT = 16, + // IP6 Address [Thomson] + MDNS_RECORDTYPE_AAAA = 28, + // Server Selection [RFC2782] + MDNS_RECORDTYPE_SRV = 33 }; enum mdns_entry_type { - MDNS_ENTRYTYPE_ANSWER = 1, - MDNS_ENTRYTYPE_AUTHORITY = 2, - MDNS_ENTRYTYPE_ADDITIONAL = 3 + MDNS_ENTRYTYPE_ANSWER = 1, + MDNS_ENTRYTYPE_AUTHORITY = 2, + MDNS_ENTRYTYPE_ADDITIONAL = 3 }; -enum mdns_class { - MDNS_CLASS_IN = 1 -}; +enum mdns_class { MDNS_CLASS_IN = 1 }; -typedef enum mdns_record_type mdns_record_type_t; -typedef enum mdns_entry_type mdns_entry_type_t; -typedef enum mdns_class mdns_class_t; +typedef enum mdns_record_type mdns_record_type_t; +typedef enum mdns_entry_type mdns_entry_type_t; +typedef enum mdns_class mdns_class_t; -typedef int (* mdns_record_callback_fn)(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); +typedef int (*mdns_record_callback_fn)(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); -typedef struct mdns_string_t mdns_string_t; -typedef struct mdns_string_pair_t mdns_string_pair_t; -typedef struct mdns_record_srv_t mdns_record_srv_t; -typedef struct mdns_record_txt_t mdns_record_txt_t; +typedef struct mdns_string_t mdns_string_t; +typedef struct mdns_string_pair_t mdns_string_pair_t; +typedef struct mdns_record_srv_t mdns_record_srv_t; +typedef struct mdns_record_txt_t mdns_record_txt_t; struct mdns_string_t { - const char* str; - size_t length; + const char* str; + size_t length; }; struct mdns_string_pair_t { - size_t offset; - size_t length; - int ref; + size_t offset; + size_t length; + int ref; }; struct mdns_record_srv_t { - uint16_t priority; - uint16_t weight; - uint16_t port; - mdns_string_t name; + uint16_t priority; + uint16_t weight; + uint16_t port; + mdns_string_t name; }; struct mdns_record_txt_t { - mdns_string_t key; - mdns_string_t value; + mdns_string_t key; + mdns_string_t value; }; -static int -mdns_socket_open_ipv4(void); +static int mdns_socket_open_ipv4(void); -static int -mdns_socket_setup_ipv4(int sock); +static int mdns_socket_setup_ipv4(int sock); #if 0 static int @@ -112,8 +110,7 @@ static int mdns_socket_setup_ipv6(int sock); #endif -static void -mdns_socket_close(int sock); +static void mdns_socket_close(int sock); #if 0 static int @@ -125,21 +122,18 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, mdns_record_callback_fn callback, void* user_data); #endif -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity); +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity); -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot); +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot); -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity); +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity); -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset); +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset); #if 0 static int @@ -147,78 +141,80 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, const void* buffer_rhs, size_t size_rhs, size_t* ofs_rhs); #endif -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length); +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length); -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity); -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity); -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr); +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr); -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr); +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr); -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity); +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity); // Implementations -static int -mdns_socket_open_ipv4(void) { - int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) - return -1; - if (mdns_socket_setup_ipv4(sock)) { - mdns_socket_close(sock); - return -1; - } - return sock; +static int mdns_socket_open_ipv4(void) { + int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) return -1; + if (mdns_socket_setup_ipv4(sock)) { + mdns_socket_close(sock); + return -1; + } + return sock; } -static int -mdns_socket_setup_ipv4(int sock) { - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = INADDR_ANY; +static int mdns_socket_setup_ipv4(int sock) { + struct sockaddr_in saddr; + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = INADDR_ANY; #ifdef __APPLE__ - saddr.sin_len = sizeof(saddr); + saddr.sin_len = sizeof(saddr); #endif - if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) - return -1; + if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) return -1; #ifdef _WIN32 - unsigned long param = 1; - ioctlsocket(sock, FIONBIO, ¶m); + unsigned long param = 1; + ioctlsocket(sock, FIONBIO, ¶m); #else - const int flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); + const int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); #endif - unsigned char ttl = 1; - unsigned char loopback = 1; - struct ip_mreq req; + unsigned char ttl = 1; + unsigned char loopback = 1; + struct ip_mreq req; - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)); - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, + sizeof(ttl)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, + sizeof(loopback)); - memset(&req, 0, sizeof(req)); - req.imr_multiaddr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - req.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) - return -1; + memset(&req, 0, sizeof(req)); + req.imr_multiaddr.s_addr = + htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + req.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) + return -1; - return 0; + return 0; } #if 0 @@ -274,67 +270,58 @@ mdns_socket_setup_ipv6(int sock) { } #endif -static void -mdns_socket_close(int sock) { +static void mdns_socket_close(int sock) { #ifdef _WIN32 - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif } -static int -mdns_is_string_ref(uint8_t val) { - return (0xC0 == (val & 0xC0)); -} +static int mdns_is_string_ref(uint8_t val) { return (0xC0 == (val & 0xC0)); } -static mdns_string_pair_t -mdns_get_next_substring(const void* rawdata, size_t size, size_t offset) { - const uint8_t* buffer = rawdata; - mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; - if (!buffer[offset]) { - pair.offset = offset; - return pair; - } - if (mdns_is_string_ref(buffer[offset])) { - if (size < offset + 2) - return pair; +static mdns_string_pair_t mdns_get_next_substring(const void* rawdata, + size_t size, size_t offset) { + const uint8_t* buffer = rawdata; + mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; + if (!buffer[offset]) { + pair.offset = offset; + return pair; + } + if (mdns_is_string_ref(buffer[offset])) { + if (size < offset + 2) return pair; - offset = (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); - if (offset >= size) - return pair; + offset = + (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); + if (offset >= size) return pair; - pair.ref = 1; - } + pair.ref = 1; + } - size_t length = (size_t)buffer[offset++]; - if (size < offset + length) - return pair; + size_t length = (size_t)buffer[offset++]; + if (size < offset + length) return pair; - pair.offset = offset; - pair.length = length; + pair.offset = offset; + pair.length = length; - return pair; + return pair; } -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset) { - size_t cur = *offset; - mdns_string_pair_t substr; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return 0; - if (substr.ref) { - *offset = cur + 2; - return 1; - } - cur = substr.offset + substr.length; - } - while (substr.length); - - *offset = cur + 1; - return 1; +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset) { + size_t cur = *offset; + mdns_string_pair_t substr; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return 0; + if (substr.ref) { + *offset = cur + 2; + return 1; + } + cur = substr.offset + substr.length; + } while (substr.length); + + *offset = cur + 1; + return 1; } #if 0 @@ -378,142 +365,133 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, } #endif -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity) { - size_t cur = *offset; - size_t end = MDNS_INVALID_POS; - mdns_string_pair_t substr; - mdns_string_t result = {str, 0}; - char* dst = str; - size_t remain = capacity; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return result; - if (substr.ref && (end == MDNS_INVALID_POS)) - end = cur + 2; - if (substr.length) { - size_t to_copy = (substr.length < remain) ? substr.length : remain; - memcpy(dst, (const char*)buffer + substr.offset, to_copy); - dst += to_copy; - remain -= to_copy; - if (remain) { - *dst++ = '.'; - --remain; - } - } - cur = substr.offset + substr.length; - } - while (substr.length); - - if (end == MDNS_INVALID_POS) - end = cur + 1; - *offset = end; - - result.length = capacity - remain; - return result; +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity) { + size_t cur = *offset; + size_t end = MDNS_INVALID_POS; + mdns_string_pair_t substr; + mdns_string_t result = {str, 0}; + char* dst = str; + size_t remain = capacity; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return result; + if (substr.ref && (end == MDNS_INVALID_POS)) end = cur + 2; + if (substr.length) { + size_t to_copy = (substr.length < remain) ? substr.length : remain; + memcpy(dst, (const char*)buffer + substr.offset, to_copy); + dst += to_copy; + remain -= to_copy; + if (remain) { + *dst++ = '.'; + --remain; + } + } + cur = substr.offset + substr.length; + } while (substr.length); + + if (end == MDNS_INVALID_POS) end = cur + 1; + *offset = end; + + result.length = capacity - remain; + return result; } -static size_t -mdns_string_find(const char* str, size_t length, char c, size_t offset) { - const void* found; - if (offset >= length) - return MDNS_INVALID_POS; - found = memchr(str + offset, c, length - offset); - if (found) - return (size_t)((const char*)found - str); - return MDNS_INVALID_POS; +static size_t mdns_string_find(const char* str, size_t length, char c, + size_t offset) { + const void* found; + if (offset >= length) return MDNS_INVALID_POS; + found = memchr(str + offset, c, length - offset); + if (found) return (size_t)((const char*)found - str); + return MDNS_INVALID_POS; } -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length) { - size_t pos = 0; - size_t last_pos = 0; - size_t remain = capacity; - unsigned char* dest = data; - while ((last_pos < length) && ((pos = mdns_string_find(name, length, '.', last_pos)) != MDNS_INVALID_POS)) { - size_t sublength = pos - last_pos; - if (sublength < remain) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - last_pos = pos + 1; - } - if (last_pos < length) { - size_t sublength = length - last_pos; - if (sublength < capacity) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - } - if (!remain) - return 0; - *dest++ = 0; - return dest; +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length) { + size_t pos = 0; + size_t last_pos = 0; + size_t remain = capacity; + unsigned char* dest = data; + while ((last_pos < length) && + ((pos = mdns_string_find(name, length, '.', last_pos)) != + MDNS_INVALID_POS)) { + size_t sublength = pos - last_pos; + if (sublength < remain) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + last_pos = pos + 1; + } + if (last_pos < length) { + size_t sublength = length - last_pos; + if (sublength < capacity) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + } + if (!remain) return 0; + *dest++ = 0; + return dest; } -static size_t -mdns_records_parse(const struct sockaddr* from, const void* buffer, size_t size, size_t* offset, - mdns_entry_type_t type, size_t records, mdns_record_callback_fn callback, - void* user_data) { - size_t parsed = 0; - int do_callback = 1; - for (size_t i = 0; i < records; ++i) { - mdns_string_skip(buffer, size, offset); - const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); - - uint16_t rtype = ntohs(*data++); - uint16_t rclass = ntohs(*data++); - uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); data += 2; - uint16_t length = ntohs(*data++); - - *offset += 10; - - if (do_callback) { - ++parsed; - if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, length, - user_data)) - do_callback = 0; - } - - *offset += length; - } - return parsed; +static size_t mdns_records_parse(const struct sockaddr* from, + const void* buffer, size_t size, + size_t* offset, mdns_entry_type_t type, + size_t records, + mdns_record_callback_fn callback, + void* user_data) { + size_t parsed = 0; + int do_callback = 1; + for (size_t i = 0; i < records; ++i) { + mdns_string_skip(buffer, size, offset); + const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); + + uint16_t rtype = ntohs(*data++); + uint16_t rclass = ntohs(*data++); + uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); + data += 2; + uint16_t length = ntohs(*data++); + + *offset += 10; + + if (do_callback) { + ++parsed; + if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, + length, user_data)) + do_callback = 0; + } + + *offset += length; + } + return parsed; } static const uint8_t mdns_services_query[] = { - // Transaction ID - 0x00, 0x00, - // Flags - 0x00, 0x00, - // 1 question - 0x00, 0x01, - // No answer, authority or additional RRs - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - // _services._dns-sd._udp.local. - 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', - 0x07, '_', 'd', 'n', 's', '-', 's', 'd', - 0x04, '_', 'u', 'd', 'p', - 0x05, 'l', 'o', 'c', 'a', 'l', - 0x00, - // PTR record - 0x00, MDNS_RECORDTYPE_PTR, - // QU (unicast response) and class IN - 0x80, MDNS_CLASS_IN -}; + // Transaction ID + 0x00, 0x00, + // Flags + 0x00, 0x00, + // 1 question + 0x00, 0x01, + // No answer, authority or additional RRs + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // _services._dns-sd._udp.local. + 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', 0x07, '_', 'd', 'n', 's', + '-', 's', 'd', 0x04, '_', 'u', 'd', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + // PTR record + 0x00, MDNS_RECORDTYPE_PTR, + // QU (unicast response) and class IN + 0x80, MDNS_CLASS_IN}; #if 0 static int @@ -645,233 +623,223 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, static uint16_t mdns_transaction_id = 0; -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity) { - if (capacity < (17 + length)) - return -1; - - uint16_t* data = buffer; - //Transaction ID - *data++ = htons(++mdns_transaction_id); - //Flags - *data++ = 0; - //Questions - *data++ = htons(1); - //No answer, authority or additional RRs - *data++ = 0; - *data++ = 0; - *data++ = 0; - //Name string - data = mdns_string_make(data, capacity - 17, name, length); - if (!data) - return -1; - //Record type - *data++ = htons(type); - //! Unicast response, class IN - *data++ = htons(0x8000U | MDNS_CLASS_IN); - - struct sockaddr_storage addr_storage; - struct sockaddr_in addr; - struct sockaddr_in6 addr6; - struct sockaddr* saddr = (struct sockaddr*)&addr_storage; - socklen_t saddrlen = sizeof(struct sockaddr_storage); - if (getsockname(sock, saddr, &saddrlen)) - return -1; - if (saddr->sa_family == AF_INET6) { - memset(&addr6, 0, sizeof(struct sockaddr_in6)); - addr6.sin6_family = AF_INET6; +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity) { + if (capacity < (17 + length)) return -1; + + uint16_t* data = buffer; + // Transaction ID + *data++ = htons(++mdns_transaction_id); + // Flags + *data++ = 0; + // Questions + *data++ = htons(1); + // No answer, authority or additional RRs + *data++ = 0; + *data++ = 0; + *data++ = 0; + // Name string + data = mdns_string_make(data, capacity - 17, name, length); + if (!data) return -1; + // Record type + *data++ = htons(type); + //! Unicast response, class IN + *data++ = htons(0x8000U | MDNS_CLASS_IN); + + struct sockaddr_storage addr_storage; + struct sockaddr_in addr; + struct sockaddr_in6 addr6; + struct sockaddr* saddr = (struct sockaddr*)&addr_storage; + socklen_t saddrlen = sizeof(struct sockaddr_storage); + if (getsockname(sock, saddr, &saddrlen)) return -1; + if (saddr->sa_family == AF_INET6) { + memset(&addr6, 0, sizeof(struct sockaddr_in6)); + addr6.sin6_family = AF_INET6; #ifdef __APPLE__ - addr6.sin6_len = sizeof(struct sockaddr_in6); + addr6.sin6_len = sizeof(struct sockaddr_in6); #endif - addr6.sin6_addr.s6_addr[0] = 0xFF; - addr6.sin6_addr.s6_addr[1] = 0x02; - addr6.sin6_addr.s6_addr[15] = 0xFB; - addr6.sin6_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr6; - saddrlen = sizeof(struct sockaddr_in6); - } - else { - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; + addr6.sin6_addr.s6_addr[0] = 0xFF; + addr6.sin6_addr.s6_addr[1] = 0x02; + addr6.sin6_addr.s6_addr[15] = 0xFB; + addr6.sin6_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr6; + saddrlen = sizeof(struct sockaddr_in6); + } else { + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; #ifdef __APPLE__ - addr.sin_len = sizeof(struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - addr.sin_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr; - saddrlen = sizeof(struct sockaddr_in); - } - - if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, - saddr, saddrlen) < 0) - return -1; - return 0; + addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + addr.sin_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr; + saddrlen = sizeof(struct sockaddr_in); + } + + if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, saddr, saddrlen) < 0) + return -1; + return 0; } -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot) { - struct sockaddr_in6 addr; - struct sockaddr* saddr = (struct sockaddr*)&addr; - memset(&addr, 0, sizeof(addr)); - saddr->sa_family = AF_INET; +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot) { + struct sockaddr_in6 addr; + struct sockaddr* saddr = (struct sockaddr*)&addr; + memset(&addr, 0, sizeof(addr)); + saddr->sa_family = AF_INET; #ifdef __APPLE__ - saddr->sa_len = sizeof(addr); + saddr->sa_len = sizeof(addr); #endif - socklen_t addrlen = sizeof(addr); - int ret = recvfrom(sock, buffer, capacity, 0, - saddr, &addrlen); - if (ret <= 0) - return 0; - - size_t data_size = (size_t)ret; - uint16_t* data = (uint16_t*)buffer; - - uint16_t transaction_id = ntohs(*data++); - ++data;// uint16_t flags = ntohs(*data++); - uint16_t questions = ntohs(*data++); - uint16_t answer_rrs = ntohs(*data++); - uint16_t authority_rrs = ntohs(*data++); - uint16_t additional_rrs = ntohs(*data++); - - if (one_shot && transaction_id != mdns_transaction_id)// || (flags != 0x8400)) - return 0; //Not a reply to our last question - - if (questions > 1) - return 0; - - //Skip questions part - int i; - for (i = 0; i < questions; ++i) { - size_t ofs = (size_t)((char*)data - (char*)buffer); - if (!mdns_string_skip(buffer, data_size, &ofs)) - return 0; - data = (void*)((char*)buffer + ofs); - ++data; - ++data; - } - - size_t records = 0; - size_t offset = (size_t)((char*)data - (char*)buffer); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ANSWER, answer_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, - callback, user_data); - return records; + socklen_t addrlen = sizeof(addr); + int ret = recvfrom(sock, buffer, capacity, 0, saddr, &addrlen); + if (ret <= 0) return 0; + + size_t data_size = (size_t)ret; + uint16_t* data = (uint16_t*)buffer; + + uint16_t transaction_id = ntohs(*data++); + ++data; // uint16_t flags = ntohs(*data++); + uint16_t questions = ntohs(*data++); + uint16_t answer_rrs = ntohs(*data++); + uint16_t authority_rrs = ntohs(*data++); + uint16_t additional_rrs = ntohs(*data++); + + if (one_shot && + transaction_id != mdns_transaction_id) // || (flags != 0x8400)) + return 0; // Not a reply to our last question + + if (questions > 1) return 0; + + // Skip questions part + int i; + for (i = 0; i < questions; ++i) { + size_t ofs = (size_t)((char*)data - (char*)buffer); + if (!mdns_string_skip(buffer, data_size, &ofs)) return 0; + data = (void*)((char*)buffer + ofs); + ++data; + ++data; + } + + size_t records = 0; + size_t offset = (size_t)((char*)data - (char*)buffer); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ANSWER, answer_rrs, callback, + user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, + callback, user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, + callback, user_data); + return records; } -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - //PTR record is just a string - if ((size >= offset + length) && (length >= 2)) - return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - mdns_string_t empty = {0, 0}; - return empty; +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity) { + // PTR record is just a string + if ((size >= offset + length) && (length >= 2)) + return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + mdns_string_t empty = {0, 0}; + return empty; } -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - mdns_record_srv_t srv; - memset(&srv, 0, sizeof(mdns_record_srv_t)); - // Read the priority, weight, port number and the discovery name - // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): - // 2 bytes network-order unsigned priority - // 2 bytes network-order unsigned weight - // 2 bytes network-order unsigned port - // string: discovery (domain) name, minimum 2 bytes when compressed - if ((size >= offset + length) && (length >= 8)) { - const uint16_t* recorddata = (const uint16_t*)((const char*)buffer + offset); - srv.priority = ntohs(*recorddata++); - srv.weight = ntohs(*recorddata++); - srv.port = ntohs(*recorddata++); - offset += 6; - srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - } - return srv; +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity) { + mdns_record_srv_t srv; + memset(&srv, 0, sizeof(mdns_record_srv_t)); + // Read the priority, weight, port number and the discovery name + // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): + // 2 bytes network-order unsigned priority + // 2 bytes network-order unsigned weight + // 2 bytes network-order unsigned port + // string: discovery (domain) name, minimum 2 bytes when compressed + if ((size >= offset + length) && (length >= 8)) { + const uint16_t* recorddata = + (const uint16_t*)((const char*)buffer + offset); + srv.priority = ntohs(*recorddata++); + srv.weight = ntohs(*recorddata++); + srv.port = ntohs(*recorddata++); + offset += 6; + srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + } + return srv; } -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr) { - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr) { + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; #ifdef __APPLE__ - addr->sin_len = sizeof(struct sockaddr_in); + addr->sin_len = sizeof(struct sockaddr_in); #endif - if ((size >= offset + length) && (length == 4)) - addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 4)) + addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); + return addr; } -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr) { - memset(addr, 0, sizeof(struct sockaddr_in6)); - addr->sin6_family = AF_INET6; +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr) { + memset(addr, 0, sizeof(struct sockaddr_in6)); + addr->sin6_family = AF_INET6; #ifdef __APPLE__ - addr->sin6_len = sizeof(struct sockaddr_in6); + addr->sin6_len = sizeof(struct sockaddr_in6); #endif - if ((size >= offset + length) && (length == 16)) - addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 16)) + addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); + return addr; } -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity) { - size_t parsed = 0; - const char* strdata; - size_t separator, sublength; - size_t end = offset + length; - - if (size < end) - end = size; - - while ((offset < end) && (parsed < capacity)) { - strdata = (const char*)buffer + offset; - sublength = *(const unsigned char*)strdata; - - ++strdata; - offset += sublength + 1; - - separator = 0; - for (size_t c = 0; c < sublength; ++c) { - //DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] - if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) - break; - if (strdata[c] == '=') { - separator = c; - break; - } - } - - if (!separator) - continue; - - if (separator < sublength) { - records[parsed].key.str = strdata; - records[parsed].key.length = separator; - records[parsed].value.str = strdata + separator + 1; - records[parsed].value.length = sublength - (separator + 1); - } - else { - records[parsed].key.str = strdata; - records[parsed].key.length = sublength; - } - - ++parsed; - } - - return parsed; +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity) { + size_t parsed = 0; + const char* strdata; + size_t separator, sublength; + size_t end = offset + length; + + if (size < end) end = size; + + while ((offset < end) && (parsed < capacity)) { + strdata = (const char*)buffer + offset; + sublength = *(const unsigned char*)strdata; + + ++strdata; + offset += sublength + 1; + + separator = 0; + for (size_t c = 0; c < sublength; ++c) { + // DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] + if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) break; + if (strdata[c] == '=') { + separator = c; + break; + } + } + + if (!separator) continue; + + if (separator < sublength) { + records[parsed].key.str = strdata; + records[parsed].key.length = separator; + records[parsed].value.str = strdata + separator + 1; + records[parsed].value.length = sublength - (separator + 1); + } else { + records[parsed].key.str = strdata; + records[parsed].key.length = sublength; + } + + ++parsed; + } + + return parsed; } #ifdef _WIN32 |