Commit 9bc9618f authored by Evan Hunt's avatar Evan Hunt

Cleanup: Added lots of documentation to libasiolink; improved some

variable names and class names.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac327@3115 e5f2f494-b856-4b98-b285-d166d9295462
parent f60239a8
......@@ -132,7 +132,7 @@ class MessageLookup : public DNSLookup {
public:
MessageLookup(AuthSrv* srv) : server_(srv) {}
virtual void operator()(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer, IOServer* server) const
OutputBufferPtr buffer, DNSServer* server) const
{
server_->processMessage(io_message, message, buffer, server);
}
......@@ -167,10 +167,10 @@ private:
AuthSrv* server_;
};
// This is a derived class of \c IOCallback, to serve
// This is a derived class of \c SimpleCallback, to serve
// as a callback in the asiolink module. It checks for queued
// configuration messages, and executes them if found.
class ConfigChecker : public IOCallback {
class ConfigChecker : public SimpleCallback {
public:
ConfigChecker(AuthSrv* srv) : server_(srv) {}
virtual void operator()(const IOMessage& io_message UNUSED_PARAM) const {
......@@ -184,14 +184,14 @@ private:
AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client) :
impl_(new AuthSrvImpl(use_cache, xfrout_client)),
checkin_provider_(new ConfigChecker(this)),
checkin_(new ConfigChecker(this)),
dns_lookup_(new MessageLookup(this)),
dns_answer_(new MessageAnswer(this))
{}
AuthSrv::~AuthSrv() {
delete impl_;
delete checkin_provider_;
delete checkin_;
delete dns_lookup_;
delete dns_answer_;
}
......@@ -276,7 +276,7 @@ AuthSrv::configSession() const {
void
AuthSrv::processMessage(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer, IOServer* server)
OutputBufferPtr buffer, DNSServer* server)
{
InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
......
......@@ -63,7 +63,7 @@ public:
void processMessage(const asiolink::IOMessage& io_message,
isc::dns::MessagePtr message,
isc::dns::OutputBufferPtr buffer,
asiolink::IOServer* server);
asiolink::DNSServer* server);
void setVerbose(bool on);
bool getVerbose() const;
isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
......@@ -79,8 +79,8 @@ public:
asiolink::DNSAnswer* getDNSAnswerProvider() const {
return (dns_answer_);
}
asiolink::IOCallback* getCheckinProvider() const {
return (checkin_provider_);
asiolink::SimpleCallback* getCheckinProvider() const {
return (checkin_);
}
///
......@@ -100,7 +100,7 @@ public:
private:
AuthSrvImpl* impl_;
asiolink::IOService* io_service_;
asiolink::IOCallback* checkin_provider_;
asiolink::SimpleCallback* checkin_;
asiolink::DNSLookup* dns_lookup_;
asiolink::DNSAnswer* dns_answer_;
};
......
......@@ -177,7 +177,7 @@ main(int argc, char* argv[]) {
auth_server->setVerbose(verbose_mode);
cout << "[b10-auth] Server created." << endl;
IOCallback* checkin = auth_server->getCheckinProvider();
SimpleCallback* checkin = auth_server->getCheckinProvider();
DNSLookup* lookup = auth_server->getDNSLookupProvider();
DNSAnswer* answer = auth_server->getDNSAnswerProvider();
......
......@@ -123,7 +123,7 @@ private:
};
// A nonoperative task object to be used in calls to processMessage()
class MockTask : public IOServer {
class MockTask : public DNSServer {
public:
MockTask() : done_(false) {}
void operator()(asio::error_code ec UNUSED_PARAM,
......
......@@ -175,7 +175,7 @@ main(int argc, char* argv[]) {
recursor ->setVerbose(verbose_mode);
cout << "[b10-recurse] Server created." << endl;
IOCallback* checkin = recursor->getCheckinProvider();
SimpleCallback* checkin = recursor->getCheckinProvider();
DNSLookup* lookup = recursor->getDNSLookupProvider();
DNSAnswer* answer = recursor->getDNSAnswerProvider();
......
......@@ -64,7 +64,7 @@ private:
public:
RecursorImpl(const char& forward) :
config_session_(NULL), verbose_mode_(false),
forward_(forward), ioquery_()
forward_(forward), rec_query_()
{}
~RecursorImpl() {
......@@ -72,19 +72,19 @@ public:
}
void querySetup(IOService& ios) {
ioquery_ = new IOQuery(ios, forward_);
rec_query_ = new RecursiveQuery(ios, forward_);
}
void queryShutdown() {
if (ioquery_) {
delete ioquery_;
if (rec_query_) {
delete rec_query_;
}
}
void processNormalQuery(const IOMessage& io_message,
const Question& question, MessagePtr message,
OutputBufferPtr buffer,
IOServer* server);
DNSServer* server);
ModuleCCSession* config_session_;
bool verbose_mode_;
......@@ -93,7 +93,7 @@ public:
const char& forward_;
/// Object to handle upstream queries
IOQuery* ioquery_;
RecursiveQuery* rec_query_;
/// Currently non-configurable, but will be.
static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
......@@ -171,7 +171,7 @@ public:
// \brief Handle the DNS Lookup
virtual void operator()(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer, IOServer* server) const
OutputBufferPtr buffer, DNSServer* server) const
{
server_->processMessage(io_message, message, buffer, server);
}
......@@ -264,10 +264,10 @@ private:
Recursor* server_;
};
// This is a derived class of \c IOCallback, to serve
// This is a derived class of \c SimpleCallback, to serve
// as a callback in the asiolink module. It checks for queued
// configuration messages, and executes them if found.
class ConfigCheck : public IOCallback {
class ConfigCheck : public SimpleCallback {
public:
ConfigCheck(Recursor* srv) : server_(srv) {}
virtual void operator()(const IOMessage& io_message UNUSED_PARAM) const {
......@@ -322,7 +322,7 @@ Recursor::configSession() const {
void
Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer, IOServer* server)
OutputBufferPtr buffer, DNSServer* server)
{
InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
// First, check the header part. If we fail even for the base header,
......@@ -403,8 +403,8 @@ Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
} else {
// The IOQuery object will post the "resume" event to the
// IOServer when an answer arrives, so we don't have to do it now.
// The RecursiveQuery object will post the "resume" event to the
// DNSServer when an answer arrives, so we don't have to do it now.
sendAnswer = false;
impl_->processNormalQuery(io_message, *question, message,
buffer, server);
......@@ -419,7 +419,7 @@ Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
void
RecursorImpl::processNormalQuery(const IOMessage& io_message,
const Question& question, MessagePtr message,
OutputBufferPtr buffer, IOServer* server)
OutputBufferPtr buffer, DNSServer* server)
{
const bool dnssec_ok = message->isDNSSECSupported();
......@@ -428,7 +428,7 @@ RecursorImpl::processNormalQuery(const IOMessage& io_message,
message->setRcode(Rcode::NOERROR());
message->setDNSSECSupported(dnssec_ok);
message->setUDPSize(RecursorImpl::DEFAULT_LOCAL_UDPSIZE);
ioquery_->sendQuery(io_message, question, buffer, server);
rec_query_->sendQuery(io_message, question, buffer, server);
}
ConstElementPtr
......
......@@ -61,7 +61,7 @@ public:
void processMessage(const asiolink::IOMessage& io_message,
isc::dns::MessagePtr message,
isc::dns::OutputBufferPtr buffer,
asiolink::IOServer* server);
asiolink::DNSServer* server);
void setVerbose(bool on);
bool getVerbose() const;
isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
......@@ -77,14 +77,14 @@ public:
asiolink::DNSAnswer* getDNSAnswerProvider() {
return (dns_answer_);
}
asiolink::IOCallback* getCheckinProvider() {
asiolink::SimpleCallback* getCheckinProvider() {
return (checkin_);
}
private:
RecursorImpl* impl_;
asiolink::IOService* io_;
asiolink::IOCallback* checkin_;
asiolink::SimpleCallback* checkin_;
asiolink::DNSLookup* dns_lookup_;
asiolink::DNSAnswer* dns_answer_;
};
......
......@@ -95,7 +95,7 @@ private:
};
// A nonoperative task object to be used in calls to processMessage()
class MockTask : public IOServer {
class MockTask : public DNSServer {
public:
MockTask() : done_(false) {}
void operator()(asio::error_code ec UNUSED_PARAM,
......
......@@ -93,7 +93,7 @@ IOMessage::IOMessage(const void* data, const size_t data_size,
remote_endpoint_(remote_endpoint)
{}
IOQuery::IOQuery(IOService& io_service, const char& forward) :
RecursiveQuery::RecursiveQuery(IOService& io_service, const char& forward) :
io_service_(io_service)
{
error_code err;
......@@ -105,9 +105,9 @@ IOQuery::IOQuery(IOService& io_service, const char& forward) :
}
void
IOQuery::sendQuery(const IOMessage& io_message,
const Question& question, OutputBufferPtr buffer,
IOServer* server)
RecursiveQuery::sendQuery(const IOMessage& io_message,
const Question& question, OutputBufferPtr buffer,
DNSServer* server)
{
// XXX: eventually we will need to be able to determine whether
......@@ -123,7 +123,7 @@ class IOServiceImpl {
public:
IOServiceImpl(const char& port,
const ip::address* v4addr, const ip::address* v6addr,
IOCallback* checkin, DNSLookup* lookup,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer);
asio::io_service io_service_;
......@@ -138,7 +138,7 @@ public:
IOServiceImpl::IOServiceImpl(const char& port,
const ip::address* const v4addr,
const ip::address* const v6addr,
IOCallback* checkin,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
udp4_server_(UDPServerPtr()), udp6_server_(UDPServerPtr()),
......@@ -191,7 +191,7 @@ IOServiceImpl::IOServiceImpl(const char& port,
}
IOService::IOService(const char& port, const char& address,
IOCallback* checkin,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
impl_(NULL)
......@@ -211,7 +211,7 @@ IOService::IOService(const char& port, const char& address,
IOService::IOService(const char& port,
const bool use_ipv4, const bool use_ipv6,
IOCallback* checkin,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
impl_(NULL)
......
......@@ -70,9 +70,9 @@ class io_service;
/// to the ASIO counterparts.
///
/// Notes to developers:
/// Currently the wrapper interface is specific to the authoritative
/// server implementation. But the plan is to generalize it and have
/// other modules use it.
/// Currently the wrapper interface is fairly specific to use by a
/// DNS server, i.e., b10-auth or b10-recurse. But the plan is to
/// generalize it and have other modules use it as well.
///
/// One obvious drawback of this approach is performance overhead
/// due to the additional layer. We should eventually evaluate the cost
......@@ -102,6 +102,11 @@ public:
isc::Exception(file, line, what) {}
};
/// \brief Forward declarations for classes used below
class SimpleCallback;
class DNSLookup;
class DNSAnswer;
/// \brief The \c IOAddress class represents an IP addresses (version
/// agnostic)
///
......@@ -188,11 +193,14 @@ public:
///
/// This method returns an IOAddress object corresponding to \c this
/// endpoint.
///
/// Note that the return value is a real object, not a reference or
/// a pointer.
///
/// This is aligned with the interface of the ASIO counterpart:
/// the \c address() method of \c ip::xxx::endpoint classes returns
/// an \c ip::address object.
///
/// This also means handling the address of an endpoint using this method
/// can be expensive. If the address information is necessary in a
/// performance sensitive context and there's a more efficient interface
......@@ -246,6 +254,7 @@ public:
/// Derived class implementations are completely hidden within the
/// implementation. User applications only get access to concrete
/// \c IOSocket objects via the abstract interfaces.
///
/// We may revisit this decision when we generalize the wrapper and more
/// modules use it. Also, at that point we may define a separate (visible)
/// derived class for testing purposes rather than providing factory methods
......@@ -381,6 +390,7 @@ public:
/// \brief Returns the endpoint that sends the message.
const IOEndpoint& getRemoteEndpoint() const { return (remote_endpoint_); }
private:
const void* data_;
const size_t data_size_;
......@@ -388,51 +398,200 @@ private:
const IOEndpoint& remote_endpoint_;
};
/// XXX: need to add doc
class IOServer;
typedef boost::shared_ptr<IOServer> IOServerPtr;
class IOServer {
/// \brief The \c IOService class is a wrapper for the ASIO \c io_service
/// class.
///
/// Currently, the interface of this class is very specific to the
/// authoritative/recursive DNS server implementationss in b10-auth
/// and b10-recurse; this is reflected in the constructor signatures.
/// Ultimately the plan is to generalize it so that other BIND 10
/// modules can use this interface, too.
class IOService {
///
/// \name Constructors and Destructor
///
/// These are currently very specific to the authoritative server
/// implementation.
///
/// Note: The copy constructor and the assignment operator are
/// intentionally defined as private, making this class non-copyable.
//@{
private:
IOService(const IOService& source);
IOService& operator=(const IOService& source);
public:
/// \brief The constructor with a specific IP address and port on which
/// the services listen on.
IOService(const char& port, const char& address,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer);
/// \brief The constructor with a specific port on which the services
/// listen on.
///
/// It effectively listens on "any" IPv4 and/or IPv6 addresses.
/// IPv4/IPv6 services will be available if and only if \c use_ipv4
/// or \c use_ipv6 is \c true, respectively.
IOService(const char& port, const bool use_ipv4, const bool use_ipv6,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer);
/// \brief The destructor.
~IOService();
//@}
/// \brief Start the underlying event loop.
///
/// This method does not return control to the caller until
/// the \c stop() method is called via some handler.
void run();
/// \brief Stop the underlying event loop.
///
/// This will return the control to the caller of the \c run() method.
void stop();
/// \brief Return the native \c io_service object used in this wrapper.
///
/// This is a short term work around to support other BIND 10 modules
/// that share the same \c io_service with the authoritative server.
/// It will eventually be removed once the wrapper interface is
/// generalized.
asio::io_service& get_io_service();
private:
IOServiceImpl* impl_;
};
/// \brief The \c DNSServer class is a wrapper (and base class) for
/// classes which provide DNS server functionality.
///
/// The classes derived from this one, \c TCPServer and \c UDPServer,
/// act as the interface layer between clients sending queries, and
/// functions defined elsewhere that provide answers to those queries.
/// Those functions are described in more detail below under
/// \c SimpleCallback, \c DNSLookup, and \c DNSAnswer.
///
/// Notes to developers:
/// When constructed, this class (and its derived classes) will have its
/// "self_" member set to point to "this". Calls to methods in the base
/// class are then rerouted via this pointer to methods in the derived
/// class. This allows code from outside asiolink, with no specific
/// knowledge of \c TCPServer or \c UDPServer, to access their methods.
///
/// This class is both assignable and copy-constructable. Its subclasses
/// use the "stackless coroutine" pattern, meaning that it will copy itself
/// when "forking", and that instances will be posted as ASIO handler
/// objects, which are always copied.
///
/// Because these objects are frequently copied, it is recommended
/// that derived classes be kept small to reduce copy overhead.
class DNSServer {
protected:
///
/// \name Constructors and destructors
///
/// This is intentionally defined as \c protected, as this base class
/// should never be instantiated except as part of a derived class.
//@{
DNSServer() : self_(this) {}
public:
IOServer() : self_(this), cloned_(false) {}
/// \brief The destructor
virtual ~DNSServer() {}
//@}
///
/// \name Class methods
///
/// These methods all make their calls indirectly via the "self_"
/// pointer, ensuring that the functions ultimately invoked will be
/// the ones in the derived class.
///
//@{
/// \brief The funtion operator
virtual void operator()(asio::error_code ec = asio::error_code(),
size_t length = 0)
{
(*self_)(ec, length);
}
virtual void doLookup() { self_->doLookup(); }
virtual void resume(const bool done) { self_->resume(done); }
virtual bool hasAnswer() { return (self_->hasAnswer()); }
virtual int value() { return (self_->value()); }
virtual IOServer* clone() { return (self_->clone()); }
/// \brief Resume processing of the server coroutine after an
/// asynchronous call (e.g., to the DNS Lookup provider) has completed.
virtual inline void resume(const bool done) { self_->resume(done); }
private:
IOServer* self_;
/// \brief Indicate whether the server is able to send an answer
/// to a query.
///
/// This is presently used only for testing purposes.
virtual inline bool hasAnswer() { return (self_->hasAnswer()); }
/// \brief Returns the current value of the 'coroutine' object
///
/// This is a temporary method, intended to be used for debugging
/// purposes during development and removed later. It allows
/// callers from outside the coroutine object to retrieve information
/// about its current state.
virtual inline int value() { return (self_->value()); }
/// \brief Returns a pointer to a clone of this DNSServer object.
///
/// When a \c DNSServer object is copied or assigned, the result will
/// normally be another \c DNSServer object containing a copy
/// of the original "self_" pointer. Calling clone() guarantees
/// that the underlying object is also correctly copied.
virtual inline DNSServer* clone() { return (self_->clone()); }
//@}
protected:
bool cloned_;
};
/// \brief Lookup handler object.
///
/// This is a protected class; it can only be instantiated
/// from within a derived class of \c DNSServer.
///
/// A server object that has received a query creates an instance
/// of this class and scheudles it on the ASIO service queue
/// using asio::io_service::post(). When the handler executes, it
/// calls the asyncLookup() method in the server object to start a
/// DNS lookup. When the lookup is complete, the server object is
/// scheduled to resume, again using io_service::post().
///
/// Note that the calling object is copied into the handler object,
/// not referenced. This is because, once the calling object yields
/// control to the handler, it falls out of scope and may disappear
template <typename T>
class AsyncLookup {
public:
AsyncLookup(T caller) : caller_(caller) {}
inline void operator()() { caller_.asyncLookup(); }
private:
T caller_;
};
/// \brief Carries out a DNS lookup.
///
/// This function calls the \c DNSLookup object specified by the
/// DNS server when the \c IOService was created, passing along
/// the details of the query and a pointer back to the current
/// server object. It is called asynchronously via the AsyncLookup
/// handler class.
virtual inline void asyncLookup() { self_->asyncLookup(); }
template <typename T>
class LookupHandler {
public:
LookupHandler(T caller) : caller_(caller) {}
void operator()() {
caller_.doLookup();
}
private:
T caller_;
DNSServer* self_;
};
/// \brief The \c DNSLookup class is an abstract base class for a DNS
/// provider function.
/// Lookup provider function.
///
/// Specific derived class implementations are hidden within the
/// implementation. Instances of the derived classes can be called
/// as functions via the operator() interface. Pointers to these
/// instances can then be provided to the \c IOService class
/// via its constructor.
///
/// A DNS Lookup provider function obtains the data needed to answer
/// a DNS query (e.g., from authoritative data source, cache, or upstream
/// query). After it has run, the OutputBuffer object passed to it
/// should contain the answer to the query, in an internal representation.
class DNSLookup {
///
/// \name Constructors and Destructor
......@@ -452,6 +611,7 @@ protected:
public:
/// \brief The destructor
virtual ~DNSLookup() {}
//@}
/// \brief The function operator
///
/// This makes its call indirectly via the "self" pointer, ensuring
......@@ -460,23 +620,27 @@ public:
virtual void operator()(const IOMessage& io_message,
isc::dns::MessagePtr message,
isc::dns::OutputBufferPtr buffer,
IOServer* server) const
DNSServer* server) const
{
(*self_)(io_message, message, buffer, server);
}
//@}
private:
DNSLookup* self_;
};
/// \brief The \c DNSAnswer class is an abstract base class for a DNS
/// provider function.
/// Answer provider function.
///
/// Specific derived class implementations are hidden within the
/// implementation. Instances of the derived classes can be called
/// as functions via the operator() interface. Pointers to these
/// instances can then be provided to the \c IOService class
/// via its constructor.
///
/// A DNS Answer provider function takes answer data that has been obtained
/// from a DNS Lookup provider functon and readies it to be sent to the
/// client. After it has run, the OutputBuffer object passed to it should
/// contain the answer to the query rendered into wire format.
class DNSAnswer {
///
/// \name Constructors and Destructor
......@@ -496,14 +660,14 @@ protected:
public:
/// \brief The destructor
virtual ~DNSAnswer() {}
//@}
/// \brief The function operator
virtual void operator()(const IOMessage& io_message,
isc::dns::MessagePtr message,
isc::dns::OutputBufferPtr buffer) const = 0;
//@}
};
/// \brief The \c IOCallback class is an abstract base class for a
/// \brief The \c SimpleCallback class is an abstract base class for a
/// simple callback function with the signature:
///