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

📄 dnsresult.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
#if defined(HAVE_CONFIG_H)
#include "resip/stack/config.hxx"
#endif

#include <algorithm>
#include <stack>

#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#ifndef __CYGWIN__
#  include <netinet/in.h>
#  include <arpa/nameser.h>
#  include <resolv.h>
#endif
#include <netdb.h>
#include <netinet/in.h>
#else
#include <Winsock2.h>
#include <svcguid.h>
#ifdef USE_IPV6
#include <ws2tcpip.h>
#endif
#endif

#if defined(USE_ARES)
#include "ares.h"
#include "ares_dns.h"
#endif

#include "rutil/DnsUtil.hxx"
#include "rutil/Inserter.hxx"
#include "rutil/Logger.hxx"
#include "rutil/ParseBuffer.hxx"
#include "rutil/Random.hxx"
#include "rutil/compat.hxx"
#include "rutil/WinLeakCheck.hxx"
#include "rutil/dns/DnsHandler.hxx"
#include "rutil/dns/QueryTypes.hxx"
#include "rutil/dns/DnsStub.hxx"
#include "rutil/dns/DnsNaptrRecord.hxx"
#include "resip/stack/DnsResult.hxx"
#include "resip/stack/DnsInterface.hxx"
#include "resip/stack/Tuple.hxx"
#include "resip/stack/Uri.hxx"
#include "rutil/WinLeakCheck.hxx"


#if !defined(USE_ARES)
#warning "ARES is required"
#endif

using namespace resip;
using namespace std;

#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS

DnsResult::DnsResult(DnsInterface& interfaceObj, DnsStub& dns, RRVip& vip, DnsHandler* handler) 
   : mInterface(interfaceObj),
     mDns(dns),
     mVip(vip),
     mHandler(handler),
     mSRVCount(0),
     mDoingEnum(false),
     mSips(false),
     mTransport(UNKNOWN_TRANSPORT),
     mPort(-1),
     mType(Pending),
     mBlacklistLastReturnedResult(false)
{
}

DnsResult::~DnsResult()
{
   //DebugLog (<< "DnsResult::~DnsResult() " << *this);
   assert(mType != Pending);
}

void 
DnsResult::transition(Type t)
{
   if ((t == Finished || t == Destroyed || t == Available) &&
       (mType == Pending))
   {
      mInterface.mActiveQueryCount--;
      assert(mInterface.mActiveQueryCount >= 0);
   }
   mType = t;
}

void
DnsResult::destroy()
{
   assert(this);
   //DebugLog (<< "DnsResult::destroy() " << *this);
   
   if (mType == Pending)
   {
      transition(Destroyed);
   }
   else
   {
      delete this;
   }
}

DnsResult::Type
DnsResult::available()
{
   assert(mType != Destroyed);
   if (mType == Available)
   {
      if (!mResults.empty())
      {
         return Available;
      }
      else
      {
         if (mBlacklistLastReturnedResult)
         {
            blacklistLastReturnedResult();
            mBlacklistLastReturnedResult = false;
         }
         primeResults();
         return available(); // recurse
      }
   }
   else
   {
      return mType;
   }
}

Tuple
DnsResult::next() 
{
   assert(available() == Available);
   Tuple next = mResults.front();
   mResults.pop_front();
   StackLog (<< "Returning next dns entry: " << next);
  
   if (mBlacklistLastReturnedResult)
   {
      blacklistLastReturnedResult();
   }
   else if (!mCurrResultPath.empty())
   {
      mBlacklistLastReturnedResult = true;
   }
   mLastReturnedResult = next;

   assert(mCurrSuccessPath.size()<=3);
   Item top;
   if (!mCurrSuccessPath.empty())
   {
      top = mCurrSuccessPath.top();
      if (top.rrType == T_A || top.rrType == T_AAAA)
      {
         mCurrSuccessPath.pop();
      }
   }
   top.domain = next.getTargetDomain();
   top.rrType = next.isV4()? T_A : T_AAAA;
   top.value = Tuple::inet_ntop(next);
   mCurrSuccessPath.push(top);
   return next;
}

void DnsResult::success()
{
   while (!mCurrSuccessPath.empty())
   {
      Item top = mCurrSuccessPath.top();
      DebugLog( << "Whitelisting " << top.domain << "(" << top.rrType << "): " << top.value);
      mVip.vip(top.domain, top.rrType, top.value);
      mCurrSuccessPath.pop();
   }
}

void
DnsResult::lookup(const Uri& uri, const std::vector<Data> &enumSuffixes)
{
   DebugLog (<< "DnsResult::lookup " << uri);
   //int type = this->mType;
   if (!enumSuffixes.empty() && uri.isEnumSearchable())
   {
      mInputUri = uri;
      mDoingEnum = true;
      std::vector<Data> enums = uri.getEnumLookups(enumSuffixes);
      assert(enums.size() <= 1);
      if (!enums.empty())
      {
         InfoLog (<< "Doing ENUM lookup on " << *enums.begin());
         mDns.lookup<RR_NAPTR>(*enums.begin(), Protocol::Enum, this); 
         return;
      }
   }

   mDoingEnum = false;
   lookupInternal(uri);
}

void
DnsResult::lookupInternal(const Uri& uri)
{
   //assert(uri.scheme() == Symbols::Sips || uri.scheme() == Symbols::Sip);  
   mSips = (uri.scheme() == Symbols::Sips);
   mTarget = (!mSips && uri.exists(p_maddr)) ? uri.param(p_maddr) : uri.host();
   mSrvKey = Symbols::UNDERSCORE + uri.scheme().substr(0, uri.scheme().size()) + Symbols::DOT;
   bool isNumeric = DnsUtil::isIpAddress(mTarget);

   if (uri.exists(p_transport))
   {
      mTransport = Tuple::toTransport(uri.param(p_transport));

      if (isNumeric) // IP address specified
      {
         mPort = getDefaultPort(mTransport, uri.port());
         Tuple tuple(mTarget, mPort, mTransport, mTarget);
         DebugLog (<< "Found immediate result: " << tuple);
         mResults.push_back(tuple);
         transition(Available);
         if (mHandler) mHandler->handle(this);         
      }
      else if (uri.port() != 0)
      {
         mPort = uri.port();
         lookupHost(mTarget); // for current target and port
      }
      else 
      { 
         if (mSips)
         {
            if (mTransport == UDP)
            {
               mTransport = DTLS;
               if (!mInterface.isSupportedProtocol(mTransport))
               {
                  transition(Finished);
                  if (mHandler) mHandler->handle(this);
                  return;
               }
               mSRVCount++;
               mDns.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this);
               StackLog (<< "Doing SRV lookup of _sips._udp." << mTarget);
            }
            else
            {
               mTransport = TLS;
               if (!mInterface.isSupportedProtocol(mTransport))
               {
                  transition(Finished);
                  if (mHandler) mHandler->handle(this);
                  return;
               }
               mSRVCount++;
               mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip,  this);
               StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget);
            }
         }
         else
         {
            if (!mInterface.isSupportedProtocol(mTransport))
            {
               transition(Finished);
               if (mHandler) mHandler->handle(this);
               return;
            }

            switch(mTransport)
            {
               case TLS: //deprecated, mean TLS over TCP
                  mSRVCount++;
                  mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
                  StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget);
                  break;
               case DTLS: //deprecated, mean TLS over TCP
                  mSRVCount++;
                  mDns.lookup<RR_SRV>("_sip._dtls." + mTarget, Protocol::Sip, this);
                  StackLog (<< "Doing SRV lookup of _sip._dtls." << mTarget);
                  break;
               case TCP:
                  mSRVCount++;
                  mDns.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this);
                  StackLog (<< "Doing SRV lookup of _sip._tcp." << mTarget);
                  break;
               case SCTP:
               case DCCP:
               case UDP:
               default: //fall through to UDP for unimplemented & unknown
                  mSRVCount++;
                  mDns.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this);
                  StackLog (<< "Doing SRV lookup of _sip._udp." << mTarget);
            }
         }
      }
   }
   else 
   {
      if (isNumeric || uri.port() != 0)
      {
         if (mSips || mTransport == TLS)
         {
            mTransport = TLS;
         }
         else 
         {
            mTransport = UDP;
         }

         if (isNumeric) // IP address specified
         {
            mPort = getDefaultPort(mTransport, uri.port());
            Tuple tuple(mTarget, mPort, mTransport, mTarget);
            mResults.push_back(tuple);
            transition(Available);
            DebugLog (<< "Numeric result so return immediately: " << tuple);
            if (mHandler) mHandler->handle(this);
         }
         else // port specified so we know the transport
         {
            mPort = uri.port();
            if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))
            {
               lookupHost(mTarget);
            }
            else
            {
               assert(0);
               if (mHandler) mHandler->handle(this);
            }
         }
      }
      else // do NAPTR
      {
         mDns.lookup<RR_NAPTR>(mTarget, Protocol::Sip, this); // for current target
      }
   }
}

void DnsResult::lookupHost(const Data& target)
{
   if (mInterface.isSupported(mTransport, V6))
   {
#ifdef USE_IPV6
      DebugLog(<< "Doing host (AAAA) lookup: " << target);
      mPassHostFromAAAAtoA = target;
      mDns.lookup<RR_AAAA>(target, Protocol::Sip, this);
#else
      assert(0);
      mDns.lookup<RR_A>(target, Protocol::Sip, this);
#endif
   }
   else if (mInterface.isSupported(mTransport, V4))
   {
      mDns.lookup<RR_A>(target, Protocol::Sip, this);
   }
   else
   {
      assert(0);
   }
}

int
DnsResult::getDefaultPort(TransportType transport, int port)
{
   if (port == 0)
   {
      switch (transport)
      {
         case UDP:
            return Symbols::DefaultSipPort;
         case TCP:
            return mSips ? Symbols::DefaultSipsPort : Symbols::DefaultSipPort;
         case TLS:
         case DTLS:
            return Symbols::DefaultSipsPort;
         default:
            ErrLog( << "Should not get this - unknown transport" );
            return Symbols::DefaultSipPort; // !cj! todo - remove 
            assert(0);
      }
   }
   else
   {
      return port;
   }

	assert(0);
	return 0;
}

void
DnsResult::primeResults()
{
   StackLog(<< "Priming " << Inserter(mSRVResults));
   //assert(mType != Pending);
   //assert(mType != Finished);
   assert(mResults.empty());

   if (!mSRVResults.empty())
   {
      SRV next = retrieveSRV();
      StackLog (<< "Primed with SRV=" << next);
      transition(Pending);
      mPort = next.port;
      mTransport = next.transport;
      StackLog (<< "No A or AAAA record for " << next.target << " in additional records");
      if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))

⌨️ 快捷键说明

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