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

Merge preparation, step 1

Doesn't compile yet. Only detected code-level conflicts resolved.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/vorner-recursor-config@3423 e5f2f494-b856-4b98-b285-d166d9295462
parents 5049b428 f8e8b2de
......@@ -62,7 +62,7 @@ public:
/// I/O service queue and return. When the server resumes, it can
/// send the reply.
///
/// \param io_message The I/O service queue
/// \param io_message The raw message received
/// \param message Pointer to the \c Message object
/// \param buffer Pointer to an \c OutputBuffer for the resposne
/// \param server Pointer to the \c DNSServer
......
......@@ -66,7 +66,7 @@ static const char* DNSPORT = "5300";
* class itself? */
static AuthSrv *auth_server;
static IOService* io_service;
static IOService io_service;
ConstElementPtr
my_config_handler(ConstElementPtr new_config) {
......@@ -82,7 +82,7 @@ my_command_handler(const string& command, ConstElementPtr args) {
/* let's add that message to our answer as well */
answer = createAnswer(0, args);
} else if (command == "shutdown") {
io_service->stop();
io_service.stop();
}
return (answer);
......@@ -193,6 +193,7 @@ main(int argc, char* argv[]) {
DNSLookup* lookup = auth_server->getDNSLookupProvider();
DNSAnswer* answer = auth_server->getDNSAnswerProvider();
DNSService* dns_service;
if (address != NULL) {
// XXX: we can only specify at most one explicit address.
// This also means the server cannot run in the dual address
......@@ -200,16 +201,17 @@ main(int argc, char* argv[]) {
// We don't bother to fix this problem, however. The -a option
// is a short term workaround until we support dynamic listening
// port allocation.
io_service = new IOService(*port, *address,
checkin, lookup, answer);
dns_service = new DNSService(io_service, *port, *address,
checkin, lookup, answer);
} else {
io_service = new IOService(*port, use_ipv4, use_ipv6,
checkin, lookup, answer);
dns_service = new DNSService(io_service, *port, use_ipv4,
use_ipv6, checkin, lookup,
answer);
}
auth_server->setIOService(*io_service);
auth_server->setIOService(io_service);
cout << "[b10-auth] IOService created." << endl;
cc_session = new Session(io_service->get_io_service());
cc_session = new Session(io_service.get_io_service());
cout << "[b10-auth] Configuration session channel created." << endl;
config_session = new ModuleCCSession(specfile, *cc_session,
......@@ -221,7 +223,7 @@ main(int argc, char* argv[]) {
changeUser(uid);
}
xfrin_session = new Session(io_service->get_io_service());
xfrin_session = new Session(io_service.get_io_service());
cout << "[b10-auth] Xfrin session channel created." << endl;
xfrin_session->establish(NULL);
xfrin_session_established = true;
......@@ -237,7 +239,7 @@ main(int argc, char* argv[]) {
auth_server->updateConfig(ElementPtr());
cout << "[b10-auth] Server started." << endl;
io_service->run();
io_service.run();
} catch (const std::exception& ex) {
cerr << "[b10-auth] Server failed: " << ex.what() << endl;
ret = 1;
......@@ -250,7 +252,6 @@ main(int argc, char* argv[]) {
delete xfrin_session;
delete config_session;
delete cc_session;
delete io_service;
delete auth_server;
return (ret);
......
......@@ -62,7 +62,7 @@ static bool verbose_mode = false;
// Default port current 5300 for testing purposes
static const string PROGRAM = "Recurse";
static IOService* io_service;
IOService io_service;
static Recursor *recursor;
ConstElementPtr
......@@ -79,7 +79,7 @@ my_command_handler(const string& command, ConstElementPtr args) {
/* let's add that message to our answer as well */
answer = createAnswer(0, args);
} else if (command == "shutdown") {
io_service->stop();
io_service.stop();
}
return (answer);
......@@ -139,11 +139,12 @@ main(int argc, char* argv[]) {
DNSLookup* lookup = recursor->getDNSLookupProvider();
DNSAnswer* answer = recursor->getDNSAnswerProvider();
io_service = new IOService(checkin, lookup, answer);
recursor->setIOService(*io_service);
DNSService dns_service(io_service, checkin, lookup, answer);
recursor->setDNSService(dns_service);
cout << "[b10-recurse] IOService created." << endl;
cc_session = new Session(io_service->get_io_service());
cc_session = new Session(io_service.get_io_service());
cout << "[b10-recurse] Configuration session channel created." << endl;
config_session = new ModuleCCSession(specfile, *cc_session,
......@@ -160,7 +161,7 @@ main(int argc, char* argv[]) {
recursor->updateConfig(config_session->getFullConfig());
cout << "[b10-recurse] Server started." << endl;
io_service->run();
io_service.run();
} catch (const std::exception& ex) {
cerr << "[b10-recurse] Server failed: " << ex.what() << endl;
ret = 1;
......@@ -168,7 +169,6 @@ main(int argc, char* argv[]) {
delete config_session;
delete cc_session;
delete io_service;
delete recursor;
return (ret);
......
......@@ -76,8 +76,8 @@ public:
queryShutdown();
}
void querySetup(IOService& ios) {
rec_query_ = new RecursiveQuery(ios, upstream_);
void querySetup(DNSService& dnss) {
rec_query_ = new RecursiveQuery(dnss, upstream_);
}
void queryShutdown() {
......@@ -316,10 +316,10 @@ Recursor::~Recursor() {
}
void
Recursor::setIOService(asiolink::IOService& ios) {
Recursor::setDNSService(asiolink::DNSService& dnss) {
impl_->queryShutdown();
impl_->querySetup(ios);
io_ = &ios;
impl_->querySetup(dnss);
dnss_ = &dnss;
}
void
......
......@@ -51,7 +51,7 @@ public:
/// I/O service queue and return. When the server resumes, it can
/// send the reply.
///
/// \param io_message The I/O service queue
/// \param io_message The raw message received
/// \param message Pointer to the \c Message object
/// \param buffer Pointer to an \c OutputBuffer for the resposne
/// \param server Pointer to the \c DNSServer
......@@ -76,10 +76,10 @@ public:
isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
/// \brief Assign an ASIO IO Service queue to this Recursor object
void setIOService(asiolink::IOService& ios);
void setDNSService(asiolink::DNSService& dnss);
/// \brief Return this object's ASIO IO Service queue
asiolink::IOService& getIOService() const { return (*io_); }
asiolink::DNSService& getDNSService() const { return (*dnss_); }
/// \brief Return pointer to the DNS Lookup callback function
asiolink::DNSLookup* getDNSLookupProvider() { return (dns_lookup_); }
......@@ -120,7 +120,7 @@ public:
private:
RecursorImpl* impl_;
asiolink::IOService* io_;
asiolink::DNSService* dnss_;
asiolink::SimpleCallback* checkin_;
asiolink::DNSLookup* dns_lookup_;
asiolink::DNSAnswer* dns_answer_;
......
......@@ -35,24 +35,12 @@ endif
noinst_PROGRAMS = $(TESTS)
EXTRA_DIST = testdata/badExampleQuery_fromWire
EXTRA_DIST += testdata/badExampleQuery_fromWire.spec
EXTRA_DIST += testdata/example.com
EXTRA_DIST += testdata/examplequery_fromWire
EXTRA_DIST += testdata/examplequery_fromWire.spec
EXTRA_DIST += testdata/example.sqlite3
EXTRA_DIST += testdata/iqueryresponse_fromWire
EXTRA_DIST += testdata/iqueryresponse_fromWire.spec
EXTRA_DIST = testdata/iqueryresponse_fromWire
EXTRA_DIST += testdata/multiquestion_fromWire
EXTRA_DIST += testdata/multiquestion_fromWire.spec
EXTRA_DIST += testdata/queryBadEDNS_fromWire
EXTRA_DIST += testdata/queryBadEDNS_fromWire.spec
EXTRA_DIST += testdata/shortanswer_fromWire
EXTRA_DIST += testdata/shortanswer_fromWire.spec
EXTRA_DIST += testdata/shortmessage_fromWire
EXTRA_DIST += testdata/shortquestion_fromWire
EXTRA_DIST += testdata/shortresponse_fromWire
EXTRA_DIST += testdata/simplequery_fromWire
EXTRA_DIST += testdata/simplequery_fromWire.spec
EXTRA_DIST += testdata/simpleresponse_fromWire
EXTRA_DIST += testdata/simpleresponse_fromWire.spec
......@@ -63,15 +63,15 @@ private:
class RecursorTest : public ::testing::Test {
protected:
RecursorTest() : ios(*TEST_PORT, true, false, NULL, NULL, NULL),
request_message(Message::RENDER),
parse_message(new Message(Message::PARSE)),
default_qid(0x1035), opcode(Opcode(Opcode::QUERY())),
qname("www.example.com"),
qclass(RRClass::IN()), qtype(RRType::A()),
io_message(NULL), endpoint(NULL), request_obuffer(0),
request_renderer(request_obuffer),
response_obuffer(new OutputBuffer(0))
RecursorTest() : server(*DEFAULT_REMOTE_ADDRESS),
request_message(Message::RENDER),
parse_message(new Message(Message::PARSE)),
default_qid(0x1035), opcode(Opcode(Opcode::QUERY())),
qname("www.example.com"),
qclass(RRClass::IN()), qtype(RRType::A()),
io_message(NULL), endpoint(NULL), request_obuffer(0),
request_renderer(request_obuffer),
response_obuffer(new OutputBuffer(0))
{
vector<pair<string, uint16_t> > upstream;
upstream.push_back(pair<string, uint16_t>(DEFAULT_REMOTE_ADDRESS, 53));
......@@ -83,7 +83,6 @@ protected:
}
MockSession notify_session;
MockServer dnsserv;
IOService ios;
Recursor server;
Message request_message;
MessagePtr parse_message;
......
......@@ -12,11 +12,12 @@ CLEANFILES = *.gcno *.gcda
# which would make the build fail with -Werror (our default setting).
lib_LTLIBRARIES = libasiolink.la
libasiolink_la_SOURCES = asiolink.cc asiolink.h
libasiolink_la_SOURCES += iosocket.h
libasiolink_la_SOURCES += iosocket.h iomessage.h
libasiolink_la_SOURCES += ioaddress.cc ioaddress.h
libasiolink_la_SOURCES += ioendpoint.cc ioendpoint.h
libasiolink_la_SOURCES += udpdns.cc internal/udpdns.h
libasiolink_la_SOURCES += tcpdns.cc internal/tcpdns.h
libasiolink_la_SOURCES += internal/coroutine.h
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
# B10_CXXFLAGS)
libasiolink_la_CXXFLAGS = $(AM_CXXFLAGS)
......
......@@ -46,15 +46,84 @@ using namespace isc::dns;
namespace asiolink {
class IOServiceImpl {
private:
IOServiceImpl(const IOService& source);
IOServiceImpl& operator=(const IOService& source);
public:
IOServiceImpl(const char& port,
/// \brief The constructor
IOServiceImpl() : io_service_() {};
/// \brief The destructor.
~IOServiceImpl() {};
//@}
/// \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() { io_service_.run(); };
/// \brief Run the underlying event loop for a single event.
///
/// This method return control to the caller as soon as the
/// first handler has completed. (If no handlers are ready when
/// it is run, it will block until one is.)
void run_one() { io_service_.run_one();} ;
/// \brief Stop the underlying event loop.
///
/// This will return the control to the caller of the \c run() method.
void stop() { io_service_.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() { return io_service_; };
private:
asio::io_service io_service_;
};
IOService::IOService() {
io_impl_ = new IOServiceImpl();
}
IOService::~IOService() {
delete io_impl_;
}
void
IOService::run() {
io_impl_->run();
}
void
IOService::run_one() {
io_impl_->run_one();
}
void
IOService::stop() {
io_impl_->stop();
}
asio::io_service&
IOService::get_io_service() {
return (io_impl_->get_io_service());
}
class DNSServiceImpl {
public:
DNSServiceImpl(IOService& io_service, const char& port,
const ip::address* v4addr, const ip::address* v6addr,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer);
asio::io_service io_service_;
//asio::io_service io_service_;
// So it does not run out of work when there are no listening sockets
asio::io_service::work work_;
void stop();
typedef boost::shared_ptr<UDPServer> UDPServerPtr;
typedef boost::shared_ptr<TCPServer> TCPServerPtr;
typedef boost::shared_ptr<DNSServer> DNSServerPtr;
......@@ -103,12 +172,14 @@ public:
}
};
IOServiceImpl::IOServiceImpl(const char& port,
const ip::address* const v4addr,
const ip::address* const v6addr,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
DNSServiceImpl::DNSServiceImpl(IOService& io_service_,
const char& port,
const ip::address* const v4addr,
const ip::address* const v6addr,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
// TODO MERGE move work to IOService
work_(io_service_),
checkin_(checkin),
lookup_(lookup),
......@@ -123,36 +194,40 @@ IOServiceImpl::IOServiceImpl(const char& port,
}
}
IOService::IOService(const char& port, const char& address,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
impl_(new IOServiceImpl(port, NULL, NULL, checkin, lookup, answer))
DNSService::DNSService(IOService& io_service,
const char& port, const char& address,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
impl_(new IOServiceImpl(io_service, port, NULL, NULL, checkin, lookup,
answer)), io_service_(io_service)
{
addServer(port, &address);
}
IOService::IOService(const char& port,
const bool use_ipv4, const bool use_ipv6,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
impl_(NULL)
DNSService::DNSService(IOService& io_service,
const char& port,
const bool use_ipv4, const bool use_ipv6,
SimpleCallback* checkin,
DNSLookup* lookup,
DNSAnswer* answer) :
impl_(NULL), io_service_(io_service)
{
const ip::address v4addr_any = ip::address(ip::address_v4::any());
const ip::address* const v4addrp = use_ipv4 ? &v4addr_any : NULL;
const ip::address v6addr_any = ip::address(ip::address_v6::any());
const ip::address* const v6addrp = use_ipv6 ? &v6addr_any : NULL;
impl_ = new IOServiceImpl(port, v4addrp, v6addrp, checkin, lookup, answer);
impl_ = new DNSServiceImpl(io_service, port, v4addrp, v6addrp, checkin, lookup, answer);
}
IOService::IOService(SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer *answer) :
impl_(new IOServiceImpl(*"", NULL, NULL, checkin, lookup, answer))
DNSService::DNSService(IOService& io_service, SimpleCallback* checkin,
DNSLookup* lookup, DNSAnswer *answer) :
impl_(new IOServiceImpl(io_service, *"0", NULL, NULL, checkin, lookup,
answer))
{
}
IOService::~IOService() {
DNSService::~DNSService() {
delete impl_;
}
......@@ -172,17 +247,17 @@ convertAddr(const string& address) {
}
void
IOService::addServer(const char& port, const string& address) {
DNSService::addServer(const char& port, const string& address) {
impl_->addServer(port, convertAddr(address));
}
void
IOService::addServer(uint16_t port, const string &address) {
DNSService::addServer(uint16_t port, const string &address) {
impl_->addServer(port, convertAddr(address));
}
void
IOService::clearServers() {
DNSService::clearServers() {
// FIXME: This does not work, it does not close the socket.
// How is it done?
impl_->servers_.clear();
......@@ -208,9 +283,9 @@ IOService::get_io_service() {
return (impl_->io_service_);
}
RecursiveQuery::RecursiveQuery(IOService& io_service,
RecursiveQuery::RecursiveQuery(DNSService& dns_service,
const std::vector<std::pair<std::string, uint16_t> >& upstream) :
io_service_(io_service), upstream_(upstream)
dns_service_(dns_service), upstream_(upstream)
{}
void
......@@ -222,7 +297,7 @@ RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
// the message should be sent via TCP or UDP, or sent initially via
// UDP and then fall back to TCP on failure, but for the moment
// we're only going to handle UDP.
asio::io_service& io = io_service_.get_io_service();
asio::io_service& io = dns_service_.get_io_service();
// TODO: Better way to choose the server
int serverIndex(random() % upstream_.size());
UDPQuery q(io, question, upstream_[serverIndex].first,
......
......@@ -38,6 +38,7 @@
#include <asiolink/ioendpoint.h>
#include <asiolink/iomessage.h>
#include <asiolink/iosocket.h>
//#include <asio/io_service.hpp>
namespace asio {
// forward declaration for IOService::get_io_service() below
......@@ -95,6 +96,7 @@ class io_service;
/// http://think-async.com/Asio/asio-1.3.1/doc/asio/reference/asio_handler_allocate.html
namespace asiolink {
struct DNSServiceImpl;
struct IOServiceImpl;
/// \brief An exception that is thrown if an error occurs within the IO
......@@ -114,18 +116,10 @@ class DNSAnswer;
/// \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.
//@{
......@@ -133,22 +127,8 @@ 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 constructor
IOService();
/// \brief The constructor without any servers.
///
/// Use addServer() to add some servers.
......@@ -188,8 +168,71 @@ public:
/// It will eventually be removed once the wrapper interface is
/// generalized.
asio::io_service& get_io_service();
private:
IOServiceImpl* impl_;
IOServiceImpl* io_impl_;
};
///
/// DNSService is the service that handles DNS queries and answers with
/// a given IOService.
///
class DNSService {
///
/// \name Constructors and Destructor
///
/// Note: The copy constructor and the assignment operator are
/// intentionally defined as private, making this class non-copyable.
//@{
private:
DNSService(const DNSService& source);
DNSService& operator=(const DNSService& source);
public:
/// \brief The constructor with a specific IP address and port on which
/// the services listen on.
///
/// \param io_service The IOService to work with
/// \param port the port to listen on
/// \param address the IP address to listen on
/// \param checkin Provider for cc-channel events (see \c SimpleCallback)
/// \param lookup The lookup provider (see \c DNSLookup)
/// \param answer The answer provider (see \c DNSAnswer)
DNSService(IOService& io_service, 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.
///
/// \param io_service The IOService to work with
/// \param port the port to listen on
/// \param ipv4 If true, listen on ipv4 'any'
/// \param ipv6 If true, listen on ipv6 'any'
/// \param checkin Provider for cc-channel events (see \c SimpleCallback)
/// \param lookup The lookup provider (see \c DNSLookup)
/// \param answer The answer provider (see \c DNSAnswer)
DNSService(IOService& io_service, const char& port,
const bool use_ipv4, const bool use_ipv6,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer);
/// \brief The destructor.
~DNSService();
//@}
/// \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() { return io_service_.get_io_service(); };
private:
DNSServiceImpl* impl_;
IOService& io_service_;
};
/// \brief The \c DNSServer class is a wrapper (and base class) for
......@@ -248,6 +291,9 @@ public:
/// \brief Resume processing of the server coroutine after an
/// asynchronous call (e.g., to the DNS Lookup provider) has completed.
///
/// \param done If true, this signals the system there is an answer
/// to return.
virtual inline void resume(const bool done) { self_->resume(done); }
/// \brief Indicate whether the server is able to send an answer
......@@ -262,6 +308,8 @@ public:
/// purposes during development and removed later. It allows
/// callers from outside the coroutine object to retrieve information
/// about its current state.
///
/// \return The value of the 'coroutine' object
virtual inline int value() { return (self_->value()); }
/// \brief Returns a pointer to a clone of this DNSServer object.
......@@ -270,6 +318,8 @@ public:
/// 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.