Browse Source

[1539] introduced class hierarchy for SocketSessionForwarder.

so that we can define and use a mock class for testing.
also added some initial tests.
JINMEI Tatuya 13 years ago
parent
commit
2baf46246b

+ 35 - 8
src/bin/auth/auth_srv.cc

@@ -25,6 +25,8 @@
 
 #include <boost/bind.hpp>
 
+#include <util/io/socketsession.h>
+
 #include <asiolink/asiolink.h>
 
 #include <config/ccsession.h>
@@ -71,6 +73,7 @@ using namespace isc::cc;
 using namespace isc::datasrc;
 using namespace isc::dns;
 using namespace isc::util;
+using namespace isc::util::io;
 using namespace isc::auth;
 using namespace isc::dns::rdata;
 using namespace isc::data;
@@ -115,7 +118,8 @@ private:
     AuthSrvImpl(const AuthSrvImpl& source);
     AuthSrvImpl& operator=(const AuthSrvImpl& source);
 public:
-    AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client);
+    AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client,
+                BaseSocketSessionForwarder& ddns_forwarder);
     ~AuthSrvImpl();
     isc::data::ConstElementPtr setDbFile(isc::data::ConstElementPtr config);
 
@@ -128,6 +132,9 @@ public:
     bool processNotify(const IOMessage& io_message, Message& message,
                        OutputBuffer& buffer,
                        auto_ptr<TSIGContext> tsig_context);
+    bool processUpdate(const IOMessage& io_message, Message& message,
+                       OutputBuffer& buffer,
+                       auto_ptr<TSIGContext> tsig_context);
 
     IOService io_service_;
 
@@ -189,6 +196,8 @@ private:
     bool xfrout_connected_;
     AbstractXfroutClient& xfrout_client_;
 
+    BaseSocketSessionForwarder& ddns_forwarder_;
+
     /// Increment query counter
     void incCounter(const int protocol);
 
@@ -199,7 +208,8 @@ private:
 };
 
 AuthSrvImpl::AuthSrvImpl(const bool use_cache,
-                         AbstractXfroutClient& xfrout_client) :
+                         AbstractXfroutClient& xfrout_client,
+                         BaseSocketSessionForwarder& ddns_forwarder) :
     config_session_(NULL),
     xfrin_session_(NULL),
     memory_client_class_(RRClass::IN()),
@@ -207,7 +217,8 @@ AuthSrvImpl::AuthSrvImpl(const bool use_cache,
     counters_(),
     keyring_(NULL),
     xfrout_connected_(false),
-    xfrout_client_(xfrout_client)
+    xfrout_client_(xfrout_client),
+    ddns_forwarder_(ddns_forwarder)
 {
     // cur_datasrc_ is automatically initialized by the default constructor,
     // effectively being an empty (sqlite) data source.  once ccsession is up
@@ -277,9 +288,10 @@ private:
     AuthSrv* server_;
 };
 
-AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client)
+AuthSrv::AuthSrv(const bool use_cache, AbstractXfroutClient& xfrout_client,
+                 BaseSocketSessionForwarder& ddns_forwarder)
 {
-    impl_ = new AuthSrvImpl(use_cache, xfrout_client);
+    impl_ = new AuthSrvImpl(use_cache, xfrout_client, ddns_forwarder);
     checkin_ = new ConfigChecker(this);
     dns_lookup_ = new MessageLookup(this);
     dns_answer_ = new MessageAnswer(this);
@@ -515,16 +527,20 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
         return;
     }
 
+    const Opcode opcode = message.getOpcode();
     bool send_answer = true;
     try {
         // update per opcode statistics counter.  This can only be reliable
         // after TSIG check succeeds.
         impl_->counters_.inc(message.getOpcode());
 
-        if (message.getOpcode() == Opcode::NOTIFY()) {
+        if (opcode == Opcode::NOTIFY()) {
             send_answer = impl_->processNotify(io_message, message, buffer,
                                                tsig_context);
-        } else if (message.getOpcode() != Opcode::QUERY()) {
+        } else if (opcode == Opcode::UPDATE()) {
+            send_answer = impl_->processUpdate(io_message, message, buffer,
+                                               tsig_context);
+        } else if (opcode != Opcode::QUERY()) {
             LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_UNSUPPORTED_OPCODE)
                       .arg(message.getOpcode().toText());
             makeErrorMessage(impl_->renderer_, message, buffer,
@@ -534,7 +550,7 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
                              Rcode::FORMERR(), tsig_context);
         } else {
             ConstQuestionPtr question = *message.beginQuestion();
-            const RRType &qtype = question->getType();
+            const RRType& qtype = question->getType();
             if (qtype == RRType::AXFR()) {
                 send_answer = impl_->processXfrQuery(io_message, message,
                                                      buffer, tsig_context);
@@ -740,6 +756,17 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
     return (true);
 }
 
+bool
+AuthSrvImpl::processUpdate(const IOMessage& /*io_message*/,
+                           Message& /*message*/, 
+                           OutputBuffer& /*buffer*/,
+                           std::auto_ptr<TSIGContext> /*tsig_context*/)
+{
+    // hardcode for initial test
+    ddns_forwarder_.connectToReceiver();
+    return (false);
+}
+
 void
 AuthSrvImpl::incCounter(const int protocol) {
     // Increment query counter.

+ 7 - 1
src/bin/auth/auth_srv.h

@@ -40,6 +40,11 @@
 #include <auth/statistics.h>
 
 namespace isc {
+namespace util {
+namespace io {
+class BaseSocketSessionForwarder;
+}
+}
 namespace datasrc {
 class InMemoryClient;
 }
@@ -96,7 +101,8 @@ public:
     /// but can refer to a local mock object for testing (or other
     /// experimental) purposes.
     AuthSrv(const bool use_cache,
-            isc::xfr::AbstractXfroutClient& xfrout_client);
+            isc::xfr::AbstractXfroutClient& xfrout_client,
+            isc::util::io::BaseSocketSessionForwarder& ddns_forwarder);
     ~AuthSrv();
     //@}
 

+ 6 - 2
src/bin/auth/benchmarks/query_bench.cc

@@ -31,9 +31,10 @@
 #include <dns/rrclass.h>
 
 #include <log/logger_support.h>
-
 #include <xfr/xfrout_client.h>
 
+#include <testutils/mockups.h>
+
 #include <auth/auth_srv.h>
 #include <auth/auth_config.h>
 #include <auth/query.h>
@@ -52,6 +53,7 @@ using namespace isc::xfr;
 using namespace isc::bench;
 using namespace isc::asiodns;
 using namespace isc::asiolink;
+using namespace isc::testutils;
 
 namespace {
 // Commonly used constant:
@@ -78,7 +80,7 @@ protected:
     QueryBenchMark(const bool enable_cache,
                    const BenchQueries& queries, Message& query_message,
                    OutputBuffer& buffer) :
-        server_(new AuthSrv(enable_cache, xfrout_client)),
+        server_(new AuthSrv(enable_cache, xfrout_client, ddns_forwarder)),
         queries_(queries),
         query_message_(query_message),
         buffer_(buffer),
@@ -103,6 +105,8 @@ public:
 
         return (queries_.size());
     }
+private:
+    MockSocketSessionForwarder ddns_forwarder;
 protected:
     AuthSrvPtr server_;
 private:

+ 4 - 1
src/bin/auth/main.cc

@@ -28,6 +28,7 @@
 #include <exceptions/exceptions.h>
 
 #include <util/buffer.h>
+#include <util/io/socketsession.h>
 
 #include <dns/message.h>
 #include <dns/messagerenderer.h>
@@ -60,6 +61,7 @@ using namespace isc::data;
 using namespace isc::dns;
 using namespace isc::log;
 using namespace isc::util;
+using namespace isc::util::io;
 using namespace isc::xfr;
 
 namespace {
@@ -130,6 +132,7 @@ main(int argc, char* argv[]) {
     bool statistics_session_established = false; // XXX (see Trac #287)
     ModuleCCSession* config_session = NULL;
     XfroutClient xfrout_client(getXfroutSocketPath());
+    SocketSessionForwarder ddns_forwarder("dummy");
     try {
         string specfile;
         if (getenv("B10_FROM_BUILD")) {
@@ -139,7 +142,7 @@ main(int argc, char* argv[]) {
             specfile = string(AUTH_SPECFILE_LOCATION);
         }
 
-        auth_server = new AuthSrv(cache, xfrout_client);
+        auth_server = new AuthSrv(cache, xfrout_client, ddns_forwarder);
         LOG_INFO(auth_logger, AUTH_SERVER_CREATED);
 
         SimpleCallback* checkin = auth_server->getCheckinProvider();

+ 18 - 1
src/bin/auth/tests/auth_srv_unittest.cc

@@ -77,7 +77,7 @@ class AuthSrvTest : public SrvTestBase {
 protected:
     AuthSrvTest() :
         dnss_(),
-        server(true, xfrout),
+        server(true, xfrout, ddns_forwarder),
         rrclass(RRClass::IN()),
         // The empty string is expected value of the parameter of
         // requestSocket, not the app_name (there's no fallback, it checks
@@ -139,6 +139,7 @@ protected:
     MockDNSService dnss_;
     MockSession statistics_session;
     MockXfroutClient xfrout;
+    MockSocketSessionForwarder ddns_forwarder;
     AuthSrv server;
     const RRClass rrclass;
     vector<uint8_t> response_data;
@@ -1385,4 +1386,20 @@ TEST_F(AuthSrvTest, queryWithThrowingInToWire) {
                 opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
 }
 
+//
+// DDNS related tests
+//
+TEST_F(AuthSrvTest, DDNSForward) {
+    EXPECT_FALSE(ddns_forwarder.isConnected());
+
+    UnitTestUtil::createRequestMessage(request_message, Opcode::UPDATE(),
+                                       default_qid, Name("example.com"),
+                                       RRClass::IN(), RRType::SOA());
+    createRequestPacket(request_message, IPPROTO_UDP);
+    server.processMessage(*io_message, *parse_message, *response_obuffer,
+                          &dnsserv);
+    EXPECT_FALSE(dnsserv.hasAnswer());
+    EXPECT_TRUE(ddns_forwarder.isConnected());
+}
+
 }

+ 2 - 1
src/bin/auth/tests/command_unittest.cc

@@ -59,7 +59,7 @@ namespace {
 class AuthCommandTest : public ::testing::Test {
 protected:
     AuthCommandTest() :
-        server_(false, xfrout_),
+        server_(false, xfrout_, ddns_forwarder_),
         rcode_(-1),
         expect_rcode_(0),
         itimer_(server_.getIOService())
@@ -72,6 +72,7 @@ protected:
     }
     MockSession statistics_session_;
     MockXfroutClient xfrout_;
+    MockSocketSessionForwarder ddns_forwarder_;
     AuthSrv server_;
     ConstElementPtr result_;
     // The shutdown command parameter

+ 2 - 1
src/bin/auth/tests/config_unittest.cc

@@ -52,7 +52,7 @@ protected:
     AuthConfigTest() :
         dnss_(),
         rrclass(RRClass::IN()),
-        server(true, xfrout),
+        server(true, xfrout, ddns_forwarder),
         // The empty string is expected value of the parameter of
         // requestSocket, not the app_name (there's no fallback, it checks
         // the empty string is passed).
@@ -63,6 +63,7 @@ protected:
     MockDNSService dnss_;
     const RRClass rrclass;
     MockXfroutClient xfrout;
+    MockSocketSessionForwarder ddns_forwarder;
     AuthSrv server;
     isc::server_common::portconfig::AddressList address_store_;
 private:

+ 51 - 0
src/lib/testutils/mockups.h

@@ -19,6 +19,8 @@
 
 #include <exceptions/exceptions.h>
 
+#include <util/io/socketsession.h>
+
 #include <cc/data.h>
 #include <cc/session.h>
 
@@ -29,6 +31,8 @@
 #include <utility>
 #include <vector>
 
+#include <sys/socket.h>
+
 namespace isc {
 namespace testutils {
 
@@ -199,6 +203,53 @@ private:
     bool disconnect_ok_;
 };
 
+// Mock socket session forwarder
+class MockSocketSessionForwarder :
+    public isc::util::io::BaseSocketSessionForwarder
+{
+public:
+    MockSocketSessionForwarder() :
+        is_connected_(false), connect_ok_(true), push_ok_(true),
+        close_ok_(true)
+    {}
+
+    virtual void connectToReceiver() {
+        if (!connect_ok_) {
+            isc_throw(isc::util::io::SocketSessionError, "socket session "
+                      "forwarding connection disabled for test");
+        }
+        is_connected_ = true;
+    }
+    virtual void close() {}
+#if 0
+    virtual void push(int sock, int family, int type, int protocol,
+                      const struct sockaddr& local_end,
+                      const struct sockaddr& remote_end,
+                      const void* data, size_t data_len)
+#endif
+    virtual void push(int, int, int, int,
+                      const struct sockaddr&,
+                      const struct sockaddr&,
+                      const void*, size_t)
+    {
+        if (!push_ok_) {
+            isc_throw(isc::util::io::SocketSessionError,
+                       "socket session forwarding is disabled for test");
+        }
+    }
+    bool isConnected() const { return (is_connected_); }
+    void disableConnect() { connect_ok_ = false; }
+    void disableClose() { close_ok_ = false; }
+    void enableClose() { close_ok_ = true; }
+    void disablePush() { push_ok_ = false; }
+
+private:
+    bool is_connected_;
+    bool connect_ok_;
+    bool push_ok_;
+    bool close_ok_;
+};
+
 } // end of testutils
 } // end of isc
 #endif  // __ISC_TESTUTILS_MOCKUPS_H

+ 2 - 1
src/lib/testutils/srv_test.cc

@@ -98,7 +98,8 @@ SrvTestBase::unsupportedRequest() {
         // set Opcode to 'i', which iterators over all possible codes except
         // the standard query and notify 
         if (i == isc::dns::Opcode::QUERY().getCode() ||
-            i == isc::dns::Opcode::NOTIFY().getCode()) {
+            i == isc::dns::Opcode::NOTIFY().getCode() ||
+            i == isc::dns::Opcode::UPDATE().getCode()) {
             continue;
         }
         createDataFromFile("simplequery_fromWire.wire");

+ 4 - 2
src/lib/util/io/socketsession.h

@@ -15,12 +15,14 @@
 #ifndef __SOCKETSESSION_H_
 #define __SOCKETSESSION_H_ 1
 
-#include <string>
-
 #include <boost/noncopyable.hpp>
 
 #include <exceptions/exceptions.h>
 
+#include <string>
+
+#include <sys/socket.h>
+
 namespace isc {
 namespace util {
 namespace io {