reSIProcate/rutil  9694
Public Member Functions | Static Public Member Functions | Private Types | Static Private Member Functions | Private Attributes | Static Private Attributes | Friends
resip::AresDns Class Reference

#include <AresDns.hxx>

Inheritance diagram for resip::AresDns:
Inheritance graph
[legend]
Collaboration diagram for resip::AresDns:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 AresDns ()
virtual ~AresDns ()
virtual int init (const std::vector< GenericIPAddress > &additionalNameservers, AfterSocketCreationFuncPtr socketfunc, int timeout=0, int tries=0, unsigned int features=0)
int internalInit (const std::vector< GenericIPAddress > &additionalNameservers, AfterSocketCreationFuncPtr socketfunc, unsigned int features=0, ares_channeldata **channel=0, int timeout=0, int tries=0)
virtual bool checkDnsChange ()
virtual unsigned int getTimeTillNextProcessMS ()
virtual void process (FdSet &fdset)
 Called once select() returns; this allows this object to inspect which of its FDs are ready, and perform any necessary IO with them.
virtual void buildFdSet (FdSet &fdset)
 Add any FDs that we are interested in watching to an fdset, with the understanding that a select() call will be made immediately after.
virtual void buildFdSet (fd_set &read, fd_set &write, int &size)
virtual void process (fd_set &read, fd_set &write)
virtual void setPollGrp (FdPollGrp *pollGrp)
virtual void processTimers ()
virtual void freeResult (ExternalDnsRawResult)
virtual void freeResult (ExternalDnsHostResult)
virtual char * errorMessage (long errorCode)
void lookup (const char *target, unsigned short type, ExternalDnsHandler *handler, void *userData)
virtual bool hostFileLookup (const char *target, in_addr &addr)
virtual bool hostFileLookupLookupOnlyMode ()
friend void::resip_AresDns_aresCallback (void *arg, int status, unsigned char *abuf, int alen)
friend void::resip_AresDns_caresCallback (void *arg, int status, int timeouts, unsigned char *abuf, int alen)

Static Public Member Functions

static void enableHostFileLookupOnlyMode (bool enable)

Private Types

typedef std::pair
< ExternalDnsHandler *, void * > 
Payload

Static Private Member Functions

static ExternalDnsRawResult makeRawResult (void *arg, int status, unsigned char *abuf, int alen)
static ExternalDnsHandlergetHandler (void *arg)

Private Attributes

struct ares_channeldata * mChannel
std::vector< GenericIPAddressmAdditionalNameservers
unsigned int mFeatures
FdPollGrpmPollGrp
std::vector< AresDnsPollItem * > mPollItems

Static Private Attributes

static volatile bool mHostFileLookupOnlyMode = false

Friends

class AresDnsPollItem

Detailed Description

Definition at line 25 of file AresDns.hxx.


Member Typedef Documentation

typedef std::pair<ExternalDnsHandler*, void*> resip::AresDns::Payload [private]

Definition at line 70 of file AresDns.hxx.


Constructor & Destructor Documentation

resip::AresDns::AresDns ( ) [inline]

Definition at line 29 of file AresDns.hxx.

References mChannel, mFeatures, and mPollGrp.

{mChannel = 0; mFeatures = 0; mPollGrp=NULL;}
AresDns::~AresDns ( ) [virtual]

Definition at line 515 of file AresDns.cxx.

References mChannel.

{
#if defined(USE_ARES)
   ares_destroy_suppress_callbacks(mChannel);
#elif defined(USE_CARES)
   ares_destroy(mChannel);
#endif
}

Member Function Documentation

void AresDns::buildFdSet ( FdSet fdset) [virtual]

Add any FDs that we are interested in watching to an fdset, with the understanding that a select() call will be made immediately after.

Parameters:
fdsetThe FdSet to be augmented

Implements resip::FdSetIOObserver.

Definition at line 620 of file AresDns.cxx.

References resip::FdSet::read, resip::FdSet::size, and resip::FdSet::write.

{
   buildFdSet(fdset.read, fdset.write, fdset.size);
}
void AresDns::buildFdSet ( fd_set &  read,
fd_set &  write,
int &  size 
) [virtual]

Implements resip::ExternalDns.

Definition at line 591 of file AresDns.cxx.

References mChannel.

{
   int newsize = ares_fds(mChannel, &read, &write);
   if ( newsize > size )
   {
      size = newsize;
   }
}
bool AresDns::checkDnsChange ( ) [virtual]

Implements resip::ExternalDns.

Definition at line 416 of file AresDns.cxx.

References InfoLog, internalInit(), mAdditionalNameservers, mChannel, mFeatures, and resip::ExternalDns::Success.

{
   // We must return 'true' if there are changes in the list of DNS servers
   struct ares_channeldata* channel = 0;
   bool bRet = false;
   int result = internalInit(mAdditionalNameservers, 0, mFeatures, &channel);
   if(result != Success || channel == 0)
   {
      // It has changed because it failed, I suppose
      InfoLog(<< " DNS server list changed");
      return true;
   }

#if defined(USE_ARES)
   {
      // Compare the two lists.  Are they different sizes?
      if(mChannel->nservers != channel->nservers)
      {
         // Yes, so they're different
         bRet = true;
      }
      else
      {
         // Compare them one-by-one
         for (int i = 0; i < mChannel->nservers; ++i)
         {
            if (mChannel->servers[i].addr.s_addr
                != channel->servers[i].addr.s_addr)
            {
               bRet = true;
               break;
            }
         }
      }

      // Destroy the secondary configuration we read
      ares_destroy_suppress_callbacks(channel);
   }
#elif defined(USE_CARES)
   {
      // Get the options, including the server list, from the old and the
      // current (i.e. just read) configuration.
      struct ares_options old;
      struct ares_options updated;
      std::memset(&old, 0, sizeof(old));
      std::memset(&updated, 0, sizeof(updated));
      int ignored;

      // Can we get the configuration?
      if(ares_save_options(mChannel, &old, &ignored) != ARES_SUCCESS
         || ares_save_options(channel, &updated, &ignored) != ARES_SUCCESS)
      {
         // It failed, so call it different
         bRet = true;
      }
      else
      {
         // Compare the two lists.  Are they different sizes?
         if(old.nservers != updated.nservers)
         {
            // Yes, so they're different
            bRet = true;
         }
         else
         {
            // Compare them one-by-one
            for (int i = 0; i < old.nservers; ++i)
            {
               if (old.servers[i].s_addr != updated.servers[i].s_addr)
               {
                  bRet = true;
                  break;
               }
            }
         }

         // Free any ares_options contents we have created.
         ares_destroy_options(&old);
         ares_destroy_options(&updated);
      }

      // Destroy the secondary configuration we read
      ares_destroy(channel);
   }
#endif

   // Report on the results
   if(!bRet)
   {
      InfoLog(<< " No changes in DNS server list");
   }
   else
   {
      InfoLog(<< " DNS server list changed");
   }

   return bRet;
}

Here is the call graph for this function:

static void resip::AresDns::enableHostFileLookupOnlyMode ( bool  enable) [inline, static]

Definition at line 60 of file AresDns.hxx.

References mHostFileLookupOnlyMode.

char * AresDns::errorMessage ( long  errorCode) [virtual]

Implements resip::ExternalDns.

Definition at line 632 of file AresDns.cxx.

{
   const char* aresMsg = ares_strerror(errorCode);

   size_t len = strlen(aresMsg);
   char* errorString = new char[len+1];

   strncpy(errorString, aresMsg, len);
   errorString[len] = '\0';
   return errorString;
}
virtual void resip::AresDns::freeResult ( ExternalDnsRawResult  ) [inline, virtual]

Implements resip::ExternalDns.

Definition at line 51 of file AresDns.hxx.

{}
virtual void resip::AresDns::freeResult ( ExternalDnsHostResult  ) [inline, virtual]

Implements resip::ExternalDns.

Definition at line 52 of file AresDns.hxx.

{}
ExternalDnsHandler * AresDns::getHandler ( void *  arg) [static, private]

Definition at line 559 of file AresDns.cxx.

Referenced by resip_AresDns_aresCallback().

{
   Payload* p = reinterpret_cast<Payload*>(arg);
   ExternalDnsHandler *thisp = reinterpret_cast<ExternalDnsHandler*>(p->first);
   return thisp;
}
unsigned int AresDns::getTimeTillNextProcessMS ( ) [virtual]

Implements resip::ExternalDns.

Definition at line 583 of file AresDns.cxx.

References mChannel.

{
   struct timeval tv;
   ares_timeout(mChannel, NULL, &tv);
   return tv.tv_sec*1000 + tv.tv_usec / 1000;
}
bool AresDns::hostFileLookup ( const char *  target,
in_addr &  addr 
) [virtual]

Implements resip::ExternalDns.

Definition at line 524 of file AresDns.cxx.

References DebugLog, and mChannel.

