in DNSServiceDiscoveryUnicast/dns-sd.c [58:159]
int ProcessMessageBySection(char *buf, ssize_t len, ns_msg msg, ns_sect section,
ServiceInstanceDetails **instanceDetails)
{
static char displayBuf[DISPLAY_BUF_SIZE];
ns_rr rr;
int messageCount = ns_msg_count(msg, section);
if (!(*instanceDetails)) {
// Allocate for ServiceInstanceDetails and initialize its members.
*instanceDetails = malloc(sizeof(ServiceInstanceDetails));
if (!(*instanceDetails)) {
Log_Debug("ERROR: recvfrom: %d (%s)\n", errno, strerror(errno));
return -1;
}
(*instanceDetails)->name = NULL;
(*instanceDetails)->host = NULL;
(*instanceDetails)->ipv4Address.s_addr = INADDR_NONE;
(*instanceDetails)->port = 0;
(*instanceDetails)->txtData = NULL;
(*instanceDetails)->txtDataLength = 0;
}
// Parse each message
for (int i = 0; i < messageCount; ++i) {
if (ns_parserr(&msg, section, i, &rr)) {
Log_Debug("ERROR: ns_parserr: %d (%s)\n", errno, strerror(errno));
return -1;
}
switch (ns_rr_type(rr)) {
case ns_t_ptr: {
int compressedNameLength =
dn_expand(buf, buf + len, ns_rr_rdata(rr), displayBuf, sizeof(displayBuf));
if (compressedNameLength > 0 && !(*instanceDetails)->name) {
(*instanceDetails)->name = strdup(displayBuf);
if (!(*instanceDetails)->name) {
Log_Debug("ERROR: strdup for instance name failed: %d (%s)\n", errno,
strerror(errno));
return -1;
}
}
break;
}
case ns_t_srv: {
// Parse the SRV record and populate the port and host fields in instance details as per
// DNS SRV record specification: https://tools.ietf.org/rfc/rfc2782.txt
// SRV record format: Priority| Weight | Port | Target
// (2 Bytes)|(2 Bytes)|(2 Bytes)|(Remaining Bytes)
const char *data = ns_rr_rdata(rr);
int compressedTargetDomainNameLength = dn_expand(
buf, buf + len, data + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t),
displayBuf, sizeof(displayBuf));
if ((*instanceDetails)->port == 0 && compressedTargetDomainNameLength > 0 &&
!(*instanceDetails)->host) {
(*instanceDetails)->port =
(uint16_t)ns_get16(data + sizeof(uint16_t) + sizeof(uint16_t));
(*instanceDetails)->host = strdup(displayBuf);
if (!(*instanceDetails)->host) {
Log_Debug("ERROR: strdup: %d (%s)\n", errno, strerror(errno));
return -1;
}
Log_Debug("%s\n", (*instanceDetails)->host);
}
break;
}
case ns_t_txt: {
// Populate name field in instance details if it hasn't been set
if (!(*instanceDetails)->name) {
(*instanceDetails)->name = strdup(ns_rr_name(rr));
if (!(*instanceDetails)->name) {
Log_Debug("ERROR: strdup(ns_rr_name(rr)): %d (%s)\n", errno, strerror(errno));
return -1;
}
}
// Get TXT record, populate txtData and txtDataLength fields in instance details
if (!(*instanceDetails)->txtData) {
(*instanceDetails)->txtData =
malloc(sizeof(unsigned char) * (size_t)(ns_rr_rdlen(rr)));
if (!(*instanceDetails)->txtData) {
Log_Debug("ERROR: malloc: %d (%s)\n", errno, strerror(errno));
return -1;
}
memcpy((*instanceDetails)->txtData, ns_rr_rdata(rr), ns_rr_rdlen(rr));
(*instanceDetails)->txtDataLength = ns_rr_rdlen(rr);
}
break;
}
case ns_t_a: {
// Get A record (host address), populate ipv4Address field in instance details
if (ns_rr_rdlen(rr) == sizeof((*instanceDetails)->ipv4Address)) {
memcpy(&(*instanceDetails)->ipv4Address.s_addr, ns_rr_rdata(rr), ns_rr_rdlen(rr));
} else {
Log_Debug("ERROR: Invalid DNS A record length: %d\n", ns_rr_rdlen(rr));
}
break;
}
default:
break;
}
}
return 0;
}