📄 dnsresolver.cxx
字号:
#if 0 // ************** debug only ************** // applicable for testLoadBalance testcase #4 only: myVDns[0]->incrTimesSelected(1); myVDns[1]->incrTimesSelected(2); myVDns[2]->incrTimesSelected(3);#endif} // loadBalance()/** * print elements in the myVDns vector */voidDnsResolver::print( int logLevel ){ VECTOR_DNS::iterator i; if ((logLevel < 0) || (logLevel >= LAST_PRIORITY)) { logLevel = LOG_DEBUG; } cpLog(logLevel, "\nprio weight target:port address\n"); for (i=myVDns.begin(); i != myVDns.end(); i++) { cpLog(logLevel, "\n%d %5d %s:%d %s\n", (*i)->getPriority(), (*i)->getWeight(), (*i)->getTarget(), (*i)->getPort(), (*i)->getAddress()); } } // print()/** * print myVDns vector including times selected to be 1st, 2nd & 3rd: * ************** use for DEBUG ONLY *************** */voidDnsResolver::printTally( ){ VECTOR_DNS::iterator i; cpLog(LOG_DEBUG, "\n****** Final tally ******\n"); for (i=myVDns.begin(); i != myVDns.end(); i++) { (*i)->printTally(); } findRecords();} // printTally()/// Build a list and print the DNS response records found //void DnsResolver::buildRecords(ns_msg handle, ns_sect section, int responseLen){ int numRecords = ns_msg_count(handle, section); cpLog(LOG_DEBUG, "Response Length is: %d\n" "Number of records found: %d\n", responseLen, numRecords); // for efficiency, reserve capacity of myVDns vector to // avoid dynamic reallocation of vector, actual size // will be <= capacity (because not all records found // will match the Record Class we are looking for: e.g. // code will ignore CNAME record myVDns.reserve( numRecords ); if (myQType == ns_t_srv) { cpLog( LOG_DEBUG, "building SRV records" ); buildSRVRecords( handle, section, responseLen, numRecords ); } else if (myQType == ns_t_a) { cpLog( LOG_DEBUG, "building A records"); buildARecords( handle, section, responseLen, numRecords ); } else { cpLog( LOG_DEBUG, "don't know how to build record type=%d", myQType ); }} // buildRecordsvoid DnsResolver::buildSRVRecords(ns_msg handle, ns_sect section, int responseLen, int numRecords){ int rrnum; /* resource record number */ int rrt; /* resource record type */ ns_rr rr; /* expanded resource record */ u_char *cp; /* character point to results (rdata in ns_rr) */ char name[NS_MAXDNAME]; /* expanded response hostname */ /* Loop through each record found */ for(rrnum = 0; rrnum < numRecords; rrnum++) { /* Expand the resource record number rrnum into rr. */ if (ns_parserr(&handle, section, rrnum, &rr)) { cpLog(LOG_DEBUG, "ns_parserr: %s, skip rr #%d\n", strerror(errno), rrnum); continue; } rrt = ns_rr_type(rr); if (rrt != ns_t_srv) { cpLog(LOG_DEBUG, "skipping record number: %d, type: %d", rrnum, rrt); continue; } DnsRecord *rec = new DnsRecord; /* Check to see if answer is authoritive */ if(!ns_msg_getflag(handle,ns_f_aa)) { cpLog(LOG_DEBUG,"Warning: Nameserver is not authoritative.\n"); } /* Set cp to point the SRV record. */ cp = (u_char *)ns_rr_rdata(rr); rec->setPriority( ns_get16(cp) ); cp += sizeof(u_short); rec->setWeight( ns_get16(cp) ); cp += sizeof(u_short); rec->setPort( ns_get16(cp) ); cp += sizeof(u_short); cp = (u_char *)expandName(cp, ns_msg_base(handle), name, sizeof(name)); rec->setTarget( name ); struct hostent hEnt; char buf[2048]; if (getHostByRecord( *rec, &hEnt, buf, sizeof(buf))==0) { unsigned char* addr = (unsigned char*)(hEnt.h_addr_list[0]); char addrBuf[1000]; sprintf(addrBuf, "%d.%d.%d.%d", int(*(addr + 0)), int(*(addr + 1)), int(*(addr + 2)), int(*(addr + 3)) ); rec->setAddress(addrBuf); } else { rec->setAddress("0.0.0.0"); } cpLog(LOG_DEBUG, "Target/address = %s/%s", name, rec->getAddress()); // put record in a multimap // mmSrv.insert( make_pair( rec->getPriority, rec ) ); // insert record at end of vector myVDns.push_back( rec ); // curious: what is the vector's capacity? // cpLog(LOG_DEBUG, "Capacity of myVDns = %d", myVDns.capacity()); cpLog(LOG_DEBUG, "\nSRV Priority field: %d\n" "SRV Weight field: %d\n" "SRV Port field: %d\n" "SRV hostname field: %s\n" "Resource Record Type: %d\n" "Record Class: %d\n" "Resource Record Time To Live (ttl): %d\n", rec->getPriority(), rec->getWeight(), rec->getPort(), name, rrt, ns_rr_class(rr), ns_rr_ttl(rr)); } myNumDns = myVDns.size(); myReady = true; cpLog(LOG_DEBUG, "Number of DNS SRV records = %d\n", myNumDns);} // buildSRVRecords()// parse the result of A Record lookup and build a DnsRecordvoid DnsResolver::buildARecords(ns_msg handle, ns_sect section, int responseLen, int numRecords){ int rrnum; /* resource record number */ int rrt; /* resource record type */ ns_rr rr; /* expanded resource record */ u_char *cp; /* character point to results (rdata in ns_rr) */ // char name[NS_MAXDNAME]; /* expanded response hostname */ /* Loop through each record found */ for(rrnum = 0; rrnum < numRecords; rrnum++) { /* Expand the resource record number rrnum into rr. */ if (ns_parserr(&handle, section, rrnum, &rr)) { cpLog(LOG_DEBUG, "ns_parserr: %s, skip rr #%d\n", strerror(errno), rrnum); continue; } rrt = ns_rr_type(rr); if (rrt != ns_t_a) { cpLog(LOG_DEBUG, "skipping record num: %d, type: %d", rrnum, rrt); continue; } DnsRecord *rec = new DnsRecord; /* Expand the resource record number rrnum into rr. */ if (ns_parserr(&handle, section, rrnum, &rr)) { cpLog(LOG_INFO, "ns_parserr: %s\n", strerror(errno)); } /* Check to see if answer is authoritive */ if(!ns_msg_getflag(handle,ns_f_aa)) cpLog(LOG_INFO,"Warning: Nameserver is not authoritative.\n"); /* Set cp to point the A record. */ cp = (u_char *)ns_rr_rdata(rr); u_int32_t ip4Addr = ns_get32(cp); struct in_addr addr; // convert ip4 @ to network byte ordering addr.s_addr = htonl(ip4Addr); string strAddr = inet_ntoa( addr ); rec->setAddress( strAddr ); rec->setPriority( DEFAULT_PRIO ); rec->setWeight( DEFAULT_WT ); rec->setTarget( myQName ); cpLog(LOG_DEBUG, "\nA Record host: %s, IP4 @: %d(%s), prio: %d, wt: %d\n" "Resource Record Type: %d\n" "Record Class: %d\n" "Resource Record Time To Live (ttl): %d\n", myQName.c_str(), ip4Addr, strAddr.c_str(), rec->getPriority(), rec->getWeight(), ns_rr_type(rr), ns_rr_class(rr), ns_rr_ttl(rr)); // insert record at end of vector myVDns.push_back( rec ); // curious: what is the vector's capacity? // cpLog(LOG_DEBUG, "Capacity of myVDns = %d", myVDns.capacity()); } myNumDns = myVDns.size(); myReady = true; cpLog(LOG_DEBUG, "Number of A records found = %d\n", myNumDns);} // buildARecords()/// compare function used to sort the DNS SRV records://struct comp_srv : public binary_function< Sptr <DnsRecord>, Sptr <DnsRecord>, bool >{ bool operator() (Sptr <DnsRecord> iRec1, Sptr <DnsRecord> iRec2) { return iRec1->getPriority() < iRec2->getPriority(); }}; // comp_srv()/** */void DnsResolver::sortByPreference( ){ cpLog( LOG_DEBUG, "\nsortByPreference():\n(orig order)"); if (myVDns.size() <= 1) { // no need to sort return; } print(LOG_DEBUG_STACK); sort(myVDns.begin(), myVDns.end(), comp_srv()); cpLog( LOG_DEBUG_STACK, "\n(new order):" ); print(LOG_DEBUG_STACK);}/**/// given the start and end indices of the svr vector, sort// the elements with that range by their weights in a // random process */void DnsResolver::sortByWeight( int startIdx, int endIdx ){ Sptr <DnsRecord> tRec; // temporary cpLog( LOG_DEBUG, "sortByWeight(): startIdx=%d, endIdx=%d", startIdx,endIdx ); if (myVDns.size() <= 1) { // no need to sort return; } int sumOfWeights = addWeights( startIdx, endIdx ); if (sumOfWeights == 0) { cpLog( LOG_DEBUG, "sum of weights is 0" ); return; // nothing to sort } int j; // calculate the sum of weights for (int i = startIdx; i < endIdx; i++) { sumOfWeights = addWeights( i, endIdx ); // generate a random weight: double randWeight = (double (rand() )/RAND_MAX) * sumOfWeights; int curWeight = 0; // sum of weights so far // traverse each element till the one before the last (endIdx), // (if j == endIdx, no need to swap) for (j = i; j <= endIdx; j++) { curWeight += myVDns[j]->getWeight(); if ( randWeight < curWeight ) { // found element matching the random weight // if randWeight falls on the current start range, skip cpLog(LOG_DEBUG_STACK, "randWeight=%d, curWeight=%d, i=%d, j=%d", randWeight, curWeight, i, j ); break; } } if (j > endIdx) { j = endIdx; // make sure j is w/i range } // swap the selected element w/ the i-th element, this // sorts the range if (i != j) { tRec = myVDns[i]; myVDns[i] = myVDns[j]; myVDns[j] = tRec; } // compute sumOfWeights for i+1 through endIdx: sumOfWeights -= myVDns[i]->getWeight(); // i th element will not be con- // sidered in the next iteration }} // sortByWeight/** * */const u_char*DnsResolver::expandName(const u_char *cp, const u_char *msg, char *name, int namelen){ cpLog( LOG_DEBUG, "expandName()" ); int n=dn_expand(msg, msg + MY_PACKETSZ, cp, name, namelen - 2); if (n < 0) { return (0); } if (name[0] == '\0') { name[0] = '.'; name[1] = '\0'; } return (cp + n);} // expandName()/** * find the range of srv records that shares the same priority: * for A records, we fake the priority, default to 10 */intDnsResolver::findPriorityRange( int startIdx){ cpLog( LOG_INFO, "findPriorityRange()" ); int length = myVDns.size(); assert( startIdx < length ); int endIdx = startIdx+1; int prio = myVDns[startIdx]->getPriority(); cpLog( LOG_DEBUG, "findPriorityRange(): prio=%d, startIdx=%d", prio, startIdx ); while ((endIdx < length) &&(prio == myVDns[endIdx]->getPriority())) { endIdx++; } return endIdx-1;} // findPriorityRange()/** calculate the total sum of the weights */int DnsResolver::addWeights( int startIdx, int endIdx ){ int sumOfWeights = 0; for (int x = startIdx; x <= endIdx; x++) { sumOfWeights += myVDns[x]->getWeight(); } return sumOfWeights;} // addWeights()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -