Browse Source

[3880] Changes after review:

 - CommandSocket, UNIXCommandSocket and ConnectionSocket classes added.
 - Updated unit-test to use
Tomek Mrugalski 10 years ago
parent
commit
d622d50755

+ 1 - 0
src/lib/config/Makefile.am

@@ -18,6 +18,7 @@ lib_LTLIBRARIES = libkea-cfgclient.la
 libkea_cfgclient_la_SOURCES = config_data.h config_data.cc
 libkea_cfgclient_la_SOURCES += module_spec.h module_spec.cc
 libkea_cfgclient_la_SOURCES += command_mgr.cc command_mgr.h
+libkea_cfgclient_la_SOURCES += command_socket.cc command_socket.h
 libkea_cfgclient_la_SOURCES += command_socket_factory.cc command_socket_factory.h
 libkea_cfgclient_la_SOURCES += config_log.h config_log.cc
 

+ 35 - 53
src/lib/config/command_mgr.cc

@@ -30,30 +30,52 @@ CommandMgr::CommandMgr() {
         boost::bind(&CommandMgr::listCommandsHandler, this, _1, _2));
 }
 
-int CommandMgr::openCommandSocket(const isc::data::ConstElementPtr& socket_info) {
-    if (socket_info_) {
+CommandSocketPtr
+CommandMgr::openCommandSocket(const isc::data::ConstElementPtr& socket_info) {
+    if (socket_) {
         isc_throw(SocketError, "There is already a control socket open");
     }
 
     socket_ = CommandSocketFactory::create(socket_info);
-    socket_info_ = socket_info;
-
-    // Install this socket in Interface Manager.
-    isc::dhcp::IfaceMgr::instance().addExternalSocket(socket_,
-        boost::bind(&isc::config::CommandMgr::connectionAcceptor, socket_));
 
     return (socket_);
 }
 
 void CommandMgr::closeCommandSocket() {
-    if (socket_info_) {
+    // First, let's close the socket for incoming new connections.
+    if (socket_) {
+        socket_->close();
+        socket_.reset();
+    }
+
+    // Now let's close all existing connections that we may have.
+    for (std::list<CommandSocketPtr>::iterator conn = connections_.begin();
+         conn != connections_.end(); ++conn) {
+        (*conn)->close();
+    }
+    connections_.clear();
+}
+
 
-        isc::dhcp::IfaceMgr::instance().deleteExternalSocket(socket_);
+void CommandMgr::addConnection(const CommandSocketPtr& conn) {
+    connections_.push_back(conn);
+}
+
+bool CommandMgr::closeConnection(int fd) {
+
+    // Let's iterate over all currently registered connections.
+    for (std::list<CommandSocketPtr>::iterator conn = connections_.begin();
+         conn != connections_.end(); ++conn) {
 
-        CommandSocketFactory::close(socket_, socket_info_);
-        socket_ = 0;
-        socket_info_.reset();
+        // If found, close it.
+        if ((*conn)->getFD() == fd) {
+            (*conn)->close();
+            connections_.erase(conn);
+            return (true);
+        }
     }
+
+    return (false);
 }
 
 CommandMgr&
@@ -105,35 +127,6 @@ void CommandMgr::deregisterAll() {
 }
 
 void
-CommandMgr::connectionAcceptor(int sockfd) {
-
-    /// @todo: Either make this generic or rename this method
-    /// to CommandSocketFactory::unixConnectionAcceptor
-    struct sockaddr_un client_addr;
-    socklen_t client_addr_len;
-    client_addr_len = sizeof(client_addr);
-
-    // Accept incoming connection. This will create a separate socket for
-    // handling this specific connection.
-    int fd2 = accept(sockfd, (struct sockaddr*) &client_addr, &client_addr_len);
-
-    // Not sure if this is really needed, but let's set it to non-blocking mode.
-    fcntl(fd2, F_SETFL, O_NONBLOCK);
-
-    // Install commandReader callback. When there's any data incoming on this
-    // socket, commandReader will be called and process it. It may also
-    // eventually close this socket.
-    isc::dhcp::IfaceMgr::instance().addExternalSocket(fd2,
-        boost::bind(&isc::config::CommandMgr::commandReader, fd2));
-
-    // Remember this socket descriptor. It will be needed when we shut down the
-    // server.
-    instance().connections_.push_back(fd2);
-
-    LOG_INFO(command_logger, COMMAND_SOCKET_CONNECTION_OPENED).arg(fd2).arg(sockfd);
-}
-
-void
 CommandMgr::commandReader(int sockfd) {
 
     // We should not expect commands bigger than 64K.
@@ -152,19 +145,8 @@ CommandMgr::commandReader(int sockfd) {
         return;
     } else if (rval == 0) {
 
-        // read of 0 bytes means end-of-file. In other words the connection is
-        // being closed.
-
-        LOG_INFO(command_logger, COMMAND_SOCKET_CONNECTION_CLOSED).arg(sockfd);
-
-        // Unregister this callback
-        isc::dhcp::IfaceMgr::instance().deleteExternalSocket(sockfd);
-
-        // Close the socket.
-        close(sockfd);
-
         // Remove it from the active connections list.
-        instance().connections_.remove(sockfd);
+        instance().closeConnection(sockfd);
 
         return;
     }

+ 25 - 20
src/lib/config/command_mgr.h

@@ -16,6 +16,7 @@
 #define COMMAND_MGR_H
 
 #include <cc/data.h>
+#include <config/command_socket.h>
 #include <boost/noncopyable.hpp>
 #include <boost/function.hpp>
 #include <string>
@@ -98,8 +99,9 @@ public:
     /// @throw SocketError if command socket is already open.
     ///
     /// @param socket_info describes control socket parameters
-    /// @return socket descriptor of the socket created
-    int openCommandSocket(const isc::data::ConstElementPtr& socket_info);
+    /// @return object representing a socket
+    CommandSocketPtr
+    openCommandSocket(const isc::data::ConstElementPtr& socket_info);
 
     /// @brief Shuts down any open control sockets
     void closeCommandSocket();
@@ -124,16 +126,6 @@ public:
     /// it may be called by external code explicitly. Hence this method is public.
     isc::data::ConstElementPtr processCommand(const isc::data::ConstElementPtr& cmd);
 
-    /// @brief Callback used to accept incoming connections.
-    ///
-    /// This callback is used on a control socket. Once called, it will accept
-    /// incoming connection, create new socket for it and install @ref commandReader
-    /// for that new socket in @ref isc::dhcp::IfaceMgr.
-    ///
-    /// @param sockfd socket descriptor of a socket capable of accepting
-    ///               incoming connections
-    static void connectionAcceptor(int sockfd);
-
     /// @brief Reads data from a socket, parses as JSON command and processes it
     ///
     /// This method is used to handle traffic on connected socket. This callback
@@ -150,12 +142,22 @@ public:
     /// handled at all times.
     void deregisterAll();
 
+    /// @brief Adds an information about opened connection socket
+    ///
+    /// @param conn Connection socket to be stored
+    void addConnection(const CommandSocketPtr& conn);
+
+    /// @brief Closes connection with a specific socket descriptor
+    ///
+    /// @param fd socket descriptor
+    /// @return true if closed successfully, false if not found
+    bool closeConnection(int fd);
 
     /// @brief Returns control socket descriptor
     ///
     /// This method should be used only in tests.
     int getControlSocketFD() const {
-        return (socket_);
+        return (socket_->getFD());
     }
 
 private:
@@ -181,14 +183,17 @@ private:
     /// @brief Container for command handlers
     HandlerContainer handlers_;
 
-    /// @brief Socket file descriptor
-    int socket_;
-
-    /// @brief Parameters for control socket
-    isc::data::ConstElementPtr socket_info_;
+    /// @brief Control socket structure
+    ///
+    /// This is the socket that accepts incoming connections. There can be at
+    /// most one (if command channel is configured).
+    CommandSocketPtr socket_;
 
-    /// @brief Socket descriptors for open connections
-    std::list<int> connections_;
+    /// @brief Sockets for open connections
+    ///
+    /// These are the sockets that are dedicated to handle a specific connection.
+    /// Their number is equal to number of current control connections.
+    std::list<CommandSocketPtr> connections_;
 };
 
 }; // end of isc::config namespace

+ 52 - 0
src/lib/config/command_socket.cc

@@ -0,0 +1,52 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config/command_socket.h>
+#include <config/command_mgr.h>
+#include <config/config_log.h>
+#include <dhcp/iface_mgr.h>
+#include <boost/bind.hpp>
+#include <unistd.h>
+
+namespace isc {
+namespace config {
+
+ConnectionSocket::ConnectionSocket(int sockfd)
+    :CommandSocket(isc::data::ConstElementPtr()) {
+        sockfd_ = sockfd;
+
+        // Install commandReader callback. When there's any data incoming on this
+        // socket, commandReader will be called and process it. It may also
+        // eventually close this socket.
+        isc::dhcp::IfaceMgr::instance().addExternalSocket(sockfd,
+            boost::bind(&ConnectionSocket::receiveHandler, this));
+    }
+
+void ConnectionSocket::close() {
+    LOG_INFO(command_logger, COMMAND_SOCKET_CONNECTION_CLOSED).arg(sockfd_);
+
+    // Unregister this callback
+    isc::dhcp::IfaceMgr::instance().deleteExternalSocket(sockfd_);
+
+    // We're closing a connection, not the whole socket. It's ok to just
+    // close the connection and don't delete anything.
+    ::close(sockfd_);
+}
+
+void ConnectionSocket::receiveHandler() {
+    CommandMgr::instance().commandReader(sockfd_);
+}
+
+};
+};

+ 123 - 0
src/lib/config/command_socket.h

@@ -0,0 +1,123 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef COMMAND_SOCKET_H
+#define COMMAND_SOCKET_H
+
+#include <cc/data.h>
+#include <unistd.h>
+
+namespace isc {
+namespace config {
+
+/// @brief An exception indicating that specified socket parameters are invalid
+class BadSocketInfo : public Exception {
+public:
+    BadSocketInfo(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief An exception indicating a problem with socket operation
+class SocketError : public Exception {
+public:
+    SocketError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief Abstract base class that represents an open command socket
+///
+/// This class is not expected to be instantiated directly. Derived classes
+/// are expected to handle specific socket types (e.g. UNIX or https).
+///
+/// For derived classes, see @ref UnixCommandSocket for a socket that
+/// accepts connections over UNIX socket and @ref ConnectionSocket that
+/// handles established connections (currently over UNIX sockets, but
+/// should be generic).
+class CommandSocket {
+public:
+    /// @brief Default constructor
+    ///
+    /// @param socket_info socket information from the config
+    CommandSocket(const isc::data::ConstElementPtr& socket_info)
+        :socket_info_(socket_info) {
+    }
+
+    /// @brief Method used to handle incoming data
+    ///
+    /// This may be registered in @ref isc::dhcp::IfaceMgr
+    virtual void receiveHandler() = 0;
+
+    /// @brief General method for closing socket.
+    ///
+    /// This is the default implementation that simply closes
+    /// the socket. Derived classes may do additional steps
+    /// to terminate the connection.
+    virtual void close() {
+        ::close(sockfd_);
+    }
+
+    /// @brief Virtual destructor.
+    virtual ~CommandSocket() {
+        close();
+    }
+
+    /// @brief Returns socket descriptor.
+    int getFD() const {
+        return (sockfd_);
+    }
+
+protected:
+    /// Stores socket descriptor.
+    int sockfd_;
+
+    /// Stores socket information.
+    isc::data::ConstElementPtr socket_info_;
+};
+
+/// Pointer to a command socket object
+typedef boost::shared_ptr<CommandSocket> CommandSocketPtr;
+
+/// @brief This class represents a straming socket for handling connections
+///
+/// Initially a socket (e.g. UNIX) is opened (represented by other classes, e.g.
+/// @ref UnixCommandSocket). Once incoming connection is detected, that class
+/// calls accept(), which returns a new socket dedicated to handling that
+/// specific connection. That socket is represented by this class.
+class ConnectionSocket : public CommandSocket {
+public:
+    /// @brief Default constructor
+    ///
+    /// This constructor is used in methods that call accept on existing
+    /// sockets. accept() returns a socket descriptor. Hence only one
+    /// parameter here.
+    ///
+    /// @param sockfd socket descriptor
+    ConnectionSocket(int sockfd);
+
+    /// @brief Method used to handle incoming data
+    ///
+    /// This method calls isc::config::CommandMgr::commandReader method.
+    virtual void receiveHandler();
+
+    /// @brief Closes socket.
+    ///
+    /// This method closes the socket, prints appropriate log message and
+    /// unregisters callback from @ref isc::dhcp::IfaceMgr.
+    virtual void close();
+};
+
+};
+};
+
+#endif

+ 130 - 79
src/lib/config/command_socket_factory.cc

@@ -14,98 +14,154 @@
 
 #include <config/command_socket_factory.h>
 #include <config/config_log.h>
-#include <cstdio>
+#include <config/command_mgr.h>
+#include <dhcp/iface_mgr.h>
+#include <boost/bind.hpp>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <string.h>
-#include <unistd.h>
+#include <cstdio>
 #include <fcntl.h>
 
-using namespace isc::config;
-
-namespace {
-
-int createUnixSocket(const std::string& file_name) {
-
-    int fd = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (fd == -1) {
-        isc_throw(isc::config::SocketError, "Failed to create AF_UNIX socket.");
-    }
-
-    // Let's remove the old file. We don't care about any possible
-    // errors here. The file should not be there if the file was
-    // shut down properly.
-    remove(file_name.c_str());
-
-    // Set this socket to be non-blocking one.
-    fcntl(fd, F_SETFL, O_NONBLOCK);
-
-    // Now bind the socket to the specified path.
-    struct sockaddr_un addr;
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, file_name.c_str(), sizeof(addr.sun_path)-1);
-    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr))) {
-        isc_throw(isc::config::SocketError, "Failed to bind socket " << fd
-                  << " to " << file_name);
-    }
-
-    // One means that we allow at most 1 awaiting connections.
-    // Any additional attempts will get ECONNREFUSED error.
-    // That means that at any given time, there may be at most one controlling
-    // connection.
-    /// @todo: Make this a configurable.
-    int status = listen(fd, 1);
-    if (status < 0) {
-        isc_throw(isc::config::SocketError, "Failed to listen on socket fd="
-                  << fd << ", filename=" << file_name);
-    }
-
-    LOG_INFO(command_logger, COMMAND_SOCKET_UNIX_OPEN).arg(fd).arg(file_name);
-
-    return (fd);
-}
-
-void closeUnixSocket(int socket_fd, const std::string& file_name) {
-    LOG_INFO(command_logger, COMMAND_SOCKET_UNIX_CLOSE).arg(socket_fd).arg(file_name);
-    close(socket_fd);
-    unlink(file_name.c_str());
-}
-
-}
-
 using namespace isc::data;
 
 namespace isc {
 namespace config {
 
-int
-CommandSocketFactory::create(const isc::data::ConstElementPtr& socket_info) {
-    if(!socket_info) {
-        isc_throw(BadSocketInfo, "Missing socket_info parameters, can't create socket.");
+/// @brief Wrapper for UNIX stream sockets
+///
+/// There are two UNIX socket types: datagram-based (equivalent of UDP) and
+/// stream-based (equivalent of TCP). This class represents stream-based
+/// sockets. It opens up a unix-socket and waits for incoming connections.
+/// Once incoming connection is detected, accept() system call is called
+/// and a new socket for that particular connection is returned. A new
+/// object of @ref ConnectionSocket is created.
+class UnixCommandSocket : public CommandSocket {
+public:
+    /// @brief Default constructor
+    ///
+    /// This socket_info map is expected to have at least one parameter:
+    /// 'socket-name' that specifies UNIX socket path. It's typically
+    /// a file somewhere in /tmp or /var/run/kea directory.
+    ///
+    /// @param socket_info socket description from the configuration
+    UnixCommandSocket(const isc::data::ConstElementPtr& socket_info)
+        : CommandSocket(socket_info) {
+
+        ConstElementPtr name = socket_info->get("socket-name");
+        if (!name) {
+            isc_throw(BadSocketInfo, "Mandatory 'socket-name' parameter missing");
+        }
+        filename_ = name->stringValue();
+
+        sockfd_ = createUnixSocket(filename_);
+
+        // Install this socket in Interface Manager.
+        isc::dhcp::IfaceMgr::instance().addExternalSocket(sockfd_,
+            boost::bind(&UnixCommandSocket::receiveHandler, this));
     }
 
-    ConstElementPtr type = socket_info->get("socket-type");
-    if (!type) {
-        isc_throw(BadSocketInfo, "Mandatory 'socket-type' parameter missing");
+private:
+
+    /// @brief Auxiliary method for creating a UNIX socket
+    ///
+    /// @param file_name specifies socket file path
+    int createUnixSocket(const std::string& file_name) {
+
+        int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (fd == -1) {
+            isc_throw(isc::config::SocketError, "Failed to create AF_UNIX socket.");
+        }
+
+        // Let's remove the old file. We don't care about any possible
+        // errors here. The file should not be there if the file was
+        // shut down properly.
+        remove(file_name.c_str());
+
+        // Set this socket to be non-blocking one.
+        fcntl(fd, F_SETFL, O_NONBLOCK);
+
+        // Now bind the socket to the specified path.
+        struct sockaddr_un addr;
+        memset(&addr, 0, sizeof(addr));
+        addr.sun_family = AF_UNIX;
+        strncpy(addr.sun_path, file_name.c_str(), sizeof(addr.sun_path)-1);
+        if (bind(fd, (struct sockaddr*)&addr, sizeof(addr))) {
+            ::close(fd);
+            remove(file_name.c_str());
+            isc_throw(isc::config::SocketError, "Failed to bind socket " << fd
+                      << " to " << file_name);
+        }
+
+        // One means that we allow at most 1 awaiting connections.
+        // Any additional attempts will get ECONNREFUSED error.
+        // That means that at any given time, there may be at most one controlling
+        // connection.
+        /// @todo: Make the number of parallel connections configurable.
+        int status = listen(fd, 1);
+        if (status < 0) {
+            ::close(fd);
+            remove(file_name.c_str());
+            isc_throw(isc::config::SocketError, "Failed to listen on socket fd="
+                      << fd << ", filename=" << file_name);
+        }
+
+        // Woohoo! Socket opened, let's log it!
+        LOG_INFO(command_logger, COMMAND_SOCKET_UNIX_OPEN).arg(fd).arg(file_name);
+
+        return (fd);
     }
 
-    ConstElementPtr name = socket_info->get("socket-name");
-    if (!name) {
-        isc_throw(BadSocketInfo, "Mandatory 'socket-name' parameter missing");
+    /// CommandMgr::connectionAcceptor(int sockfd) {
+    /// @brief Callback used to accept incoming connections.
+    ///
+    /// This callback is used on a control socket. Once called, it will accept
+    /// incoming connection, create new socket for it and install
+    /// @ref commandReader for that new socket in @ref isc::dhcp::IfaceMgr.
+    void receiveHandler() {
+
+        // This method is specific to receiving data over UNIX socket, so using
+        // sockaddr_un instead of sockaddr_storage here is ok.
+        struct sockaddr_un client_addr;
+        socklen_t client_addr_len;
+        client_addr_len = sizeof(client_addr);
+
+        // Accept incoming connection. This will create a separate socket for
+        // handling this specific connection.
+        int fd2 = accept(sockfd_, static_cast<struct sockaddr*>(&client_addr),
+                         &client_addr_len);
+
+        // And now create an object that represents that new connection.
+        CommandSocketPtr conn(new ConnectionSocket(fd2));
+
+        // Not sure if this is really needed, but let's set it to non-blocking
+        // mode.
+        fcntl(fd2, F_SETFL, O_NONBLOCK);
+
+        // Remember this socket descriptor. It will be needed when we shut down
+        // the server.
+        CommandMgr::instance().addConnection(conn);
+
+        LOG_INFO(command_logger, COMMAND_SOCKET_CONNECTION_OPENED).arg(fd2)
+            .arg(sockfd_);
     }
 
-    if (type->stringValue() == "unix") {
-        return (createUnixSocket(name->stringValue()));
-    } else {
-        isc_throw(BadSocketInfo, "Specified socket type ('" + type->stringValue()
-                  + "') is not supported.");
+    // This method is called when we shutdown the connection.
+    void close() {
+        LOG_INFO(command_logger, COMMAND_SOCKET_UNIX_CLOSE).arg(sockfd_)
+            .arg(filename_);
+
+        isc::dhcp::IfaceMgr::instance().deleteExternalSocket(sockfd_);
+
+        ::close(sockfd_);
+        remove(filename_.c_str());
     }
-}
 
-void CommandSocketFactory::close(int socket_fd,
-                                 const isc::data::ConstElementPtr& socket_info) {
+    std::string filename_;
+};
 
+CommandSocketPtr
+CommandSocketFactory::create(const isc::data::ConstElementPtr& socket_info) {
     if(!socket_info) {
         isc_throw(BadSocketInfo, "Missing socket_info parameters, can't create socket.");
     }
@@ -115,13 +171,8 @@ void CommandSocketFactory::close(int socket_fd,
         isc_throw(BadSocketInfo, "Mandatory 'socket-type' parameter missing");
     }
 
-    ConstElementPtr name = socket_info->get("socket-name");
-    if (!name) {
-        isc_throw(BadSocketInfo, "Mandatory 'socket-name' parameter missing");
-    }
-
     if (type->stringValue() == "unix") {
-        return (closeUnixSocket(socket_fd, name->stringValue()));
+        return (CommandSocketPtr(new UnixCommandSocket(socket_info)));
     } else {
         isc_throw(BadSocketInfo, "Specified socket type ('" + type->stringValue()
                   + "') is not supported.");

+ 2 - 26
src/lib/config/command_socket_factory.h

@@ -16,25 +16,11 @@
 #define COMMAND_SOCKET_FACTORY_H
 
 #include <cc/data.h>
+#include <config/command_socket.h>
 
 namespace isc {
 namespace config {
 
-/// @brief An exception indicating that specified socket parameters are invalid
-class BadSocketInfo : public Exception {
-public:
-    BadSocketInfo(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) { };
-};
-
-/// @brief An exception indicating a problem with socket operation
-class SocketError : public Exception {
-public:
-    SocketError(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) { };
-};
-
-
 /// A factory class for opening command socket
 ///
 /// This class provides an interface for opening command socket.
@@ -52,19 +38,9 @@ public:
     ///
     /// @param socket_info structure that describes the socket
     /// @return socket descriptor
-    static int create(const isc::data::ConstElementPtr& socket_info);
-
-    /// @brief Closes specified socket
-    ///
-    /// In most cases it will be a simple close() call, but in more complex
-    /// (e.g. https) it may perform certain shutdown operations before
-    /// closing.
-    /// @param socket_fd file descriptor of the socket
-    /// @param socket_info structure that was used to open the socket
-    static void close(int socket_fd, const isc::data::ConstElementPtr& socket_info);
+    static CommandSocketPtr create(const isc::data::ConstElementPtr& socket_info);
 };
 
-
 };
 };
 

+ 6 - 4
src/lib/config/tests/command_socket_factory_unittests.cc

@@ -16,6 +16,7 @@
 
 #include <cc/data.h>
 #include <config/command_mgr.h>
+#include <config/command_socket.h>
 #include <config/command_socket_factory.h>
 #include <cstdio>
 
@@ -65,11 +66,12 @@ TEST_F(CommandSocketFactoryTest, unixCreate) {
                  isc::config::BadSocketInfo);
 
     socket_info->set("socket-name", Element::create(SOCKET_NAME));
-    int fd;
-    EXPECT_NO_THROW(fd = CommandSocketFactory::create(socket_info));
-    EXPECT_NE(-1, fd);
+    CommandSocketPtr sock;
+    EXPECT_NO_THROW(sock = CommandSocketFactory::create(socket_info));
+    ASSERT_TRUE(sock);
+    EXPECT_NE(-1, sock->getFD());
 
     // It should be possible to close the socket.
-    EXPECT_NO_THROW(CommandSocketFactory::close(fd, socket_info));
+    EXPECT_NO_THROW(sock->close());
 }