⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dnsresult.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
      {
         assert(mCurrResultPath.size()<=2);
         Item top;
         if (!mCurrResultPath.empty())
         {
            top = mCurrResultPath.top();
            if (top.rrType == T_SRV)
            {
               vector<Data> records;
               records.push_back(top.value);
               mDns.blacklist(top.domain, top.rrType, Protocol::Sip, records);
               mCurrResultPath.pop();
            }
            else
            {
               assert(top.rrType==T_NAPTR);
            }
         }

         while (!mCurrSuccessPath.empty())
         {
            top = mCurrSuccessPath.top();
            if (top.rrType != T_NAPTR)
            {
               mCurrSuccessPath.pop();
            }
            else
            {
               break;
            }
         }
         top.domain = next.key;
         top.rrType = T_SRV;
         top.value = next.target + ":" + Data(next.port);
         mCurrResultPath.push(top);
         mCurrSuccessPath.push(top);
         lookupHost(next.target);
      }
      else
      {
         assert(0);
         if (mHandler) mHandler->handle(this);
      }
      // don't call primeResults since we need to wait for the response to
      // AAAA/A query first
   }
   else
   {
      bool changed = (mType == Pending);
      transition(Finished);
      if (!mCurrResultPath.empty())
      {
         assert(mCurrResultPath.size()<=2);
         while (!mCurrResultPath.empty())
         {
            Item top = mCurrResultPath.top();
            vector<Data> records;
            records.push_back(top.value);
            mDns.blacklist(top.domain, top.rrType, Protocol::Sip, records);
            mCurrResultPath.pop();
         }
      }
      if (changed && mHandler) mHandler->handle(this);
   }

   // Either we are finished or there are results primed
   //assert(mType == Finished ||        // !slg! handle() might end up destroying the DnsResult - so we can't safely do this assert
   //       mType == Pending || 
   //       (mType == Available && !mResults.empty())
   //   );
}

// implement the selection algorithm from rfc2782 (SRV records)
DnsResult::SRV 
DnsResult::retrieveSRV()
{
    // !ah! if mTransport is known -- should we ignore those that don't match?!
   assert(!mSRVResults.empty());

   const SRV& srv = *mSRVResults.begin();
   if (srv.cumulativeWeight == 0)
   {
      int priority = srv.priority;
   
     mCumulativeWeight=0;
      //!dcm! -- this should be fixed properly; TCP req. lines were being sent
      //out on UDP
      TransportType transport = mSRVResults.begin()->transport;      
      for (std::vector<SRV>::iterator i=mSRVResults.begin(); 
           i!=mSRVResults.end() 
              && i->priority == priority 
              && i->transport == transport; i++)
      {
         mCumulativeWeight += i->weight;
         i->cumulativeWeight = mCumulativeWeight;
      }
   }
   
   int selected = Random::getRandom() % (mCumulativeWeight+1);

   StackLog (<< "cumulative weight = " << mCumulativeWeight << " selected=" << selected);

   std::vector<SRV>::iterator i;
   for (i=mSRVResults.begin(); i!=mSRVResults.end(); i++)
   {
      if (i->cumulativeWeight >= selected)
      {
         break;
      }
   }
   
   if (i == mSRVResults.end())
   {
      InfoLog (<< "SRV Results problem selected=" << selected << " cum=" << mCumulativeWeight);
   }
   assert(i != mSRVResults.end());
   SRV next = *i;
   mCumulativeWeight -= next.cumulativeWeight;
   mSRVResults.erase(i);
   
   StackLog (<< "SRV: " << Inserter(mSRVResults));

   return next;
}

// adapted from the adig.c example in ares
const unsigned char* 
DnsResult::skipDNSQuestion(const unsigned char *aptr,
                           const unsigned char *abuf,
                           int alen)
{
   char *name=0;
   int status=0;
   int len=0;
   
   // Parse the question name. 
   status = ares_expand_name(aptr, abuf, alen, &name, &len);
   if (status != ARES_SUCCESS)
   {
      StackLog (<< "Failed parse of RR");
      return NULL;
   }
   aptr += len;

   // Make sure there's enough data after the name for the fixed part
   // of the question.
   if (aptr + QFIXEDSZ > abuf + alen)
   {
      free(name);
      StackLog (<< "Failed parse of RR");
      return NULL;
   }

   // Parse the question type and class. 
   //int type = DNS_QUESTION_TYPE(aptr);
   //int dnsclass = DNS_QUESTION_CLASS(aptr);
   aptr += QFIXEDSZ;
   
   free(name);
   return aptr;
}

DnsResult::NAPTR::NAPTR() : order(0), pref(0)
{
}

bool 
DnsResult::NAPTR::operator<(const DnsResult::NAPTR& rhs) const
{
   if (key.empty()) // default value
   {
      return false;
   }
   else if (rhs.key.empty()) // default value
   {
      return true;
   }
   else if (order < rhs.order)
   {
      return true;
   }
   else if (order == rhs.order)
   {
      if (pref < rhs.pref)
      {
         return true;
      }
      else if (pref == rhs.pref)
      {
         return replacement < rhs.replacement;
      }
   }
   return false;
}

DnsResult::SRV::SRV() : priority(0), weight(0), cumulativeWeight(0), port(0)
{
}

bool 
DnsResult::SRV::operator<(const DnsResult::SRV& rhs) const
{
   if (transport < rhs.transport)
   {
      return true;
   }
   else if (transport == rhs.transport)
   {
      if (priority < rhs.priority)
      {
         return true;
      }
      else if (priority == rhs.priority)
      {
         if (weight < rhs.weight)
         {
            return true;
         }
         else if (weight == rhs.weight)
         {
            if (target < rhs.target)
            {
               return true;
            }
         }
      }
   }
   return false;
}

