LCOV - code coverage report
Current view: top level - server_common - socket_request.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 120 128 93.8 %
Date: 2012-05-15 Functions: 14 14 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 203 401 50.6 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : #include <config.h>
      15                 :            : 
      16                 :            : #include "socket_request.h"
      17                 :            : #include <server_common/logger.h>
      18                 :            : 
      19                 :            : #include <config/ccsession.h>
      20                 :            : #include <cc/session.h>
      21                 :            : #include <cc/data.h>
      22                 :            : #include <util/io/fd.h>
      23                 :            : #include <util/io/fd_share.h>
      24                 :            : 
      25                 :            : #include <sys/un.h>
      26                 :            : #include <sys/socket.h>
      27                 :            : #include <cerrno>
      28                 :            : #include <csignal>
      29                 :            : #include <cstddef>
      30                 :            : 
      31                 :            : namespace isc {
      32                 :            : namespace server_common {
      33                 :            : 
      34                 :            : namespace {
      35                 :            : SocketRequestor* requestor(NULL);
      36                 :            : 
      37                 :            : // Before the boss process calls send_fd, it first sends this
      38                 :            : // string to indicate success, followed by the file descriptor
      39                 :            : const std::string& CREATOR_SOCKET_OK() {
      40 [ +  + ][ +  - ]:          9 :     static const std::string str("1\n");
                 [ +  - ]
      41                 :            :     return (str);
      42                 :            : }
      43                 :            : 
      44                 :            : // Before the boss process calls send_fd, it sends this
      45                 :            : // string to indicate failure. It will not send a file descriptor.
      46                 :            : const std::string& CREATOR_SOCKET_UNAVAILABLE() {
      47 [ +  + ][ +  - ]:         10 :     static const std::string str("0\n");
                 [ +  - ]
      48                 :            :     return (str);
      49                 :            : }
      50                 :            : 
      51                 :            : // The name of the ccsession command to request a socket from boss
      52                 :            : // (the actual format of command and response are hardcoded in their
      53                 :            : // respective methods)
      54                 :            : const std::string& REQUEST_SOCKET_COMMAND() {
      55 [ +  + ][ +  - ]:         51 :     static const std::string str("get_socket");
                 [ +  - ]
      56                 :            :     return (str);
      57                 :            : }
      58                 :            : 
      59                 :            : // The name of the ccsession command to tell boss we no longer need
      60                 :            : // a socket (the actual format of command and response are hardcoded
      61                 :            : // in their respective methods)
      62                 :            : const std::string& RELEASE_SOCKET_COMMAND() {
      63 [ +  + ][ +  - ]:         12 :     static const std::string str("drop_socket");
                 [ +  - ]
      64                 :            :     return (str);
      65                 :            : }
      66                 :            : 
      67                 :            : // RCode constants for the get_token command
      68                 :            : const size_t SOCKET_ERROR_CODE = 2;
      69                 :            : const size_t SHARE_ERROR_CODE = 3;
      70                 :            : 
      71                 :            : // A helper converter from numeric protocol ID to the corresponding string.
      72                 :            : // used both for generating a message for the boss process and for logging.
      73                 :            : inline const char*
      74                 :            : protocolString(SocketRequestor::Protocol protocol) {
      75      [ +  -  - ]:         62 :     switch (protocol) {
              [ +  -  + ]
      76                 :            :     case SocketRequestor::TCP:
      77                 :            :         return ("TCP");
      78                 :            :     case SocketRequestor::UDP:
      79                 :            :         return ("UDP");
      80                 :            :     default:
      81                 :            :         return ("unknown protocol");
      82                 :            :     }
      83                 :            : }
      84                 :            : 
      85                 :            : // Creates the cc session message to request a socket.
      86                 :            : // The actual command format is hardcoded, and should match
      87                 :            : // the format as read in bind10_src.py.in
      88                 :            : isc::data::ConstElementPtr
      89                 :         57 : createRequestSocketMessage(SocketRequestor::Protocol protocol,
      90                 :            :                            const std::string& address, uint16_t port,
      91                 :            :                            SocketRequestor::ShareMode share_mode,
      92                 :            :                            const std::string& share_name)
      93                 :            : {
      94                 :         57 :     const isc::data::ElementPtr request = isc::data::Element::createMap();
      95 [ +  - ][ +  - ]:        114 :     request->set("address", isc::data::Element::create(address));
                 [ +  - ]
      96 [ +  - ][ +  - ]:        114 :     request->set("port", isc::data::Element::create(port));
      97         [ +  + ]:         57 :     if (protocol != SocketRequestor::TCP && protocol != SocketRequestor::UDP) {
      98 [ +  - ][ +  - ]:          6 :         isc_throw(InvalidParameter, "invalid protocol: " << protocol);
                 [ +  - ]
      99                 :            :     }
     100                 :         54 :     request->set("protocol",
     101 [ +  - ][ +  - ]:        108 :                  isc::data::Element::create(protocolString(protocol)));
                 [ +  - ]
     102   [ +  +  +  + ]:         54 :     switch (share_mode) {
     103                 :            :     case SocketRequestor::DONT_SHARE:
     104 [ +  - ][ +  - ]:         84 :         request->set("share_mode", isc::data::Element::create("NO"));
                 [ +  - ]
     105                 :            :         break;
     106                 :            :     case SocketRequestor::SHARE_SAME:
     107 [ +  - ][ +  - ]:         12 :         request->set("share_mode", isc::data::Element::create("SAMEAPP"));
                 [ +  - ]
     108                 :            :         break;
     109                 :            :     case SocketRequestor::SHARE_ANY:
     110 [ +  - ][ +  - ]:          6 :         request->set("share_mode", isc::data::Element::create("ANY"));
                 [ +  - ]
     111                 :            :         break;
     112                 :            :     default:
     113 [ +  - ][ +  - ]:          6 :         isc_throw(InvalidParameter, "invalid share mode: " << share_mode);
                 [ +  - ]
     114                 :            :     }
     115 [ +  - ][ +  - ]:        102 :     request->set("share_name", isc::data::Element::create(share_name));
                 [ +  - ]
     116                 :            : 
     117         [ +  - ]:        102 :     return (isc::config::createCommand(REQUEST_SOCKET_COMMAND(), request));
     118                 :            : }
     119                 :            : 
     120                 :            : isc::data::ConstElementPtr
     121                 :         12 : createReleaseSocketMessage(const std::string& token) {
     122                 :         12 :     const isc::data::ElementPtr release = isc::data::Element::createMap();
     123 [ +  - ][ +  - ]:         24 :     release->set("token", isc::data::Element::create(token));
                 [ +  - ]
     124                 :            : 
     125         [ +  - ]:         24 :     return (isc::config::createCommand(RELEASE_SOCKET_COMMAND(), release));
     126                 :            : }
     127                 :            : 
     128                 :            : // Checks and parses the response receive from Boss
     129                 :            : // If successful, token and path will be set to the values found in the
     130                 :            : // answer.
     131                 :            : // If the response was an error response, or does not contain the
     132                 :            : // expected elements, a CCSessionError is raised.
     133                 :            : void
     134                 :         36 : readRequestSocketAnswer(isc::data::ConstElementPtr recv_msg,
     135                 :            :                         std::string& token, std::string& path)
     136                 :            : {
     137                 :            :     int rcode;
     138                 :            :     isc::data::ConstElementPtr answer = isc::config::parseAnswer(rcode,
     139         [ +  - ]:         36 :                                                                  recv_msg);
     140                 :            :     // Translate known rcodes to the corresponding exceptions
     141         [ +  + ]:         36 :     if (rcode == SOCKET_ERROR_CODE) {
     142 [ +  - ][ +  - ]:          6 :         isc_throw(SocketRequestor::SocketAllocateError, answer->str());
                 [ +  - ]
     143                 :            :     }
     144         [ +  + ]:         33 :     if (rcode == SHARE_ERROR_CODE) {
     145 [ +  - ][ +  - ]:          6 :         isc_throw(SocketRequestor::ShareError, answer->str());
                 [ +  - ]
     146                 :            :     }
     147                 :            :     // The unknown exceptions
     148         [ +  + ]:         30 :     if (rcode != 0) {
     149 [ +  - ][ +  - ]:          6 :         isc_throw(isc::config::CCSessionError,
         [ +  - ][ +  - ]
     150                 :            :                   "Error response when requesting socket: " << answer->str());
     151                 :            :     }
     152                 :            : 
     153 [ +  + ][ +  - ]:         27 :     if (!answer || !answer->contains("token") || !answer->contains("path")) {
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
         [ +  + ][ +  + ]
         [ #  # ][ #  # ]
     154 [ +  - ][ +  - ]:          6 :         isc_throw(isc::config::CCSessionError,
     155                 :            :                   "Malformed answer when requesting socket");
     156                 :            :     }
     157 [ +  - ][ +  - ]:         72 :     token = answer->get("token")->stringValue();
                 [ +  - ]
     158 [ +  - ][ +  - ]:         72 :     path = answer->get("path")->stringValue();
                 [ +  - ]
     159                 :         24 : }
     160                 :            : 
     161                 :            : // Connect to the domain socket that has been received from Boss.
     162                 :            : // (i.e. the one that is used to pass created sockets over).
     163                 :            : //
     164                 :            : // This should only be called if the socket had not been connected to
     165                 :            : // already. To get the socket and reuse existing ones, use
     166                 :            : // getFdShareSocket()
     167                 :            : //
     168                 :            : // \param path The domain socket to connect to
     169                 :            : // \exception SocketError if the socket cannot be connected to
     170                 :            : // \return the socket file descriptor
     171                 :            : int
     172                 :         15 : createFdShareSocket(const std::string& path) {
     173                 :            :     // TODO: Current master has socketsession code and better way
     174                 :            :     // of handling errors without potential leaks for this. It is
     175                 :            :     // not public there at this moment, but when this is merged
     176                 :            :     // we should make a ticket to move this functionality to the
     177                 :            :     // SocketSessionReceiver and use that.
     178                 :         15 :     const int sock_pass_fd = socket(AF_UNIX, SOCK_STREAM, 0);
     179         [ -  + ]:         15 :     if (sock_pass_fd == -1) {
     180 [ #  # ][ #  # ]:          0 :         isc_throw(SocketRequestor::SocketError,
         [ #  # ][ #  # ]
                 [ #  # ]
     181                 :            :                   "Unable to open domain socket " << path <<
     182                 :            :                   ": " << strerror(errno));
     183                 :            :     }
     184                 :            :     struct sockaddr_un sock_pass_addr;
     185                 :         15 :     sock_pass_addr.sun_family = AF_UNIX;
     186         [ +  + ]:         15 :     if (path.size() >= sizeof(sock_pass_addr.sun_path)) {
     187                 :          6 :         close(sock_pass_fd);
     188 [ +  - ][ +  - ]:         12 :         isc_throw(SocketRequestor::SocketError,
         [ +  - ][ +  - ]
     189                 :            :                   "Unable to open domain socket " << path <<
     190                 :            :                   ": path too long");
     191                 :            :     }
     192                 :            : #ifdef HAVE_SA_LEN
     193                 :            :     sock_pass_addr.sun_len = path.size();
     194                 :            : #endif
     195                 :            :     strcpy(sock_pass_addr.sun_path, path.c_str());
     196                 :          9 :     const socklen_t len = path.size() + offsetof(struct sockaddr_un, sun_path);
     197                 :            :     // Yes, C-style cast bad. See previous comment about SocketSessionReceiver.
     198         [ +  + ]:          9 :     if (connect(sock_pass_fd, (const struct sockaddr*)&sock_pass_addr,
     199                 :          9 :                 len) == -1) {
     200                 :          6 :         close(sock_pass_fd);
     201 [ +  - ][ +  - ]:         12 :         isc_throw(SocketRequestor::SocketError,
         [ +  - ][ +  - ]
                 [ +  - ]
     202                 :            :                   "Unable to open domain socket " << path <<
     203                 :            :                   ": " << strerror(errno));
     204                 :            :     }
     205                 :          3 :     return (sock_pass_fd);
     206                 :            : }
     207                 :            : 
     208                 :            : // Reads a socket fd over the given socket (using recv_fd()).
     209                 :            : //
     210                 :            : // \exception SocketError if the socket cannot be read
     211                 :            : // \return the socket fd that has been read
     212                 :            : int
     213                 :         12 : getSocketFd(const std::string& token, int sock_pass_fd) {
     214                 :            :     // Tell the boss the socket token.
     215                 :         12 :     const std::string token_data = token + "\n";
     216         [ +  + ]:         12 :     if (!isc::util::io::write_data(sock_pass_fd, token_data.c_str(),
     217         [ +  - ]:         12 :                                    token_data.size())) {
     218 [ +  - ][ +  - ]:          4 :         isc_throw(SocketRequestor::SocketError, "Error writing socket token");
                 [ +  - ]
     219                 :            :     }
     220                 :            : 
     221                 :            :     // Boss first sends some data to signal that getting the socket
     222                 :            :     // from its cache succeeded
     223                 :            :     char status[3];        // We need a space for trailing \0, hence 3
     224                 :            :     memset(status, 0, 3);
     225 [ +  - ][ -  + ]:         10 :     if (isc::util::io::read_data(sock_pass_fd, status, 2) < 2) {
     226 [ #  # ][ #  # ]:          0 :         isc_throw(SocketRequestor::SocketError,
                 [ #  # ]
     227                 :            :                   "Error reading status code while requesting socket");
     228                 :            :     }
     229                 :            :     // Actual status value hardcoded by boss atm.
     230         [ +  + ]:         10 :     if (CREATOR_SOCKET_UNAVAILABLE() == status) {
     231 [ +  - ][ +  - ]:          2 :         isc_throw(SocketRequestor::SocketError,
                 [ +  - ]
     232                 :            :                   "CREATOR_SOCKET_UNAVAILABLE returned");
     233         [ -  + ]:          9 :     } else if (CREATOR_SOCKET_OK() != status) {
     234 [ #  # ][ #  # ]:          0 :         isc_throw(SocketRequestor::SocketError,
         [ #  # ][ #  # ]
                 [ #  # ]
     235                 :            :                   "Unknown status code returned before recv_fd '" << status <<
     236                 :            :                   "'");
     237                 :            :     }
     238                 :            : 
     239         [ +  - ]:          9 :     const int passed_sock_fd = isc::util::io::recv_fd(sock_pass_fd);
     240                 :            : 
     241                 :            :     // check for error values of passed_sock_fd (see fd_share.h)
     242         [ +  + ]:          9 :     if (passed_sock_fd < 0) {
     243      [ +  -  - ]:          1 :         switch (passed_sock_fd) {
     244                 :            :         case isc::util::io::FD_SYSTEM_ERROR:
     245 [ +  - ][ +  - ]:          2 :             isc_throw(SocketRequestor::SocketError,
                 [ +  - ]
     246                 :            :                       "FD_SYSTEM_ERROR while requesting socket");
     247                 :            :             break;
     248                 :            :         case isc::util::io::FD_OTHER_ERROR:
     249 [ #  # ][ #  # ]:          0 :             isc_throw(SocketRequestor::SocketError,
                 [ #  # ]
     250                 :            :                       "FD_OTHER_ERROR while requesting socket");
     251                 :            :             break;
     252                 :            :         default:
     253 [ #  # ][ #  # ]:          0 :             isc_throw(SocketRequestor::SocketError,
                 [ #  # ]
     254                 :            :                       "Unknown error while requesting socket");
     255                 :            :         }
     256                 :            :     }
     257                 :          8 :     return (passed_sock_fd);
     258                 :            : }
     259                 :            : 
     260                 :            : // This implementation class for SocketRequestor uses
     261                 :            : // a CC session for communication with the boss process,
     262                 :            : // and fd_share to read out the socket(s).
     263                 :            : // Since we only use a reference to the session, it must never
     264                 :            : // be closed during the lifetime of this class
     265                 :            : class SocketRequestorCCSession : public SocketRequestor {
     266                 :            : public:
     267                 :            :     SocketRequestorCCSession(cc::AbstractSession& session,
     268                 :            :                              const std::string& app_name) :
     269                 :            :         session_(session),
     270         [ +  - ]:         18 :         app_name_(app_name)
     271                 :            :     {
     272                 :            :         // We need to filter SIGPIPE to prevent it from happening in
     273                 :            :         // getSocketFd() while writing to the UNIX domain socket after the
     274                 :            :         // remote end closed it.  See lib/util/io/socketsession for more
     275                 :            :         // background details.
     276                 :            :         // Note: we should eventually unify this level of details into a single
     277                 :            :         // module.  Setting a single filter here should be considered a short
     278                 :            :         // term workaround.
     279         [ -  + ]:         18 :         if (std::signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
     280 [ #  # ][ #  # ]:          0 :             isc_throw(Unexpected, "Failed to filter SIGPIPE: " <<
                 [ #  # ]
     281                 :            :                       strerror(errno));
     282                 :            :         }
     283 [ +  - ][ +  - ]:         36 :         LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, SOCKETREQUESTOR_CREATED).
                 [ -  + ]
     284 [ +  - ][ +  - ]:         18 :             arg(app_name);
     285                 :            :     }
     286                 :            : 
     287                 :         16 :     ~SocketRequestorCCSession() {
     288                 :            :         closeFdShareSockets();
     289 [ +  - ][ +  - ]:         16 :         LOG_DEBUG(logger, DBGLVL_TRACE_BASIC, SOCKETREQUESTOR_DESTROYED);
         [ +  - ][ +  - ]
     290                 :         32 :     }
     291                 :            : 
     292                 :         57 :     virtual SocketID requestSocket(Protocol protocol,
     293                 :            :                                    const std::string& address,
     294                 :            :                                    uint16_t port, ShareMode share_mode,
     295                 :            :                                    const std::string& share_name)
     296                 :            :     {
     297                 :            :         const isc::data::ConstElementPtr request_msg =
     298                 :            :             createRequestSocketMessage(protocol, address, port,
     299                 :            :                                        share_mode,
     300                 :            :                                        share_name.empty() ? app_name_ :
     301         [ +  + ]:         57 :                                        share_name);
     302                 :            : 
     303                 :            :         // Send it to boss
     304 [ +  - ][ +  - ]:        153 :         const int seq = session_.group_sendmsg(request_msg, "Boss");
         [ +  - ][ +  - ]
     305                 :            : 
     306                 :            :         // Get the answer from the boss.
     307                 :            :         // Just do a blocking read, we can't really do much anyway
     308                 :            :         isc::data::ConstElementPtr env, recv_msg;
     309 [ +  - ][ +  + ]:         51 :         if (!session_.group_recvmsg(env, recv_msg, false, seq)) {
     310 [ +  - ][ +  - ]:         30 :             isc_throw(isc::config::CCSessionError,
     311                 :            :                       "Incomplete response when requesting socket");
     312                 :            :         }
     313                 :            : 
     314                 :            :         // Read the socket file from the answer
     315                 :         36 :         std::string token, path;
     316         [ +  + ]:         36 :         readRequestSocketAnswer(recv_msg, token, path);
     317                 :            :         // get the domain socket over which we will receive the
     318                 :            :         // real socket
     319                 :         12 :         const int sock_pass_fd = getFdShareSocket(path);
     320                 :            : 
     321                 :            :         // and finally get the socket itself
     322         [ +  + ]:         12 :         const int passed_sock_fd = getSocketFd(token, sock_pass_fd);
     323 [ +  - ][ +  - ]:         16 :         LOG_DEBUG(logger, DBGLVL_TRACE_DETAIL, SOCKETREQUESTOR_GETSOCKET).
                 [ +  - ]
     324 [ +  - ][ +  - ]:          8 :             arg(protocolString(protocol)).arg(address).arg(port).
         [ +  - ][ +  - ]
     325 [ +  - ][ +  - ]:          8 :             arg(passed_sock_fd).arg(token).arg(path);
                 [ +  - ]
     326                 :          8 :         return (SocketID(passed_sock_fd, token));
     327                 :            :     }
     328                 :            : 
     329                 :         12 :     virtual void releaseSocket(const std::string& token) {
     330                 :            :         const isc::data::ConstElementPtr release_msg =
     331                 :         12 :             createReleaseSocketMessage(token);
     332                 :            : 
     333                 :            :         // Send it to boss
     334 [ +  - ][ +  - ]:         36 :         const int seq = session_.group_sendmsg(release_msg, "Boss");
         [ +  - ][ +  - ]
     335 [ +  - ][ +  - ]:         24 :         LOG_DEBUG(logger, DBGLVL_TRACE_DETAIL, SOCKETREQUESTOR_RELEASESOCKET).
                 [ +  - ]
     336 [ +  - ][ +  - ]:         12 :             arg(token);
     337                 :            : 
     338                 :            :         // Get the answer from the boss.
     339                 :            :         // Just do a blocking read, we can't really do much anyway
     340                 :            :         isc::data::ConstElementPtr env, recv_msg;
     341 [ +  - ][ +  + ]:         12 :         if (!session_.group_recvmsg(env, recv_msg, false, seq)) {
     342 [ +  - ][ +  - ]:          6 :             isc_throw(isc::config::CCSessionError,
     343                 :            :                       "Incomplete response when sending drop socket command");
     344                 :            :         }
     345                 :            : 
     346                 :            :         // Answer should just be success
     347                 :            :         int rcode;
     348                 :            :         isc::data::ConstElementPtr error = isc::config::parseAnswer(rcode,
     349         [ +  - ]:          9 :                                                                     recv_msg);
     350         [ +  + ]:          9 :         if (rcode != 0) {
     351 [ +  - ][ +  - ]:          6 :             isc_throw(SocketError,
         [ +  - ][ +  - ]
                 [ +  - ]
     352                 :            :                       "Error requesting release of socket: " << error->str());
     353                 :            :         }
     354                 :          6 :     }
     355                 :            : 
     356                 :            : private:
     357                 :            :     // Returns the domain socket file descriptor
     358                 :            :     // If we had not opened it yet, opens it now
     359                 :            :     int
     360                 :            :     getFdShareSocket(const std::string& path) {
     361         [ +  + ]:         24 :         if (fd_share_sockets_.find(path) == fd_share_sockets_.end()) {
     362         [ +  + ]:         15 :             const int new_fd = createFdShareSocket(path);
     363                 :            :             // Technically, the (creation and) assignment of the new map entry
     364                 :            :             // could thrown an exception and lead to FD leak.  This should be
     365                 :            :             // cleaned up later (see comment about SocketSessionReceiver above)
     366         [ +  - ]:          3 :             fd_share_sockets_[path] = new_fd;
     367                 :            :             return (new_fd);
     368                 :            :         } else {
     369         [ +  - ]:          9 :             return (fd_share_sockets_[path]);
     370                 :            :         }
     371                 :            :     }
     372                 :            : 
     373                 :            :     // Closes the sockets that has been used for fd_share
     374                 :            :     void
     375                 :            :     closeFdShareSockets() {
     376         [ +  + ]:         18 :         for (std::map<std::string, int>::const_iterator it =
     377                 :         32 :                 fd_share_sockets_.begin();
     378                 :         36 :              it != fd_share_sockets_.end();
     379                 :            :              ++it) {
     380         [ +  - ]:          2 :             close((*it).second);
     381                 :            :         }
     382                 :            :     }
     383                 :            : 
     384                 :            :     cc::AbstractSession& session_;
     385                 :            :     const std::string app_name_;
     386                 :            :     std::map<std::string, int> fd_share_sockets_;
     387                 :            : };
     388                 :            : 
     389                 :            : }
     390                 :            : 
     391                 :            : SocketRequestor&
     392                 :        305 : socketRequestor() {
     393         [ +  + ]:        305 :     if (requestor != NULL) {
     394                 :        302 :         return (*requestor);
     395                 :            :     } else {
     396         [ +  - ]:          6 :         isc_throw(InvalidOperation, "The socket requestor is not initialized");
     397                 :            :     }
     398                 :            : }
     399                 :            : 
     400                 :            : void
     401                 :         18 : initSocketRequestor(cc::AbstractSession& session,
     402                 :            :                     const std::string& app_name)
     403                 :            : {
     404         [ -  + ]:         18 :     if (requestor != NULL) {
     405         [ #  # ]:          0 :         isc_throw(InvalidOperation,
     406                 :            :                   "The socket requestor was already initialized");
     407                 :            :     } else {
     408                 :         18 :         requestor = new SocketRequestorCCSession(session, app_name);
     409                 :            :     }
     410                 :         18 : }
     411                 :            : 
     412                 :            : void
     413                 :        241 : initTestSocketRequestor(SocketRequestor* new_requestor) {
     414                 :        241 :     requestor = new_requestor;
     415                 :        241 : }
     416                 :            : 
     417                 :            : void
     418                 :         16 : cleanupSocketRequestor() {
     419         [ +  - ]:         16 :     if (requestor != NULL) {
     420         [ +  - ]:         16 :         delete requestor;
     421                 :         16 :         requestor = NULL;
     422                 :            :     } else {
     423         [ #  # ]:          0 :         isc_throw(InvalidOperation, "The socket requestor is not initialized");
     424                 :            :     }
     425                 :         16 : }
     426                 :            : 
     427                 :            : }
     428                 :          5 : }

Generated by: LCOV version 1.9