Browse Source

on second thought, it would be better to separate constructors for the explicit address case and the "any" address case.
This will make the validation process a lot easier and helps reduce code duplicate.
option conflict between -a and -4|-6 is now caught in main.cc.


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac221b@2471 e5f2f494-b856-4b98-b285-d166d9295462

JINMEI Tatuya 15 years ago
parent
commit
84bdd04537
4 changed files with 72 additions and 111 deletions
  1. 48 91
      src/bin/auth/asio_link.cc
  2. 3 2
      src/bin/auth/asio_link.h
  3. 13 3
      src/bin/auth/main.cc
  4. 8 15
      src/bin/auth/tests/asio_link_unittest.cc

+ 48 - 91
src/bin/auth/asio_link.cc

@@ -295,17 +295,17 @@ private:
 class TCPServer {
 public:
     TCPServer(AuthSrv* auth_server, io_service& io_service,
-              int af, uint16_t port) :
+              const ip::address& addr, const uint16_t port) :
         auth_server_(auth_server), io_service_(io_service),
         acceptor_(io_service_), listening_(new TCPClient(auth_server_,
                                                          io_service_)),
         custom_callback_(NULL)
     {
-        tcp::endpoint endpoint(af == AF_INET6 ? tcp::v6() : tcp::v4(), port);
+        tcp::endpoint endpoint(addr, port);
         acceptor_.open(endpoint.protocol());
         // Set v6-only (we use a different instantiation for v4,
         // otherwise asio will bind to both v4 and v6
-        if (af == AF_INET6) {
+        if (addr.is_v6()) {
             acceptor_.set_option(ip::v6_only(true));
         }
         acceptor_.set_option(tcp::acceptor::reuse_address(true));
@@ -316,23 +316,6 @@ public:
                                            listening_, placeholders::error));
     }
 
-    TCPServer(AuthSrv* auth_server, io_service& io_service,
-              asio::ip::address addr, uint16_t port) :
-        auth_server_(auth_server),
-        io_service_(io_service), acceptor_(io_service_),
-        listening_(new TCPClient(auth_server, io_service_))
-    {
-        tcp::endpoint endpoint(addr, port);
-        acceptor_.open(endpoint.protocol());
-
-        acceptor_.set_option(tcp::acceptor::reuse_address(true));
-        acceptor_.bind(endpoint);
-        acceptor_.listen();
-        acceptor_.async_accept(listening_->getSocket(),
-                               boost::bind(&TCPServer::handleAccept, this,
-                                           listening_, placeholders::error));
-    }
-
     ~TCPServer() { delete listening_; }
 
     void handleAccept(TCPClient* new_client,
@@ -370,10 +353,10 @@ private:
 class UDPServer {
 public:
     UDPServer(AuthSrv* auth_server, io_service& io_service,
-              int af, uint16_t port) :
+              const ip::address& addr, const uint16_t port) :
         auth_server_(auth_server),
         io_service_(io_service),
-        socket_(io_service, af == AF_INET6 ? udp::v6() : udp::v4()),
+        socket_(io_service, addr.is_v6() ? udp::v6() : udp::v4()),
         io_socket_(socket_),
         response_buffer_(0),
         response_renderer_(response_buffer_),
@@ -382,29 +365,15 @@ public:
     {
         // Set v6-only (we use a different instantiation for v4,
         // otherwise asio will bind to both v4 and v6
-        if (af == AF_INET6) {
+        if (addr.is_v6()) {
             socket_.set_option(asio::ip::v6_only(true));
-            socket_.bind(udp::endpoint(udp::v6(), port));
+            socket_.bind(udp::endpoint(addr, port));
         } else {
-            socket_.bind(udp::endpoint(udp::v4(), port));
+            socket_.bind(udp::endpoint(addr, port));
         }
         startReceive();
     }
 
-    UDPServer(AuthSrv* auth_server, io_service& io_service,
-              asio::ip::address addr, uint16_t port) :
-        auth_server_(auth_server), io_service_(io_service),
-        socket_(io_service, addr.is_v6() ? udp::v6() : udp::v4()),
-        io_socket_(socket_),
-        response_buffer_(0),
-        response_renderer_(response_buffer_),
-        dns_message_(Message::PARSE),
-        custom_callback_(NULL)
-    {
-        socket_.bind(udp::endpoint(addr, port));
-        startReceive();
-    }
-
     void handleRequest(const asio::error_code& error,
                        size_t bytes_recvd)
     {
@@ -483,8 +452,8 @@ private:
 
 class IOServiceImpl {
 public:
-    IOServiceImpl(AuthSrv* auth_server, const char* address, const char& port,
-                  const bool use_ipv4, const bool use_ipv6);
+    IOServiceImpl(AuthSrv* auth_server, const char& port,
+                  const ip::address& v4addr, const ip::address& v6addr);
     asio::io_service io_service_;
     AuthSrv* auth_server_;
 
@@ -499,9 +468,9 @@ public:
     IOService::IOCallBack callback_;
 };
 
-IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char* const address,
-                             const char& port, const bool use_ipv4,
-                             const bool use_ipv6) :
+IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char& port,
+                             const ip::address& v4addr,
+                             const ip::address& v6addr) :
     auth_server_(auth_server),
     udp4_server_(UDPServerPtr()), udp6_server_(UDPServerPtr()),
     tcp4_server_(TCPServerPtr()), tcp6_server_(TCPServerPtr())
@@ -515,57 +484,45 @@ IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char* const address,
                   ex.what());
     }
 
-    if (address != NULL) {
-        error_code err;
-        const ip::address addr = ip::address::from_string(address, err);
-        if (err) {
-            isc_throw(IOError, "Invalid IP address '" << address << "': "
-                      << err.message());
-        }
-
-        if (addr.is_v6() && !use_ipv6) {
-            isc_throw(IOError,
-                      "IPv6 address is specified while IPv6 is disabled: "
-                      << addr);
-        }
-
-        if (addr.is_v4() && !use_ipv4) {
-            isc_throw(IOError,
-                      "IPv4 address is specified while IPv4 is disabled: "
-                      << addr);
-        }
+    if (v4addr.is_v4()) {
+        udp4_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
+                                                  v4addr, portnum));
+        tcp4_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
+                                                  v4addr, portnum));
+    }
+    if (v6addr.is_v6()) {
+        udp6_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
+                                                  v6addr, portnum));
+        tcp6_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
+                                                  v6addr, portnum));
+    }
+}
 
-        if (addr.is_v4()) {
-            udp4_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
-                                                      addr, portnum));
-            tcp4_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
-                                                      addr, portnum));
-         } else {
-            udp6_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
-                                                      addr, portnum));
-            tcp6_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
-                                                      addr, portnum));
-        }
-    } else {
-        if (use_ipv4) {
-            udp4_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
-                                                      AF_INET, portnum));
-            tcp4_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
-                                                      AF_INET, portnum));
-        }
-        if (use_ipv6) {
-            udp6_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
-                                                      AF_INET6, portnum));
-            tcp6_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
-                                                      AF_INET6, portnum));
-        }
+IOService::IOService(AuthSrv* auth_server, const char& port,
+                     const char& address) :
+    impl_(NULL)
+{
+    error_code err;
+    const ip::address addr = ip::address::from_string(&address, err);
+    if (err) {
+        isc_throw(IOError, "Invalid IP address '" << &address << "': "
+                  << err.message());
     }
+
+    impl_ = new IOServiceImpl(auth_server, port,
+                              addr.is_v4() ? addr : ip::address::address(),
+                              addr.is_v6() ? addr : ip::address::address());
 }
 
-IOService::IOService(AuthSrv* auth_server, const char* const address,
-                     const char& port, const bool use_ipv4,
-                     const bool use_ipv6) {
-    impl_ = new IOServiceImpl(auth_server, address, port, use_ipv4, use_ipv6);
+IOService::IOService(AuthSrv* auth_server, const char& port,
+                     const bool use_ipv4, const bool use_ipv6) :
+    impl_(NULL)
+{
+    const ip::address v4addr = use_ipv4 ? ip::address(ip::address_v4::any()) :
+        ip::address::address();
+    const ip::address v6addr = use_ipv6 ? ip::address(ip::address_v6::any()) :
+        ip::address::address();
+    impl_ = new IOServiceImpl(auth_server, port, v4addr, v6addr);
 }
 
 IOService::~IOService() {

+ 3 - 2
src/bin/auth/asio_link.h

@@ -389,8 +389,9 @@ private:
 public:
     /// \brief The constructor.  Currently very specific to the authoritative
     /// server implementation.
-    IOService(AuthSrv* auth_server, const char* const address,
-              const char& port, bool use_ipv4, bool use_ipv6);
+    IOService(AuthSrv* auth_server, const char& address, const char& port);
+    IOService(AuthSrv* auth_server, const char& port,
+              const bool use_ipv4, const bool use_ipv6);
     /// \brief The destructor.
     ~IOService();
     //@}

+ 13 - 3
src/bin/auth/main.cc

@@ -101,7 +101,7 @@ main(int argc, char* argv[]) {
     const char* address = NULL;
     bool use_ipv4 = true, use_ipv6 = true, cache = true;
 
-    while ((ch = getopt(argc, argv, "46np:v")) != -1) {
+    while ((ch = getopt(argc, argv, "a:46np:v")) != -1) {
         switch (ch) {
         case '4':
             // Note that -4 means "ipv4 only", we need to set "use_ipv6" here,
@@ -141,6 +141,11 @@ main(int argc, char* argv[]) {
         usage();
     }
 
+    if ((!use_ipv4 || !use_ipv6) && address != NULL) {
+        cerr << "[b10-auth] Error: -4|-6 and -a can't coexist" << endl;
+        usage();
+    }
+
     int ret = 0;
 
     // XXX: we should eventually pass io_service here.
@@ -162,8 +167,13 @@ main(int argc, char* argv[]) {
         auth_server->setVerbose(verbose_mode);
         cout << "[b10-auth] Server created." << endl;
 
-        io_service = new asio_link::IOService(auth_server, address, *port,
-                                              use_ipv4, use_ipv6);
+        if (address != NULL) {
+            io_service = new asio_link::IOService(auth_server, *port,
+                                                  *address);
+        } else {
+            io_service = new asio_link::IOService(auth_server, *port,
+                                                  use_ipv4, use_ipv6);
+        }
         cout << "[b10-auth] IOService created." << endl;
 
         cc_session = new Session(io_service->get_io_service());

+ 8 - 15
src/bin/auth/tests/asio_link_unittest.cc

@@ -90,25 +90,18 @@ TEST(IOSocketTest, dummySockets) {
 }
 
 TEST(IOServiceTest, badPort) {
-    EXPECT_THROW(IOService(NULL, NULL, *"65536", true, false), IOError);
-    EXPECT_THROW(IOService(NULL, NULL, *"5300.0", true, false), IOError);
-    EXPECT_THROW(IOService(NULL, NULL, *"-1", true, false), IOError);
-    EXPECT_THROW(IOService(NULL, NULL, *"domain", true, false), IOError);
+    EXPECT_THROW(IOService(NULL, *"65536", true, false), IOError);
+    EXPECT_THROW(IOService(NULL, *"5300.0", true, false), IOError);
+    EXPECT_THROW(IOService(NULL, *"-1", true, false), IOError);
+    EXPECT_THROW(IOService(NULL, *"domain", true, false), IOError);
 }
 
 TEST(IOServiceTest, badAddress) {
-    EXPECT_THROW(IOService(NULL, "192.0.2.1.1", *TEST_PORT, true, false),
+    EXPECT_THROW(IOService(NULL, *TEST_PORT, *"192.0.2.1.1"),
                  IOError);
-    EXPECT_THROW(IOService(NULL, "2001:db8:::1", *TEST_PORT, true, false),
+    EXPECT_THROW(IOService(NULL, *TEST_PORT, *"2001:db8:::1"),
                  IOError);
-    EXPECT_THROW(IOService(NULL, "localhost", *TEST_PORT, true, false),
-                 IOError);
-}
-
-TEST(IOServiceTest, addressFamilyMismatch) {
-    EXPECT_THROW(IOService(NULL, "192.0.2.1", *TEST_PORT, false, true),
-                 IOError);
-    EXPECT_THROW(IOService(NULL, "2001:db8::1", *TEST_PORT, true, false),
+    EXPECT_THROW(IOService(NULL, *TEST_PORT, *"localhost"),
                  IOError);
 }
 
@@ -207,7 +200,7 @@ private:
 };
 
 ASIOLinkTest::ASIOLinkTest() :
-    io_service_(NULL, NULL, *TEST_PORT, true, true),
+    io_service_(NULL, *TEST_PORT, true, true),
     sock_(-1), res_(NULL)
 {
     io_service_.setCallBack(ASIOCallBack(this));