{
   assert(target);

   hostent *hostdata = 0;

   // Look this up
   int status =
#if defined(USE_ARES)
     hostfile_lookup(target, &hostdata)
#elif defined(USE_CARES)
     ares_gethostbyname_file(mChannel, target, AF_INET, &hostdata)
#endif
     ;

   if (status != ARES_SUCCESS)
   {
      DebugLog(<< "hostFileLookup failed for " << target);
      return false;
   }
   sockaddr_in saddr;
   memset(&saddr,0,sizeof(saddr));  /* Initialize sockaddr fields. */
   saddr.sin_family = AF_INET;
   memcpy((char *)&(saddr.sin_addr.s_addr),(char *)hostdata->h_addr_list[0], (size_t)hostdata->h_length);
   addr = saddr.sin_addr;
#if defined(USE_ARES)
   // for resip-ares, the hostdata (and its contents) is dynamically allocated
   ares_free_hostent(hostdata);
#endif

   DebugLog(<< "hostFileLookup succeeded for " << target);
   return true;
}
virtual bool resip::AresDns::hostFileLookupLookupOnlyMode ( ) [inline, virtual]

Implements resip::ExternalDns.

Definition at line 59 of file AresDns.hxx.

References mHostFileLookupOnlyMode.

int AresDns::init ( const std::vector< GenericIPAddress > &  additionalNameservers,
AfterSocketCreationFuncPtr  socketfunc,
int  timeout = 0,
int  tries = 0,
unsigned int  features = 0 
) [virtual]

Implements resip::ExternalDns.

Definition at line 170 of file AresDns.cxx.

References internalInit(), mAdditionalNameservers, mChannel, mFeatures, mHostFileLookupOnlyMode, and resip::ExternalDns::Success.

{
   mAdditionalNameservers = additionalNameservers;
   mFeatures = features;

   int ret = internalInit(additionalNameservers,
                          socketfunc,
                          features,
                          &mChannel,
                          timeout,
                          tries);

   if (ret != Success)
      return ret;

#ifdef WIN32
      // For windows OSs it is uncommon to run a local DNS server.  Therefor if there
      // are no defined DNS servers in windows networking and ARES just returned the
      // loopback address (ie. default localhost server / named)
      // then put resip DNS resolution into hostfile lookup only mode
      if(mChannel->nservers == 1 &&
         mChannel->servers[0].default_localhost_server)
      {
         // enable hostfile only lookup mode
         mHostFileLookupOnlyMode = true;
      }
      else
      {
         // disable hostfile only lookup mode
         mHostFileLookupOnlyMode = false;
      }
#endif

   return Success;
}

Here is the call graph for this function:

int AresDns::internalInit ( const std::vector< GenericIPAddress > &  additionalNameservers,
AfterSocketCreationFuncPtr  socketfunc,
unsigned int  features = 0,
ares_channeldata **  channel = 0,
int  timeout = 0,
int  tries = 0 
)

Definition at line 211 of file AresDns.cxx.

References resip::ExternalDns::BuildMismatch, ErrLog, resip::DnsUtil::inet_ntop(), InfoLog, mChannel, mPollGrp, mPollItems, resip::AresDnsPollItem::socket_poll_cb(), resip::ExternalDns::Success, resip::ExternalDns::TryServersOfNextNetworkUponRcode3, and WarningLog.

Referenced by checkDnsChange(), and init().

