|
|
@ -15,9 +15,17 @@ using namespace Rcpp; |
|
|
|
# define sleep(x) Sleep(x * 1000) |
|
|
|
#else |
|
|
|
# include <netdb.h> |
|
|
|
# include <ifaddrs.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
static uint32_t service_address_ipv4; |
|
|
|
static uint8_t service_address_ipv6[16]; |
|
|
|
|
|
|
|
static int has_ipv4; |
|
|
|
static int has_ipv6; |
|
|
|
|
|
|
|
static char addrbuffer[64]; |
|
|
|
static char entrybuffer[256]; |
|
|
|
static char namebuffer[256]; |
|
|
|
//static char sendbuffer[256];
|
|
|
|
static mdns_record_txt_t txtbuffer[128]; |
|
|
@ -30,13 +38,15 @@ typedef struct { |
|
|
|
int port; |
|
|
|
} service_record_t; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static mdns_string_t |
|
|
|
ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr, size_t addrlen) { |
|
|
|
ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr, |
|
|
|
size_t addrlen) { |
|
|
|
char host[NI_MAXHOST] = {0}; |
|
|
|
char service[NI_MAXSERV] = {0}; |
|
|
|
int ret = getnameinfo((const struct sockaddr*)addr, addrlen, |
|
|
|
host, NI_MAXHOST, service, NI_MAXSERV, |
|
|
|
NI_NUMERICSERV | NI_NUMERICHOST); |
|
|
|
int ret = getnameinfo((const struct sockaddr*)addr, (socklen_t)addrlen, host, NI_MAXHOST, |
|
|
|
service, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); |
|
|
|
int len = 0; |
|
|
|
if (ret == 0) { |
|
|
|
if (addr->sin_port != 0) |
|
|
@ -44,18 +54,21 @@ static mdns_string_t |
|
|
|
else |
|
|
|
len = snprintf(buffer, capacity, "%s", host); |
|
|
|
} |
|
|
|
if (len >= (int)capacity) len = (int)capacity - 1; |
|
|
|
mdns_string_t str = {buffer, (size_t)len}; |
|
|
|
if (len >= (int)capacity) |
|
|
|
len = (int)capacity - 1; |
|
|
|
mdns_string_t str; |
|
|
|
str.str = buffer; |
|
|
|
str.length = len; |
|
|
|
return str; |
|
|
|
} |
|
|
|
|
|
|
|
static mdns_string_t |
|
|
|
ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr, size_t addrlen) { |
|
|
|
ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr, |
|
|
|
size_t addrlen) { |
|
|
|
char host[NI_MAXHOST] = {0}; |
|
|
|
char service[NI_MAXSERV] = {0}; |
|
|
|
int ret = getnameinfo((const struct sockaddr*)addr, addrlen, |
|
|
|
host, NI_MAXHOST, service, NI_MAXSERV, |
|
|
|
NI_NUMERICSERV | NI_NUMERICHOST); |
|
|
|
int ret = getnameinfo((const struct sockaddr*)addr, (socklen_t)addrlen, host, NI_MAXHOST, |
|
|
|
service, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); |
|
|
|
int len = 0; |
|
|
|
if (ret == 0) { |
|
|
|
if (addr->sin6_port != 0) |
|
|
@ -65,7 +78,9 @@ static mdns_string_t |
|
|
|
} |
|
|
|
if (len >= (int)capacity) |
|
|
|
len = (int)capacity - 1; |
|
|
|
mdns_string_t str = {buffer, (size_t)len}; |
|
|
|
mdns_string_t str; |
|
|
|
str.str = buffer; |
|
|
|
str.length = len; |
|
|
|
return str; |
|
|
|
} |
|
|
|
|
|
|
@ -76,15 +91,228 @@ static mdns_string_t |
|
|
|
return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr, addrlen); |
|
|
|
} |
|
|
|
|
|
|
|
static int query_callback(int sock, const struct sockaddr* from, size_t addrlen, |
|
|
|
mdns_entry_type_t entry, uint16_t transaction_id, |
|
|
|
uint16_t rtype, uint16_t rclass, uint32_t ttl, |
|
|
|
const void* data, size_t size, size_t offset, size_t length, |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
open_client_sockets(int* sockets, int max_sockets, int port) { |
|
|
|
// When sending, each socket can only send to one network interface
|
|
|
|
// Thus we need to open one socket for each interface and address family
|
|
|
|
int num_sockets = 0; |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
IP_ADAPTER_ADDRESSES* adapter_address = 0; |
|
|
|
ULONG address_size = 8000; |
|
|
|
unsigned int ret; |
|
|
|
unsigned int num_retries = 4; |
|
|
|
do { |
|
|
|
adapter_address = malloc(address_size); |
|
|
|
ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST, 0, |
|
|
|
adapter_address, &address_size); |
|
|
|
if (ret == ERROR_BUFFER_OVERFLOW) { |
|
|
|
free(adapter_address); |
|
|
|
adapter_address = 0; |
|
|
|
} else { |
|
|
|
break; |
|
|
|
} |
|
|
|
} while (num_retries-- > 0); |
|
|
|
|
|
|
|
if (!adapter_address || (ret != NO_ERROR)) { |
|
|
|
free(adapter_address); |
|
|
|
printf("Failed to get network adapter addresses\n"); |
|
|
|
return num_sockets; |
|
|
|
} |
|
|
|
|
|
|
|
int first_ipv4 = 1; |
|
|
|
int first_ipv6 = 1; |
|
|
|
for (PIP_ADAPTER_ADDRESSES adapter = adapter_address; adapter; adapter = adapter->Next) { |
|
|
|
if (adapter->TunnelType == TUNNEL_TYPE_TEREDO) |
|
|
|
continue; |
|
|
|
if (adapter->OperStatus != IfOperStatusUp) |
|
|
|
continue; |
|
|
|
|
|
|
|
for (IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress; unicast; |
|
|
|
unicast = unicast->Next) { |
|
|
|
if (unicast->Address.lpSockaddr->sa_family == AF_INET) { |
|
|
|
struct sockaddr_in* saddr = (struct sockaddr_in*)unicast->Address.lpSockaddr; |
|
|
|
if ((saddr->sin_addr.S_un.S_un_b.s_b1 != 127) || |
|
|
|
(saddr->sin_addr.S_un.S_un_b.s_b2 != 0) || |
|
|
|
(saddr->sin_addr.S_un.S_un_b.s_b3 != 0) || |
|
|
|
(saddr->sin_addr.S_un.S_un_b.s_b4 != 1)) { |
|
|
|
int log_addr = 0; |
|
|
|
if (first_ipv4) { |
|
|
|
service_address_ipv4 = saddr->sin_addr.S_un.S_addr; |
|
|
|
first_ipv4 = 0; |
|
|
|
log_addr = 1; |
|
|
|
} |
|
|
|
has_ipv4 = 1; |
|
|
|
if (num_sockets < max_sockets) { |
|
|
|
saddr->sin_port = htons((unsigned short)port); |
|
|
|
int sock = mdns_socket_open_ipv4(saddr); |
|
|
|
if (sock >= 0) { |
|
|
|
sockets[num_sockets++] = sock; |
|
|
|
log_addr = 1; |
|
|
|
} else { |
|
|
|
log_addr = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
if (log_addr) { |
|
|
|
char buffer[128]; |
|
|
|
mdns_string_t addr = ipv4_address_to_string(buffer, sizeof(buffer), saddr, |
|
|
|
sizeof(struct sockaddr_in)); |
|
|
|
// printf("Local IPv4 address: %.*s\n", MDNS_STRING_FORMAT(addr));
|
|
|
|
} |
|
|
|
} |
|
|
|
} else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) { |
|
|
|
struct sockaddr_in6* saddr = (struct sockaddr_in6*)unicast->Address.lpSockaddr; |
|
|
|
static const unsigned char localhost[] = {0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
0, 0, 0, 0, 0, 0, 0, 1}; |
|
|
|
static const unsigned char localhost_mapped[] = {0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
0, 0, 0xff, 0xff, 0x7f, 0, 0, 1}; |
|
|
|
if ((unicast->DadState == NldsPreferred) && |
|
|
|
memcmp(saddr->sin6_addr.s6_addr, localhost, 16) && |
|
|
|
memcmp(saddr->sin6_addr.s6_addr, localhost_mapped, 16)) { |
|
|
|
int log_addr = 0; |
|
|
|
if (first_ipv6) { |
|
|
|
memcpy(service_address_ipv6, &saddr->sin6_addr, 16); |
|
|
|
first_ipv6 = 0; |
|
|
|
log_addr = 1; |
|
|
|
} |
|
|
|
has_ipv6 = 1; |
|
|
|
if (num_sockets < max_sockets) { |
|
|
|
saddr->sin6_port = htons((unsigned short)port); |
|
|
|
int sock = mdns_socket_open_ipv6(saddr); |
|
|
|
if (sock >= 0) { |
|
|
|
sockets[num_sockets++] = sock; |
|
|
|
log_addr = 1; |
|
|
|
} else { |
|
|
|
log_addr = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
if (log_addr) { |
|
|
|
char buffer[128]; |
|
|
|
mdns_string_t addr = ipv6_address_to_string(buffer, sizeof(buffer), saddr, |
|
|
|
sizeof(struct sockaddr_in6)); |
|
|
|
// printf("Local IPv6 address: %.*s\n", MDNS_STRING_FORMAT(addr));
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
free(adapter_address); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
struct ifaddrs* ifaddr = 0; |
|
|
|
struct ifaddrs* ifa = 0; |
|
|
|
|
|
|
|
if (getifaddrs(&ifaddr) < 0) |
|
|
|
printf("Unable to get interface addresses\n"); |
|
|
|
|
|
|
|
int first_ipv4 = 1; |
|
|
|
int first_ipv6 = 1; |
|
|
|
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { |
|
|
|
if (!ifa->ifa_addr) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (ifa->ifa_addr->sa_family == AF_INET) { |
|
|
|
struct sockaddr_in* saddr = (struct sockaddr_in*)ifa->ifa_addr; |
|
|
|
if (saddr->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { |
|
|
|
int log_addr = 0; |
|
|
|
if (first_ipv4) { |
|
|
|
service_address_ipv4 = saddr->sin_addr.s_addr; |
|
|
|
first_ipv4 = 0; |
|
|
|
log_addr = 1; |
|
|
|
} |
|
|
|
has_ipv4 = 1; |
|
|
|
if (num_sockets < max_sockets) { |
|
|
|
saddr->sin_port = htons(port); |
|
|
|
int sock = mdns_socket_open_ipv4(saddr); |
|
|
|
if (sock >= 0) { |
|
|
|
sockets[num_sockets++] = sock; |
|
|
|
log_addr = 1; |
|
|
|
} else { |
|
|
|
log_addr = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
if (log_addr) { |
|
|
|
char buffer[128]; |
|
|
|
mdns_string_t addr = ipv4_address_to_string(buffer, sizeof(buffer), saddr, |
|
|
|
sizeof(struct sockaddr_in)); |
|
|
|
// printf("Local IPv4 address: %.*s\n", MDNS_STRING_FORMAT(addr));
|
|
|
|
} |
|
|
|
} |
|
|
|
} else if (ifa->ifa_addr->sa_family == AF_INET6) { |
|
|
|
struct sockaddr_in6* saddr = (struct sockaddr_in6*)ifa->ifa_addr; |
|
|
|
static const unsigned char localhost[] = {0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
0, 0, 0, 0, 0, 0, 0, 1}; |
|
|
|
static const unsigned char localhost_mapped[] = {0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
0, 0, 0xff, 0xff, 0x7f, 0, 0, 1}; |
|
|
|
if (memcmp(saddr->sin6_addr.s6_addr, localhost, 16) && |
|
|
|
memcmp(saddr->sin6_addr.s6_addr, localhost_mapped, 16)) { |
|
|
|
int log_addr = 0; |
|
|
|
if (first_ipv6) { |
|
|
|
memcpy(service_address_ipv6, &saddr->sin6_addr, 16); |
|
|
|
first_ipv6 = 0; |
|
|
|
log_addr = 1; |
|
|
|
} |
|
|
|
has_ipv6 = 1; |
|
|
|
if (num_sockets < max_sockets) { |
|
|
|
saddr->sin6_port = htons(port); |
|
|
|
int sock = mdns_socket_open_ipv6(saddr); |
|
|
|
if (sock >= 0) { |
|
|
|
sockets[num_sockets++] = sock; |
|
|
|
log_addr = 1; |
|
|
|
} else { |
|
|
|
log_addr = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
if (log_addr) { |
|
|
|
char buffer[128]; |
|
|
|
mdns_string_t addr = ipv6_address_to_string(buffer, sizeof(buffer), saddr, |
|
|
|
sizeof(struct sockaddr_in6)); |
|
|
|
// printf("Local IPv6 address: %.*s\n", MDNS_STRING_FORMAT(addr));
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
freeifaddrs(ifaddr); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return num_sockets; |
|
|
|
} |
|
|
|
|
|
|
|
static int query_callback(int sock, |
|
|
|
const struct sockaddr* from, |
|
|
|
size_t addrlen, |
|
|
|
mdns_entry_type_t entry, |
|
|
|
uint16_t transaction_id, |
|
|
|
uint16_t rtype, |
|
|
|
uint16_t rclass, |
|
|
|
uint32_t ttl, |
|
|
|
const void* data, |
|
|
|
size_t size, |
|
|
|
size_t name_offset, |
|
|
|
size_t name_length, |
|
|
|
size_t offset, |
|
|
|
size_t length, |
|
|
|
void* user_data) { |
|
|
|
|
|
|
|
// static int query_callback(int sock, const struct sockaddr* from, size_t addrlen,
|
|
|
|
// mdns_entry_type_t entry, uint16_t transaction_id,
|
|
|
|
// uint16_t rtype, 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, addrlen); |
|
|
|
std::string fromstr = std::string(fromaddrstr.str, fromaddrstr.length); |
|
|
|
|
|
|
|
mdns_string_t entrystr = |
|
|
|
mdns_string_extract(data, size, &name_offset, entrybuffer, sizeof(entrybuffer)); |
|
|
|
|
|
|
|
const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" : |
|
|
|
((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); |
|
|
|
|
|
|
@ -200,54 +428,57 @@ static int query_callback(int sock, const struct sockaddr* from, size_t addrlen, |
|
|
|
} |
|
|
|
|
|
|
|
// [[Rcpp::export]]
|
|
|
|
std::string int_bnjr_discover(int scan_time = 10L, std::string proto = "ipv4") { |
|
|
|
std::string int_bnjr_discover(int scan_time = 10L) { |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
WORD versionWanted = MAKEWORD(1, 1); |
|
|
|
WSADATA wsaData; |
|
|
|
if (WSAStartup(versionWanted, &wsaData)) { |
|
|
|
Rf_warning("Failed to initialize WinSock\n"); |
|
|
|
return(); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
if (!((proto == "ipv4") || (proto == "ipv6"))) proto = "ipv4"; |
|
|
|
|
|
|
|
size_t capacity = 2048; |
|
|
|
void* buffer = malloc(capacity); |
|
|
|
//void* user_data = 0;
|
|
|
|
size_t records; |
|
|
|
int sockets[32]; |
|
|
|
int num_sockets = open_client_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]), 0); |
|
|
|
if (num_sockets <= 0) Rf_error("Failed to open any client sockets\n"); |
|
|
|
|
|
|
|
std::string out; |
|
|
|
|
|
|
|
std::FILE* tmpf = std::tmpfile(); |
|
|
|
|
|
|
|
int port = 0; |
|
|
|
int sock = (proto == "ipv4") ? mdns_socket_open_ipv4(port) : mdns_socket_open_ipv6(port); |
|
|
|
|
|
|
|
if (sock < 0) { |
|
|
|
Rf_warning("Failed to open socket: %s\n", strerror(errno)); |
|
|
|
goto quit_int_bnjr_discover; |
|
|
|
} |
|
|
|
|
|
|
|
if (mdns_discovery_send(sock)) { |
|
|
|
Rf_warning("Failed to send DNS-DS discovery: %s\n", strerror(errno)); |
|
|
|
goto quit_int_bnjr_discover; |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock) { |
|
|
|
if ((mdns_discovery_send(sockets[isock])) && (errno != EHOSTUNREACH)) |
|
|
|
Rf_warning("Failed to send DNS-DS discovery: %s\n", strerror(errno)); |
|
|
|
} |
|
|
|
|
|
|
|
for (int i = 0; i < scan_time; ++i) { |
|
|
|
|
|
|
|
do { |
|
|
|
records = mdns_discovery_recv( |
|
|
|
sock, buffer, capacity, query_callback, tmpf |
|
|
|
); |
|
|
|
} while (records); |
|
|
|
|
|
|
|
if (records) i = 0; |
|
|
|
size_t capacity = 2048; |
|
|
|
void* buffer = malloc(capacity); |
|
|
|
void* user_data = 0; |
|
|
|
size_t records; |
|
|
|
|
|
|
|
sleep(1); |
|
|
|
int res; |
|
|
|
|
|
|
|
do { |
|
|
|
struct timeval timeout; |
|
|
|
timeout.tv_sec = scan_time; |
|
|
|
timeout.tv_usec = 0; |
|
|
|
|
|
|
|
int nfds; |
|
|
|
nfds = 0; |
|
|
|
fd_set readfs; |
|
|
|
FD_ZERO(&readfs); |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock) { |
|
|
|
if (sockets[isock] >= nfds) |
|
|
|
nfds = sockets[isock] + 1; |
|
|
|
FD_SET(sockets[isock], &readfs); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
records = 0; |
|
|
|
res = select(nfds, &readfs, 0, 0, &timeout); |
|
|
|
if (res > 0) { |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock) { |
|
|
|
if (FD_ISSET(sockets[isock], &readfs)) { |
|
|
|
records += mdns_discovery_recv(sockets[isock], |
|
|
|
buffer, |
|
|
|
capacity, |
|
|
|
query_callback, |
|
|
|
tmpf); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} while (res > 0); |
|
|
|
|
|
|
|
std::rewind(tmpf); |
|
|
|
|
|
|
@ -259,71 +490,69 @@ std::string int_bnjr_discover(int scan_time = 10L, std::string proto = "ipv4") { |
|
|
|
|
|
|
|
std::fclose(tmpf); |
|
|
|
|
|
|
|
quit_int_bnjr_discover: |
|
|
|
|
|
|
|
free(buffer); |
|
|
|
free(buffer); |
|
|
|
|
|
|
|
if (sock >= 0) mdns_socket_close(sock); |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
WSACleanup(); |
|
|
|
#endif |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock){ |
|
|
|
mdns_socket_close(sockets[isock]); |
|
|
|
} |
|
|
|
|
|
|
|
return(out); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// [[Rcpp::export]]
|
|
|
|
std::string int_bnjr_query(std::string q, int scan_time = 5L, std::string proto = "ipv4") { |
|
|
|
std::string int_bnjr_query(std::string q, int scan_time = 5L) { |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
WORD versionWanted = MAKEWORD(1, 1); |
|
|
|
WSADATA wsaData; |
|
|
|
if (WSAStartup(versionWanted, &wsaData)) { |
|
|
|
Rf_warning("Failed to initialize WinSock\n"); |
|
|
|
return(); |
|
|
|
} |
|
|
|
#endif |
|
|
|
int sockets[32]; |
|
|
|
int query_id[32]; |
|
|
|
|
|
|
|
if (!((proto == "ipv4") || (proto == "ipv6"))) proto = "ipv4"; |
|
|
|
int num_sockets = open_client_sockets(sockets, sizeof(sockets) / sizeof(sockets[0]), 0); |
|
|
|
if (num_sockets <= 0) Rf_error("Failed to open any client sockets"); |
|
|
|
|
|
|
|
size_t capacity = 2048; |
|
|
|
void* buffer = malloc(capacity); |
|
|
|
//void* user_data = 0;
|
|
|
|
void* user_data = 0; |
|
|
|
size_t records; |
|
|
|
|
|
|
|
std::FILE* tmpf = std::tmpfile(); |
|
|
|
|
|
|
|
std::string out; |
|
|
|
|
|
|
|
int port = 0; |
|
|
|
int sock = (proto == "ipv4") ? mdns_socket_open_ipv4(port) : mdns_socket_open_ipv6(port); |
|
|
|
|
|
|
|
if (sock < 0) { |
|
|
|
Rf_warning("Failed to open socket: %s\n", strerror(errno)); |
|
|
|
goto quit_int_bnjr_query_send; |
|
|
|
} |
|
|
|
|
|
|
|
if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR, |
|
|
|
q.c_str(), q.length(), |
|
|
|
buffer, capacity)) { |
|
|
|
Rf_warning("Failed to send mDNS query: %s\n", strerror(errno)); |
|
|
|
goto quit_int_bnjr_query_send; |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock) { |
|
|
|
query_id[isock] = mdns_query_send(sockets[isock], MDNS_RECORDTYPE_PTR, q.c_str(), |
|
|
|
q.length(), buffer, capacity, 0); |
|
|
|
if ((query_id[isock] < 0) && (errno != EHOSTUNREACH)) |
|
|
|
Rf_warning("Failed to send mDNS query: %s\n", strerror(errno)); |
|
|
|
} |
|
|
|
|
|
|
|
for (int i = 0; i < scan_time; ++i) { |
|
|
|
|
|
|
|
do { |
|
|
|
records = mdns_query_recv( |
|
|
|
sock, buffer, capacity, query_callback, tmpf, 1 |
|
|
|
); |
|
|
|
} while (records); |
|
|
|
int res; |
|
|
|
|
|
|
|
if (records) i = 0; |
|
|
|
do { |
|
|
|
struct timeval timeout; |
|
|
|
timeout.tv_sec = scan_time; |
|
|
|
timeout.tv_usec = 0; |
|
|
|
|
|
|
|
sleep(1); |
|
|
|
int nfds = 0; |
|
|
|
fd_set readfs; |
|
|
|
FD_ZERO(&readfs); |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock) { |
|
|
|
if (sockets[isock] >= nfds) |
|
|
|
nfds = sockets[isock] + 1; |
|
|
|
FD_SET(sockets[isock], &readfs); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
records = 0; |
|
|
|
res = select(nfds, &readfs, 0, 0, &timeout); |
|
|
|
if (res > 0) { |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock) { |
|
|
|
if (FD_ISSET(sockets[isock], &readfs)) { |
|
|
|
records += mdns_query_recv(sockets[isock], buffer, capacity, query_callback, |
|
|
|
tmpf, query_id[isock]); |
|
|
|
} |
|
|
|
FD_SET(sockets[isock], &readfs); |
|
|
|
} |
|
|
|
} |
|
|
|
} while (res > 0); |
|
|
|
|
|
|
|
std::rewind(tmpf); |
|
|
|
|
|
|
@ -335,15 +564,10 @@ std::string int_bnjr_query(std::string q, int scan_time = 5L, std::string proto |
|
|
|
|
|
|
|
std::fclose(tmpf); |
|
|
|
|
|
|
|
quit_int_bnjr_query_send: |
|
|
|
free(buffer); |
|
|
|
|
|
|
|
free(buffer); |
|
|
|
|
|
|
|
if (sock >= 0) mdns_socket_close(sock); |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
WSACleanup(); |
|
|
|
#endif |
|
|
|
for (int isock = 0; isock < num_sockets; ++isock) |
|
|
|
mdns_socket_close(sockets[isock]); |
|
|
|
|
|
|
|
return(out); |
|
|
|
|
|
|
|