reSIProcate/stack  9694
Classes | Public Types | Public Member Functions | Private Member Functions | Private Attributes | Friends
resip::DnsResult Class Reference

#include <DnsResult.hxx>

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

List of all members.

Classes

struct  Item
class  NAPTR
class  SRV

Public Types

enum  Type { Available, Pending, Finished, Destroyed }
typedef std::vector< DataDataVector

Public Member Functions

 RESIP_HeapCount (DnsResult)
 DnsResult (DnsInterface &interfaceObj, DnsStub &dns, RRVip &vip, DnsHandler *handler)
virtual ~DnsResult ()
void lookup (const Uri &uri, const std::vector< Data > &enumSuffixes)
bool blacklistLast (UInt64 expiry)
bool greylistLast (UInt64 expiry)
Type available ()
Tuple next ()
void whitelistLast ()
Data target () const
unsigned int getSRVResultsSize () const
void destroy ()

Private Member Functions

void lookupInternal (const Uri &uri)
int getDefaultPort (TransportType transport, int port)
void lookupHost (const Data &target)
SRV retrieveSRV ()
void primeResults ()
void transition (Type t)
void onDnsResult (const DNSResult< DnsHostRecord > &)
void onDnsResult (const DNSResult< DnsAAAARecord > &)
void onDnsResult (const DNSResult< DnsSrvRecord > &)
void onDnsResult (const DNSResult< DnsNaptrRecord > &)
void onDnsResult (const DNSResult< DnsCnameRecord > &)
void onEnumResult (const DNSResult< DnsNaptrRecord > &result)
void onNaptrResult (const DNSResult< DnsNaptrRecord > &result)
void clearCurrPath ()

Private Attributes

DnsInterfacemInterface
DnsStubmDns
RRVipmVip
DnsHandlermHandler
int mSRVCount
Uri mInputUri
bool mDoingEnum
bool mSips
Data mTarget
Data mSrvKey
TransportType mTransport
int mPort
bool mHaveChosenTransport
Type mType
Data mPassHostFromAAAAtoA
std::deque< TuplemResults
std::vector< TuplemGreylistedTuples
std::map< Data, NAPTRmTopOrderedNAPTRs
int mCumulativeWeight
std::vector< SRVmSRVResults
std::vector< ItemmLastReturnedPath
std::vector< ItemmCurrentPath
bool mHaveReturnedResults
Tuple mLastResult

Friends

class DnsInterface
EncodeStreamoperator<< (EncodeStream &strm, const DnsResult &)
EncodeStreamoperator<< (EncodeStream &strm, const DnsResult::SRV &)
EncodeStreamoperator<< (EncodeStream &strm, const DnsResult::NAPTR &)

Detailed Description

Definition at line 35 of file DnsResult.hxx.


Member Typedef Documentation

typedef std::vector<Data> resip::DnsResult::DataVector

Definition at line 52 of file DnsResult.hxx.


Member Enumeration Documentation

Enumerator:
Available 
Pending 
Finished 
Destroyed 

Definition at line 42 of file DnsResult.hxx.

      {
         Available, // A result is available now
         Pending,   // More results may be pending 
         Finished,  // No more results available and none pending
         Destroyed  // the associated transaction has been deleted
                     // (ie, this DnsResult will delete itself as soon as it
                     // gets a new result)
      } Type;

Constructor & Destructor Documentation

DnsResult::DnsResult ( DnsInterface interfaceObj,
DnsStub dns,
RRVip vip,
DnsHandler handler 
)

Definition at line 50 of file DnsResult.cxx.

   : mInterface(interfaceObj),
     mDns(dns),
     mVip(vip),
     mHandler(handler),
     mSRVCount(0),
     mDoingEnum(false),
     mSips(false),
     mTransport(UNKNOWN_TRANSPORT),
     mPort(-1),
     mHaveChosenTransport(false),
     mType(Pending),
     mCumulativeWeight(0),
     mHaveReturnedResults(false)
{
}
DnsResult::~DnsResult ( ) [virtual]

Definition at line 67 of file DnsResult.cxx.

References mType, and Pending.

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

Member Function Documentation

DnsResult::Type DnsResult::available ( )

Tries to load the next tuple. If Available is returned, the tuple may be accessed using current().

Returns:
Available if there is a result ready, Pending if it needs to follow an SRV (more results might come in later), or Finished if there are definitively no more results.
Note:
ALWAYS call this before calling next()

Definition at line 141 of file DnsResult.cxx.

References Available, Destroyed, mResults, mType, and primeResults().

Referenced by resip::StatelessMessage::handle(), resip::TestDnsHandler::handle(), resip::TransactionState::handleSync(), next(), resip::TransactionState::processNoDnsResults(), and resip::TransactionState::processTransportFailure().

{
   assert(mType != Destroyed);
   if (mType == Available)
   {
      if (!mResults.empty())
      {
         return Available;
      }
      else
      {
         primeResults();
         return available(); // recurse
      }
   }
   else
   {
      return mType;
   }
}

Here is the call graph for this function:

bool DnsResult::blacklistLast ( UInt64  expiry)

Blacklist the last returned result until the specified time (ms)

Parameters:
expiryThe absolute expiry, in ms, of this blacklist.
Returns:
true iff the last result could be blacklisted
Note:
This is a no-op if no results have been returned.

Definition at line 103 of file DnsResult.cxx.

References resip::TupleMarkManager::BLACK, DebugLog, resip::DnsInterface::getMarkManager(), resip::TupleMarkManager::mark(), mHaveReturnedResults, mInterface, mLastResult, mLastReturnedPath, mVip, and resip::RRVip::removeVip().

Referenced by resip::TestDnsHandler::handle(), and resip::TransactionState::sendToTU().

{
   if(mHaveReturnedResults)
   {
      assert(!mLastReturnedPath.empty());
      assert(mLastReturnedPath.size()<=3);
      Item top = mLastReturnedPath.back();
   
      mInterface.getMarkManager().mark(mLastResult,expiry,TupleMarkManager::BLACK);
   
      DebugLog( << "Remove vip " << top.domain << "(" << top.rrType << ")");
      mVip.removeVip(top.domain, top.rrType);
      return true;
   }
   
   return false;
}

Here is the call graph for this function:

void DnsResult::clearCurrPath ( ) [private]

Definition at line 1326 of file DnsResult.cxx.

References mCurrentPath.

Referenced by onDnsResult(), and primeResults().

{
   while (!mCurrentPath.empty())
   {
      mCurrentPath.pop_back();
   }
}
void DnsResult::destroy ( )

Definition at line 86 of file DnsResult.cxx.

References Destroyed, Finished, mType, Pending, and transition().

Referenced by resip::StatelessMessage::handle(), onDnsResult(), resip::TransactionState::processClientInvite(), resip::TransactionState::processClientNonInvite(), and resip::TransactionState::~TransactionState().

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

Here is the call graph for this function:

int DnsResult::getDefaultPort ( TransportType  transport,
int  port 
) [private]

Definition at line 493 of file DnsResult.cxx.

References resip::Symbols::DefaultSipPort, resip::Symbols::DefaultSipsPort, resip::DTLS, ErrLog, mSips, resip::TCP, resip::TLS, and resip::UDP.

Referenced by lookupInternal(), and onDnsResult().

{
   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;
}
unsigned int resip::DnsResult::getSRVResultsSize ( ) const [inline]

Definition at line 125 of file DnsResult.hxx.

References mSRVResults.

{return (unsigned int)mSRVResults.size();}
bool DnsResult::greylistLast ( UInt64  expiry)

Greylist the last returned result until the specified time (ms) Greylisting a tuple effectively de-prioritizes it, so it will not be tried if there are any non-grey or blacklisted tuples left to try.

Parameters:
expiryThe absolute expiry, in ms, of this blacklist.
Returns:
true iff the last result could be greylisted
Note:
This is a no-op if no results have been returned.

Definition at line 122 of file DnsResult.cxx.

References DebugLog, resip::DnsInterface::getMarkManager(), resip::TupleMarkManager::GREY, resip::TupleMarkManager::mark(), mHaveReturnedResults, mInterface, mLastResult, mLastReturnedPath, mVip, and resip::RRVip::removeVip().

Referenced by resip::TestDnsHandler::handle(), resip::TransactionState::processTransportFailure(), and resip::TransactionState::sendToTU().

{
   if(mHaveReturnedResults)
   {
      assert(!mLastReturnedPath.empty());
      assert(mLastReturnedPath.size()<=3);
      Item top = mLastReturnedPath.back();
   
      mInterface.getMarkManager().mark(mLastResult,expiry,TupleMarkManager::GREY);
   
      DebugLog( << "Remove vip " << top.domain << "(" << top.rrType << ")");
      mVip.removeVip(top.domain, top.rrType);
      return true;
   }
   
   return false;
}

Here is the call graph for this function:

void DnsResult::lookup ( const Uri uri,
const std::vector< Data > &  enumSuffixes 
)

Starts a lookup. Has the rules for determining the transport from a uri as per rfc3263 and then does a NAPTR lookup or an A lookup depending on the uri.

Parameters:
uriThe uri to resolve.
enumSuffixesIf the uri is enum searchable, this is the list of enum suffixes (for example "e164.arpa") that will be used in the attempt to resolve this uri.

Definition at line 201 of file DnsResult.cxx.

References DebugLog, resip::RRList::Protocol::Enum, resip::Uri::getEnumLookups(), InfoLog, resip::Uri::isEnumSearchable(), resip::DnsStub::lookup(), lookupInternal(), mDns, mDoingEnum, and mInputUri.

Referenced by resip::DnsInterface::lookup().

{
   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);
}

Here is the call graph for this function:

void DnsResult::lookupHost ( const Data target) [private]

Definition at line 467 of file DnsResult.cxx.

References CritLog, DebugLog, resip::DnsInterface::isSupported(), resip::DnsStub::lookup(), mDns, mInterface, mPassHostFromAAAAtoA, mTransport, resip::RRList::Protocol::Sip, target(), resip::V4, and resip::V6.

Referenced by lookupInternal(), onDnsResult(), and primeResults().

{
   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
   {
      CritLog(<<"Cannot lookup target="<<target
              <<" because DnsInterface doesn't support transport="<<mTransport);
      assert(0);
   }
}

Here is the call graph for this function:

void DnsResult::lookupInternal ( const Uri uri) [private]

Definition at line 224 of file DnsResult.cxx.

References Available, resip::TupleMarkManager::BLACK, resip::DCCP, DebugLog, resip::Symbols::DOT, resip::DTLS, resip::Uri::exists(), Finished, getDefaultPort(), resip::DnsInterface::getMarkManager(), resip::TupleMarkManager::getMarkType(), resip::TupleMarkManager::GREY, resip::DnsHandler::handle(), resip::Uri::host(), resip::DnsUtil::isIpAddress(), resip::DnsInterface::isSupported(), resip::DnsInterface::isSupportedProtocol(), resip::DnsStub::lookup(), lookupHost(), mDns, mHandler, mHaveChosenTransport, mInterface, mPort, mResults, mSips, mSRVCount, mSrvKey, mTarget, mTransport, resip::TupleMarkManager::OK, resip::ParserCategory::param(), resip::Uri::port(), resip::Uri::scheme(), resip::SCTP, resip::RRList::Protocol::Sip, resip::Symbols::Sips, resip::Data::size(), StackLog, resip::Data::substr(), resip::DnsStub::supportedType(), T_NAPTR, T_SRV, resip::TCP, resip::TLS, resip::Tuple::toTransport(), transition(), resip::UDP, resip::Symbols::UNDERSCORE, resip::UNKNOWN_TRANSPORT, resip::V4, and resip::V6.

Referenced by lookup(), and onEnumResult().

{
   //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));
      mHaveChosenTransport=true;
      
      if (isNumeric) // IP address specified
      {
         mPort = getDefaultPort(mTransport, uri.port());
         Tuple tuple(mTarget, mPort, mTransport, mTarget);

         // ?bwc? If this is greylisted, what can we do? This is the only result
         if(!(mInterface.getMarkManager().getMarkType(tuple)==TupleMarkManager::BLACK))
         {
            DebugLog (<< "Found immediate result: " << tuple);
            mResults.push_back(tuple);
            transition(Available);
            if (mHandler) mHandler->handle(this);
         }
         else
         {
            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;
               }
               if(!mDns.supportedType(T_SRV)) 
               {
                  mPort = getDefaultPort(mTransport, uri.port());
                  lookupHost(mTarget); // for current target and port
               }
               else
               {
                  mSRVCount++;
                  mDns.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this);
                  StackLog (<< "Doing SRV lookup of _sips._udp." << mTarget);
               }
            }
            else
            {
               mTransport = TLS;
               mHaveChosenTransport=true;
               if (!mInterface.isSupportedProtocol(mTransport))
               {
                  transition(Finished);
                  if (mHandler) mHandler->handle(this);
                  return;
               }
               if(!mDns.supportedType(T_SRV)) 
               {
                  mPort = getDefaultPort(mTransport, uri.port());
                  lookupHost(mTarget); // for current target and port
               }
               else
               {
                  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;
            }

            if(!mDns.supportedType(T_SRV)) 
            {
               mPort = getDefaultPort(mTransport, uri.port());
               lookupHost(mTarget); // for current target and port
               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 // transport parameter is not specified
   {
      // if hostname is numeric, a port is specified, or NAPTR queries are not support by the DNS layer - skip NAPTR lookup
      if (isNumeric || uri.port() != 0 || !mDns.supportedType(T_NAPTR))
      {
         TupleMarkManager::MarkType mark=TupleMarkManager::BLACK;
         Tuple tuple;
         
         if(isNumeric)
         {
            if(mSips)
            {
               if((mInterface.isSupported(TLS, V4) ||
                   mInterface.isSupported(TLS, V6)))
               {
                  mTransport=TLS;
                  mPort = getDefaultPort(mTransport,uri.port());
                  tuple=Tuple(mTarget,mPort,mTransport,mTarget);
                  mark=mInterface.getMarkManager().getMarkType(tuple);
               }
            }
            else
            {
               if(mark!=TupleMarkManager::OK && (mInterface.isSupported(UDP, V4) ||
                                    mInterface.isSupported(UDP, V6)))
               {
                  mTransport=UDP;
                  mPort = getDefaultPort(mTransport,uri.port());
                  tuple=Tuple(mTarget,mPort,mTransport,mTarget);
                  mark=mInterface.getMarkManager().getMarkType(tuple);
               }
               
               if(mark!=TupleMarkManager::OK && (mInterface.isSupported(TCP, V4) ||
                                    mInterface.isSupported(TCP, V6)))
               {
                  mTransport=TCP;
                  mPort = getDefaultPort(mTransport,uri.port());
                  tuple=Tuple(mTarget,mPort,mTransport,mTarget);
                  mark=mInterface.getMarkManager().getMarkType(tuple);
               }
               
               if(mark!=TupleMarkManager::OK && (mInterface.isSupported(TLS, V4) ||
                                    mInterface.isSupported(TLS, V6)))
               {
                  mTransport=TLS;
                  mPort = getDefaultPort(mTransport,uri.port());
                  tuple=Tuple(mTarget,mPort,mTransport,mTarget);
                  mark=mInterface.getMarkManager().getMarkType(tuple);
               }
            }
            
            if(mark==TupleMarkManager::OK || mark==TupleMarkManager::GREY)
            {
               mHaveChosenTransport=true;
               mResults.push_back(tuple);
               transition(Available);
               DebugLog (<< "Numeric result so return immediately: " << tuple);
            }
            else
            {
               // .bwc. Numeric result is blacklisted. Oh well.
               assert(mResults.empty());
               transition(Available);
               DebugLog(<< "Numeric result, but this result is currently blacklisted: " << tuple);
            }
            
            if (mHandler) mHandler->handle(this);

         }
         else // host is not numeric, so we need to make a query
         {
            mTransport=UNKNOWN_TRANSPORT;
            
            if(mSips)
            {
               if(mInterface.isSupported(TLS, V4) || mInterface.isSupported(TLS, V6))
               {
                  mTransport=TLS;
               }
            }
            else if(mInterface.isSupported(UDP, V4) || mInterface.isSupported(UDP, V6))
            {
               mTransport=UDP;
            }
            else if(mInterface.isSupported(TCP, V4) || mInterface.isSupported(TCP, V6))
            {
               mTransport=TCP;
            }
            else if(mInterface.isSupported(TLS, V4) || mInterface.isSupported(TLS, V6))
            {
               mTransport=TLS;
            }
            
            if(mTransport!=UNKNOWN_TRANSPORT)
            {
               mPort=getDefaultPort(mTransport,uri.port());
               lookupHost(mTarget);
            }
            else
            {
               // !bwc! Debatable.
               assert(0);
               if (mHandler) mHandler->handle(this);
            }
         }
      }
      else // do NAPTR
      {
         mDns.lookup<RR_NAPTR>(mTarget, Protocol::Sip, this); // for current target
      }
   }
}

Here is the call graph for this function:

Tuple DnsResult::next ( )

Return the next tuple available for this query.

Returns:
The next Tuple available for this query.
Note:
ALWAYS call available() and verify the return is Available before calling this function.
This no longer results in the last result being blacklisted. To blacklist the last result, use blacklistLast().

Definition at line 163 of file DnsResult.cxx.

References Available, available(), resip::DnsResult::Item::domain, resip::Tuple::inet_ntop(), mCurrentPath, mHaveReturnedResults, mLastResult, mLastReturnedPath, mResults, resip::DnsResult::Item::rrType, StackLog, T_A, T_AAAA, and resip::DnsResult::Item::value.

Referenced by resip::StatelessMessage::handle(), resip::TestDnsHandler::handle(), resip::TransactionState::handleSync(), primeResults(), resip::TransactionState::processTransportFailure(), and retrieveSRV().

{
   assert(available()==Available);
   assert(mCurrentPath.size()<=3);
   
   mLastResult=mResults.front();
   mResults.pop_front();
   
   if(!mCurrentPath.empty() && 
      (mCurrentPath.back().rrType==T_A || mCurrentPath.back().rrType==T_AAAA))
   {
      mCurrentPath.pop_back();
   }
   
   Item AorAAAA;
   AorAAAA.domain = mLastResult.getTargetDomain();
   AorAAAA.rrType = mLastResult.isV4() ? T_A : T_AAAA;
   AorAAAA.value = Tuple::inet_ntop(mLastResult);
   mCurrentPath.push_back(AorAAAA);
   
   StackLog (<< "Returning next dns entry: " << mLastResult);
   mLastReturnedPath=mCurrentPath;
   mHaveReturnedResults=true;
   return mLastResult;
}

Here is the call graph for this function:

void DnsResult::onDnsResult ( const DNSResult< DnsHostRecord > &  result) [private, virtual]

Implements resip::DnsResultSink.

Definition at line 756 of file DnsResult.cxx.

References Available, resip::TupleMarkManager::BLACK, resip::Data::c_str(), clearCurrPath(), destroy(), Destroyed, Finished, resip::DnsInterface::getMarkManager(), resip::TupleMarkManager::getMarkType(), resip::TupleMarkManager::GREY, resip::DnsHandler::handle(), resip::DnsInterface::isSupported(), mGreylistedTuples, mHandler, mInterface, mPort, mResults, resip::DNSResult< T >::msg, mSRVCount, mSRVResults, mTarget, mTransport, mType, resip::TupleMarkManager::OK, Pending, resip::DNSResult< T >::records, StackLog, resip::DNSResult< T >::status, transition(), resip::UDP, resip::V4, and resip::V6.

{
   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);
         
         switch(mInterface.getMarkManager().getMarkType(tuple))
         {
            case TupleMarkManager::OK:
               StackLog (<< "Adding " << tuple << " to result set");
               mResults.push_back(tuple);
               break;
            case TupleMarkManager::GREY:
               StackLog(<< "Adding greylisted tuple " << tuple);
               mGreylistedTuples.push_back(tuple);
               break;
            case TupleMarkManager::BLACK:
            default:
               ;// .bwc. Do nothing.
         }
      
      }
      
   }
   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);
                      
                      if(mInterface.getMarkManager().getMarkType(tuple)!=TupleMarkManager::BLACK)
                      {
                        // .bwc. This is the only result we have, so it doesn't
                        // matter if it is greylisted.
                        StackLog (<< "Adding (WIN) " << tuple << " to result set");
                        mResults.push_back(tuple);
                        transition(Available);
                      }
                   
                   }
                }
             }
             delete [] pQueryResult;
             WSALookupServiceEnd(hQuery);
         }
         
         if(mResults.empty())
         {
            if(mSRVResults.empty())
            {
               if (mGreylistedTuples.empty())
               {
                  transition(Finished);
                  clearCurrPath();
               }
               else
               {
                  for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
                  {
                     mResults.push_back(*i);
                  }
                  mGreylistedTuples.clear();
                  transition(Available);
               }
            }
            else
            {
               transition(Available);
            }
         }
#else
         // .bwc. If this A query failed, don't give up if there are more SRVs!
         if(mSRVResults.empty())
         {
            if (mGreylistedTuples.empty())
            {
               transition(Finished);
               clearCurrPath();
            }
            else
            {
               for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
               {
                  mResults.push_back(*i);
               }
               mGreylistedTuples.clear();
               transition(Available);
            }
         }
         else
         {
            transition(Available);
         }
#endif
      }
      else 
      {
         transition(Available);
      }
      if (changed && mHandler) mHandler->handle(this);
   }
}

Here is the call graph for this function:

void DnsResult::onDnsResult ( const DNSResult< DnsAAAARecord > &  result) [private, virtual]

Implements resip::DnsResultSink.

Definition at line 915 of file DnsResult.cxx.

References resip::TupleMarkManager::BLACK, destroy(), Destroyed, resip::DnsInterface::getMarkManager(), resip::TupleMarkManager::getMarkType(), resip::TupleMarkManager::GREY, resip::DnsInterface::isSupported(), resip::DnsStub::lookup(), mDns, mGreylistedTuples, mInterface, mPassHostFromAAAAtoA, mPort, mResults, resip::DNSResult< T >::msg, mTarget, mTransport, mType, resip::TupleMarkManager::OK, resip::DNSResult< T >::records, resip::RRList::Protocol::Sip, StackLog, resip::DNSResult< T >::status, and resip::V6.

{
#ifdef USE_IPV6
   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);
         
         switch(mInterface.getMarkManager().getMarkType(tuple))
         {
            case TupleMarkManager::OK:
               StackLog (<< "Adding " << tuple << " to result set");
               mResults.push_back(tuple);
               break;
            case TupleMarkManager::GREY:
               StackLog(<< "Adding greylisted tuple " << tuple);
               mGreylistedTuples.push_back(tuple);
               break;
            case TupleMarkManager::BLACK:
            default:
               ;// .bwc. Do nothing.
         }
      
      }
      
   }
   else
   {
      StackLog (<< "Failed async AAAA query: " << result.msg);
   }
   // funnel through to host processing
   mDns.lookup<RR_A>(mPassHostFromAAAAtoA, Protocol::Sip, this);
#else
   assert(0);
#endif
}

Here is the call graph for this function:

void DnsResult::onDnsResult ( const DNSResult< DnsSrvRecord > &  result) [private, virtual]

Implements resip::DnsResultSink.

Definition at line 970 of file DnsResult.cxx.

References resip::Symbols::DefaultSipPort, resip::Symbols::DefaultSipsPort, destroy(), Destroyed, resip::DNSResult< T >::domain, resip::DTLS, resip::Data::find(), getDefaultPort(), resip::DnsInterface::isSupported(), resip::DnsResult::SRV::key, lookupHost(), mHaveChosenTransport, mInterface, mPort, mSips, mSRVCount, mSRVResults, mTarget, mTopOrderedNAPTRs, mTransport, mType, resip::DnsResult::SRV::naptrpref, resip::Data::npos, resip::DnsResult::SRV::port, primeResults(), resip::DnsResult::SRV::priority, resip::DNSResult< T >::records, StackLog, resip::DNSResult< T >::status, resip::DnsResult::SRV::target, resip::TCP, resip::TLS, resip::DnsResult::SRV::transport, resip::UDP, resip::UNKNOWN_TRANSPORT, resip::V4, resip::V6, and resip::DnsResult::SRV::weight.

{
   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();
         // fillin srv.naptrpref - if found in NAPTR map, then SRV query was driven from a NAPTR lookup
         std::map<Data, NAPTR>::iterator itNaptr = mTopOrderedNAPTRs.find(srv.key);
         if(itNaptr != mTopOrderedNAPTRs.end())
         {
            srv.naptrpref = itNaptr->second.pref;
         }
         else
         {
            srv.naptrpref = 0;
         }
         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;
         }
         else if (srv.key.find("_dtls") != Data::npos)
         {
            srv.transport = DTLS;
         }
         else if (srv.key.find("_tls") != Data::npos)
         {
            srv.transport = TLS;
         }
         else if (srv.key.find("_tcp") != Data::npos)
         {
            srv.transport = TCP;
         }
         else
         {
            StackLog (<< "Skipping SRV " << srv.key);
            continue;
         }
         
         if(!mHaveChosenTransport || srv.transport==mTransport)
         {
            // .bwc. If we have not committed to a given transport, or we have 
            // committed to a given transport which this SRV matches, we will
            // add this SRV. We do not add SRVs that do not match a transport
            // we have committed to.
            mSRVResults.push_back(srv);
         }
      }
   }
   else
   {
      StackLog (<< "SRV lookup failed: " << result.domain << " " << result.status);
   }

   // no outstanding queries 
   if (mSRVCount == 0) 
   {
      if (mSRVResults.empty())
      {
         if (mTransport == UNKNOWN_TRANSPORT)
         {
            if (mSips)
            {
               mTransport = TLS;
               mHaveChosenTransport=true;
               mPort = Symbols::DefaultSipsPort;
            }
            else
            {
               if (mInterface.isSupported(UDP, V4))
               {
                  mTransport = UDP;
                  mHaveChosenTransport=true;
               }
               else if (mInterface.isSupported(TCP, V4))
               {
                  mTransport = TCP;
                  mHaveChosenTransport=true;
               }
               /* Yes, there is the possibility that at this point mTransport
                  is still UNKNOWN_TRANSPORT, but this is likely to fail just as
                  well as defaulting to UDP when there isn't an interface that
                  supports UDP.
                  It doesn't support failover to TCP when there is a UDP failure,
                  but neither does the original code.
                  This fixes the case where there is no UDP transport, but
                  there was no explicit ;transport=tcp on the uri.
                  (mjf)
                */
               mPort = Symbols::DefaultSipPort;
            }
         }
         else
         {
            mPort = getDefaultPort(mTransport, 0);
         }
         
         StackLog (<< "No SRV records for " << mTarget << ". Trying A records");
         if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))
         {
            lookupHost(mTarget);
         }
         else
         {
            primeResults();
         }
      }
      else
      {
         std::sort(mSRVResults.begin(),mSRVResults.end()); // !jf! uggh
         primeResults();
      }
   }
}

Here is the call graph for this function:

void DnsResult::onDnsResult ( const DNSResult< DnsNaptrRecord > &  result) [private, virtual]

Implements resip::DnsResultSink.

Definition at line 1297 of file DnsResult.cxx.

References destroy(), Destroyed, mDoingEnum, mInputUri, mTarget, mType, onEnumResult(), onNaptrResult(), StackLog, and resip::DNSResult< T >::status.

{
   StackLog (<< "Received NAPTR result for: " << mInputUri << " target=" << mTarget);
   StackLog (<< "DnsResult::onDnsResult() " << result.status);

   // This function assumes that the NAPTR query that caused this
   // callback is the ONLY outstanding query that might cause
   // a callback into this object
   if (mType == Destroyed)
   {
      destroy();
      return;
   }

   if (mDoingEnum)
   {
      onEnumResult(result);
   }
   else
   {
      onNaptrResult(result);
   }
  
}

Here is the call graph for this function:

void DnsResult::onDnsResult ( const DNSResult< DnsCnameRecord > &  result) [private, virtual]

Implements resip::DnsResultSink.

Definition at line 1322 of file DnsResult.cxx.

{
}
void DnsResult::onEnumResult ( const DNSResult< DnsNaptrRecord > &  result) [private]

Definition at line 1115 of file DnsResult.cxx.

References enumService1, enumService2, ErrLog, resip::Data::from(), InfoLog, resip::isEqualNoCase(), lookupInternal(), mDoingEnum, mHandler, mInputUri, resip::DnsNaptrRecord::order(), resip::DnsNaptrRecord::preference(), resip::DNSResult< T >::records, resip::DnsNaptrRecord::regexp(), resip::DnsHandler::rewriteRequest(), and resip::DNSResult< T >::status.

Referenced by onDnsResult().

{
   mDoingEnum = false;
   
   if (result.status == 0)
   {
      DnsNaptrRecord best;
      best.order() = -1;

      for (vector<DnsNaptrRecord>::const_iterator i = result.records.begin(); i != result.records.end(); ++i)
      {
         InfoLog (<< "service=" << i->service()
                  << " order=" << i->order()
                  << " flags="  << i->flags() 
                  << " regexp substitution=" << i->regexp().replacement()
                  << " replacement=" << i->replacement());

         if ( (isEqualNoCase(i->service(), enumService1) ||
               isEqualNoCase(i->service(), enumService2) )  && // only E2U records
              //i->flags().find("u") != Data::npos && // must be terminal record
              i->replacement().empty() )
               
         {
            if (best.order() == -1)
            {
               best = *i;
            }
            else if (i->order() < best.order())
            {
               best = *i;
            }
            else if (i->order() == best.order() && 
                     i->preference() < best.preference())
            {
               best = *i;
            }
         }
      }
      
      if (best.order() != -1)
      {
         InfoLog (<< "Found an enum result: " << best.regexp().replacement());
         try
         {
            Uri rewrite(best.regexp().apply(Data::from(mInputUri)));
            InfoLog (<< "Rewrote uri " << mInputUri << " -> " << rewrite);
            mHandler->rewriteRequest(rewrite);
            lookupInternal(rewrite);
         }
         catch (ParseException&  e )
         {
            ErrLog(<<"Caught exception: "<< e);
            lookupInternal(mInputUri);
         }
      }
      else
      {
         lookupInternal(mInputUri);
      }
   }
   else
   {
      lookupInternal(mInputUri);
   }
}

Here is the call graph for this function:

void DnsResult::onNaptrResult ( const DNSResult< DnsNaptrRecord > &  result) [private]

Definition at line 1182 of file DnsResult.cxx.

References DebugLog, resip::DNSResult< T >::domain, resip::DTLS, resip::Data::find(), Finished, resip::DnsResult::NAPTR::flags, resip::DnsHandler::handle(), resip::DnsInterface::isSupported(), resip::DnsInterface::isSupportedProtocol(), resip::DnsResult::NAPTR::key, resip::DnsStub::lookup(), mDns, mHandler, mInterface, resip::DNSResult< T >::msg, mSips, mSRVCount, mTarget, mTopOrderedNAPTRs, resip::DnsResult::NAPTR::order, Pending, resip::DnsResult::NAPTR::pref, resip::DNSResult< T >::records, resip::DnsResult::NAPTR::regex, resip::DnsNaptrRecord::RegExp::regexp(), resip::DnsResult::NAPTR::replacement, resip::DnsResult::NAPTR::service, resip::RRList::Protocol::Sip, StackLog, resip::DNSResult< T >::status, resip::TCP, resip::TLS, transition(), and resip::UDP.

Referenced by onDnsResult().

{
   bool bFail = false;
   if (result.status == 0)
   {
      int preferredNAPTROrder=65536; // order is unsigned short - so max is 65535, initialize to one higher
      std::list<NAPTR> supportedNAPTRs;
      for (vector<DnsNaptrRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
      {
         NAPTR naptr;
         naptr.key = (*it).name();
         naptr.flags = (*it).flags();
         naptr.order = (*it).order();
         naptr.pref = (*it).preference();
         naptr.regex = (*it).regexp();
         naptr.replacement = (*it).replacement();
         naptr.service = (*it).service();
         
         StackLog (<< "Received NAPTR record: " << naptr);
         
         if ( !mSips || naptr.service.find("SIPS") == 0)
         {
            if (mInterface.isSupported(naptr.service))
            {
               supportedNAPTRs.push_back(naptr);
               if(naptr.order < preferredNAPTROrder)
               {               
                  preferredNAPTROrder = naptr.order;
               }
            }
         }
      }

      // This means that dns / NAPTR is misconfigured for this client 
      if (supportedNAPTRs.empty())
      {
         StackLog (<< "There are no NAPTR records supported by this client so do an SRV lookup instead");
         bFail = true;
      }
      else
      {
         // Go through NAPTR's and issue SRV queries for each supported record, that has equal
         // ordering to the most preferred order discovered above
         transition(Pending);
         for (std::list<NAPTR>::const_iterator it = supportedNAPTRs.begin(); it != supportedNAPTRs.end(); ++it)
         {
            if(preferredNAPTROrder == (*it).order)
            {
               StackLog (<< "NAPTR record is supported and matches highes priority order. doing SRV query: " << (*it));
               mTopOrderedNAPTRs[(*it).replacement] = (*it);
               mSRVCount++;
               mDns.lookup<RR_SRV>((*it).replacement, Protocol::Sip, this);
            }
         }
      }
   }
   else
   {
      if (result.status > 6)
      {
         DebugLog (<< "NAPTR lookup failed: " << result.domain << " " << result.msg);
      }
      else
      {
         StackLog (<< "NAPTR lookup failed: " << result.domain << " " << result.msg);
      }
      bFail = true;
   }

   if (bFail)
   {
      if (mSips)
      {
         if (!mInterface.isSupportedProtocol(TLS))
         {
            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(TLS))
         {
            mDns.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
            ++mSRVCount;
            StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget);
         }
         if (mInterface.isSupportedProtocol(DTLS))
         {
            mDns.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this);
            ++mSRVCount;
            StackLog (<< "Doing SRV lookup of _sips._udp." << mTarget);
         }
         if (mInterface.isSupportedProtocol(TCP))
         {
            mDns.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this);
            ++mSRVCount;
            StackLog (<< "Doing SRV lookup of _sip._tcp." << mTarget);
         }
         if (mInterface.isSupportedProtocol(UDP))
         {
            mDns.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this);
            ++mSRVCount;
            StackLog (<< "Doing SRV lookup of _sip._udp." << mTarget);
         }
      }
   }
}

Here is the call graph for this function:

void DnsResult::primeResults ( ) [private]

Definition at line 522 of file DnsResult.cxx.

References Available, clearCurrPath(), resip::DnsResult::Item::domain, Finished, resip::DnsHandler::handle(), resip::Inserter(), resip::DnsInterface::isSupported(), resip::DnsResult::SRV::key, lookupHost(), mCurrentPath, mGreylistedTuples, mHandler, mInterface, mPort, mResults, mSRVResults, mTopOrderedNAPTRs, mTransport, mType, next(), Pending, resip::DnsResult::SRV::port, retrieveSRV(), resip::DnsResult::Item::rrType, StackLog, T_NAPTR, T_SRV, resip::DnsResult::SRV::target, transition(), resip::DnsResult::SRV::transport, resip::V4, resip::V6, and resip::DnsResult::Item::value.

Referenced by available(), and onDnsResult().

{
   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))
      {
         Item item;
         clearCurrPath();
         // Check if SRV came from a NAPTR look up
         std::map<Data, NAPTR>::iterator it = mTopOrderedNAPTRs.find(next.key);
         if(it != mTopOrderedNAPTRs.end())
         {
            item.domain = (*it).second.key;
            item.rrType = T_NAPTR;
            item.value = (*it).second.replacement;
            mCurrentPath.push_back(item);
         }
         item.domain = next.key;
         item.rrType = T_SRV;
         item.value = next.target + ":" + Data(next.port);
         mCurrentPath.push_back(item);
         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 if(!mGreylistedTuples.empty())
   {
      for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
      {
         mResults.push_back(*i);
      }
      mGreylistedTuples.clear();
      transition(Available);
   }
   else
   {
      bool changed = (mType == Pending);
      transition(Finished);
      if (changed && mHandler) mHandler->handle(this);
   }

   // Either we are finished or there are results primed
}

Here is the call graph for this function:

resip::DnsResult::RESIP_HeapCount ( DnsResult  )
DnsResult::SRV DnsResult::retrieveSRV ( ) [private]

Definition at line 585 of file DnsResult.cxx.

References resip::Random::getRandom(), InfoLog, resip::Inserter(), mCumulativeWeight, mHaveChosenTransport, mSRVCount, mSRVResults, mTransport, next(), resip::DnsResult::SRV::priority, StackLog, resip::DnsResult::SRV::transport, and resip::UNKNOWN_TRANSPORT.

Referenced by primeResults().

{
    // !ah! if mTransport is known -- should we ignore those that don't match?!
   assert(!mSRVResults.empty());
   assert(mSRVCount==0);

   const SRV& srv = *mSRVResults.begin();
   int priority = srv.priority;
   TransportType transport=UNKNOWN_TRANSPORT;
   
   if(!mHaveChosenTransport)
   {
      // .bwc. We have not chosen a transport yet; this happens when we fail
      // to find a NAPTR record, and the transport is not specified in the uri.
      // In this contingency, we manufacture best-guess SRV queries for each
      // transport we support, and try one transport at a time. This
      // means we might try more than one transport for the uri in question.
      transport = srv.transport;
   }
   else
   {
      // .bwc. We chose our transport before we started looking up SRVs.
      // All SRVs must match. 
      
      transport=mTransport;
      assert(mSRVResults.begin()->transport==transport);
   }
   
   if (mCumulativeWeight == 0)
   {
      for (std::vector<SRV>::iterator i=mSRVResults.begin(); 
           i!=mSRVResults.end() 
              && i->priority == priority 
              && i->transport == transport; i++)
      {
         assert(i->weight>=0);
         mCumulativeWeight += i->weight;
      }
   }
   
   int selected =0;
   if(mCumulativeWeight!=0)
   {
      selected = Random::getRandom() % (mCumulativeWeight);
   }
   else
   {
      // .bwc. All of the remaining SRVs (at this priority/type) have a weight
      // of 0. The best we can do here is pick arbitrarily. In this case, we 
      // will end up picking the first.
      // (selected will be less than the weight of the first SRV, causing the
      // loop below to break on the first iteration)
      selected=-1;
   }
   
   StackLog (<< "cumulative weight = " << mCumulativeWeight << " selected=" << selected);

   std::vector<SRV>::iterator i;
   int cumulativeWeight=0;
   for (i=mSRVResults.begin(); i!=mSRVResults.end(); ++i)
   {
      cumulativeWeight+=i->weight;
      if (cumulativeWeight > selected)
      {
         break;
      }
   }
   
   if (i == mSRVResults.end())
   {
      InfoLog (<< "SRV Results problem selected=" << selected << " cum=" << mCumulativeWeight);
   }
   assert(i != mSRVResults.end());
   SRV next = *i;
   mCumulativeWeight -= next.weight;
   mSRVResults.erase(i);
   
   if(!mSRVResults.empty())
   {
      int nextPriority=mSRVResults.begin()->priority;
      TransportType nextTransport=mSRVResults.begin()->transport;
      
      // .bwc. If we have finished traversing a priority value/transport type,
      // we reset the cumulative weight to 0, to prompt its recalculation.
      if(priority!=nextPriority || transport!=nextTransport)
      {
         mCumulativeWeight=0;
      }
   }
   
   StackLog (<< "SRV: " << Inserter(mSRVResults));

   return next;
}

Here is the call graph for this function:

Data resip::DnsResult::target ( ) const [inline]
void DnsResult::transition ( Type  t) [private]

Definition at line 74 of file DnsResult.cxx.

References Available, Destroyed, Finished, mType, and Pending.

Referenced by destroy(), lookupInternal(), onDnsResult(), onNaptrResult(), and primeResults().

{
   if((t == Pending || t== Available) && 
         (mType== Finished || mType == Destroyed) )
   {
      assert(0);
   }
   
   mType = t;
}
void DnsResult::whitelistLast ( )

Whitelist the last tuple returned by next(). This means that the path to this result (NAPTR->SRV->A/AAAA) will be favored by the resolver from now on. (ie, this NAPTR will be favored above all others that match, even if the order/preference changes in the DNS, and this A/AAAA record will be favored above all others that match, even if new ones are added.)

Note:
It can be argued that using this is harmful, since the load- leveling capabilities of DNS are ignored from here on.
This will also re-order SRV records, but the order in which SRVs arrive is ignored by DnsResult (they are just re-sorted)

Definition at line 190 of file DnsResult.cxx.

References DebugLog, mLastReturnedPath, mVip, and resip::RRVip::vip().

Referenced by resip::TransactionState::sendToTU().

{
   std::vector<Item>::iterator i;
   for (i=mLastReturnedPath.begin(); i!=mLastReturnedPath.end(); ++i)
   {
      DebugLog( << "Whitelisting " << i->domain << "(" << i->rrType << "): " << i->value);
      mVip.vip(i->domain, i->rrType, i->value);
   }
}

Here is the call graph for this function:


Friends And Related Function Documentation

friend class DnsInterface [friend]

Definition at line 241 of file DnsResult.hxx.

EncodeStream& operator<< ( EncodeStream strm,
const DnsResult  
) [friend]
EncodeStream& operator<< ( EncodeStream strm,
const DnsResult::SRV  
) [friend]
EncodeStream& operator<< ( EncodeStream strm,
const DnsResult::NAPTR  
) [friend]

Member Data Documentation

Definition at line 236 of file DnsResult.hxx.

Referenced by retrieveSRV().

std::vector<Item> resip::DnsResult::mCurrentPath [private]
Author:
bwc The current DNS path we are working on. (ie NAPTR -> SRV -> A/AAAA) There is at most one of these types in here at any given time, and they will always be in order. This exists solely to allow mLastReturnedPath to be defined.

Definition at line 283 of file DnsResult.hxx.

Referenced by clearCurrPath(), next(), and primeResults().

Definition at line 187 of file DnsResult.hxx.

Referenced by lookup(), lookupHost(), lookupInternal(), onDnsResult(), and onNaptrResult().

Definition at line 192 of file DnsResult.hxx.

Referenced by lookup(), onDnsResult(), and onEnumResult().

Definition at line 230 of file DnsResult.hxx.

Referenced by onDnsResult(), and primeResults().

Definition at line 189 of file DnsResult.hxx.

Referenced by lookupInternal(), onDnsResult(), onEnumResult(), onNaptrResult(), and primeResults().

Author:
bwc This is set to true when the RFC 3263 logic has chosen the transport it will be using. Incoming SRVs will be filtered according to mTransport if mHaveChosenTransport is true. It is VITAL that this boolean not change during the phase where we are acquiring/processing SRV records, because the state of this boolean denotes whether we filtered incoming SRVs or not. (If it changes halfway through, some of the SRVs will have been filtered, but some won't, and this will break retrieveSRV() )

Definition at line 211 of file DnsResult.hxx.

Referenced by lookupInternal(), onDnsResult(), and retrieveSRV().

Definition at line 285 of file DnsResult.hxx.

Referenced by blacklistLast(), greylistLast(), and next().

Definition at line 191 of file DnsResult.hxx.

Referenced by lookup(), onDnsResult(), and onEnumResult().

Definition at line 289 of file DnsResult.hxx.

Referenced by blacklistLast(), greylistLast(), and next().

std::vector<Item> resip::DnsResult::mLastReturnedPath [private]
Author:
bwc This is a snapshot of mCurrentPath when it was returned last. (This will be empty if we haven't returned anything) This is primarily used for whitelisting the last returned result.

Definition at line 274 of file DnsResult.hxx.

Referenced by blacklistLast(), greylistLast(), next(), and whitelistLast().

Definition at line 223 of file DnsResult.hxx.

Referenced by lookupHost(), and onDnsResult().

int resip::DnsResult::mPort [private]

Definition at line 198 of file DnsResult.hxx.

Referenced by lookupInternal(), onDnsResult(), and primeResults().

std::deque<Tuple> resip::DnsResult::mResults [private]

Definition at line 229 of file DnsResult.hxx.

Referenced by available(), lookupInternal(), next(), onDnsResult(), and primeResults().

bool resip::DnsResult::mSips [private]

Definition at line 194 of file DnsResult.hxx.

Referenced by getDefaultPort(), lookupInternal(), onDnsResult(), and onNaptrResult().

Definition at line 190 of file DnsResult.hxx.

Referenced by lookupInternal(), onDnsResult(), onNaptrResult(), and retrieveSRV().

Definition at line 196 of file DnsResult.hxx.

Referenced by lookupInternal().

std::vector<SRV> resip::DnsResult::mSRVResults [private]

Definition at line 239 of file DnsResult.hxx.

Referenced by getSRVResultsSize(), onDnsResult(), primeResults(), and retrieveSRV().

Definition at line 195 of file DnsResult.hxx.

Referenced by lookupInternal(), onDnsResult(), onNaptrResult(), and target().

Definition at line 233 of file DnsResult.hxx.

Referenced by onDnsResult(), onNaptrResult(), and primeResults().

Definition at line 197 of file DnsResult.hxx.

Referenced by lookupHost(), lookupInternal(), onDnsResult(), primeResults(), and retrieveSRV().

Author:
bwc DnsResult::transition is the ONLY function that should ever touch this (This is because we need to notify mInterface when we are done making queries, and this is when we transition from either Pending or Available to either Destroyed or Finished.)

Definition at line 220 of file DnsResult.hxx.

Referenced by available(), destroy(), onDnsResult(), primeResults(), transition(), and ~DnsResult().

Definition at line 188 of file DnsResult.hxx.

Referenced by blacklistLast(), greylistLast(), and whitelistLast().


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