|
reSIProcate/rutil
9694
|


Public Types | |
| enum | { MAX_REQUERIES = 5 } |
Public Member Functions | |
| Query (DnsStub &stub, ResultTransform *transform, ResultConverter *resultConv, const Data &target, int rrType, bool followCname, int proto, DnsResultSink *s) | |
| virtual | ~Query () |
| void | go () |
| void | process (int status, const unsigned char *abuf, const int alen) |
| void | onDnsRaw (int status, const unsigned char *abuf, int alen) |
| void | followCname (const unsigned char *aptr, const unsigned char *abuf, const int alen, bool &bGotAnswers, bool &bDeleteThis, Data &targetToQuery) |
Private Attributes | |
| int | mRRType |
| DnsStub & | mStub |
| ResultTransform * | mTransform |
| ResultConverter * | mResultConverter |
| Data | mTarget |
| int | mProto |
| int | mReQuery |
| DnsResultSink * | mSink |
| bool | mFollowCname |
Static Private Attributes | |
| static DnsResourceRecordsByPtr | Empty |
Definition at line 233 of file DnsStub.hxx.
| anonymous enum |
| DnsStub::Query::Query | ( | DnsStub & | stub, |
| ResultTransform * | transform, | ||
| ResultConverter * | resultConv, | ||
| const Data & | target, | ||
| int | rrType, | ||
| bool | followCname, | ||
| int | proto, | ||
| DnsResultSink * | s | ||
| ) |
Definition at line 398 of file DnsStub.cxx.
: mRRType(rrType), mStub(stub), mTransform(transform), mResultConverter(resultConv), mTarget(target), mProto(proto), mReQuery(0), mSink(s), mFollowCname(followCname) { assert(s); }
| DnsStub::Query::~Query | ( | ) | [virtual] |
Definition at line 414 of file DnsStub.cxx.
{
delete mResultConverter; //.dcm. flyweight?
}
| void DnsStub::Query::followCname | ( | const unsigned char * | aptr, |
| const unsigned char * | abuf, | ||
| const int | alen, | ||
| bool & | bGotAnswers, | ||
| bool & | bDeleteThis, | ||
| Data & | targetToQuery | ||
| ) |
Definition at line 684 of file DnsStub.cxx.
References ErrLog, and resip::BaseException::getMessage().
{
bGotAnswers = true;
bDeleteThis = true;
char* name = 0;
long len = 0;
if (ARES_SUCCESS != ares_expand_name(aptr, abuf, alen, &name, &len))
{
ErrLog(<< "Failed DNS preparse for " << targetToQuery);
mResultConverter->notifyUser(mTarget, ARES_EFORMERR, "Failed DNS preparse", Empty, mSink);
bGotAnswers = false;
return;
}
targetToQuery = name;
aptr += len;
try
{
mStub.cache(name, abuf, alen);
}
catch (BaseException& e)
{
ErrLog(<< "Failed to cache result for " << targetToQuery << ": " << e.getMessage());
mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink);
bGotAnswers = false;
return;
}
if (mRRType != T_CNAME)
{
if (DNS_RR_TYPE(aptr) == T_CNAME)
{
if (mFollowCname && mReQuery < MAX_REQUERIES)
{
++mReQuery;
int status = 0;
bool cached = false;
do
{
DnsResourceRecordsByPtr cnames;
cached = mStub.mRRCache.lookup(targetToQuery, T_CNAME, mProto, cnames, status);
if (cached)
{
++mReQuery;
targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname();
}
} while(mReQuery < MAX_REQUERIES && cached);
DnsResourceRecordsByPtr result;
if (!mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, result, status))
{
mStub.lookupRecords(targetToQuery, mRRType, this);
bDeleteThis = false;
bGotAnswers = false;
}
}
else
{
mReQuery = 0;
mResultConverter->notifyUser(mTarget, 1, mStub.errorMessage(1), Empty, mSink);
bGotAnswers = false;
}
}
}
free(name);
}

