📄 dnsresult.cxx
字号:
{ mDns.lookup<RR_A>(target, Protocol::Sip, this); } else { assert(0); }}intDnsResult::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;}voidDnsResult::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)) { Item top; while (!mCurrentPath.empty()) { top = mCurrentPath.back(); if (top.rrType != T_NAPTR) { mCurrentPath.pop_back(); } else { break; } } top.domain = next.key; top.rrType = T_SRV; top.value = next.target + ":" + Data(next.port); mCurrentPath.push_back(top); 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}// implement the selection algorithm from rfc2782 (SRV records)DnsResult::SRV DnsResult::retrieveSRV(){ // !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;}// adapted from the adig.c example in aresconst unsigned char* DnsResult::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) { StackLog (<< "Failed parse of RR"); return NULL; } 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); StackLog (<< "Failed parse of RR"); return NULL; } // Parse the question type and class. //int type = DNS_QUESTION_TYPE(aptr); //int dnsclass = DNS_QUESTION_CLASS(aptr); aptr += QFIXEDSZ; free(name); return aptr;}DnsResult::NAPTR::NAPTR() : order(0), pref(0){}bool DnsResult::NAPTR::operator<(const DnsResult::NAPTR& rhs) const{ if (key.empty()) // default value { return false; } else if (rhs.key.empty()) // default value { return true; } else if (order < rhs.order) { return true; } else if (order == rhs.order) { if (pref < rhs.pref) { return true; } else if (pref == rhs.pref) { return replacement < rhs.replacement; } } return false;}DnsResult::SRV::SRV() : priority(0), weight(0), port(0){}bool DnsResult::SRV::operator<(const DnsResult::SRV& rhs) const{ if (transport < rhs.transport) { return true; } else if (transport == rhs.transport) { if (priority < rhs.priority) { return true; } else if (priority == rhs.priority) { if (weight < rhs.weight) { return true; } else if (weight == rhs.weight) { if (target < rhs.target) { return true; } } } } return false;}void DnsResult::onDnsResult(const DNSResult<DnsHostRecord>& result){ 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); }}#ifdef USE_IPV6void DnsResult::onDnsResult(const DNSResult<DnsAAAARecord>& result){ 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -