📄 dnsstub.cxx
字号:
// WINCE -- stl headers have to be defined before standard c headers because of // MS non-consistent declaration of time_t. we defined _USE_32BIT_TIME_T// in all projects and that solved the issue with beta compiler, however // release version messes time_t definition again#include <set>#include <vector>#include <cassert>#if defined(USE_ARES)#include "ares.h"#include "ares_dns.h"#endif#ifndef WIN32#ifndef __CYGWIN__#include <arpa/nameser.h>#endif#endif#include "rutil/Logger.hxx"#include "rutil/Socket.hxx"#include "rutil/compat.hxx"#include "rutil/BaseException.hxx"#include "rutil/Data.hxx"#include "rutil/Inserter.hxx"#include "rutil/dns/DnsStub.hxx"#include "rutil/dns/ExternalDns.hxx"#include "rutil/dns/ExternalDnsFactory.hxx"#include "rutil/dns/QueryTypes.hxx"#include "rutil/WinLeakCheck.hxx"using namespace resip;using namespace std;#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNSDnsStub::DnsResourceRecordsByPtr DnsStub::Query::Empty;DnsStub::NameserverList DnsStub::EmptyNameserverList;int DnsStub::mDnsTimeout = 0;int DnsStub::mDnsTries = 0;unsigned int DnsStub::mDnsFeatures = 0;voidDnsResultSink::onLogDnsResult(const DNSResult<DnsHostRecord>& rr){ DebugLog (<< rr);}#if defined(USE_IPV6)voidDnsResultSink::onLogDnsResult(const DNSResult<DnsAAAARecord>& rr){ DebugLog (<< rr);}#endifvoidDnsResultSink::onLogDnsResult(const DNSResult<DnsSrvRecord>& rr){ DebugLog (<< rr);}voidDnsResultSink::onLogDnsResult(const DNSResult<DnsNaptrRecord>& rr){ DebugLog (<< rr);}voidDnsResultSink::onLogDnsResult(const DNSResult<DnsCnameRecord>& rr){ DebugLog (<< rr);}DnsStub::DnsStub(const NameserverList& additional, AfterSocketCreationFuncPtr socketFunc) : mTransform(0), mDnsProvider(ExternalDnsFactory::createExternalDns()){ int retCode = mDnsProvider->init(additional, socketFunc, mDnsTimeout, mDnsTries, mDnsFeatures); if (retCode != ExternalDns::Success) { if (retCode == ExternalDns::BuildMismatch) { assert(0); throw DnsStubException("Library was not build w/ required capabilities(probably USE_IPV6 resip/ares mismatch", __FILE__,__LINE__); } Data err(Data::Take, mDnsProvider->errorMessage(retCode)); ErrLog (<< "Failed to initialize async dns library: " << err); throw DnsStubException("Failed to initialize async dns library " + err, __FILE__,__LINE__); }}DnsStub::~DnsStub(){ for (set<Query*>::iterator it = mQueries.begin(); it != mQueries.end(); ++it) { delete *it; } delete mDnsProvider;}bool DnsStub::requiresProcess(){ return mDnsProvider->requiresProcess();}void DnsStub::buildFdSet(FdSet& fdset){ mDnsProvider->buildFdSet(fdset.read, fdset.write, fdset.size);}void DnsStub::process(FdSet& fdset){ while (mCommandFifo.messageAvailable()) { Command* command = mCommandFifo.getNext(); command->execute(); delete command; } mDnsProvider->process(fdset.read, fdset.write);}void DnsStub::cache(const Data& key, in_addr addr){ DnsHostRecord record(key, addr); RRCache::instance()->updateCacheFromHostFile(record);}void DnsStub::cache(const Data& key, const unsigned char* abuf, int alen){ vector<RROverlay> overlays; // skip header const unsigned char* aptr = abuf + HFIXEDSZ; int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions. for (int i = 0; i < qdcount && aptr; ++i) { aptr = skipDNSQuestion(aptr, abuf, alen); } // answers. int ancount = DNS_HEADER_ANCOUNT(abuf); for (int i = 0; i < ancount; i++) { aptr = createOverlay(abuf, alen, aptr, overlays); } // name server records. int nscount = DNS_HEADER_NSCOUNT(abuf); for (int i = 0; i < nscount; i++) { aptr = createOverlay(abuf, alen, aptr, overlays, true); } // additional records. int arcount = DNS_HEADER_ARCOUNT(abuf); for (int i = 0; i < arcount; i++) { aptr = createOverlay(abuf, alen, aptr, overlays); } // sort overlays by type. sort(overlays.begin(), overlays.end()); vector<RROverlay>::iterator itLow = lower_bound(overlays.begin(), overlays.end(), *overlays.begin()); vector<RROverlay>::iterator itHigh = upper_bound(overlays.begin(), overlays.end(), *overlays.begin()); while (itLow != overlays.end()) { RRCache::instance()->updateCache(key, (*itLow).type(), itLow, itHigh); itLow = itHigh; if (itHigh != overlays.end()) { itHigh = upper_bound(itLow, overlays.end(), *itLow); } }}void DnsStub::cacheTTL(const Data& key, int rrType, int status, const unsigned char* abuf, int alen){ // skip header const unsigned char* aptr = abuf + HFIXEDSZ; int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions. for (int i = 0; i < qdcount && aptr; ++i) { aptr = skipDNSQuestion(aptr, abuf, alen); } vector<RROverlay> overlays; // answers. int ancount = DNS_HEADER_ANCOUNT(abuf); if (ancount != 0) return; // name server records. int nscount = DNS_HEADER_NSCOUNT(abuf); if (nscount == 0) return; vector<RROverlay> soa; aptr = createOverlay(abuf, alen, aptr, soa); assert (!soa.empty()); RRCache::instance()->cacheTTL(key, rrType, status, soa[0]);}const unsigned char* DnsStub::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) { throw DnsStubException("Failed DNS preparse", __FILE__, __LINE__); } 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); throw DnsStubException("Failed DNS preparse", __FILE__, __LINE__); } aptr += QFIXEDSZ; free(name); return aptr;}boolDnsStub::supportedType(int type){#ifdef USE_IPV6 return (T_A == type || T_AAAA == type || T_NAPTR == type || T_SRV == type || T_CNAME == type || T_SOA == type);#else return (T_A == type || T_NAPTR == type || T_SRV == type || T_CNAME == type || T_SOA == type);#endif}const unsigned char*DnsStub::createOverlay(const unsigned char* abuf, const int alen, const unsigned char* aptr, vector<RROverlay>& overlays, bool discard){ const unsigned char* rptr = aptr; char* name = 0; int len = 0; int status = ares_expand_name(aptr, abuf, alen, &name, &len); if (ARES_SUCCESS != status) { throw DnsStubException("Failed overlay creation", __FILE__, __LINE__); } free(name); aptr += len; int type = DNS_RR_TYPE(aptr); int dlen = DNS_RR_LEN(aptr); if (!supportedType(type)) { aptr += RRFIXEDSZ; aptr += dlen; return aptr; } // rewind before handing it off to overlay. aptr -= len; if (!discard) { RROverlay overlay(aptr, abuf, alen); overlays.push_back(overlay); } return rptr + len + RRFIXEDSZ + dlen;}voidDnsStub::removeQuery(Query* query){ set<Query*>::iterator it = mQueries.find(query); if (it != mQueries.end()) { mQueries.erase(it); }}void DnsStub::setResultTransform(ResultTransform* transform){ mTransform = transform;}void DnsStub::removeResultTransform(){ mTransform = 0;}DnsStub::Query::Query(DnsStub& stub, ResultTransform* transform, ResultConverter* resultConv, const Data& target, int rrType, bool followCname, int proto, DnsResultSink* s) : mRRType(rrType), mStub(stub), mTransform(transform), mResultConverter(resultConv), mTarget(target), mProto(proto), mReQuery(0), mSink(s), mFollowCname(followCname){ assert(s); }DnsStub::Query::~Query() { delete mResultConverter; //.dcm. flyweight?}static Data typeToData(int rr){ // !dcm! fix this if (rr == RR_A::getRRType()) { return RR_A::getRRTypeName(); }#if defined(USE_IPV6) else if(rr == RR_AAAA::getRRType()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -