📄 dnsresult.cxx
字号:
#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/TupleMarkManager.hxx"#include "resip/stack/Tuple.hxx"#include "resip/stack/Uri.hxx"#include "rutil/WinLeakCheck.hxx"#include "rutil/Timer.hxx"#if !defined(USE_ARES)#warning "ARES is required"#endifusing namespace resip;using namespace std;#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNSDnsResult::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), mHaveChosenTransport(false), mType(Pending), mCumulativeWeight(0), mHaveReturnedResults(false){}DnsResult::~DnsResult(){ //DebugLog (<< "DnsResult::~DnsResult() " << *this); assert(mType != Pending);}void DnsResult::transition(Type t){ if ((t == Finished || t == Destroyed) && (mType == Pending || mType == Available)) { mInterface.mActiveQueryCount--; assert(mInterface.mActiveQueryCount >= 0); } if((t == Pending || t== Available) && (mType== Finished || mType == Destroyed) ) { assert(0); } mType = t;}voidDnsResult::destroy(){ assert(this); //DebugLog (<< "DnsResult::destroy() " << *this); if (mType == Pending) { transition(Destroyed); } else { transition(Finished); delete this; }}boolDnsResult::blacklistLast(UInt64 expiry){ 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;}boolDnsResult::greylistLast(UInt64 expiry){ 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;}DnsResult::TypeDnsResult::available(){ assert(mType != Destroyed); if (mType == Available) { if (!mResults.empty()) { return Available; } else { primeResults(); return available(); // recurse } } else { return mType; }}TupleDnsResult::next(){ 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;}voidDnsResult::whitelistLast(){ 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); }}voidDnsResult::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);}voidDnsResult::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)); 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; mHaveChosenTransport=true; 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; mHaveChosenTransport=true; 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) { 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=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 } }}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))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -