Commit bf38ef9c authored by Michal Vaner's avatar Michal Vaner
Browse files

An interface change to pass back timeouts

This change will allow passing a timeout (and, in future, possibly more
errors) from UDPQuery. UDPQuery no longer needs a server to resume, it
can call anything that is passed there.

The interface change propagation is stopped directly above it by a hack.
Maybe it will propagate more or the Callback will be more general (not
just for UDPQuery).

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/vorner-recursor-timeouts@3393 e5f2f494-b856-4b98-b285-d166d9295462
parent 99c244d9
......@@ -227,6 +227,18 @@ RecursiveQuery::RecursiveQuery(DNSService& dns_service, const char& forward,
dns_service_(dns_service), ns_addr_(&forward), port_(port)
{}
namespace {
// This is just temporary so the interface change does not propagate too far
struct ServerNotify : public UDPQuery::Callback {
DNSServer *server;
virtual void operator()(UDPQuery::Result result) {
server->resume(result == UDPQuery::SUCCESS);
}
};
}
void
RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
DNSServer* server)
......@@ -237,7 +249,11 @@ RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
// UDP and then fall back to TCP on failure, but for the moment
// we're only going to handle UDP.
asio::io_service& io = dns_service_.get_io_service();
UDPQuery q(io, question, ns_addr_, port_, buffer, server);
boost::shared_ptr<ServerNotify> callback(new ServerNotify);
// FIXME This is said it does problems when it is shared pointer, as
// it is destroyed too soon. But who deletes it now?
callback->server = server->clone();
UDPQuery q(io, question, ns_addr_, port_, buffer, callback);
io.post(q);
}
......
......@@ -180,11 +180,28 @@ private:
//
class UDPQuery : public coroutine {
public:
// TODO Maybe this should be more generic than just for UDPQuery?
/**
* \short Result of the query
*
* This is related only to contacting the remote server. If the answer
* indicates error, it is still counted as SUCCESS here, if it comes back.
*/
enum Result {
SUCCESS,
TIME_OUT
};
/// Abstract callback for the UDPQuery.
class Callback {
public:
/// This will be called when the UDPQuery is completed
virtual void operator()(Result result) = 0;
};
explicit UDPQuery(asio::io_service& io_service,
const isc::dns::Question& q,
const IOAddress& addr, uint16_t port,
isc::dns::OutputBufferPtr buffer,
DNSServer* server);
boost::shared_ptr<Callback> callback, int timeout = -1);
void operator()(asio::error_code ec = asio::error_code(),
size_t length = 0);
private:
......@@ -211,20 +228,15 @@ private:
// The output buffer supplied by the caller. The resposne frmo
// the upstream server will be copied here.
isc::dns::OutputBufferPtr buffer_;;
isc::dns::OutputBufferPtr buffer_;
// These are allocated for each new query and are stored as
// shared pointers to minimize copy overhead.
isc::dns::OutputBufferPtr msgbuf_;
boost::shared_array<char> data_;
// The UDP or TCP Server object from which the query originated.
// Note: Using a shared_ptr for this can cause problems when
// control is being transferred from this coroutine to the server;
// the reference count can drop to zero and cause the server to be
// destroyed before it executes. Consequently in this case it's
// safer to use a raw pointer.
DNSServer* server_;
// This will be called when we are done.
boost::shared_ptr<Callback> callback_;
};
}
......
......@@ -176,8 +176,9 @@ UDPServer::resume(const bool done) {
/// The constructor
UDPQuery::UDPQuery(io_service& io_service,
const Question& q, const IOAddress& addr, uint16_t port,
OutputBufferPtr buffer, DNSServer* server) :
question_(q), buffer_(buffer), server_(server->clone())
OutputBufferPtr buffer,
boost::shared_ptr<Callback> callback, int timeout) :
question_(q), buffer_(buffer), callback_(callback)
{
udp proto = (addr.getFamily() == AF_INET) ? udp::v4() : udp::v6();
socket_.reset(new udp::socket(io_service, proto));
......@@ -232,8 +233,8 @@ UDPQuery::operator()(error_code ec, size_t length) {
/// be unnecessary.)
buffer_->writeData(data_.get(), length);
/// Signal the DNSServer object to resume processing.
server_->resume(true);
/// We are done
(*callback_)(SUCCESS);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment