/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "runtime/ErrorMgr.h"
#include "runtime/LogComment.h"
#include "runtime/polyErrors.h"
#include "dns/DnsMgr.h"
#include "dns/DnsQuery.h"
#include "dns/DnsResp.h"
#include "dns/DnsXact.h"
DnsXact::DnsXact() {
reset();
}
DnsXact::~DnsXact() {
Assert(!theOwner);
}
// note: keep in syn with partial reset in DnsXact::retry()!
void DnsXact::reset() {
Assert(!thePendAlarmCnt);
theOwner = 0;
theReason = 0;
theQueryAddr = theRespAddr = NetAddr();
theTimeout = Time();
theId = theIdx = -1;
theTryCount = 0;
doRetry = false;
}
void DnsXact::exec(DnsMgr *anOwner, const NetAddr &ns) {
Assert(!theOwner && anOwner);
theOwner = anOwner;
exec(ns);
}
void DnsXact::retry(const NetAddr &ns) {
Assert(theOwner && theReason);
// partial reset
theRespAddr = NetAddr();
doRetry = false;
exec(ns);
}
void DnsXact::exec(const NetAddr &ns) {
Assert(ns);
theId = DnsMsg::NextId();
theTryCount++;
DnsQuery q(theType);
q.queryAddr(theQueryAddr);
q.id(theId);
if (Should(q.sendTo(ns, theOwner->socket()))) {
if (theTimeout >= 0)
sleepFor(theTimeout);
} else {
// try again ASAP
doRetry = true;
sleepFor(Time(0,0));
}
}
void DnsXact::wakeUp(const Alarm &a) {
AlarmUser::wakeUp(a);
// note: doRetry may be set in DnsXact::exec to postpone finish
if (!doRetry) {
doRetry = true;
if (ReportError(errDnsRepTimeout)) {
Comment << theOwner->addr() << " failed to lookup "
<< theQueryAddr << " after " << theTryCount << " attempts; "
<< "last req id: " << theId << endc;
}
}
finish();
}
void DnsXact::noteReply(const DnsResp &rep) {
cancelAlarms();
if (rep.error()) {
if (ReportError(rep.error()))
Comment << "DNS error while resolving " << theQueryAddr << endc;
// XXX: when to retry?
} else
if (rep.queryAddr().sameButPort(theQueryAddr)) {
Assert(rep.answers().count() > 0);
Should(rep.answers().count() == 1);
theRespAddr = *rep.answers()[0];
theRespAddr.port(theQueryAddr.port());
doRetry = false;
} else {
if (ReportError(errDnsRepMismatch))
Comment << "asked for " << theQueryAddr << ", got response for " << rep.queryAddr() << endc;
doRetry = true;
}
finish();
}
void DnsXact::finish() {
DnsMgr *owner = theOwner;
theOwner = 0;
owner->noteXactDone(this);
}
int DnsXact::logCat() const {
Assert(theOwner);
return theOwner->logCat();
}
syntax highlighted by Code2HTML, v. 0.9.1