15#if !defined(USE_CARES)
26#if !defined(__CYGWIN__)
27#include <arpa/nameser.h>
32#pragma GCC diagnostic push
33#pragma GCC diagnostic warning "-Wdeprecated-declarations"
36#pragma warning(3 : 4996)
41#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS
61 mChannel(chan), mFd(fd), mUsingTcp(using_tcp), mServerIdx(server_idx),
71 mPollGrp->delPollItem(mPollHandle);
77 mPollHandle = mPollGrp->
addPollItem(mFd, mMask,
this);
85 mPollGrp->modPollItem(mPollHandle, mMask);
96 static void socket_poll_cb(
void *cb_data,
122AresDnsPollItem::socket_poll_cb(
void *cb_data,
130 AresDns::PollItemsMap::iterator it = ares->mPollItems.find(fd);
131 AresDnsPollItem* olditem(NULL);
132 if ( it != ares->mPollItems.end() )
137 olditem = it->second;
145 ares->mPollItems[fd] =
new AresDnsPollItem(grp, fd, using_tcp, *ares, channel, server_idx);
150 ares->mPollItems.erase(it);
168#elif defined(USE_CARES)
186 mPollGrp->delPollItem(mPollHandle);
192 mPollHandle = mPollGrp->
addPollItem(mPollSocket, mMask,
this);
202 mPollGrp->modPollItem(mPollHandle, mMask);
210 static void sockstate_cb(
void* data, ares_socket_t sock,
int read,
int write);
224 ares_process_fd(mChannel, mPollSocket, mPollSocket);
228 ares_process_fd(mChannel,
229 (mask &
FPEM_Read) ? mPollSocket : ARES_SOCKET_BAD,
230 (mask &
FPEM_Write) ? mPollSocket : ARES_SOCKET_BAD);
234AresDnsPollItem::sockstate_cb(
void* data, ares_socket_t sock,
int read,
int write)
237 AresDns::PollItemsMap::iterator it = ares->mPollItems.find(sock);
242 if (it == ares->mPollItems.end())
244 ares->mPollItems[sock] =
245 new AresDnsPollItem( ares->mPollGrp, sock, mask, ares->mChannel);
250 it->second->updateMask(mask);
259 AresDnsPollItem* item = it->second;
260 ares->mPollItems.erase(it);
270#if ARES_VERSION >= 0x011800
273 char* csv = ares_get_servers_csv(channel);
283 struct ares_addr_port_node* head = 0;
284 if (ares_get_servers_ports(channel, &head) !=
ARES_SUCCESS)
288 for (
struct ares_addr_port_node* node = head; node; node = node->next)
290 if (!servers.
empty())
294 if (node->family == AF_INET6)
298 memcpy(&addr6, &node->addr.addr6,
sizeof(addr6));
310 servers +=
":" +
Data(node->udp_port);
312 ares_free_data(head);
321setCaresServers(
ares_channel channel,
const std::vector<GenericIPAddress>& nameservers)
325 for (
size_t i = 0; i < nameservers.size(); ++i)
327 const bool v4 = nameservers[i].isVersion4();
330 :
DnsUtil::inet_ntop(nameservers[i].v6Address.sin6_addr);
334 WarningLog (<<
"Ignoring non-IPv4 additional name server (IPv6 support was not enabled)");
339 const unsigned short port = ntohs(v4 ? nameservers[i].v4Address.sin_port
340 : nameservers[i].v6Address.sin6_port);
351 csv += (v4 ? address :
"[" + address +
"]") +
":" +
Data(port);
358 return ares_set_servers_ports_csv(channel, csv.
c_str());
361#if !defined(USE_IPV6)
368 const std::string servers(caresServers(channel).c_str());
370 bool dropped =
false;
371 for (
size_t start = 0; start < servers.
size(); )
373 size_t end = servers.
find(
',', start);
374 if (end == std::string::npos)
376 end = servers.
size();
378 const std::string server = servers.
substr(start, end - start);
381 const size_t firstColon = server.
find(
':');
382 if (server.empty() || server[0] ==
'[' ||
383 (firstColon != std::string::npos && server.find(
':', firstColon + 1) != std::string::npos))
385 dropped = dropped || !server.empty();
388 ipv4 += (ipv4.empty() ?
"" :
",") + server;
394 InfoLog(<<
"DNS initialization: ignoring IPv6 name servers (IPv6 support was not enabled)");
395 return ares_set_servers_ports_csv(channel, ipv4.empty() ?
"127.0.0.1" : ipv4.c_str());
403AresDns::caresSocketConfigure(
Socket s,
int type,
void* data)
406 if (ares->mSocketFunc)
408 ares->mSocketFunc(s, type == SOCK_STREAM ?
TCP :
UDP, __FILE__, __LINE__);
414AresDns::caresSocketConnected(
Socket s,
int type,
void* data)
419 ares->mSocketFunc(s, type == SOCK_STREAM ?
TCP :
UDP, __FILE__, __LINE__);
432volatile bool AresDns::mHostFileLookupOnlyMode =
false;
437 for(PollItemsMap::iterator i=mPollItems.begin();
438 i!=mPollItems.end(); ++i)
440 i->second->resetPollGrp(grp);
446AresDns::clearPollItems()
449 items.swap(mPollItems);
450 for(PollItemsMap::iterator i=items.begin();
462 unsigned int features)
464 mAdditionalNameservers = additionalNameservers;
465 mSocketFunc = socketfunc;
467 return init(timeout, tries, features);
473 mFeatures = features;
489#if defined(WIN32) && defined(USE_ARES)
498 mHostFileLookupOnlyMode =
true;
503 mHostFileLookupOnlyMode =
false;
513 unsigned int features,
537 if (cap != requiredCap)
539 ErrLog (<<
"Build mismatch (ipv4/ipv6) problem in ares library");
548 memset(&opt,
'\0',
sizeof(opt));
565#if defined(USE_CARES)
583 opt.sock_state_cb = AresDnsPollItem::sockstate_cb;
584 opt.sock_state_cb_data =
this;
585 optmask |= ARES_OPT_SOCK_STATE_CB;
590#if !defined(USE_IPV6)
593 std::vector<in_addr> ipv4Nameservers;
594 for (
size_t i = 0; i < additionalNameservers.size(); i++)
596 if (additionalNameservers[i].isVersion4())
598 ipv4Nameservers.push_back(additionalNameservers[i].v4Address.sin_addr);
602 WarningLog (<<
"Ignoring non-IPv4 additional name server (IPv6 support was not enabled)");
605 if (ipv4Nameservers.empty())
607 if (additionalNameservers.empty())
617 opt.
nservers = (int)additionalNameservers.size();
621 for (
size_t i =0; i < additionalNameservers.size(); i++)
623 if (additionalNameservers[i].isVersion4())
626 opt.
servers[i].
addr = additionalNameservers[i].v4Address.sin_addr;
631 opt.
servers[i].
addr6 = additionalNameservers[i].v6Address.sin6_addr;
635 opt.
nservers = (int)ipv4Nameservers.size();
636 opt.
servers =
new in_addr[ipv4Nameservers.size()];
637 for (
size_t i = 0; i < ipv4Nameservers.size(); i++)
639 opt.
servers[i] = ipv4Nameservers[i];
648#elif defined(USE_CARES)
650 if (status ==
ARES_SUCCESS && !additionalNameservers.empty())
652 status = setCaresServers(*channel, additionalNameservers);
654#if !defined(USE_IPV6)
657 status = dropIpv6Servers(*channel);
662 ares_set_socket_configure_callback(*channel, &AresDns::caresSocketConfigure,
this);
663 ares_set_socket_callback(*channel, &AresDns::caresSocketConnected,
this);
668 ErrLog (<<
"Failed to initialize DNS library (status=" << status <<
")");
676 InfoLog(<<
"DNS initialization: found " << (*channel)->nservers <<
" name servers");
677 for (
int i = 0; i < (*channel)->nservers; ++i)
680 if((*channel)->servers[i].family == AF_INET6)
694 (*channel)->timeout = timeout;
699 (*channel)->tries = tries;
710#elif defined(USE_CARES)
713 InfoLog(<<
"DNS initialization: using c-ares v"
714 << ::ares_version(NULL));
716 InfoLog(<<
"DNS initialization: name servers " << caresServers(*channel));
727 mAdditionalNameservers = additional;
735 int result =
internalInit(mAdditionalNameservers, 0, mFeatures, &channel);
736 if(result !=
Success || channel == 0)
739 InfoLog(<<
" DNS server list changed");
754 for (
int i = 0; i < mChannel->
nservers; ++i)
780#elif defined(USE_CARES)
785 const Data old = caresServers(mChannel);
786 const Data updated = caresServers(channel);
787 bRet = old.
empty() || updated.
empty() || old != updated;
797 InfoLog(<<
" No changes in DNS server list");
801 InfoLog(<<
" DNS server list changed");
821 hostent *hostdata = 0;
827#elif defined(USE_CARES)
828 ares_gethostbyname_file(mChannel, target, AF_INET, &hostdata)
834 DebugLog(<<
"hostFileLookup failed for " << target);
838 memset(&saddr,0,
sizeof(saddr));
839 saddr.sin_family = AF_INET;
840 memcpy((
char *)&(saddr.sin_addr.s_addr),(
char *)hostdata->h_addr_list[0], (
size_t)hostdata->h_length);
841 addr = saddr.sin_addr;
847 DebugLog(<<
"hostFileLookup succeeded for " << target);
852AresDns::getHandler(
void* arg)
854 return reinterpret_cast<Payload*
>(arg)->handler;
858AresDns::makeRawResult(
void *arg,
int status,
unsigned char *abuf,
int alen)
860 void* userArg =
reinterpret_cast<Payload*
>(arg)->userData;
877 tv.tv_sec = maxSystemTime / 1000;
878 tv.tv_usec = 1000 * (maxSystemTime % 1000);
880 return tv.tv_sec*1000 + tv.tv_usec / 1000;
886#if defined(USE_CARES)
890 for (PollItemsMap::const_iterator i = mPollItems.begin(); i != mPollItems.end(); ++i)
892 const Socket fd = i->first;
901 if ((
int)fd + 1 > size)
907 int newsize =
ares_fds(mChannel, &read, &write);
908 if ( newsize > size )
920 ares_process_fd(mChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
944#if defined(USE_CARES)
948 std::vector<std::pair<Socket, FdPollEventMask> > ready;
949 for (PollItemsMap::const_iterator i = mPollItems.begin(); i != mPollItems.end(); ++i)
952 if (FD_ISSET(i->first, &read))
956 if (FD_ISSET(i->first, &write))
962 ready.push_back(std::make_pair(i->first, mask));
965 for (
size_t i = 0; i < ready.size(); ++i)
967 ares_process_fd(mChannel,
968 (ready[i].second &
FPEM_Read) ? ready[i].first : ARES_SOCKET_BAD,
969 (ready[i].second &
FPEM_Write) ? ready[i].first : ARES_SOCKET_BAD);
971 ares_process_fd(mChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
982 size_t len = strlen(aresMsg);
983 char* errorString =
new char[len+1];
985 snprintf(errorString, len+1,
"%s", aresMsg);
986 errorString[len] =
'\0';
990#if defined(USE_CARES) && ARES_VERSION >= 0x011c00
995resip_AresDns_caresDnsrecCallback(
void* arg, ares_status_t status,
size_t timeouts,
996 const ares_dns_record_t* dnsrec)
998 unsigned char* abuf = 0;
1002 ares_status_t writeStatus = ares_dns_write(dnsrec, &abuf, &alen);
1005 status = writeStatus;
1016#if defined(USE_CARES) && ARES_VERSION >= 0x011c00
1018 ares_query_dnsrec(mChannel, target, ARES_CLASS_IN, (ares_dns_rec_type_t)type,
1019 resip_AresDns_caresDnsrecCallback,
new Payload(handler, userData,
this), 0);
1022#
if defined(USE_ARES)
1024#elif defined(USE_CARES)
1027 new Payload(handler, userData,
this));
1034 resip::AresDns::Payload* p =
reinterpret_cast<resip::AresDns::Payload*
>(arg);
1047 p->handler->handleDnsRaw(resip::AresDns::makeRawResult(arg, status, abuf, alen));
1053 unsigned char *abuf,
int alen)
1056 return ::resip_AresDns_aresCallback(arg, status, abuf, alen);
1066#if defined(USE_IPV6)
1067 else if (rrtype ==
T_AAAA)
1076 else if (rrtype ==
T_SRV)
void resip_AresDns_caresCallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
void resip_AresDns_aresCallback(void *arg, int status, unsigned char *abuf, int alen)
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
int ares_capabilities(int capmask)
@ ARES_POLLACTION_WRITEOFF
@ ARES_POLLACTION_WRITEON
void ares_free_string(char *str)
int ares_init_options_with_socket_function(ares_channel *channelptr, struct ares_options *options, int optmask, socket_function_ptr)
struct timeval * ares_timeout(ares_channel channel, struct timeval *maxtv, struct timeval *tv)
void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
const char * ares_strerror(int code)
void ares_destroy(ares_channel channel)
#define ARES_EDESTRUCTION
#define ARES_FLAG_NOCHECKRESP
void ares_process_poll(ares_channel channel, int server_idx, int rdFd, int wrFd, time_t now)
int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
int hostfile_lookup(const char *name, struct hostent **host)
void ares_free_hostent(struct hostent *host)
void ares_query(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg)
#define ARES_FLAG_TRY_NEXT_SERVER_ON_RCODE3
int ares_init_options(ares_channel *channelptr, struct ares_options *options, int optmask)
enum ares_poll_action ares_poll_action_t
void ares_destroy_suppress_callbacks(ares_channel channel)
void ares_process_set_poll_cb(ares_channel channel, ares_poll_cb_func *cb_func, void *cb_data)
virtual void setPollGrp(FdPollGrp *pollGrp)
virtual void processTimers()
virtual bool checkDnsChange()
static const char * dnsRRTypeToString(int rrtype)
int internalInit(const std::vector< GenericIPAddress > &additionalNameservers, AfterSocketCreationFuncPtr socketfunc, unsigned int features=0, ares_channeldata **channel=0, int timeout=0, int tries=0, bool useStateFunc=false)
virtual char * errorMessage(long errorCode)
virtual int init(const std::vector< GenericIPAddress > &additionalNameservers, AfterSocketCreationFuncPtr socketfunc, int timeout=0, int tries=0, unsigned int features=0)
virtual unsigned int getTimeTillNextProcessMS()
void lookup(const char *target, unsigned short type, ExternalDnsHandler *handler, void *userData)
virtual bool hostFileLookup(const char *target, in_addr &addr)
virtual void process(FdSet &fdset)
friend void::resip_AresDns_caresCallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
friend void::resip_AresDns_aresCallback(void *arg, int status, unsigned char *abuf, int alen)
virtual void changeNameServers(const std::vector< GenericIPAddress > &additional)
virtual void buildFdSet(FdSet &fdset)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
static const Data Empty
Constant that represents a zero-length data.
const char * c_str() const
Returns a null-terminated string representing.
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
bool empty() const noexcept
Checks whether the Data is empty.
size_type size() const noexcept
Returns the number of bytes in this Data.
size_type find(const Data &match, size_type start=0) const
Finds a specified sequence of bytes in this Data.
Provides a collection of utility functions for manipulating DNS names and IP addresses and discoverin...
static Data inet_ntop(const struct in_addr &addr)
Converts from the network format to presentation format.
static bool getEnablePostConnectSocketFuncCall()
@ TryServersOfNextNetworkUponRcode3
virtual FdPollItemHandle addPollItem(Socket sock, FdPollEventMask newMask, FdPollItemIf *item)=0
Object-oriented wrapper for your platform's file-descriptor set.
static unsigned getMaxSystemTimeWaitMs(void)
On windows, change getSystemTime() to not use the actual clock time returned by ::GetSystemTime().
dcm! – add UnusedChecking(_enum) below;
void(* AfterSocketCreationFuncPtr)(Socket s, int transportType, const char *file, int line)
unsigned short FdPollEventMask
struct server_state * servers
struct multiFamilyAddr * servers
int default_localhost_server