void DnsResult::onDnsResult(const DNSResult<DnsHostRecord>& result)
{
   if (!mInterface.isSupported(mTransport, V4) && !mInterface.isSupported(mTransport, V6))
   {
      return;
   }
   StackLog (<< "Received dns result for: " << mTarget);
   StackLog (<< "DnsResult::onDnsResult() " << result.status);
   
   // This function assumes that the A query that caused this callback
   // is the _only_ outstanding DNS query that might result in a
   // callback into this function
   if ( mType == Destroyed )
   {
      destroy();
      return;
   }

   if (result.status == 0)
   {
      for (vector<DnsHostRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
      {
         in_addr addr;
         addr.s_addr = (*it).addr().s_addr;
         Tuple tuple(addr, mPort, mTransport, mTarget);
         StackLog (<< "Adding " << tuple << " to result set");
         mResults.push_back(tuple);
      }
   }
   else
   {
      StackLog (<< "Failed async A query: " << result.msg);
   }

   if (mSRVCount == 0)
   {
      bool changed = (mType == Pending);
      if (mResults.empty())
      {
#ifdef WIN32_SYNCRONOUS_RESOLUTION_ON_ARES_FAILURE
         // Try Windows Name Resolution (not asyncronous)
         WSAQUERYSET QuerySet = { 0 };
	     GUID guidServiceTypeUDP = SVCID_UDP(mPort);
	     GUID guidServiceTypeTCP = SVCID_TCP(mPort);
         HANDLE hQuery;
         QuerySet.dwSize = sizeof(WSAQUERYSET);
         QuerySet.lpServiceClassId = mTransport == UDP ? &guidServiceTypeUDP : &guidServiceTypeTCP;
         QuerySet.dwNameSpace = NS_ALL;
         QuerySet.lpszServiceInstanceName = (char *)mTarget.c_str();
         if(WSALookupServiceBegin(&QuerySet, LUP_RETURN_ADDR, &hQuery) == 0)
         {
             DWORD dwQuerySize = 256;   // Starting size
             int iRet = 0;
             bool fDone = false;
             LPWSAQUERYSET pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize];
             while(iRet == 0 && pQueryResult)
             {
                iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
                if(pQueryResult && iRet == -1 && GetLastError() == WSAEFAULT)
                {
                   delete [] pQueryResult;
                   pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize]; // Re-allocate new size
                   iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
                }
                if(pQueryResult && iRet == 0)
                {
                   for(DWORD i = 0; i < pQueryResult->dwNumberOfCsAddrs; i++)
                   {
     	              SOCKADDR_IN *pSockAddrIn = (SOCKADDR_IN *)pQueryResult->lpcsaBuffer[i].RemoteAddr.lpSockaddr;
                      Tuple tuple(pSockAddrIn->sin_addr, mPort, mTransport, mTarget);
                      StackLog (<< "Adding (WIN) " << tuple << " to result set");
                      mResults.push_back(tuple);
                      mType = Available;
                   }
                }
             }
             delete [] pQueryResult;
             WSALookupServiceEnd(hQuery);
         }
         if(mResults.empty())
         {
            mType = Finished; 
         }
#else
         mType = Finished; 
#endif
         clearCurrPath();
      }
      else 
      {
         if (mSRVResults.empty())
         {
            transition(Available);
         }
         else
         {
            mType = Available;
         }
         addToPath(mResults);
      }
      if (changed && mHandler) mHandler->handle(this);
   }
}

#ifdef USE_IPV6
void DnsResult::onDnsResult(const DNSResult<DnsAAAARecord>& result)
{
   StackLog (<< "Received AAAA result for: " << mTarget);
   if (!mInterface.isSupported(mTransport, V6))
   {
      return;
   }
   StackLog (<< "DnsResult::onDnsResult() " << result.status);
   assert(mInterface.isSupported(mTransport, V6));

   // This function assumes that the AAAA query that caused this callback
   // is the _only_ outstanding DNS query that might result in a
   // callback into this function
   if ( mType == Destroyed )
   {
      destroy();
      return;
   }

   if (result.status == 0)
   {
      for (vector<DnsAAAARecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
      {
         Tuple tuple((*it).v6Address(), mPort, mTransport, mTarget);
         StackLog (<< "Adding " << tuple << " to result set");
         mResults.push_back(tuple);
      }
   }
   else
   {
      StackLog (<< "Failed async AAAA query: " << result.msg);
   }
   // funnel through to host processing
   mDns.lookup<RR_A>(mPassHostFromAAAAtoA, Protocol::Sip, this);

}
#endif

void DnsResult::onDnsResult(const DNSResult<DnsSrvRecord>& result)
{
   StackLog (<< "Received SRV result for: " << mTarget);
   assert(mSRVCount>=0);
   mSRVCount--;
   StackLog (<< "DnsResult::onDnsResult() " << mSRVCount << " status=" << result.status);

   // There could be multiple SRV queries outstanding, but there will be no
   // other DNS queries outstanding that might cause a callback into this
   // object.
   if (mType == Destroyed && mSRVCount == 0)
   {
      destroy();
      return;
   }

   if (result.status == 0)
   {
      for (vector<DnsSrvRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
      {
         SRV srv;
         srv.key = (*it).name();
         srv.priority = (*it).priority();
         srv.weight = (*it).weight();
         srv.port = (*it).port();
         srv.target = (*it).target();
         if (srv.key.find("_sips._udp") != Data::npos)
         {
            srv.transport = DTLS;
         }
         else if (srv.key.find("_sips._tcp") != Data::npos)
         {
            srv.transport = TLS;
         }
         else if (srv.key.find("_udp") != Data::npos)
         {
            srv.transport = UDP;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -