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

Re: [reSIProcate-users] DNS timeout bug in 1.9.x


Sorry for my mistake, the details is:

I have modified the "static int init_by_defaults_windows_nameservers_getadaptersaddresses" function in 1.9.x then got the issue fixed, the new code is below(in nit_by_defaults_windows_nameservers_getadaptersaddresses function, it called  "get_physical_address" function):


/*
 * V4. Get the physical address of the first NIC whose list of DNS servers contain 'addr'.
 * return: ARES_SUCCESS, etc.
 */
static int get_physical_address(char *physicalAddr, int physicalAddrBufSz, int* physAddrLen, struct in_addr addr)
{
#ifdef WIN32
  DWORD (WINAPI * GetAdaptersAddressesProc)(ULONG, DWORD, VOID *, IP_ADAPTER_ADDRESSES *, ULONG *);
  HANDLE hLib = 0;
  DWORD dwRet = ERROR_BUFFER_OVERFLOW;
  DWORD dwSize = 0;
  IP_ADAPTER_ADDRESSES *pAdapterAddresses = 0;
  int rc = ARES_ENOTFOUND;

  memset(physicalAddr, '\0', physicalAddrBufSz);
  *physAddrLen = 0;

  hLib = LoadLibrary(TEXT("iphlpapi.dll"));
  if (!hLib)
    return ARES_ENOTIMP;

  (void*)GetAdaptersAddressesProc = GetProcAddress(hLib, TEXT("GetAdaptersAddresses"));
  if(!GetAdaptersAddressesProc)
  {
    rc = ARES_ENOTIMP;
    goto cleanup;
  }

  // Getting buffer size, expects overflow error
  dwRet = (*GetAdaptersAddressesProc)(AF_UNSPEC, 0, NULL, NULL, &dwSize);
  assert(dwRet == ERROR_BUFFER_OVERFLOW);
  if (dwRet == ERROR_BUFFER_OVERFLOW)
  {
    pAdapterAddresses = (IP_ADAPTER_ADDRESSES *) LocalAlloc(LMEM_ZEROINIT, dwSize);
    if (! pAdapterAddresses)
    {
      rc = ARES_ENOMEM;
      goto cleanup;
    }
  }
  else
  {
    rc = ARES_ENODATA;
    goto cleanup;
  }

  dwRet = (*GetAdaptersAddressesProc)(AF_UNSPEC, 0, NULL, pAdapterAddresses, &dwSize);
  if (dwRet != ERROR_SUCCESS)
  {
    rc = ARES_ENODATA;
    goto cleanup;
  }

  {
    IP_ADAPTER_ADDRESSES * AI = NULL;
    for (AI = pAdapterAddresses; AI != NULL; AI = AI->Next)
    {
      PIP_ADAPTER_DNS_SERVER_ADDRESS dnsServers = AI->FirstDnsServerAddress;
      // find 'addr' in adapter's list of dns servers.
      for (; dnsServers; dnsServers = dnsServers->Next)
      {
        if (! dnsServers->Address.lpSockaddr)
          continue;

        if (dnsServers->Address.lpSockaddr->sa_family == AF_INET)
        {
          struct sockaddr_in sockAddr = *(struct sockaddr_in*)(dnsServers->Address.lpSockaddr);
          if (memcmp(&addr, &sockAddr.sin_addr.s_addr, sizeof(struct in_addr)) == 0)
          {
            *physAddrLen = AI->PhysicalAddressLength;
            if (*physAddrLen > physicalAddrBufSz)
              *physAddrLen = physicalAddrBufSz;
            memcpy(physicalAddr, &AI->PhysicalAddress[0], *physAddrLen);
            rc = ARES_SUCCESS;
            goto cleanup;
          }
        }
      }
    }
  }
  rc = ARES_ENOTFOUND;

cleanup:
  if (hLib)
    FreeLibrary(hLib);
  if (pAdapterAddresses)
    LocalFree(pAdapterAddresses);
  return rc;
#else // WIN32
  return ARES_ENOTIMP;
#endif // WIN32
}

#ifdef WIN32
static int init_by_defaults_windows_nameservers_getadaptersaddresses(ares_channel channel)
{
     /*
      * Way of getting nameservers that should work on all Windows from 98 on.
      */
      FIXED_INFO *     FixedInfo;
      ULONG            ulOutBufLen;
      DWORD            dwRetVal;
      IP_ADDR_STRING * pIPAddr;
 HANDLE           hLib;
 int num;
 DWORD (WINAPI *GetNetworkParams)(FIXED_INFO*, DWORD*); 

 hLib = LoadLibrary(TEXT("iphlpapi.dll"));
 if(!hLib)
 {
 return ARES_ENOTIMP;
 }

 (void*)GetNetworkParams = GetProcAddress(hLib, TEXT("GetNetworkParams"));
 if(!GetNetworkParams)
 {
 FreeLibrary(hLib);
 return ARES_ENOTIMP;
 }
      //printf("ARES: figuring out DNS servers\n");
      FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );
      ulOutBufLen = sizeof( FIXED_INFO );

      if( ERROR_BUFFER_OVERFLOW == (*GetNetworkParams)( FixedInfo, &ulOutBufLen ) ) 
 {
        GlobalFree( FixedInfo );
        FixedInfo = (FIXED_INFO *)GlobalAlloc( GPTR, ulOutBufLen );
      }

      if ( dwRetVal = (*GetNetworkParams)( FixedInfo, &ulOutBufLen ) )
      {
        //printf("ARES: couldn't get network params\n");
        GlobalFree( FixedInfo );
     FreeLibrary(hLib);
        return ARES_ENODATA;
      }
      else
      {
       /**
        printf( "Host Name: %s\n", FixedInfo -> HostName );
        printf( "Domain Name: %s\n", FixedInfo -> DomainName );
        printf( "DNS Servers:\n" );
        printf( "\t%s\n", FixedInfo -> DnsServerList.IpAddress.String );
        **/

        // Count how many nameserver entries we have and allocate memory for them.
        num = 0;
        pIPAddr = &FixedInfo->DnsServerList;     
        while ( pIPAddr && strlen(pIPAddr->IpAddress.String) > 0)
        {
          num++;
          pIPAddr = pIPAddr ->Next;
        }
        if(num>0)
        {
           channel->servers = malloc( (num) * sizeof(struct server_state));
  if (!channel->servers)
  {
          GlobalFree( FixedInfo );
        FreeLibrary(hLib);
  return ARES_ENOMEM;
  }
           memset(channel->servers, '\0', num * sizeof(struct server_state));

  channel->nservers = 0;
           pIPAddr = &FixedInfo->DnsServerList;   
           while ( pIPAddr && strlen(pIPAddr->IpAddress.String) > 0)
  {
             struct in_addr addr;
             addr.s_addr = inet_addr(pIPAddr->IpAddress.String);
             // append unique only
             if (find_server(channel->servers, channel->nservers, addr) == -1)
             {
                // printf( "ARES: %s\n", pIPAddr ->IpAddress.String );
#ifdef USE_IPV6  
                channel->servers[ channel->nservers ].family = AF_INET;
#endif
                channel->servers[channel->nservers].addr = addr;
                if ((channel->flags & ARES_FLAG_TRY_NEXT_SERVER_ON_RCODE3))
                {
                   get_physical_address(channel->servers[channel->nservers].physical_addr,
                                        MAX_ADAPTER_ADDRESS_LENGTH,
                                        &channel->servers[channel->nservers].physical_addr_len,
                                        addr);
                }
      channel->nservers++;
             }

             pIPAddr = pIPAddr ->Next;
           }
           //printf("ARES: got all %d nameservers\n",num);
        }
        else
        {
    /* If no specified servers, try a local named. */
  channel->servers = malloc(sizeof(struct server_state));
  if (!channel->servers)
              return ARES_ENOMEM;
           memset(channel->servers, '\0', sizeof(struct server_state));

#ifdef USE_IPV6  
           channel->servers[0].family = AF_INET;
#endif

  channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK);
           channel->servers[0].default_localhost_server = 1;
  channel->nservers = 1;
        }

        GlobalFree( FixedInfo );
   FreeLibrary(hLib);
 }
 return ARES_SUCCESS;
}


On Wed, Feb 26, 2014 at 3:11 PM, Herbert Karajan <boost.regex@xxxxxxxxx> wrote:
I have more stuff here:

in ares_init.c file, if replace the function 

"#ifdef WIN32
static int init_by_defaults_windows_nameservers_getadaptersaddresses(ares_channel channel)" in 1.9.x by same function which is in 1.8.x, then get it works, the issue disappear.

Best regards,




On Tue, Feb 25, 2014 at 11:15 PM, Herbert Karajan <boost.regex@xxxxxxxxx> wrote:
Note: I'm using the Win 8 and VC++9


On Tue, Feb 25, 2014 at 11:12 PM, Herbert Karajan <boost.regex@xxxxxxxxx> wrote:
Hi Scott, attached the 1.8.5 log,

I'm use the stackThread class as below:

mStackThread(mStack);
mStackThread.run();


I also created a DUM thread in my application:


void DumThread::thread()
{
while(!ThreadIf::isShutdown())
{
Lock lock(mDumMutex);
while (true)
{
if (!mDum.process())
{
break;
}
}
}
}



On Tue, Feb 25, 2014 at 10:52 PM, Scott Godin <sgodin@xxxxxxxxxxxxxxx> wrote:
To help speed up the investigation, can you post the log file when trying with 1.8.x?  What OS/platform are you using?   Can you also post your stack/dum processing loop (are you using EventStackThread or the old buildFdSet/process mechanism?

Thanks,
Scott


On Tue, Feb 25, 2014 at 4:50 AM, Herbert Karajan <boost.regex@xxxxxxxxx> wrote:
Hi, I got a "503 DNS timeout" error after I update my application to resip 1.9.0 and  1.9.1, it works fine after converted back to 1.8.x.

Please find attached the log file.

_______________________________________________
resiprocate-users mailing list
resiprocate-users@xxxxxxxxxxxxxxx
List Archive: http://list.resiprocate.org/archive/resiprocate-users/