{
   if(*channel)
   {
#if defined(USE_ARES)
      ares_destroy_suppress_callbacks(*channel);
#elif defined(USE_CARES)
      // Callbacks will be supressed by looking for the ARES_EDESTRUCTION
      // sentinel status
      ares_destroy(*channel);
#endif
      *channel = 0;
   }

#if defined(USE_ARES)

#ifdef USE_IPV6
   int requiredCap = ARES_CAP_IPV6;
#else
   int requiredCap = 0;
#endif

   // Only the contrib/ares has this function
   int cap = ares_capabilities(requiredCap);
   if (cap != requiredCap)
   {
      ErrLog (<< "Build mismatch (ipv4/ipv6) problem in ares library"); // !dcm!
      return BuildMismatch;
   }
#endif

   int status;
   ares_options opt;
   int optmask = 0;

   memset(&opt, '\0', sizeof(opt));

#if defined(USE_ARES)
   // TODO: What is this and how does it map to c-ares?
   if ((features & ExternalDns::TryServersOfNextNetworkUponRcode3))
   {
      optmask |= ARES_OPT_FLAGS;
      opt.flags |= ARES_FLAG_TRY_NEXT_SERVER_ON_RCODE3;
   }
#endif

#if defined(USE_CARES)
   // In c-ares, we can actually set the timeout and retries via the API
   if (timeout > 0)
   {
      opt.timeout = timeout;
      optmask |= ARES_OPT_TIMEOUT;
   }

   if (tries > 0)
   {
      opt.tries = tries;
      optmask |= ARES_OPT_TRIES;
   }
#endif

   if (additionalNameservers.empty())
   {
#if defined(USE_ARES)
      status = ares_init_options_with_socket_function(channel, &opt, optmask, socketfunc);
#elif defined(USE_CARES)
      // TODO: Does the socket function matter?
      status = ares_init_options(channel, &opt, optmask);
#endif
   }
   else
   {
      optmask |= ARES_OPT_SERVERS;
      opt.nservers = (int)additionalNameservers.size();

#if defined(USE_IPV6) && defined(USE_ARES)
      // With contrib/ares, you can configure IPv6 addresses for the
      // nameservers themselves.
      opt.servers = new multiFamilyAddr[additionalNameservers.size()];
      for (size_t i =0; i < additionalNameservers.size(); i++)
      {
         if (additionalNameservers[i].isVersion4())
         {
            opt.servers[i].family = AF_INET;
            opt.servers[i].addr = additionalNameservers[i].v4Address.sin_addr;
         }
         else
         {
            opt.servers[i].family = AF_INET6;
            opt.servers[i].addr6 = additionalNameservers[i].v6Address.sin6_addr;
         }
      }
#else
      // If we're only supporting IPv4 or we are using c-ares, we can't
      // support additional nameservers that are IPv6 right now.
      opt.servers = new in_addr[additionalNameservers.size()];
      for (size_t i =0; i < additionalNameservers.size(); i++)
      {
         if(additionalNameservers[i].isVersion4())
         {
            opt.servers[i] = additionalNameservers[i].v4Address.sin_addr;
         }
         else
         {
#if defined(USE_CARES)
           WarningLog (<< "Ignoring non-IPv4 additional name server (not yet supported with c-ares)");
#elif defined(USE_ARES)
           WarningLog (<< "Ignoring non-IPv4 additional name server (IPv6 support was not enabled)");
#endif
         }
      }
#endif

#if defined(USE_ARES)
      status = ares_init_options_with_socket_function(channel, &opt, optmask, socketfunc);
#elif defined(USE_CARES)
      // TODO: Does the socket function matter?
      status = ares_init_options(channel, &opt, optmask);
#endif

      delete [] opt.servers;
      opt.servers = 0;
   }
   if (status != ARES_SUCCESS)
   {
      ErrLog (<< "Failed to initialize DNS library (status=" << status << ")");
      return status;
   }
   else
   {

#if defined(USE_ARES)

      InfoLog(<< "DNS initialization: found  " << (*channel)->nservers << " name servers");
      for (int i = 0; i < (*channel)->nservers; ++i)
      {
#ifdef USE_IPV6
         if((*channel)->servers[i].family == AF_INET6) 
         {
            InfoLog(<< " name server: " << DnsUtil::inet_ntop((*channel)->servers[i].addr6));
         } 
         else
#endif
         {
            InfoLog(<< " name server: " << DnsUtil::inet_ntop((*channel)->servers[i].addr));
         }
      }

      // In ares, we must manipulate these directly
      if (timeout > 0)
      {
         mChannel->timeout = timeout;
      }

      if (tries > 0)
      {
         mChannel->tries = tries;
      }

#ifndef USE_CARES
      if ( mPollGrp )
      {
         // expand vector to hold {nservers} and init to NULL
         mPollItems.insert( mPollItems.end(), (*channel)->nservers, (AresDnsPollItem*)0);
         // tell ares to let us know when things change
         ares_process_set_poll_cb(mChannel, AresDnsPollItem::socket_poll_cb, this);
      }
#endif

#elif defined(USE_CARES)
      {
         // Log which version of c-ares we're using
         InfoLog(<< "DNS initialization: using c-ares v"
                 << ::ares_version(NULL));

         // Ask for the current configuration so we can print the servers found
         struct ares_options options;
         std::memset(&options, 0, sizeof(options));
         int ignored;
         if(ares_save_options(*channel, &options, &ignored) == ARES_SUCCESS)
         {
            InfoLog(<< "DNS initialization: found "
                    << options.nservers << " name servers");

            // Log them all
            for (int i = 0; i < options.nservers; ++i)
            {
               InfoLog(<< " name server: "
                       << DnsUtil::inet_ntop(options.servers[i]));
            }
            ares_destroy_options(&options);
         }
      }
#endif

      return Success;
   }
}

Here is the call graph for this function:

void AresDns::lookup ( const char *  target,
unsigned short  type,
ExternalDnsHandler handler,
void *  userData 
) [virtual]

Implements resip::ExternalDns.

Definition at line 645 of file AresDns.cxx.

References mChannel, resip_AresDns_aresCallback(), and resip_AresDns_caresCallback().

{
   ares_query(mChannel, target, C_IN, type,
#if defined(USE_ARES)
              resip_AresDns_aresCallback,
#elif defined(USE_CARES)
              resip_AresDns_caresCallback,
#endif
              new Payload(handler, userData));
}

Here is the call graph for this function:

ExternalDnsRawResult AresDns::makeRawResult ( void *  arg,
int  status,
unsigned char *  abuf,
int  alen 
) [static, private]

Definition at line 567 of file AresDns.cxx.

Referenced by resip_AresDns_aresCallback().

{
   Payload* p = reinterpret_cast<Payload*>(arg);
   void* userArg = reinterpret_cast<void*>(p->second);

   if (status != ARES_SUCCESS)
   {
      return ExternalDnsRawResult(status, abuf, alen, userArg);
   }
   else
   {
      return ExternalDnsRawResult(abuf, alen, userArg);
   }
}
void AresDns::process ( FdSet fdset) [virtual]

Called once select() returns; this allows this object to inspect which of its FDs are ready, and perform any necessary IO with them.

Parameters:
fdsetThe FdSet after the call to select().

Implements resip::FdSetIOObserver.

Definition at line 614 of file AresDns.cxx.

References resip::FdSet::read, and resip::FdSet::write.

{
   process(fdset.read, fdset.write);
}
void AresDns::process ( fd_set &  read,
fd_set &  write 
) [virtual]

Implements resip::ExternalDns.

Definition at line 626 of file AresDns.cxx.

References mChannel.

{
   ares_process(mChannel, &read, &write);
}
void AresDns::processTimers ( ) [virtual]

Implements resip::ExternalDns.

Definition at line 601 of file AresDns.cxx.

References mChannel, and mPollGrp.

{
#ifdef USE_CARES
   return;
#else
   assert( mPollGrp!=0 );
   time_t timeSecs;
   time(&timeSecs);
   ares_process_poll(mChannel, /*server*/-1, /*rd*/-1, /*wr*/-1, timeSecs);
#endif
}
void AresDns::setPollGrp ( FdPollGrp pollGrp) [virtual]

Implements resip::ExternalDns.

Definition at line 144 of file AresDns.cxx.

References mPollGrp, mPollItems, resip::FdPollGrp::registerFdSetIOObserver(), and resip::FdPollGrp::unregisterFdSetIOObserver().

{
#ifdef USE_CARES
   if(mPollGrp)
   {
      mPollGrp->unregisterFdSetIOObserver(*this);
   }
   mPollGrp=grp;
   if(mPollGrp)
   {
      mPollGrp->registerFdSetIOObserver(*this);
   }
#else
   for(std::vector<AresDnsPollItem*>::iterator i=mPollItems.begin();
         i!=mPollItems.end(); ++i)
   {
      if(*i)
      {
         (*i)->resetPollGrp(grp);
      }
   }
   mPollGrp = grp;
#endif
}

Here is the call graph for this function:

resip::AresDns::void::resip_AresDns_aresCallback ( void *  arg,
int  status,
unsigned char *  abuf,
int  alen 
)
resip::AresDns::void::resip_AresDns_caresCallback ( void *  arg,
int  status,
int  timeouts,
unsigned char *  abuf,
int  alen 
)

Friends And Related Function Documentation

friend class AresDnsPollItem [friend]

Definition at line 27 of file AresDns.hxx.


Member Data Documentation

Definition at line 74 of file AresDns.hxx.

Referenced by checkDnsChange(), and init().

struct ares_channeldata* resip::AresDns::mChannel [private]
unsigned int resip::AresDns::mFeatures [private]

Definition at line 75 of file AresDns.hxx.

Referenced by AresDns(), checkDnsChange(), and init().

volatile bool AresDns::mHostFileLookupOnlyMode = false [static, private]

Definition at line 76 of file AresDns.hxx.

Referenced by enableHostFileLookupOnlyMode(), hostFileLookupLookupOnlyMode(), and init().

Definition at line 79 of file AresDns.hxx.

Referenced by internalInit(), setPollGrp(), and resip::AresDnsPollItem::socket_poll_cb().


The documentation for this class was generated from the following files: