< Previous by Date Date Index Next by Date >
  Thread Index Next in Thread >

[reSIProcate] Followup on c-ares support


First, thanks again for the help so far.  With a little more digging
and some help from others, including the c-ares mailing list, I've
managed to get further along in using c-ares with resiprocate.

I have identified a set of "obvious" features that resiprocate depends
on simply by looking at the API differences between contrib/ares and
c-ares.  I have not searched for embedded behavioural changes that may
have been made to contrib/ares without API changes.  However,
especially if c-ares vs contrib/ares were to remain a choice at
configuration time, I think this is okay, at least as a starting point
because c-ares "works".

The attached patch will allow resiprocate to be configured against the
trunk version of c-ares (1.5.3 + patches).  Of course, it still allows
resiprocate to be configured to use contrib/ares as well.  With this
patch against resiprocate-1.4.1, the following features are missing
only when using c-ares:

 1. TryServersOfNextNetworkUponRcode3

   I've read the mailing list history on item 7, and I'm still
   digesting that.  It seems to be only supported on Windows in the
   current contrib/ares source, though.

 2. AfterSocketCreationFuncPtr

   I haven't been able to find much information about the purpose of
   the AfterSocketCreationFuncPtr feature, except I found some note
   about it being related to QoS.

   Is there a reason only UDP sockets from ares are identified via
   this function?  If I can supply the reasons this is important for
   QoS, and we can figure out what to do about TCP, there's probably a
   good argument to be made for adding an analogue of this to c-ares.
 
 3. DNS servers with IPv6 addresses themselves

   contrib/ares can have IPv4 and IPv6 addresses of DNS _servers_
   configured (via the additionalNameservers argument and via built-in
   config parsing), while c-ares can only contact IPv4 addressed DNS
   servers at the moment.  Note that this has nothing to do with AAAA
   record lookups, which work fine when using c-ares.
    
   This seems like a good candidate for a new c-ares feature, and I
   will ask about it on the c-ares list and report back.

-- 
----------------------------------------------------------
Brad Spencer - spencer@xxxxxxxxxxxxx - www.starscale.com
diff -ur orig/Makefile resiprocate-1.4.1/Makefile
--- orig/Makefile	2008-05-09 16:19:21.000000000 -0300
+++ resiprocate-1.4.1/Makefile	2008-11-18 23:44:00.000000000 -0400
@@ -159,7 +159,12 @@
 
 tfmcontrib: cppunit netxx
 
-contrib: ares 
+# Only build contrib/ares if we need it
+ifeq ($(USE_CARES),no)
+contrib: ares
+else
+contrib: 
+endif
 
 ###########################################################################
 # Various clean targets
diff -ur orig/build/Makefile.osarch resiprocate-1.4.1/build/Makefile.osarch
--- orig/build/Makefile.osarch	2007-11-27 19:16:08.000000000 -0400
+++ resiprocate-1.4.1/build/Makefile.osarch	2008-11-18 23:44:00.000000000 -0400
@@ -78,6 +78,11 @@
 LDLIBS_LAST += -lprofiler
 endif
 
+# This is needed for c-ares-1.5.3 on Linux, at least
+ifeq ($(USE_CARES),yes)
+LDLIBS_LAST += -lrt
+endif
+
 endif
 
 
diff -ur orig/build/Makefile.pkg resiprocate-1.4.1/build/Makefile.pkg
--- orig/build/Makefile.pkg	2008-06-18 22:16:26.000000000 -0300
+++ resiprocate-1.4.1/build/Makefile.pkg	2008-11-18 23:44:00.000000000 -0400
@@ -81,10 +81,22 @@
 MYSQL_DEFINES += USE_MYSQL
 endif
 
-ARES_INCLUDEDIRS := $(ROOT)/contrib/ares
-ARES_LIBDIRS := $(ROOT)/contrib/ares-build.$(OS_ARCH)
-ARES_LIBNAME := ares
-ARES_DEFINES := 
+# We can only use one of CARES or ARES, and to avoid mucking up all the
+# packaging stuff, let's just swap one in for another since they are almost
+# interchangeable anyway.  
+ifeq ($(USE_CARES),no)
+   ARES_INCLUDEDIRS := $(ROOT)/contrib/ares
+   ARES_LIBDIRS := $(ROOT)/contrib/ares-build.$(OS_ARCH)
+   ARES_LIBNAME := ares
+   ARES_DEFINES := 
+else
+   # The CARES_INCLUDEDIRS and CARES_LIBDIRS variables are set by configure in
+   # Makefile.conf
+   ARES_INCLUDEDIRS := $(CARES_INCLUDEDIRS)
+   ARES_LIBDIRS := $(CARES_LIBDIRS)
+   ARES_LIBNAME := cares
+   ARES_DEFINES :=
+endif
 
 S2C_INCLUDEDIRS := $(ROOT)/p2p/s2c/s2c
 S2C_LIBDIRS := $(ROOT)/p2p/s2c/s2c/obj.$(TARGET_NAME)
@@ -232,7 +244,13 @@
 $(RECON_DEPENDS):
 	cd $(ROOT)/resip/recon; $(MAKE)
 
+# Use c-ares (external) or contrib/ares?
+ifeq ($(USE_CARES),yes)
+DEFINES += USE_CARES
+else
 DEFINES += USE_ARES
+endif
+
 ifeq ($(USE_IPV6),yes)
 DEFINES += USE_IPV6
 endif
diff -ur orig/configure resiprocate-1.4.1/configure
--- orig/configure	2008-09-23 05:30:37.000000000 -0300
+++ resiprocate-1.4.1/configure	2008-11-18 23:44:00.000000000 -0400
@@ -57,7 +57,10 @@
 # USE_SIGCOMP := no
 # SIGCOMP_BASEDIR:= /usr/local
 INSTALL_PREFIX := /usr/local
-ARES_PREFIX := /usr/local " > build/Makefile.conf
+ARES_PREFIX := /usr/local
+USE_CARES := no
+CARES_INCDIR :=
+CARES_LIBDIR := " > build/Makefile.conf
     exit
   fi
   echo "*** Leaving build/Makefile.conf unmodified"
@@ -412,6 +415,27 @@
     evaldefault => 1,
     option      => "ares-prefix",
   },
+  {
+    name        => "USE_CARES",
+    description => "Build against external c-ares instead of internal ares?",
+    default     => "no",
+    validate    => [@yesno],
+    flag        => "cares",
+  },
+  {
+    name        => "CARES_INCLUDEDIRS",
+    description => "If --with-cares, the directory containing its headers.",
+    default     => "",
+    evaldefault => 0,
+    option      => "cares-headers",
+  },
+  {
+    name        => "CARES_LIBDIRS",
+    description => "If --with-cares, the directory containing its libraries.",
+    default     => "",
+    evaldefault => 0,
+    option      => "cares-libs",
+  },
 );
 
 if (open (CONF, "build/Makefile.conf"))
diff -ur orig/resip/stack/DnsInterface.cxx resiprocate-1.4.1/resip/stack/DnsInterface.cxx
--- orig/resip/stack/DnsInterface.cxx	2008-08-15 17:59:01.000000000 -0300
+++ resiprocate-1.4.1/resip/stack/DnsInterface.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -13,14 +13,6 @@
 #endif
 #endif
 
-
-
-
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
-
 #include "rutil/compat.hxx"
 #include "rutil/Logger.hxx"
 #include "rutil/BaseException.hxx"
diff -ur orig/resip/stack/DnsResult.cxx resiprocate-1.4.1/resip/stack/DnsResult.cxx
--- orig/resip/stack/DnsResult.cxx	2008-09-23 05:30:37.000000000 -0300
+++ resiprocate-1.4.1/resip/stack/DnsResult.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -24,10 +24,7 @@
 #endif
 #endif
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "rutil/dns/AresCompat.hxx"
 
 #include "rutil/DnsUtil.hxx"
 #include "rutil/Inserter.hxx"
@@ -49,10 +46,6 @@
 
 #include "rutil/Timer.hxx"
 
-#if !defined(USE_ARES)
-#warning "ARES is required"
-#endif
-
 using namespace resip;
 using namespace std;
 
@@ -673,7 +666,7 @@
 {
    char *name=0;
    int status=0;
-   int len=0;
+   ares_length_type len=0;
    
    // Parse the question name. 
    status = ares_expand_name(aptr, abuf, alen, &name, &len);
Only in resiprocate-1.4.1/rutil/dns: AresCompat.hxx
diff -ur orig/rutil/dns/AresDns.cxx resiprocate-1.4.1/rutil/dns/AresDns.cxx
--- orig/rutil/dns/AresDns.cxx	2008-08-15 17:59:01.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/AresDns.cxx	2008-11-18 23:44:08.000000000 -0400
@@ -5,18 +5,12 @@
 #include "rutil/dns/AresDns.hxx"
 #include "rutil/GenericIPAddress.hxx"
 
-#include "ares.h"
-#include "ares_dns.h"
-#include "ares_private.h"
+#include "AresCompat.hxx"
 
 #include "rutil/Logger.hxx"
 #include "rutil/DnsUtil.hxx"
 #include "rutil/WinLeakCheck.hxx"
 
-#if !defined(USE_ARES)
-#error Must have ARES
-#endif
-
 #if !defined(WIN32)
 #if !defined(__CYGWIN__)
 #include <arpa/nameser.h>
@@ -34,71 +28,98 @@
               int tries,
               unsigned int features)
 {
-	mAdditionalNameservers = additionalNameservers;
-	mFeatures = features;
-
-	int ret = internalInit(additionalNameservers,
-              socketfunc,
-              features,
-				  &mChannel);
-
-	if(ret != Success)
-		return ret;
-
-   if (timeout > 0)
-   {
-      mChannel->timeout = timeout;
-   }
+   mAdditionalNameservers = additionalNameservers;
+   mFeatures = features;
+   
+   int ret = internalInit(additionalNameservers,
+                          socketfunc,
+                          features,
+                          &mChannel,
+                          timeout,
+                          tries);
 
-   if (tries > 0)
-   {
-      mChannel->tries = tries;
-   }
+   if (ret != Success)
+      return ret;
 
    return Success;      
 }
 
 int 
 AresDns::internalInit(const std::vector<GenericIPAddress>& additionalNameservers,
-              AfterSocketCreationFuncPtr socketfunc,
-              unsigned int features,
-				  ares_channeldata** channel
+                      AfterSocketCreationFuncPtr socketfunc,
+                      unsigned int features,
+                      ares_channeldata** channel,
+                      int timeout,
+                      int tries
 )
 {
+   if(*channel)
+   {
+#if !defined(USE_CARES)
+      ares_destroy_suppress_callbacks(*channel);
+#else
+      // Callbacks will be supressed by looking for the ARES_EDESTRUCTION
+      // sentinel status
+      ares_destroy(*channel);
+#endif
+      *channel = 0;
+   }
+
+#if !defined(USE_CARES)
+
 #ifdef USE_IPV6
    int requiredCap = ARES_CAP_IPV6;
 #else
    int requiredCap = 0;
 #endif
 
-	if(*channel)
-	{
-		ares_destroy_suppress_callbacks(*channel);
-		*channel = 0;
-	}
-
-
+   // 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_CARES)
+   // 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_CARES)
       status = ares_init_options_with_socket_function(channel, &opt, optmask, socketfunc);
+#else
+      // TODO: Does the socket function matter?
+      status = ares_init_options(channel, &opt, optmask);
+#endif
    }
    else
    { 
@@ -127,68 +148,182 @@
          opt.servers[i] = additionalNameservers[i].v4Address.sin_addr;
       }
 #endif
+
+#if !defined(USE_CARES)
       status = ares_init_options_with_socket_function(channel, &opt, optmask, socketfunc);
+#else
+      // TODO: Does the socket function matter?
+      status = ares_init_options(channel, &opt, optmask);
+#endif
+      
       delete [] opt.servers;
       opt.servers = 0;
    }
-	if (status != ARES_SUCCESS)
+   if (status != ARES_SUCCESS)
    {
       ErrLog (<< "Failed to initialize DNS library (status=" << status << ")");
       return status;
    }
    else
    {
+
+#if !defined(USE_CARES)
+      
       InfoLog(<< "DNS initialization: found  " << (*channel)->nservers << " name servers");
       for (int i = 0; i < (*channel)->nservers; ++i)
       {
          InfoLog(<< " name server: " << DnsUtil::inet_ntop((*channel)->servers[i].addr));
+      } 
+
+#else
+      {
+         // 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
+
+#if !defined(USE_CARES)
+      // In ares, we must manipulate these directly
+      if (timeout > 0)
+      {
+         mChannel->timeout = timeout;
+      }
+      
+      if (tries > 0)
+      {
+         mChannel->tries = tries;
       }
+#endif
+      
       return Success;      
    }
 }
 
 bool AresDns::checkDnsChange()
 {
-	//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)
-	{
-		bRet = true;
-	}
-	else if(channel->nservers != mChannel->nservers)
-	{
-		bRet = true;
-	}
-	else
-	{
-		for (int i = 0; i < mChannel->nservers; i++)
-		{
-			if (channel->servers[i].addr.s_addr != mChannel->servers[i].addr.s_addr)
-			{
-				bRet = true;
-				break;
-			}
-		}
-	}
-	ares_destroy_suppress_callbacks(channel);
-
-	if(!bRet)
-	{
-		InfoLog(<< " No changes in DNS server list");
-	}
-	else
-	{
-		InfoLog(<< " DNS server list changed");
-	}
+   // 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_CARES)
+   {
+      // 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);
+   }
+#else
+   {
+      // 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;
+               }
+            }
+         }
 
-	return bRet;
+         // 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;
 }
 
 AresDns::~AresDns()
 {
+#if !defined(USE_CARES)
    ares_destroy_suppress_callbacks(mChannel);
+#else
+   ares_destroy(mChannel);
+#endif
 }
 
 bool AresDns::hostFileLookup(const char* target, in_addr &addr)
@@ -196,7 +311,15 @@
    assert(target);
 
    hostent *hostdata = 0;
-   int status = hostfile_lookup(target, &hostdata);
+
+   // Look this up
+   int status = 
+#if !defined(USE_CARES)
+     hostfile_lookup(target, &hostdata)
+#else
+     ares_gethostbyname_file(mChannel, target, AF_INET, &hostdata)
+#endif
+     ;
 
    if (status != ARES_SUCCESS)
    {
@@ -273,17 +396,39 @@
 void
 AresDns::lookup(const char* target, unsigned short type, ExternalDnsHandler* handler, void* userData)
 {
-   ares_query(mChannel, target, C_IN, type, AresDns::aresCallback, new Payload(handler, userData));
+   ares_query(mChannel, target, C_IN, type,
+#if !defined(USE_CARES)
+              aresCallback,
+#else
+              caresCallback,
+#endif
+              new Payload(handler, userData));
 }
 
 void
 AresDns::aresCallback(void *arg, int status, unsigned char *abuf, int alen)
 {
+#if defined(USE_CARES)
+   // If this is destruction, skip it.  We do this here for completeness.
+   if(status == ARES_EDESTRUCTION)
+   {
+      return;
+   }
+#endif
+   
    getHandler(arg)->handleDnsRaw(makeRawResult(arg, status, abuf, alen));
    Payload* p = reinterpret_cast<Payload*>(arg);
    delete p;
 }
 
+void
+AresDns::caresCallback(void *arg, int status, int timeouts,
+                       unsigned char *abuf, int alen)
+{
+   // Simply ignore the timeouts argument
+   return AresDns::aresCallback(arg, status, abuf, alen);
+}
+
 /* ====================================================================
  * The Vovida Software License, Version 1.0 
  * 
diff -ur orig/rutil/dns/AresDns.hxx resiprocate-1.4.1/rutil/dns/AresDns.hxx
--- orig/rutil/dns/AresDns.hxx	2008-08-15 17:59:01.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/AresDns.hxx	2008-11-18 23:44:00.000000000 -0400
@@ -22,8 +22,8 @@
       virtual int init(const std::vector<GenericIPAddress>& additionalNameservers,
                        AfterSocketCreationFuncPtr socketfunc, int timeout=0, int tries=0, unsigned int features=0); 
 
-      virtual int internalInit(const std::vector<GenericIPAddress>& additionalNameservers,
-                       AfterSocketCreationFuncPtr socketfunc, unsigned int features=0, ares_channeldata** channel = 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();
 
@@ -47,6 +47,7 @@
       static ExternalDnsRawResult makeRawResult(void *arg, int status, unsigned char *abuf, int alen);
       static ExternalDnsHandler* getHandler(void* arg);
       static void aresCallback(void *arg, int status, unsigned char* abuf, int alen);
+      static void caresCallback(void *arg, int status, int timeouts, unsigned char* abuf, int alen);
 	  struct ares_channeldata* mChannel;
 	  std::vector<GenericIPAddress> mAdditionalNameservers;
 	  unsigned int mFeatures;
diff -ur orig/rutil/dns/DnsAAAARecord.cxx resiprocate-1.4.1/rutil/dns/DnsAAAARecord.cxx
--- orig/rutil/dns/DnsAAAARecord.cxx	2008-09-23 05:30:37.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/DnsAAAARecord.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -2,10 +2,7 @@
 #include "rutil/config.hxx"
 #endif
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "AresCompat.hxx"
 
 #ifndef __CYGWIN__
 #ifndef RRFIXEDSZ
diff -ur orig/rutil/dns/DnsCnameRecord.cxx resiprocate-1.4.1/rutil/dns/DnsCnameRecord.cxx
--- orig/rutil/dns/DnsCnameRecord.cxx	2008-07-25 17:54:42.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/DnsCnameRecord.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -4,10 +4,7 @@
 
 #include <stdlib.h>
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "AresCompat.hxx"
 
 #ifndef __CYGWIN__
 #ifndef RRFIXEDSZ
@@ -26,7 +23,7 @@
 DnsCnameRecord::DnsCnameRecord(const RROverlay& overlay)
 {
    char* name = 0;
-   int len = 0;
+   ares_length_type len = 0;
    if (ARES_SUCCESS != ares_expand_name(overlay.data()-overlay.nameLength()-RRFIXEDSZ, overlay.msg(), overlay.msgLength(), &name, &len))
    {
       throw CnameException("Failed parse of CNAME record", __FILE__, __LINE__);
diff -ur orig/rutil/dns/DnsHostRecord.cxx resiprocate-1.4.1/rutil/dns/DnsHostRecord.cxx
--- orig/rutil/dns/DnsHostRecord.cxx	2008-07-25 17:54:42.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/DnsHostRecord.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -4,10 +4,7 @@
 
 #include <stdlib.h>
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "AresCompat.hxx"
 
 #ifndef __CYGWIN__
 #ifndef RRFIXEDSZ
@@ -27,7 +24,7 @@
 DnsHostRecord::DnsHostRecord(const RROverlay& overlay)
 {
    char* name = 0;
-   int len = 0;
+   ares_length_type len = 0;
    ares_expand_name(overlay.data()-overlay.nameLength()-RRFIXEDSZ, overlay.msg(), overlay.msgLength(), &name, &len);
    mName = name;
    free(name);
diff -ur orig/rutil/dns/DnsNaptrRecord.cxx resiprocate-1.4.1/rutil/dns/DnsNaptrRecord.cxx
--- orig/rutil/dns/DnsNaptrRecord.cxx	2008-07-25 17:54:42.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/DnsNaptrRecord.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -4,10 +4,7 @@
 
 #include <stdlib.h>
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "AresCompat.hxx"
 
 #ifndef __CYGWIN__
 #ifndef RRFIXEDSZ
@@ -92,11 +89,10 @@
    return mReplacement;
 }
 
-
 DnsNaptrRecord::DnsNaptrRecord(const RROverlay& overlay)
 {
    char* name = 0;
-   int len = 0;
+   ares_length_type len = 0;
    if (ARES_SUCCESS != ares_expand_name(overlay.data()-overlay.nameLength()-RRFIXEDSZ, overlay.msg(), overlay.msgLength(), &name, &len))
    {
       throw NaptrException("Failed parse of NAPTR record", __FILE__, __LINE__);
diff -ur orig/rutil/dns/DnsSrvRecord.cxx resiprocate-1.4.1/rutil/dns/DnsSrvRecord.cxx
--- orig/rutil/dns/DnsSrvRecord.cxx	2008-07-25 17:54:42.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/DnsSrvRecord.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -4,10 +4,7 @@
 
 #include <stdlib.h>
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "AresCompat.hxx"
 
 #ifndef __CYGWIN__
 #ifndef RRFIXEDSZ
@@ -26,7 +23,7 @@
 DnsSrvRecord::DnsSrvRecord(const RROverlay& overlay)
 {
    char* name = 0;
-   int len = 0;
+   ares_length_type len = 0;
    if (ARES_SUCCESS != ares_expand_name(overlay.data()-overlay.nameLength()-RRFIXEDSZ, overlay.msg(), overlay.msgLength(), &name, &len))
    {
       throw SrvException("Failed parse of SRV record", __FILE__, __LINE__);
diff -ur orig/rutil/dns/DnsStub.cxx resiprocate-1.4.1/rutil/dns/DnsStub.cxx
--- orig/rutil/dns/DnsStub.cxx	2008-09-23 05:30:37.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/DnsStub.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -6,10 +6,7 @@
 #include <vector>
 #include <cassert>
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "AresCompat.hxx"
 
 #ifndef WIN32
 #ifndef __CYGWIN__
@@ -232,7 +229,7 @@
 {
    char *name=0;
    int status=0;
-   int len=0;
+   ares_length_type len = 0;
    
    // Parse the question name. 
    status = ares_expand_name(aptr, abuf, alen, &name, &len);
@@ -289,7 +286,12 @@
 {
    const unsigned char* rptr = aptr;
    char* name = 0;
+#if !defined(USE_CARES)
    int len = 0;
+#else
+   long len = 0;
+#endif
+   
    int status = ares_expand_name(aptr, abuf, alen, &name, &len);
    if (ARES_SUCCESS != status)
    {
@@ -595,7 +597,11 @@
    bDeleteThis = true;
 
    char* name = 0;
+#if !defined(USE_CARES)
    int len = 0;
+#else
+   long len = 0;
+#endif
 
    if (ARES_SUCCESS != ares_expand_name(aptr, abuf, alen, &name, &len))
    {
diff -ur orig/rutil/dns/LocalDns.cxx resiprocate-1.4.1/rutil/dns/LocalDns.cxx
--- orig/rutil/dns/LocalDns.cxx	2006-02-16 19:58:28.000000000 -0400
+++ resiprocate-1.4.1/rutil/dns/LocalDns.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -6,9 +6,7 @@
 #include "ares.h"
 #include "ares_dns.h"
 
-#if !defined(USE_ARES)
-#error Must have ARES
-#endif
+#include "AresCompat.hxx"
 
 #if !defined(WIN32)
 #include <arpa/nameser.h>
diff -ur orig/rutil/dns/RRCache.cxx resiprocate-1.4.1/rutil/dns/RRCache.cxx
--- orig/rutil/dns/RRCache.cxx	2008-01-18 18:08:13.000000000 -0400
+++ resiprocate-1.4.1/rutil/dns/RRCache.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -2,8 +2,7 @@
 #include "rutil/config.hxx"
 #endif
 
-#include "ares.h"
-#include "ares_dns.h"
+#include "AresCompat.hxx"
 
 #ifndef WIN32
 #include <sys/types.h>
@@ -211,7 +210,7 @@
    // overlay is a soa answer.
    if (overlay.type() != T_SOA) return -1;
    char* name = 0;
-   int len = 0;
+   ares_length_type len = 0;
    ares_expand_name(overlay.data(), overlay.msg(), overlay.msgLength(), &name, &len);
    const unsigned char* pPos = overlay.data() + len;
    free(name);
diff -ur orig/rutil/dns/RROverlay.cxx resiprocate-1.4.1/rutil/dns/RROverlay.cxx
--- orig/rutil/dns/RROverlay.cxx	2007-05-04 21:40:47.000000000 -0300
+++ resiprocate-1.4.1/rutil/dns/RROverlay.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -2,10 +2,7 @@
 #include "rutil/config.hxx"
 #endif
 
-#if defined(USE_ARES)
-#include "ares.h"
-#include "ares_dns.h"
-#endif
+#include "AresCompat.hxx"
 
 #ifndef __CYGWIN__
 #ifndef RRFIXEDSZ
@@ -38,7 +35,7 @@
    mType(-1)
 {
    char *name;
-   int len = 0;
+   ares_length_type len = 0;
 
    // Parse the RR name. 
    int status = ares_expand_name(aptr, abuf, alen, &name, &len);
diff -ur orig/rutil/dns/RRVip.cxx resiprocate-1.4.1/rutil/dns/RRVip.cxx
--- orig/rutil/dns/RRVip.cxx	2006-02-16 19:58:28.000000000 -0400
+++ resiprocate-1.4.1/rutil/dns/RRVip.cxx	2008-11-18 23:44:00.000000000 -0400
@@ -2,8 +2,7 @@
 #include "rutil/config.hxx"
 #endif
 
-#include "ares.h"
-#include "ares_dns.h"
+#include "AresCompat.hxx"
 
 #include <map>
 #include <list>
--- /dev/null	2008-11-16 13:32:59.720045000 -0400
+++ resiprocate-1.4.1/rutil/dns/AresCompat.hxx	2008-11-18 23:44:00.000000000 -0400
@@ -0,0 +1,97 @@
+#if !defined(RESIP_ARES_COMPAT_HXX)
+#define RESIP_ARES_COMPAT_HXX
+
+// This header hides some of the differences between contrib/ares and c-ares
+//
+// GOTCHA: This must only be included from .cxx files.  Ideally, it would only
+// be included from .cxx files inside this directory, but there is some
+// leakage at the moment :(
+
+#if defined(USE_ARES)
+#  include "ares.h"
+#  include "ares_dns.h"
+#  include "ares_private.h"
+#elif defined(USE_CARES)
+#  include "ares.h"
+#  include "ares_version.h"
+#else
+#  error Must have ARES or C-ARES
+#endif
+
+// These are not part of the c-ares API, but are used by this library
+#if !defined(DNS__16BIT)
+#  define DNS__16BIT(p)             (((p)[0] << 8) | (p)[1])   
+#  define DNS__32BIT(p)		    (((p)[0] << 24) | ((p)[1] << 16) | \
+				      ((p)[2] << 8) | (p)[3])
+#  define DNS_HEADER_QDCOUNT(h)     DNS__16BIT((h) + 4)
+#  define DNS_HEADER_ANCOUNT(h)     DNS__16BIT((h) + 6)
+#  define DNS_HEADER_NSCOUNT(h)     DNS__16BIT((h) + 8)
+#  define DNS_HEADER_ARCOUNT(h)     DNS__16BIT((h) + 10)
+#  define DNS_RR_TYPE(r)            DNS__16BIT(r)
+#  define DNS_RR_LEN(r)             DNS__16BIT((r) + 8)
+#  define DNS_RR_TTL(r)             DNS__32BIT((r) + 4)
+#endif
+
+namespace resip
+{
+  // To avoid #ifdefs on every call to ares_expand_name() and so on, we define
+  // the type that is used to return lengths from that function.  This can be
+  // int or long.
+#if !defined(USE_CARES)
+  typedef int ares_length_type;
+#else
+  typedef long ares_length_type;
+#endif
+}
+
+#endif
+
+/* ====================================================================
+ * The Vovida Software License, Version 1.0 
+ * 
+ * Copyright (c) 2000-2005 Vovida Networks, Inc.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The names "VOCAL", "Vovida Open Communication Application Library",
+ *    and "Vovida Open Communication Application Library (VOCAL)" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact vocal@xxxxxxxxxxx
+ *
+ * 4. Products derived from this software may not be called "VOCAL", nor
+ *    may "VOCAL" appear in their name, without prior written
+ *    permission of Vovida Networks, Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
+ * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
+ * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by Vovida
+ * Networks, Inc. and many individuals on behalf of Vovida Networks,
+ * Inc.  For more information on Vovida Networks, Inc., please see
+ * <http://www.vovida.org/>.
+ *
+ */
--- resiprocate-1.4.1/rutil/dns/DnsAAAARecord.cxx~	2008-11-22 15:43:27.000000000 -0400
+++ resiprocate-1.4.1/rutil/dns/DnsAAAARecord.cxx	2008-11-22 16:03:40.000000000 -0400
@@ -26,7 +26,7 @@
 {
 #ifdef USE_IPV6
    char* name = 0;
-   int len = 0;
+   ares_length_type len = 0;
    ares_expand_name(overlay.data()-overlay.nameLength()-RRFIXEDSZ, overlay.msg(), overlay.msgLength(), &name, &len);
    mName = name;
    free(name);
--- resiprocate-1.4.1/rutil/dns/AresDns.cxx~	2008-11-22 15:43:27.000000000 -0400
+++ resiprocate-1.4.1/rutil/dns/AresDns.cxx	2008-11-22 16:02:57.000000000 -0400
@@ -126,7 +126,9 @@
       optmask |= ARES_OPT_SERVERS;
       opt.nservers = additionalNameservers.size();
       
-#ifdef USE_IPV6
+#if defined(USE_IPV6) && !defined(USE_CARES)
+      // 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++)
       {
@@ -142,10 +144,25 @@
          }                  
       }
 #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++)
       {
-         opt.servers[i] = additionalNameservers[i].v4Address.sin_addr;
+         if(additionalNameservers[i].isVersion4()) 
+         {
+            opt.servers[i] = additionalNameservers[i].v4Address.sin_addr;
+         }
+         else
+         {
+           WarningLog (<< "Ignoring non-IPv4 additional name server "
+#if !defined(USE_CARES)
+                       "(not yet supported with c-ares)"
+#else
+                       "(IPv6 support was not enabled)"
+#endif
+                       );
+         }
       }
 #endif
 

Attachment: signature.asc
Description: Digital signature