| void DnsStub::Query::go | ( | ) |
Definition at line 452 of file DnsStub.cxx.
References resip::Data::c_str(), resip::DnsStub::mTransform, StackLog, T_A, resip::DnsStub::ResultTransform::transform(), and typeToData().
Referenced by resip::DnsStub::query().
{
StackLog(<< "DNS query of:" << mTarget << " " << typeToData(mRRType));
DnsResourceRecordsByPtr records;
int status = 0;
bool cached = false;
Data targetToQuery = mTarget;
cached = mStub.mRRCache.lookup(mTarget, mRRType, mProto, records, status);
if (!cached)
{
if (mRRType != T_CNAME)
{
do
{
DnsResourceRecordsByPtr cnames;
cached = mStub.mRRCache.lookup(targetToQuery, T_CNAME, mProto, cnames, status);
if (cached)
{
targetToQuery = (dynamic_cast<DnsCnameRecord*>(cnames[0]))->cname();
}
} while(cached);
}
}
if (targetToQuery != mTarget)
{
StackLog(<< mTarget << " mapped to CNAME " << targetToQuery);
cached = mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, records, status);
}
if (!cached)
{
if(mStub.mDnsProvider && mStub.mDnsProvider->hostFileLookupLookupOnlyMode())
{
assert(mRRType == T_A);
StackLog (<< targetToQuery << " not cached. Doing hostfile lookup");
in_addr address;
if (mStub.mDnsProvider->hostFileLookup(targetToQuery.c_str(), address))
{
mStub.cache(mTarget, address);
DnsResourceRecordsByPtr result;
int queryStatus = 0;
mStub.mRRCache.lookup(mTarget, mRRType, mProto, result, queryStatus);
if (mTransform)
{
mTransform->transform(mTarget, mRRType, result);
}
mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink);
}
else
{
// Not in hosts file - return error - or.. we could fallback to doing the lookupRecords call on the local named
mResultConverter->notifyUser(mTarget, ARES_ENOTFOUND, mStub.errorMessage(ARES_ENOTFOUND), Empty, mSink);
}
mReQuery = 0;
mStub.removeQuery(this);
delete this;
return;
}
else
{
StackLog (<< targetToQuery << " not cached. Doing external dns lookup");
mStub.lookupRecords(targetToQuery, mRRType, this);
}
}
else // is cached
{
if (mTransform && !records.empty())
{
mTransform->transform(mTarget, mRRType, records);
}
mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), records, mSink);
mStub.removeQuery(this);
delete this;
}
}

| void DnsStub::Query::onDnsRaw | ( | int | status, |
| const unsigned char * | abuf, | ||
| int | alen | ||
| ) | [virtual] |
Implements resip::DnsRawSink.
Definition at line 678 of file DnsStub.cxx.
References resip::DnsStub::process().
{
process(status, abuf, alen);
}

| void DnsStub::Query::process | ( | int | status, |
| const unsigned char * | abuf, | ||
| const int | alen | ||
| ) |
Definition at line 534 of file DnsStub.cxx.
References DebugLog, ErrLog, resip::BaseException::getMessage(), InfoLog, resip::DnsStub::mTransform, T_A, and resip::DnsStub::ResultTransform::transform().
{
if (status != 0)
{
switch (status)
{
case ARES_ENODATA:
case ARES_EFORMERR:
case ARES_ESERVFAIL:
case ARES_ENOTFOUND:
case ARES_ENOTIMP:
case ARES_EREFUSED:
if(mRRType == T_A)
{
in_addr address;
if (mStub.mDnsProvider->hostFileLookup(mTarget.c_str(), address))
{
mStub.cache(mTarget, address);
mReQuery = 0;
DnsResourceRecordsByPtr result;
int queryStatus = 0;
mStub.mRRCache.lookup(mTarget, mRRType, mProto, result, queryStatus);
if (mTransform)
{
mTransform->transform(mTarget, mRRType, result);
}
mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink);
mStub.removeQuery(this);
delete this;
return;
}
}
try
{
mStub.cacheTTL(mTarget, mRRType, status, abuf, alen);
}
catch (BaseException& e)
{
// if the response isn't parsable, we might want to consider caching
// TTL anyways to delay the query attempt for this record.
ErrLog(<< "Couldn't parse failure response to lookup for " << mTarget);
InfoLog(<< e.getMessage());
}
break;
case ARES_ECONNREFUSED:
case ARES_ETIMEOUT:
ErrLog (<< "Connection error " << mStub.errorMessage(status) << " for " << mTarget);
break;
case ARES_EBADRESP:
ErrLog (<< "Server response error " << mStub.errorMessage(status) << " for " << mTarget);
break;
case ARES_EOF:
case ARES_EFILE:
case ARES_ENOMEM:
case ARES_EDESTRUCTION:
ErrLog (<< "Error " << mStub.errorMessage(status) << " for " << mTarget);
break;
case ARES_EBADNAME:
ErrLog(<< "Garbage hostname failed to resolve: " << mStub.errorMessage(status) << " for " << mTarget);
break;
case ARES_EBADQUERY:
ErrLog(<< "Query was malformed (probably because hostname was "
"too long) " << mStub.errorMessage(status) << " for "
<< mTarget);
break;
case ARES_EBADFAMILY:
ErrLog (<< "Bad lookup type " << mStub.errorMessage(status) << " for " << mTarget);
// .bwc. This should not happen. If it does, we have code to fix.
assert(0);
break;
default:
ErrLog (<< "Unknown error " << mStub.errorMessage(status) << " for " << mTarget);
assert(0);
break;
}
// For other error status values, we may also want to cacheTTL to delay
// requeries. Especially if the server refuses.
mResultConverter->notifyUser(mTarget, status, mStub.errorMessage(status), Empty, mSink);
mReQuery = 0;
mStub.removeQuery(this);
delete this;
return;
}
bool bDeleteThis = true;
// skip header
const unsigned char* aptr = abuf + HFIXEDSZ;
int qdcount = DNS_HEADER_QDCOUNT(abuf); // questions.
for (int i = 0; i < qdcount && aptr; ++i)
{
try
{
aptr = mStub.skipDNSQuestion(aptr, abuf, alen);
}
catch (BaseException& e)
{
ErrLog(<< "Error parsing DNS record for " << mTarget << ": " << e.getMessage());
mResultConverter->notifyUser(mTarget, ARES_EFORMERR, e.getMessage(), Empty, mSink);
mStub.removeQuery(this);
delete this;
return;
}
}
int ancount = DNS_HEADER_ANCOUNT(abuf);
if (ancount == 0)
{
mResultConverter->notifyUser(mTarget, 0, mStub.errorMessage(0), Empty, mSink);
}
else
{
bool bGotAnswers = true;
Data targetToQuery;
followCname(aptr, abuf, alen, bGotAnswers, bDeleteThis, targetToQuery);
if (bGotAnswers)
{
mReQuery = 0;
DnsResourceRecordsByPtr result;
int queryStatus = 0;
if (mTarget != targetToQuery) DebugLog (<< mTarget << " mapped to " << targetToQuery << " and returned result");
mStub.mRRCache.lookup(targetToQuery, mRRType, mProto, result, queryStatus);
if (mTransform)
{
mTransform->transform(mTarget, mRRType, result);
}
mResultConverter->notifyUser(mTarget, queryStatus, mStub.errorMessage(queryStatus), result, mSink);
}
}
if (bDeleteThis)
{
mStub.removeQuery(this);
delete this;
}
}

DnsStub::DnsResourceRecordsByPtr DnsStub::Query::Empty [static, private] |
Definition at line 248 of file DnsStub.hxx.
bool resip::DnsStub::Query::mFollowCname [private] |
Definition at line 257 of file DnsStub.hxx.
int resip::DnsStub::Query::mProto [private] |
Definition at line 254 of file DnsStub.hxx.
int resip::DnsStub::Query::mReQuery [private] |
Definition at line 255 of file DnsStub.hxx.
Definition at line 252 of file DnsStub.hxx.
int resip::DnsStub::Query::mRRType [private] |
Definition at line 249 of file DnsStub.hxx.
DnsResultSink* resip::DnsStub::Query::mSink [private] |
Definition at line 256 of file DnsStub.hxx.
DnsStub& resip::DnsStub::Query::mStub [private] |
Definition at line 250 of file DnsStub.hxx.
Data resip::DnsStub::Query::mTarget [private] |
Definition at line 253 of file DnsStub.hxx.
ResultTransform* resip::DnsStub::Query::mTransform [private] |
Definition at line 251 of file DnsStub.hxx.
1.7.5.1