📄 dnsresult.cxx
字号:
// 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);}#endifvoid 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; } 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(); } }}voidDnsResult::onEnumResult(const DNSResult<DnsNaptrRecord>& result){ mDoingEnum = false; if (result.status == 0) { static Data enumService1("e2u+sip"); static Data enumService2("sip+e2u"); 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); }}voidDnsResult::onNaptrResult(const DNSResult<DnsNaptrRecord>& result){ bool bFail = false; if (result.status == 0) { 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 (<< "Adding NAPTR record: " << naptr); if ( !mSips || naptr.service.find("SIPS") == 0) { if (mInterface.isSupported(naptr.service) && naptr < mPreferredNAPTR) { mPreferredNAPTR = naptr; StackLog (<< "Picked preferred: " << mPreferredNAPTR); } } } // This means that dns / NAPTR is misconfigured for this client if (mPreferredNAPTR.key.empty()) { StackLog (<< "There are no NAPTR records supported by this client so do an SRV lookup instead"); bFail = true; } else { transition(Pending); Item item; item.domain = mPreferredNAPTR.key; item.rrType = T_NAPTR; item.value = mPreferredNAPTR.replacement; clearCurrPath(); mCurrentPath.push_back(item); mSRVCount++; InfoLog (<< "Doing SRV lookup of " << mPreferredNAPTR.replacement); mDns.lookup<RR_SRV>(mPreferredNAPTR.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); } } }}void DnsResult::onDnsResult(const DNSResult<DnsNaptrRecord>& result){ 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); } }void DnsResult::onDnsResult(const DNSResult<DnsCnameRecord>& result){}void DnsResult::clearCurrPath(){ while (!mCurrentPath.empty()) { mCurrentPath.pop_back(); }}std::ostream& resip::operator<<(std::ostream& strm, const resip::DnsResult& result){ strm << result.mTarget << " --> " << Inserter(result.mResults); return strm;}std::ostream& resip::operator<<(std::ostream& strm, const resip::DnsResult::NAPTR& naptr){ strm << "key=" << naptr.key << " order=" << naptr.order << " pref=" << naptr.pref << " flags=" << naptr.flags << " service=" << naptr.service << " regex=" << naptr.regex.regexp() << " -> " << naptr.regex.replacement() << " replacement=" << naptr.replacement; return strm;}std::ostream& resip::operator<<(std::ostream& strm, const resip::DnsResult::SRV& srv){ strm << "key=" << srv.key << " t=" << Tuple::toData(srv.transport) << " p=" << srv.priority << " w=" << srv.weight << " port=" << srv.port << " target=" << srv.target; return strm;}// Copyright (c) 2003, Jason Fischl /* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -