Browse Source

[805] Convert asio based exceptions to IOError

Michal 'vorner' Vaner 13 years ago
parent
commit
7319f20804

+ 4 - 6
src/lib/asiodns/dns_service.h

@@ -94,13 +94,12 @@ public:
     /// Adds a new TCP server using an already opened file descriptor (eg. it
     /// only wraps it so the file descriptor is usable within the event loop).
     ///
-    /// If you pass bad data (eg. opened UDP socket as fd), this will not detect
-    /// it right away, but successfull operations might fail.
-    ///
     /// \param fd the file descriptor to be used.
     /// \param af the address family of the file descriptor. Must be either
     ///     AF_INET or AF_INET6.
     /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6.
+    /// \throw isc::asiolink::IOError when a low-level error happens, like the
+    ///     fd is not a valid descriptor or it can't be listened on.
     void addServerTCPFromFD(int fd, int af);
     /// \brief Add another UDP server to the service from already opened
     ///    file descriptor
@@ -108,13 +107,12 @@ public:
     /// Adds a new UDP server using an already opened file descriptor (eg. it
     /// only wraps it so the file descriptor is usable within the event loop).
     ///
-    /// If you pass bad data (eg. opened TCP socket as fd), this will not detect
-    /// it right away, but successfull operations might fail.
-    ///
     /// \param fd the file descriptor to be used.
     /// \param af the address family of the file descriptor. Must be either
     ///     AF_INET or AF_INET6.
     /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6.
+    /// \throw isc::asiolink::IOError when a low-level error happens, like the
+    ///     fd is not a valid descriptor or it can't be listened on.
     void addServerUDPFromFD(int fd, int af);
     /// \brief Remove all servers from the service
     void clearServers();

+ 10 - 3
src/lib/asiodns/tcp_server.cc

@@ -81,11 +81,18 @@ TCPServer::TCPServer(io_service& io_service, int fd, int af,
         isc_throw(InvalidParameter, "Address family must be either AF_INET "
                   "or AF_INET6, not " << af);
     }
-    logger.debug(DBGLVL_TRACE_BASIC, ASIODNS_FD_ADD_TCP, fd);
+    logger.debug(DBGLVL_TRACE_BASIC, ASIODNS_FD_ADD_TCP).arg(fd);
 
     acceptor_.reset(new tcp::acceptor(io_service));
-    acceptor_->assign(af == AF_INET6 ? tcp::v6() : tcp::v4(), fd);
-    acceptor_->listen();
+    try {
+        acceptor_->assign(af == AF_INET6 ? tcp::v6() : tcp::v4(), fd);
+        acceptor_->listen();
+    }
+    // Whatever the thing throws, it is something from ASIO and we convert
+    // it
+    catch (const std::exception& exception) {
+        isc_throw(IOError, exception.what());
+    }
 }
 
 void

+ 2 - 0
src/lib/asiodns/tcp_server.h

@@ -51,6 +51,8 @@ public:
     /// \param lookup the callbackprovider for DNS lookup events
     /// \param answer the callbackprovider for DNS answer events
     /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
+    /// \throw isc::asiolink::IOError when a low-level error happens, like the
+    ///     fd is not a valid descriptor or it can't be listened on.
     TCPServer(asio::io_service& io_service, int fd, int af,
               const isc::asiolink::SimpleCallback* checkin = NULL,
               const DNSLookup* lookup = NULL, const DNSAnswer* answer = NULL);

+ 12 - 2
src/lib/asiodns/tests/dns_server_unittest.cc

@@ -603,15 +603,25 @@ TYPED_TEST(DNSServerTest, stopTCPServeMoreThanOnce) {
 }
 
 // It raises an exception when invalid address family is passed
-TEST_F(DNSServerTestBase, exceptions) {
+TEST_F(DNSServerTestBase, invalidFamily) {
     // We abuse DNSServerTestBase for this test, as we don't need the
     // initialization.
     commonSetup();
-    // We use the 0 fd as it should not be touched anyway
     EXPECT_THROW(UDPServer(service, 0, AF_UNIX, checker_, lookup_,
                            answer_), isc::InvalidParameter);
     EXPECT_THROW(TCPServer(service, 0, AF_UNIX, checker_, lookup_,
                            answer_), isc::InvalidParameter);
 }
 
+// It raises an exception when invalid address family is passed
+TEST_F(DNSServerTestBase, invalidFD) {
+    // We abuse DNSServerTestBase for this test, as we don't need the
+    // initialization.
+    commonSetup();
+    EXPECT_THROW(UDPServer(service, -1, AF_INET, checker_, lookup_,
+                           answer_), isc::asiolink::IOError);
+    EXPECT_THROW(TCPServer(service, -1, AF_INET, checker_, lookup_,
+                           answer_), isc::asiolink::IOError);
+}
+
 }

+ 9 - 2
src/lib/asiodns/udp_server.cc

@@ -85,12 +85,19 @@ struct UDPServer::Data {
             isc_throw(InvalidParameter, "Address family must be either AF_INET "
                       "or AF_INET6, not " << af);
         }
-        logger.debug(DBGLVL_TRACE_BASIC, ASIODNS_FD_ADD_UDP, fd);
+        logger.debug(DBGLVL_TRACE_BASIC, ASIODNS_FD_ADD_UDP).arg(fd);
         // We must use different instantiations for v4 and v6;
         // otherwise ASIO will bind to both
         udp proto = af == AF_INET6 ? udp::v6() : udp::v4();
         socket_.reset(new udp::socket(io_service));
-        socket_->assign(proto, fd);
+        try {
+            socket_->assign(proto, fd);
+        }
+        // Whatever the thing throws, it is something from ASIO and we convert
+        // it
+        catch (const std::exception& exception) {
+            isc_throw(IOError, exception.what());
+        }
     }
 
     /*

+ 2 - 0
src/lib/asiodns/udp_server.h

@@ -60,6 +60,8 @@ public:
     /// \param lookup the callbackprovider for DNS lookup events
     /// \param answer the callbackprovider for DNS answer events
     /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
+    /// \throw isc::asiolink::IOError when a low-level error happens, like the
+    ///     fd is not a valid descriptor.
     UDPServer(asio::io_service& io_service, int fd, int af,
               isc::asiolink::SimpleCallback* checkin = NULL,
               DNSLookup* lookup = NULL, DNSAnswer* answer = NULL);