📄 pdns.cxx
字号:
PObject::Comparison PDNS::SRVRecord::Compare(const PObject & obj) const
{
const SRVRecord * other = dynamic_cast<const SRVRecord *>(&obj);
if (other == NULL)
return LessThan;
if (priority < other->priority)
return LessThan;
else if (priority > other->priority)
return GreaterThan;
if (weight < other->weight)
return LessThan;
else if (weight > other->weight)
return GreaterThan;
return EqualTo;
}
void PDNS::SRVRecord::PrintOn(ostream & strm) const
{
strm << "host=" << hostName << ":" << port << "(" << hostAddress << "), "
<< "priority=" << priority << ", "
<< "weight=" << weight;
}
/////////////////////////////////////////////////
PDNS::SRVRecord * PDNS::SRVRecordList::HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results)
{
PDNS::SRVRecord * record = NULL;
if (
(dnsRecord->Flags.S.Section == DnsSectionAnswer) &&
(dnsRecord->wType == DNS_TYPE_SRV) &&
(strlen(dnsRecord->Data.SRV.pNameTarget) > 0) &&
(strcmp(dnsRecord->Data.SRV.pNameTarget, ".") != 0)
) {
record = new SRVRecord();
record->hostName = PString(dnsRecord->Data.SRV.pNameTarget);
record->port = dnsRecord->Data.SRV.wPort;
record->priority = dnsRecord->Data.SRV.wPriority;
record->weight = dnsRecord->Data.SRV.wWeight;
// see if any A records match this hostname
PDNS_RECORD aRecord = results;
while (aRecord != NULL) {
if ((dnsRecord->Flags.S.Section == DnsSectionAddtional) && (dnsRecord->wType == DNS_TYPE_A)) {
record->hostAddress = PIPSocket::Address(dnsRecord->Data.A.IpAddress);
break;
}
aRecord = aRecord->pNext;
}
// if no A record found, then get address the hard way
if (aRecord == NULL)
PIPSocket::GetHostAddress(record->hostName, record->hostAddress);
}
return record;
}
void PDNS::SRVRecordList::PrintOn(ostream & strm) const
{
PINDEX i;
for (i = 0; i < GetSize(); i++)
strm << (*this)[i] << endl;
}
PDNS::SRVRecord * PDNS::SRVRecordList::GetFirst()
{
if (GetSize() == 0)
return NULL;
// create a list of all prioities, to save time
priPos = 0;
priList.SetSize(0);
PINDEX i;
if (GetSize() > 0) {
priList.SetSize(1);
WORD lastPri = (*this)[0].priority;
priList[0] = lastPri;
(*this)[0].used = FALSE;
for (i = 1; i < GetSize(); i++) {
(*this)[i].used = FALSE;
if ((*this)[i].priority != lastPri) {
priPos++;
priList.SetSize(priPos);
lastPri = (*this)[i].priority;
priList[priPos] = lastPri;
}
}
}
priPos = 0;
return GetNext();
}
PDNS::SRVRecord * PDNS::SRVRecordList::GetNext()
{
if (priList.GetSize() == 0)
return NULL;
while (priPos < priList.GetSize()) {
WORD currentPri = priList[priPos];
// find first record at current priority
PINDEX firstPos;
for (firstPos = 0; (firstPos < GetSize()) && ((*this)[firstPos].priority != currentPri); firstPos++)
;
if (firstPos == GetSize())
return NULL;
// calculate total of all unused weights at this priority
unsigned totalWeight = (*this)[firstPos].weight;
PINDEX i = firstPos + 1;
PINDEX count = 1;
while (i < GetSize() && ((*this)[i].priority == currentPri)) {
if (!(*this)[i].used) {
totalWeight += (*this)[i].weight;
count ++;
}
++i;
}
// if no matches found, go to the next priority level
if (count == 0) {
priPos++;
continue;
}
// selected the correct item
if (totalWeight > 0) {
unsigned targetWeight = PRandom::Number() % (totalWeight+1);
totalWeight = 0;
for (i = 0; i < GetSize() && ((*this)[i].priority == currentPri); i++) {
if (!(*this)[i].used) {
totalWeight += (*this)[i].weight;
if (totalWeight >= targetWeight) {
(*this)[i].used = TRUE;
return &(*this)[i];
}
}
}
}
// pick a random item at this priority
PINDEX j = firstPos + ((count == 0) ? 0 : (PRandom::Number() % count) );
count = 0;
for (i = 0; i < GetSize() && ((*this)[i].priority == currentPri); i++) {
if (!(*this)[i].used) {
if (count == j) {
(*this)[i].used = TRUE;
return &(*this)[i];
}
count++;
}
}
// go to the next priority level
priPos++;
}
return NULL;
}
BOOL PDNS::GetSRVRecords(
const PString & _service,
const PString & type,
const PString & domain,
PDNS::SRVRecordList & recordList
)
{
if (_service.IsEmpty())
return FALSE;
PStringStream service;
if (_service[0] != '_')
service << '_';
service << _service << "._" << type << '.' << domain;
return GetSRVRecords(service, recordList);
}
BOOL PDNS::LookupSRV(
const PURL & url,
const PString & service,
PStringList & returnList)
{
WORD defaultPort = url.GetPort();
PIPSocketAddressAndPortVector info;
if (!LookupSRV(url.GetHostName(), service, defaultPort, info)) {
PTRACE(6,"DNS\tSRV Lookup Fail no domain " << url );
return FALSE;
}
PString user = url.GetUserName();
if (user.GetLength() > 0)
user = user + "@";
PIPSocketAddressAndPortVector::const_iterator r;
for (r = info.begin(); r != info.end(); ++r)
returnList.AppendString(user + r->address.AsString() + ":" + PString(PString::Unsigned, r->port));
return returnList.GetSize() != 0;;
}
BOOL PDNS::LookupSRV(
const PString & domain, ///< domain to lookup
const PString & service, ///< service to use
WORD defaultPort, ///< default port to use
PIPSocketAddressAndPortVector & addrList ///< list of sockets and ports
)
{
if (domain.GetLength() == 0) {
PTRACE(6,"DNS\tSRV lookup failed - cannot resolve hostname " << domain);
return FALSE;
}
PTRACE(6,"DNS\tSRV Lookup " << domain << " service " << service);
PDNS::SRVRecordList srvRecords;
PString srvLookupStr = service;
if (srvLookupStr.Right(1) != ".")
srvLookupStr += ".";
srvLookupStr += domain;
BOOL found = PDNS::GetRecords(srvLookupStr, srvRecords);
if (found) {
PTRACE(6,"DNS\tSRV Record found " << domain << " service " << service);
PDNS::SRVRecord * recPtr = srvRecords.GetFirst();
while (recPtr != NULL) {
PIPSocketAddressAndPort addrAndPort;
addrAndPort.address = recPtr->hostAddress;
if (recPtr->port > 0)
addrAndPort.port = recPtr->port;
else
addrAndPort.port = defaultPort;
addrList.push_back(addrAndPort);
recPtr = srvRecords.GetNext();
}
}
return found;
}
///////////////////////////////////////////////////////
PObject::Comparison PDNS::MXRecord::Compare(const PObject & obj) const
{
const MXRecord * other = dynamic_cast<const MXRecord *>(&obj);
if (other == NULL)
return LessThan;
if (preference < other->preference)
return LessThan;
else if (preference > other->preference)
return GreaterThan;
return EqualTo;
}
void PDNS::MXRecord::PrintOn(ostream & strm) const
{
strm << "host=" << hostName << "(" << hostAddress << "), "
<< "preference=" << preference;
}
///////////////////////////////////////////////////////
PDNS::MXRecord * PDNS::MXRecordList::HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results)
{
MXRecord * record = NULL;
if (
(dnsRecord->Flags.S.Section == DnsSectionAnswer) &&
(dnsRecord->wType == DNS_TYPE_MX) &&
(strlen(dnsRecord->Data.MX.pNameExchange) > 0)
) {
record = new MXRecord();
record->hostName = PString(dnsRecord->Data.MX.pNameExchange);
record->preference = dnsRecord->Data.MX.wPreference;
// see if any A records match this hostname
PDNS_RECORD aRecord = results;
while (aRecord != NULL) {
if ((dnsRecord->Flags.S.Section == DnsSectionAddtional) && (dnsRecord->wType == DNS_TYPE_A)) {
record->hostAddress = PIPSocket::Address(dnsRecord->Data.A.IpAddress);
break;
}
aRecord = aRecord->pNext;
}
// if no A record found, then get address the hard way
if (aRecord == NULL)
PIPSocket::GetHostAddress(record->hostName, record->hostAddress);
}
return record;
}
void PDNS::MXRecordList::PrintOn(ostream & strm) const
{
PINDEX i;
for (i = 0; i < GetSize(); i++)
strm << (*this)[i] << endl;
}
PDNS::MXRecord * PDNS::MXRecordList::GetFirst()
{
PINDEX i;
for (i = 0; i < GetSize(); i++)
(*this)[i].used = FALSE;
lastIndex = 0;
return GetNext();
}
PDNS::MXRecord * PDNS::MXRecordList::GetNext()
{
if (GetSize() == 0)
return NULL;
if (lastIndex >= GetSize())
return NULL;
return (PDNS::MXRecord *)GetAt(lastIndex++);
}
#endif // P_DNS
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -