Update mdns dependency to latest development release
This commit is contained in:
parent
4bae567c4c
commit
6157668057
1 changed files with 217 additions and 135 deletions
352
dependencies/mdns/mdns.h
vendored
352
dependencies/mdns/mdns.h
vendored
|
|
@ -94,6 +94,7 @@ typedef struct mdns_record_ptr_t mdns_record_ptr_t;
|
|||
typedef struct mdns_record_a_t mdns_record_a_t;
|
||||
typedef struct mdns_record_aaaa_t mdns_record_aaaa_t;
|
||||
typedef struct mdns_record_txt_t mdns_record_txt_t;
|
||||
typedef struct mdns_query_t mdns_query_t;
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef int mdns_size_t;
|
||||
|
|
@ -154,6 +155,8 @@ struct mdns_record_t {
|
|||
mdns_record_aaaa_t aaaa;
|
||||
mdns_record_txt_t txt;
|
||||
} data;
|
||||
uint16_t rclass;
|
||||
uint32_t ttl;
|
||||
};
|
||||
|
||||
struct mdns_header_t {
|
||||
|
|
@ -165,6 +168,12 @@ struct mdns_header_t {
|
|||
uint16_t additional_rrs;
|
||||
};
|
||||
|
||||
struct mdns_query_t {
|
||||
mdns_record_type_t type;
|
||||
const char* name;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
// mDNS/DNS-SD public API
|
||||
|
||||
//! Open and setup a IPv4 socket for mDNS/DNS-SD. To bind the socket to a specific interface, pass
|
||||
|
|
@ -233,7 +242,19 @@ static inline int
|
|||
mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, void* buffer,
|
||||
size_t capacity, uint16_t query_id);
|
||||
|
||||
//! Receive unicast responses to a mDNS query sent with mdns_discovery_recv, optionally filtering
|
||||
//! Send a multicast mDNS query on the given socket for the given service names. The supplied buffer
|
||||
//! will be used to build the query packet and must be 32 bit aligned. The query ID can be set to
|
||||
//! non-zero to filter responses, however the RFC states that the query ID SHOULD be set to 0 for
|
||||
//! multicast queries. Each additional service name query consists of a triplet - a record type
|
||||
//! (mdns_record_type_t), a name string pointer (const char*) and a name length (size_t). The list
|
||||
//! of variable arguments should be terminated with a record type of 0. The query will request a
|
||||
//! unicast response if the socket is bound to an ephemeral port, or a multicast response if the
|
||||
//! socket is bound to mDNS port 5353. Returns the used query ID, or <0 if error.
|
||||
static inline int
|
||||
mdns_multiquery_send(int sock, const mdns_query_t* query, size_t count, void* buffer,
|
||||
size_t capacity, uint16_t query_id);
|
||||
|
||||
//! Receive unicast responses to a mDNS query sent with mdns_[multi]query_send, optionally filtering
|
||||
//! out any responses not matching the given query ID. Set the query ID to 0 to parse all responses,
|
||||
//! even if it is not matching the query ID set in a specific query. Any data will be piped to the
|
||||
//! given callback for parsing. Buffer must be 32 bit aligned. Parsing is stopped when callback
|
||||
|
|
@ -251,8 +272,8 @@ static inline int
|
|||
mdns_query_answer_unicast(int sock, const void* address, size_t address_size, void* buffer,
|
||||
size_t capacity, uint16_t query_id, mdns_record_type_t record_type,
|
||||
const char* name, size_t name_length, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count,
|
||||
mdns_record_t* additional, size_t additional_count);
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count);
|
||||
|
||||
//! Send a variable multicast mDNS query answer to any question with variable number of records. Use
|
||||
//! the top bit of the query class field (MDNS_UNICAST_RESPONSE) in the query recieved to determine
|
||||
|
|
@ -260,23 +281,23 @@ mdns_query_answer_unicast(int sock, const void* address, size_t address_size, vo
|
|||
//! aligned. Returns 0 if success, or <0 if error.
|
||||
static inline int
|
||||
mdns_query_answer_multicast(int sock, void* buffer, size_t capacity, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count,
|
||||
mdns_record_t* additional, size_t additional_count);
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count);
|
||||
|
||||
//! Send a variable multicast mDNS announcement (as an unsolicited answer) with variable number of
|
||||
//! records.Buffer must be 32 bit aligned. Returns 0 if success, or <0 if error. Use this on service
|
||||
//! startup to announce your instance to the local network.
|
||||
static inline int
|
||||
mdns_announce_multicast(int sock, void* buffer, size_t capacity, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count, mdns_record_t* additional,
|
||||
size_t additional_count);
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count);
|
||||
|
||||
//! Send a variable multicast mDNS announcement. Use this on service end for removing the resource
|
||||
//! from the local network. The records must be identical to the according announcement.
|
||||
static inline int
|
||||
mdns_goodbye_multicast(int sock, void* buffer, size_t capacity, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count, mdns_record_t* additional,
|
||||
size_t additional_count);
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count);
|
||||
|
||||
// Parse records functions
|
||||
|
||||
|
|
@ -317,6 +338,9 @@ mdns_string_skip(const void* buffer, size_t size, size_t* offset);
|
|||
static inline size_t
|
||||
mdns_string_find(const char* str, size_t length, char c, size_t offset);
|
||||
|
||||
//! Compare if two strings are equal. If the strings are equal it returns >0 and the offset variables are
|
||||
//! updated to the end of the corresponding strings. If the strings are not equal it returns 0 and
|
||||
//! the offset variables are NOT updated.
|
||||
static inline int
|
||||
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);
|
||||
|
|
@ -829,7 +853,7 @@ mdns_multicast_send(int sock, const void* buffer, size_t size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline const uint8_t mdns_services_query[] = {
|
||||
static const uint8_t mdns_services_query[] = {
|
||||
// Query ID
|
||||
0x00, 0x00,
|
||||
// Flags
|
||||
|
|
@ -882,20 +906,18 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, mdns_record_callbac
|
|||
|
||||
// It seems some implementations do not fill the correct questions field,
|
||||
// so ignore this check for now and only validate answer string
|
||||
/*
|
||||
if (questions != 1)
|
||||
return 0;
|
||||
*/
|
||||
// if (questions != 1)
|
||||
// return 0;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < questions; ++i) {
|
||||
size_t ofs = MDNS_POINTER_DIFF(data, buffer);
|
||||
size_t verify_ofs = 12;
|
||||
size_t offset = MDNS_POINTER_DIFF(data, buffer);
|
||||
size_t verify_offset = 12;
|
||||
// Verify it's our question, _services._dns-sd._udp.local.
|
||||
if (!mdns_string_equal(buffer, data_size, &ofs, mdns_services_query,
|
||||
sizeof(mdns_services_query), &verify_ofs))
|
||||
if (!mdns_string_equal(buffer, data_size, &offset, mdns_services_query,
|
||||
sizeof(mdns_services_query), &verify_offset))
|
||||
return 0;
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET(buffer, ofs);
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET(buffer, offset);
|
||||
|
||||
uint16_t rtype = mdns_ntohs(data++);
|
||||
uint16_t rclass = mdns_ntohs(data++);
|
||||
|
|
@ -906,31 +928,33 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, mdns_record_callbac
|
|||
}
|
||||
|
||||
for (i = 0; i < answer_rrs; ++i) {
|
||||
size_t ofs = MDNS_POINTER_DIFF(data, buffer);
|
||||
size_t verify_ofs = 12;
|
||||
size_t offset = MDNS_POINTER_DIFF(data, buffer);
|
||||
size_t verify_offset = 12;
|
||||
// Verify it's an answer to our question, _services._dns-sd._udp.local.
|
||||
size_t name_offset = ofs;
|
||||
int is_answer = mdns_string_equal(buffer, data_size, &ofs, mdns_services_query,
|
||||
sizeof(mdns_services_query), &verify_ofs);
|
||||
size_t name_length = ofs - name_offset;
|
||||
if ((ofs + 10) > data_size)
|
||||
size_t name_offset = offset;
|
||||
int is_answer = mdns_string_equal(buffer, data_size, &offset, mdns_services_query,
|
||||
sizeof(mdns_services_query), &verify_offset);
|
||||
if (!is_answer && !mdns_string_skip(buffer, data_size, &offset))
|
||||
break;
|
||||
size_t name_length = offset - name_offset;
|
||||
if ((offset + 10) > data_size)
|
||||
return records;
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET(buffer, ofs);
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET(buffer, offset);
|
||||
|
||||
uint16_t rtype = mdns_ntohs(data++);
|
||||
uint16_t rclass = mdns_ntohs(data++);
|
||||
uint32_t ttl = mdns_ntohl(data);
|
||||
data += 2;
|
||||
uint16_t length = mdns_ntohs(data++);
|
||||
if (length > (data_size - ofs))
|
||||
if (length > (data_size - offset))
|
||||
return 0;
|
||||
|
||||
if (is_answer) {
|
||||
++records;
|
||||
ofs = MDNS_POINTER_DIFF(data, buffer);
|
||||
offset = MDNS_POINTER_DIFF(data, buffer);
|
||||
if (callback &&
|
||||
callback(sock, saddr, addrlen, MDNS_ENTRYTYPE_ANSWER, query_id, rtype, rclass, ttl,
|
||||
buffer, data_size, name_offset, name_length, ofs, length, user_data))
|
||||
buffer, data_size, name_offset, name_length, offset, length, user_data))
|
||||
return records;
|
||||
}
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET_CONST(data, length);
|
||||
|
|
@ -975,27 +999,22 @@ mdns_socket_listen(int sock, void* buffer, size_t capacity, mdns_record_callback
|
|||
uint16_t query_id = mdns_ntohs(data++);
|
||||
uint16_t flags = mdns_ntohs(data++);
|
||||
uint16_t questions = mdns_ntohs(data++);
|
||||
/*
|
||||
This data is unused at the moment, skip
|
||||
uint16_t answer_rrs = mdns_ntohs(data++);
|
||||
uint16_t authority_rrs = mdns_ntohs(data++);
|
||||
uint16_t additional_rrs = mdns_ntohs(data++);
|
||||
*/
|
||||
data += 3;
|
||||
|
||||
size_t parsed = 0;
|
||||
size_t records;
|
||||
size_t total_records = 0;
|
||||
for (int iquestion = 0; iquestion < questions; ++iquestion) {
|
||||
size_t question_offset = MDNS_POINTER_DIFF(data, buffer);
|
||||
size_t offset = question_offset;
|
||||
size_t verify_ofs = 12;
|
||||
size_t verify_offset = 12;
|
||||
int dns_sd = 0;
|
||||
if (mdns_string_equal(buffer, data_size, &offset, mdns_services_query,
|
||||
sizeof(mdns_services_query), &verify_ofs)) {
|
||||
sizeof(mdns_services_query), &verify_offset)) {
|
||||
dns_sd = 1;
|
||||
} else {
|
||||
offset = question_offset;
|
||||
if (!mdns_string_skip(buffer, data_size, &offset))
|
||||
break;
|
||||
} else if (!mdns_string_skip(buffer, data_size, &offset)) {
|
||||
break;
|
||||
}
|
||||
size_t length = offset - question_offset;
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET_CONST(buffer, offset);
|
||||
|
|
@ -1004,7 +1023,7 @@ mdns_socket_listen(int sock, void* buffer, size_t capacity, mdns_record_callback
|
|||
uint16_t rclass = mdns_ntohs(data++);
|
||||
uint16_t class_without_flushbit = rclass & ~MDNS_CACHE_FLUSH;
|
||||
|
||||
// Make sure we get a question of class IN
|
||||
// Make sure we get a question of class IN or ANY
|
||||
if (!((class_without_flushbit == MDNS_CLASS_IN) ||
|
||||
(class_without_flushbit == MDNS_CLASS_ANY))) {
|
||||
break;
|
||||
|
|
@ -1013,20 +1032,48 @@ mdns_socket_listen(int sock, void* buffer, size_t capacity, mdns_record_callback
|
|||
if (dns_sd && flags)
|
||||
continue;
|
||||
|
||||
++parsed;
|
||||
++total_records;
|
||||
if (callback && callback(sock, saddr, addrlen, MDNS_ENTRYTYPE_QUESTION, query_id, rtype,
|
||||
rclass, 0, buffer, data_size, question_offset, length,
|
||||
question_offset, length, user_data))
|
||||
break;
|
||||
return total_records;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
size_t offset = MDNS_POINTER_DIFF(data, buffer);
|
||||
records = mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
|
||||
MDNS_ENTRYTYPE_ANSWER, query_id, answer_rrs, callback, user_data);
|
||||
total_records += records;
|
||||
if (records != answer_rrs)
|
||||
return total_records;
|
||||
|
||||
records =
|
||||
mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
|
||||
MDNS_ENTRYTYPE_AUTHORITY, query_id, authority_rrs, callback, user_data);
|
||||
total_records += records;
|
||||
if (records != authority_rrs)
|
||||
return total_records;
|
||||
|
||||
records = mdns_records_parse(sock, saddr, addrlen, buffer, data_size, &offset,
|
||||
MDNS_ENTRYTYPE_ADDITIONAL, query_id, additional_rrs, callback,
|
||||
user_data);
|
||||
|
||||
return total_records;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, void* buffer,
|
||||
size_t capacity, uint16_t query_id) {
|
||||
if (capacity < (17 + length))
|
||||
mdns_query_t query;
|
||||
query.type = type;
|
||||
query.name = name;
|
||||
query.length = length;
|
||||
return mdns_multiquery_send(sock, &query, 1, buffer, capacity, query_id);
|
||||
}
|
||||
|
||||
static inline int
|
||||
mdns_multiquery_send(int sock, const mdns_query_t* query, size_t count, void* buffer, size_t capacity,
|
||||
uint16_t query_id) {
|
||||
if (!count || (capacity < (sizeof(struct mdns_header_t) + (6 * count))))
|
||||
return -1;
|
||||
|
||||
// Ask for a unicast response since it's a one-shot query
|
||||
|
|
@ -1046,25 +1093,30 @@ mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t leng
|
|||
|
||||
struct mdns_header_t* header = (struct mdns_header_t*)buffer;
|
||||
// Query ID
|
||||
header->query_id = htons(query_id);
|
||||
header->query_id = htons((unsigned short)query_id);
|
||||
// Flags
|
||||
header->flags = 0;
|
||||
// Questions
|
||||
header->questions = htons(1);
|
||||
header->questions = htons((unsigned short)count);
|
||||
// No answer, authority or additional RRs
|
||||
header->answer_rrs = 0;
|
||||
header->authority_rrs = 0;
|
||||
header->additional_rrs = 0;
|
||||
// Fill in question
|
||||
// Name string
|
||||
// Fill in questions
|
||||
void* data = MDNS_POINTER_OFFSET(buffer, sizeof(struct mdns_header_t));
|
||||
data = mdns_string_make(buffer, capacity, data, name, length, 0);
|
||||
if (!data)
|
||||
return -1;
|
||||
// Record type
|
||||
data = mdns_htons(data, type);
|
||||
//! Optional unicast response based on local port, class IN
|
||||
data = mdns_htons(data, rclass);
|
||||
for (size_t iq = 0; iq < count; ++iq) {
|
||||
// Name string
|
||||
data = mdns_string_make(buffer, capacity, data, query[iq].name, query[iq].length, 0);
|
||||
if (!data)
|
||||
return -1;
|
||||
size_t remain = capacity - MDNS_POINTER_DIFF(data, buffer);
|
||||
if (remain < 4)
|
||||
return -1;
|
||||
// Record type
|
||||
data = mdns_htons(data, query[iq].type);
|
||||
//! Optional unicast response based on local port, class IN
|
||||
data = mdns_htons(data, rclass);
|
||||
}
|
||||
|
||||
size_t tosend = MDNS_POINTER_DIFF(data, buffer);
|
||||
if (mdns_multicast_send(sock, buffer, (size_t)tosend))
|
||||
|
|
@ -1100,19 +1152,16 @@ mdns_query_recv(int sock, void* buffer, size_t capacity, mdns_record_callback_fn
|
|||
if ((only_query_id > 0) && (query_id != only_query_id))
|
||||
return 0; // Not a reply to the wanted one-shot query
|
||||
|
||||
if (questions > 1)
|
||||
return 0;
|
||||
|
||||
// Skip questions part
|
||||
int i;
|
||||
for (i = 0; i < questions; ++i) {
|
||||
size_t ofs = MDNS_POINTER_DIFF(data, buffer);
|
||||
if (!mdns_string_skip(buffer, data_size, &ofs))
|
||||
size_t offset = MDNS_POINTER_DIFF(data, buffer);
|
||||
if (!mdns_string_skip(buffer, data_size, &offset))
|
||||
return 0;
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET_CONST(buffer, ofs);
|
||||
/* Record type and class not used, skip
|
||||
uint16_t rtype = mdns_ntohs(data++);
|
||||
uint16_t rclass = mdns_ntohs(data++);*/
|
||||
data = (const uint16_t*)MDNS_POINTER_OFFSET_CONST(buffer, offset);
|
||||
// Record type and class not used, skip
|
||||
// uint16_t rtype = mdns_ntohs(data++);
|
||||
// uint16_t rclass = mdns_ntohs(data++);
|
||||
data += 2;
|
||||
}
|
||||
|
||||
|
|
@ -1161,7 +1210,7 @@ mdns_answer_add_question_unicast(void* buffer, size_t capacity, void* data,
|
|||
|
||||
static inline void*
|
||||
mdns_answer_add_record_header(void* buffer, size_t capacity, void* data, mdns_record_t record,
|
||||
uint16_t rclass, uint32_t ttl, mdns_string_table_t* string_table) {
|
||||
mdns_string_table_t* string_table) {
|
||||
data = mdns_string_make(buffer, capacity, data, record.name.str, record.name.length, string_table);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
|
@ -1170,20 +1219,20 @@ mdns_answer_add_record_header(void* buffer, size_t capacity, void* data, mdns_re
|
|||
return 0;
|
||||
|
||||
data = mdns_htons(data, record.type);
|
||||
data = mdns_htons(data, rclass);
|
||||
data = mdns_htonl(data, ttl);
|
||||
data = mdns_htons(data, record.rclass);
|
||||
data = mdns_htonl(data, record.ttl);
|
||||
data = mdns_htons(data, 0); // Length, to be filled later
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
mdns_answer_add_record(void* buffer, size_t capacity, void* data, mdns_record_t record,
|
||||
uint16_t rclass, uint32_t ttl, mdns_string_table_t* string_table) {
|
||||
mdns_string_table_t* string_table) {
|
||||
// TXT records will be coalesced into one record later
|
||||
if (!data || (record.type == MDNS_RECORDTYPE_TXT))
|
||||
return data;
|
||||
|
||||
data = mdns_answer_add_record_header(buffer, capacity, data, record, rclass, ttl, string_table);
|
||||
data = mdns_answer_add_record_header(buffer, capacity, data, record, string_table);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1234,8 +1283,20 @@ mdns_answer_add_record(void* buffer, size_t capacity, void* data, mdns_record_t
|
|||
return data;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mdns_record_update_rclass_ttl(mdns_record_t* record, uint16_t rclass, uint32_t ttl) {
|
||||
if (!record->rclass)
|
||||
record->rclass = rclass;
|
||||
if (!record->ttl || !ttl)
|
||||
record->ttl = ttl;
|
||||
record->rclass &= (uint16_t)(MDNS_CLASS_IN | MDNS_CACHE_FLUSH);
|
||||
// Never flush PTR record
|
||||
if (record->type == MDNS_RECORDTYPE_PTR)
|
||||
record->rclass &= ~(uint16_t)MDNS_CACHE_FLUSH;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
mdns_answer_add_txt_record(void* buffer, size_t capacity, void* data, mdns_record_t* records,
|
||||
mdns_answer_add_txt_record(void* buffer, size_t capacity, void* data, const mdns_record_t* records,
|
||||
size_t record_count, uint16_t rclass, uint32_t ttl,
|
||||
mdns_string_table_t* string_table) {
|
||||
// Pointer to length of record to be filled at end
|
||||
|
|
@ -1247,17 +1308,19 @@ mdns_answer_add_txt_record(void* buffer, size_t capacity, void* data, mdns_recor
|
|||
if (records[irec].type != MDNS_RECORDTYPE_TXT)
|
||||
continue;
|
||||
|
||||
mdns_record_t record = records[irec];
|
||||
mdns_record_update_rclass_ttl(&record, rclass, ttl);
|
||||
if (!record_data) {
|
||||
data = mdns_answer_add_record_header(buffer, capacity, data, records[irec], rclass, ttl,
|
||||
string_table);
|
||||
data = mdns_answer_add_record_header(buffer, capacity, data, record, string_table);
|
||||
if (!data)
|
||||
return data;
|
||||
record_length = MDNS_POINTER_OFFSET(data, -2);
|
||||
record_data = data;
|
||||
}
|
||||
|
||||
// TXT strings are unlikely to be shared, just make then raw. Also need one byte for
|
||||
// termination, thus the <= check
|
||||
size_t string_length =
|
||||
records[irec].data.txt.key.length + records[irec].data.txt.value.length + 1;
|
||||
size_t string_length = record.data.txt.key.length + record.data.txt.value.length + 1;
|
||||
if (!data)
|
||||
return 0;
|
||||
remain = capacity - MDNS_POINTER_DIFF(data, buffer);
|
||||
|
|
@ -1266,11 +1329,11 @@ mdns_answer_add_txt_record(void* buffer, size_t capacity, void* data, mdns_recor
|
|||
|
||||
unsigned char* strdata = (unsigned char*)data;
|
||||
*strdata++ = (unsigned char)string_length;
|
||||
memcpy(strdata, records[irec].data.txt.key.str, records[irec].data.txt.key.length);
|
||||
strdata += records[irec].data.txt.key.length;
|
||||
memcpy(strdata, record.data.txt.key.str, record.data.txt.key.length);
|
||||
strdata += record.data.txt.key.length;
|
||||
*strdata++ = '=';
|
||||
memcpy(strdata, records[irec].data.txt.value.str, records[irec].data.txt.value.length);
|
||||
strdata += records[irec].data.txt.value.length;
|
||||
memcpy(strdata, record.data.txt.value.str, record.data.txt.value.length);
|
||||
strdata += record.data.txt.value.length;
|
||||
|
||||
data = strdata;
|
||||
}
|
||||
|
|
@ -1283,7 +1346,7 @@ mdns_answer_add_txt_record(void* buffer, size_t capacity, void* data, mdns_recor
|
|||
}
|
||||
|
||||
static inline uint16_t
|
||||
mdns_answer_get_record_count(mdns_record_t* records, size_t record_count) {
|
||||
mdns_answer_get_record_count(const mdns_record_t* records, size_t record_count) {
|
||||
// TXT records will be coalesced into one record
|
||||
uint16_t total_count = 0;
|
||||
uint16_t txt_record = 0;
|
||||
|
|
@ -1300,12 +1363,15 @@ static inline int
|
|||
mdns_query_answer_unicast(int sock, const void* address, size_t address_size, void* buffer,
|
||||
size_t capacity, uint16_t query_id, mdns_record_type_t record_type,
|
||||
const char* name, size_t name_length, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count,
|
||||
mdns_record_t* additional, size_t additional_count) {
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count) {
|
||||
if (capacity < (sizeof(struct mdns_header_t) + 32 + 4))
|
||||
return -1;
|
||||
|
||||
uint16_t rclass = MDNS_CACHE_FLUSH | MDNS_CLASS_IN;
|
||||
// According to RFC 6762:
|
||||
// The cache-flush bit MUST NOT be set in any resource records in a response message
|
||||
// sent in legacy unicast responses to UDP ports other than 5353.
|
||||
uint16_t rclass = MDNS_CLASS_IN;
|
||||
uint32_t ttl = 10;
|
||||
|
||||
// Basic answer structure
|
||||
|
|
@ -1325,21 +1391,31 @@ mdns_query_answer_unicast(int sock, const void* address, size_t address_size, vo
|
|||
&string_table);
|
||||
|
||||
// Fill in answer
|
||||
data = mdns_answer_add_record(buffer, capacity, data, answer, rclass, ttl, &string_table);
|
||||
answer.rclass = rclass;
|
||||
answer.ttl = ttl;
|
||||
data = mdns_answer_add_record(buffer, capacity, data, answer, &string_table);
|
||||
|
||||
// Fill in authority records
|
||||
for (size_t irec = 0; data && (irec < authority_count); ++irec)
|
||||
data = mdns_answer_add_record(buffer, capacity, data, authority[irec], rclass, ttl,
|
||||
&string_table);
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, authority, authority_count, rclass,
|
||||
ttl, &string_table);
|
||||
for (size_t irec = 0; data && (irec < authority_count); ++irec) {
|
||||
mdns_record_t record = authority[irec];
|
||||
record.rclass = rclass;
|
||||
if (!record.ttl)
|
||||
record.ttl = ttl;
|
||||
data = mdns_answer_add_record(buffer, capacity, data, record, &string_table);
|
||||
}
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, authority, authority_count,
|
||||
rclass, ttl, &string_table);
|
||||
|
||||
// Fill in additional records
|
||||
for (size_t irec = 0; data && (irec < additional_count); ++irec)
|
||||
data = mdns_answer_add_record(buffer, capacity, data, additional[irec], rclass, ttl,
|
||||
&string_table);
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, additional, additional_count, rclass,
|
||||
ttl, &string_table);
|
||||
for (size_t irec = 0; data && (irec < additional_count); ++irec) {
|
||||
mdns_record_t record = additional[irec];
|
||||
record.rclass = rclass;
|
||||
if (!record.ttl)
|
||||
record.ttl = ttl;
|
||||
data = mdns_answer_add_record(buffer, capacity, data, record, &string_table);
|
||||
}
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, additional, additional_count,
|
||||
rclass, ttl, &string_table);
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
|
|
@ -1347,11 +1423,11 @@ mdns_query_answer_unicast(int sock, const void* address, size_t address_size, vo
|
|||
return mdns_unicast_send(sock, address, address_size, buffer, tosend);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
mdns_answer_multicast_rclass_ttl(int sock, void* buffer, size_t capacity, uint16_t rclass,
|
||||
mdns_record_t answer, mdns_record_t* authority, size_t authority_count,
|
||||
mdns_record_t* additional, size_t additional_count, uint32_t ttl) {
|
||||
mdns_answer_multicast_rclass_ttl(int sock, void* buffer, size_t capacity, mdns_record_t answer,
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count,
|
||||
uint16_t rclass, uint32_t ttl) {
|
||||
if (capacity < (sizeof(struct mdns_header_t) + 32 + 4))
|
||||
return -1;
|
||||
|
||||
|
|
@ -1368,21 +1444,27 @@ mdns_answer_multicast_rclass_ttl(int sock, void* buffer, size_t capacity, uint16
|
|||
void* data = MDNS_POINTER_OFFSET(buffer, sizeof(struct mdns_header_t));
|
||||
|
||||
// Fill in answer
|
||||
data = mdns_answer_add_record(buffer, capacity, data, answer, rclass, ttl, &string_table);
|
||||
mdns_record_t record = answer;
|
||||
mdns_record_update_rclass_ttl(&record, rclass, ttl);
|
||||
data = mdns_answer_add_record(buffer, capacity, data, record, &string_table);
|
||||
|
||||
// Fill in authority records
|
||||
for (size_t irec = 0; data && (irec < authority_count); ++irec)
|
||||
data = mdns_answer_add_record(buffer, capacity, data, authority[irec], rclass, ttl,
|
||||
&string_table);
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, authority, authority_count, rclass,
|
||||
ttl, &string_table);
|
||||
for (size_t irec = 0; data && (irec < authority_count); ++irec) {
|
||||
record = authority[irec];
|
||||
mdns_record_update_rclass_ttl(&record, rclass, ttl);
|
||||
data = mdns_answer_add_record(buffer, capacity, data, record, &string_table);
|
||||
}
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, authority, authority_count,
|
||||
rclass, ttl, &string_table);
|
||||
|
||||
// Fill in additional records
|
||||
for (size_t irec = 0; data && (irec < additional_count); ++irec)
|
||||
data = mdns_answer_add_record(buffer, capacity, data, additional[irec], rclass, ttl,
|
||||
&string_table);
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, additional, additional_count, rclass,
|
||||
ttl, &string_table);
|
||||
for (size_t irec = 0; data && (irec < additional_count); ++irec) {
|
||||
record = additional[irec];
|
||||
mdns_record_update_rclass_ttl(&record, rclass, ttl);
|
||||
data = mdns_answer_add_record(buffer, capacity, data, record, &string_table);
|
||||
}
|
||||
data = mdns_answer_add_txt_record(buffer, capacity, data, additional, additional_count,
|
||||
rclass, ttl, &string_table);
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
|
|
@ -1390,39 +1472,32 @@ mdns_answer_multicast_rclass_ttl(int sock, void* buffer, size_t capacity, uint16
|
|||
return mdns_multicast_send(sock, buffer, tosend);
|
||||
}
|
||||
|
||||
static inline int
|
||||
mdns_answer_multicast_rclass(int sock, void* buffer, size_t capacity, uint16_t rclass,
|
||||
mdns_record_t answer, mdns_record_t* authority, size_t authority_count,
|
||||
mdns_record_t* additional, size_t additional_count) {
|
||||
return mdns_answer_multicast_rclass_ttl(sock, buffer, capacity, rclass, answer, authority,
|
||||
authority_count, additional, additional_count, 60);
|
||||
}
|
||||
|
||||
static inline int
|
||||
mdns_query_answer_multicast(int sock, void* buffer, size_t capacity, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count,
|
||||
mdns_record_t* additional, size_t additional_count) {
|
||||
uint16_t rclass = MDNS_CLASS_IN;
|
||||
return mdns_answer_multicast_rclass(sock, buffer, capacity, rclass, answer, authority,
|
||||
authority_count, additional, additional_count);
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count) {
|
||||
return mdns_answer_multicast_rclass_ttl(sock, buffer, capacity, answer, authority,
|
||||
authority_count, additional, additional_count,
|
||||
MDNS_CLASS_IN, 60);
|
||||
}
|
||||
|
||||
static inline int
|
||||
mdns_announce_multicast(int sock, void* buffer, size_t capacity, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count, mdns_record_t* additional,
|
||||
size_t additional_count) {
|
||||
uint16_t rclass = MDNS_CLASS_IN | MDNS_CACHE_FLUSH;
|
||||
return mdns_answer_multicast_rclass(sock, buffer, capacity, rclass, answer, authority,
|
||||
authority_count, additional, additional_count);
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count) {
|
||||
return mdns_answer_multicast_rclass_ttl(sock, buffer, capacity, answer, authority,
|
||||
authority_count, additional, additional_count,
|
||||
MDNS_CLASS_IN | MDNS_CACHE_FLUSH, 60);
|
||||
}
|
||||
|
||||
static inline int
|
||||
mdns_goodbye_multicast(int sock, void* buffer, size_t capacity, mdns_record_t answer,
|
||||
mdns_record_t* authority, size_t authority_count, mdns_record_t* additional,
|
||||
size_t additional_count) {
|
||||
uint16_t rclass = MDNS_CLASS_IN | MDNS_CACHE_FLUSH;
|
||||
return mdns_answer_multicast_rclass_ttl(sock, buffer, capacity, rclass, answer, authority,
|
||||
authority_count, additional, additional_count, 0);
|
||||
const mdns_record_t* authority, size_t authority_count,
|
||||
const mdns_record_t* additional, size_t additional_count) {
|
||||
// Goodbye should have ttl of 0
|
||||
return mdns_answer_multicast_rclass_ttl(sock, buffer, capacity, answer, authority,
|
||||
authority_count, additional, additional_count,
|
||||
MDNS_CLASS_IN, 0);
|
||||
}
|
||||
|
||||
static inline mdns_string_t
|
||||
|
|
@ -1497,14 +1572,19 @@ mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t len
|
|||
strdata = (const char*)MDNS_POINTER_OFFSET(buffer, offset);
|
||||
size_t sublength = *(const unsigned char*)strdata;
|
||||
|
||||
if (sublength >= (end - offset))
|
||||
break;
|
||||
|
||||
++strdata;
|
||||
offset += sublength + 1;
|
||||
|
||||
size_t separator = 0;
|
||||
size_t separator = sublength;
|
||||
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))
|
||||
if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) {
|
||||
separator = 0;
|
||||
break;
|
||||
}
|
||||
if (strdata[c] == '=') {
|
||||
separator = c;
|
||||
break;
|
||||
|
|
@ -1522,6 +1602,8 @@ mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t len
|
|||
} else {
|
||||
records[parsed].key.str = strdata;
|
||||
records[parsed].key.length = sublength;
|
||||
records[parsed].value.str = 0;
|
||||
records[parsed].value.length = 0;
|
||||
}
|
||||
|
||||
++parsed;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue