LCOV - code coverage report
Current view: top level - eventdispatcher - tcp_server.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 77 1.3 %
Date: 2022-06-18 10:10:36 Functions: 2 13 15.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/eventdispatcher
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : 
      20             : /** \file
      21             :  * \brief TCP server definition.
      22             :  *
      23             :  * Class used to handle events.
      24             :  */
      25             : 
      26             : // to get the POLLRDHUP definition
      27             : #ifndef _GNU_SOURCE
      28             : #define _GNU_SOURCE
      29             : #endif
      30             : 
      31             : 
      32             : // self
      33             : //
      34             : #include    "eventdispatcher/tcp_server.h"
      35             : 
      36             : #include    "eventdispatcher/exception.h"
      37             : 
      38             : 
      39             : // snaplogger lib
      40             : //
      41             : #include    <snaplogger/message.h>
      42             : 
      43             : 
      44             : // snapdev lib
      45             : //
      46             : #include    <snapdev/not_reached.h>
      47             : 
      48             : 
      49             : // C++ lib
      50             : //
      51             : #include    <cstring>
      52             : 
      53             : 
      54             : // C lib
      55             : //
      56             : #include    <poll.h>
      57             : 
      58             : 
      59             : // last include
      60             : //
      61             : #include    <snapdev/poison.h>
      62             : 
      63             : 
      64             : 
      65             : namespace ed
      66             : {
      67             : 
      68             : 
      69             : 
      70             : /** \brief Initialize the server and start listening for connections.
      71             :  *
      72             :  * The server constructor creates a socket, binds it, and then listen to it.
      73             :  *
      74             :  * By default the server accepts a maximum of \p max_connections (set to
      75             :  * 0 or less to get the default tcp_server::MAX_CONNECTIONS) in its waiting queue.
      76             :  * If you use the server and expect a low connection rate, you may want to
      77             :  * reduce the count to 5. Although some very busy servers use larger numbers.
      78             :  * This value gets clamped to a minimum of 5 and a maximum of 1,000.
      79             :  *
      80             :  * Note that the maximum number of connections is actually limited to
      81             :  * /proc/sys/net/core/somaxconn connections. This number is generally 128 
      82             :  * in 2016. So the  super high limit of 1,000 is anyway going to be ignored
      83             :  * by the OS.
      84             :  *
      85             :  * The address is made non-reusable (which is the default for TCP sockets.)
      86             :  * It is possible to mark the server address as immediately reusable by
      87             :  * setting the \p reuse_addr to true.
      88             :  *
      89             :  * By default the server is marked as "keepalive". You can turn it off
      90             :  * using the keepalive() function with false.
      91             :  *
      92             :  * \exception tcp_client_server_parameter_error
      93             :  * This exception is raised if the address parameter is an empty string or
      94             :  * otherwise an invalid IP address, or if the port is out of range.
      95             :  *
      96             :  * \exception tcp_client_server_runtime_error
      97             :  * This exception is raised if the socket cannot be created, bound to
      98             :  * the specified IP address and port, or listen() fails on the socket.
      99             :  *
     100             :  * \param[in] address  The address to listen on. It may be set to "0.0.0.0".
     101             :  * \param[in] max_connections  The number of connections to keep in the listen queue.
     102             :  * \param[in] reuse_addr  Whether to mark the socket with the SO_REUSEADDR flag.
     103             :  * \param[in] auto_close  Automatically close the client socket in accept and the destructor.
     104             :  */
     105           0 : tcp_server::tcp_server(
     106             :           addr::addr const & address
     107             :         , int max_connections
     108             :         , bool reuse_addr
     109           0 :         , bool auto_close)
     110           0 :     : f_max_connections(max_connections <= 0 ? MAX_CONNECTIONS : max_connections)
     111             :     , f_address(address)
     112           0 :     , f_auto_close(auto_close)
     113             : {
     114           0 :     if(f_max_connections < 5)
     115             :     {
     116           0 :         f_max_connections = 5;
     117             :     }
     118           0 :     else if(f_max_connections > 1000)
     119             :     {
     120           0 :         f_max_connections = 1000;
     121             :     }
     122             : 
     123           0 :     f_socket = f_address.create_socket(
     124             :                   (reuse_addr
     125             :                         ? addr::addr::SOCKET_FLAG_REUSE
     126             :                         : 0));
     127           0 :     if(f_socket < 0)
     128             :     {
     129           0 :         int const e(errno);
     130           0 :         SNAP_LOG_ERROR
     131             :             << "addr::create_socket() failed to create a socket descriptor (errno: "
     132           0 :             << std::to_string(e)
     133             :             << " -- "
     134           0 :             << strerror(e)
     135             :             << ")"
     136             :             << SNAP_LOG_SEND;
     137           0 :         throw runtime_error("could not create socket for client");
     138             :     }
     139             : 
     140           0 :     if(f_address.bind(f_socket) != 0)
     141             :     {
     142           0 :         close(f_socket);
     143           0 :         std::stringstream ss;
     144             :         ss << "could not bind the socket to \""
     145           0 :            << f_address.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT)
     146           0 :            << "\"\n";
     147           0 :         SNAP_LOG_ERROR
     148             :             << ss
     149             :             << SNAP_LOG_SEND;
     150           0 :         throw runtime_error(ss.str());
     151             :     }
     152             : 
     153             :     // start listening, we expect the caller to then call accept() to
     154             :     // acquire connections
     155             :     //
     156           0 :     if(listen(f_socket, f_max_connections) < 0)
     157             :     {
     158           0 :         close(f_socket);
     159             :         throw runtime_error(
     160             :                   "could not listen to the socket bound to \""
     161           0 :                 + f_address.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT)
     162           0 :                 + "\"");
     163             :     }
     164           0 : }
     165             : 
     166             : 
     167             : /** \brief Clean up the server sockets.
     168             :  *
     169             :  * This function ensures that the server sockets get cleaned up.
     170             :  *
     171             :  * If the \p auto_close parameter was set to true in the constructor, then
     172             :  * the last accepter socket gets closed by this function.
     173             :  *
     174             :  * \note
     175             :  * DO NOT use the shutdown() call since we may end up forking and using
     176             :  * that connection in the child.
     177             :  */
     178           0 : tcp_server::~tcp_server()
     179             : {
     180           0 :     close(f_socket);
     181           0 :     if(f_auto_close && f_accepted_socket != -1)
     182             :     {
     183           0 :         close(f_accepted_socket);
     184             :     }
     185           0 : }
     186             : 
     187             : 
     188             : /** \brief Retrieve the socket descriptor.
     189             :  *
     190             :  * This function returns the socket descriptor. It can be used to
     191             :  * tweak things on the socket such as making it non-blocking or
     192             :  * directly accessing the data.
     193             :  *
     194             :  * \return The socket descriptor.
     195             :  */
     196           0 : int tcp_server::get_socket() const
     197             : {
     198           0 :     return f_socket;
     199             : }
     200             : 
     201             : 
     202             : /** \brief Retrieve the maximum number of connections.
     203             :  *
     204             :  * This function returns the maximum number of connections that can
     205             :  * be accepted by the socket. This was set by the constructor and
     206             :  * it cannot be changed later.
     207             :  *
     208             :  * \return The maximum number of incoming connections.
     209             :  */
     210           0 : int tcp_server::get_max_connections() const
     211             : {
     212           0 :     return f_max_connections;
     213             : }
     214             : 
     215             : 
     216             : /** \brief Retrieve the server IP address and port.
     217             :  *
     218             :  * This function returns the IP address used to bind the socket. This
     219             :  * is the address clients have to use to connect to the server unless
     220             :  * the address was set to all zeroes (0.0.0.0) in which case any user
     221             :  * can connect.
     222             :  *
     223             :  * The IP address cannot be changed.
     224             :  *
     225             :  * \return The server IP address.
     226             :  */
     227           0 : addr::addr tcp_server::get_address() const
     228             : {
     229           0 :     return f_address;
     230             : }
     231             : 
     232             : 
     233             : /** \brief Return the current status of the keepalive flag.
     234             :  *
     235             :  * This function returns the current status of the keepalive flag. This
     236             :  * flag is set to true by default (in the constructor.) It can be
     237             :  * changed with the set_keepalive() function.
     238             :  *
     239             :  * The flag is used to mark new connections with the SO_KEEPALIVE flag.
     240             :  * This is used whenever a service may take a little to long to answer
     241             :  * and avoid losing the TCP connection before the answer is sent to
     242             :  * the client.
     243             :  *
     244             :  * \return The current status of the keepalive flag.
     245             :  */
     246           0 : bool tcp_server::get_keepalive() const
     247             : {
     248           0 :     return f_keepalive;
     249             : }
     250             : 
     251             : 
     252             : /** \brief Set the keepalive flag.
     253             :  *
     254             :  * This function sets the keepalive flag to either true (i.e. mark connection
     255             :  * sockets with the SO_KEEPALIVE flag) or false. The default is true (as set
     256             :  * in the constructor,) because in most cases this is a feature people want.
     257             :  *
     258             :  * \param[in] yes  Whether to keep new connections alive even when no traffic
     259             :  * goes through.
     260             :  */
     261           0 : void tcp_server::set_keepalive(bool yes)
     262             : {
     263           0 :     f_keepalive = yes;
     264           0 : }
     265             : 
     266             : 
     267             : /** \brief Return the current status of the close_on_exec flag.
     268             :  *
     269             :  * This function returns the current status of the close_on_exec flag. This
     270             :  * flag is set to false by default (in the constructor.) It can be
     271             :  * changed with the set_close_on_exec() function.
     272             :  *
     273             :  * The flag is used to atomically mark new connections with the FD_CLOEXEC
     274             :  * flag. This prevents child processes from inheriting the socket (i.e. if
     275             :  * you use the system() function, for example, that process would inherit
     276             :  * your socket).
     277             :  *
     278             :  * \return The current status of the close_on_exec flag.
     279             :  */
     280           0 : bool tcp_server::get_close_on_exec() const
     281             : {
     282           0 :     return f_close_on_exec;
     283             : }
     284             : 
     285             : 
     286             : /** \brief Set the close_on_exec flag.
     287             :  *
     288             :  * This function sets the close_on_exec flag to either true (i.e. mark connection
     289             :  * sockets with the FD_CLOEXEC flag) or false. The default is false (as set
     290             :  * in the constructor,) because in our legacy code, the flag is not expected
     291             :  * to be set.
     292             :  *
     293             :  * \param[in] yes  Whether to close on exec() or not.
     294             :  */
     295           0 : void tcp_server::set_close_on_exec(bool yes)
     296             : {
     297           0 :     f_close_on_exec = yes;
     298           0 : }
     299             : 
     300             : 
     301             : /** \brief Accept a connection.
     302             :  *
     303             :  * A TCP server accepts incoming connections. This call is a blocking call.
     304             :  * If no connections are available on the line, then the call blocks until
     305             :  * a connection becomes available.
     306             :  *
     307             :  * To prevent being blocked by this call you can either check the status of
     308             :  * the file descriptor (use the get_socket() function to retrieve the
     309             :  * descriptor and use an appropriate wait with 0 as a timeout,) or transform
     310             :  * the socket in a non-blocking socket (not tested, though.)
     311             :  *
     312             :  * This TCP socket implementation is expected to be used in one of two ways:
     313             :  *
     314             :  * (1) the main server accepts connections and then fork()'s to handle the
     315             :  * transaction with the client, in that case we want to set the \p auto_close
     316             :  * parameter of the constructor to true so the accept() function automatically
     317             :  * closes the last accepted socket.
     318             :  *
     319             :  * (2) the main server keeps a set of connections and handles them alongside
     320             :  * the main server connection. Although there are limits to what you can do
     321             :  * in this way, it is very efficient, but this also means the accept() call
     322             :  * cannot close the last accepted socket since the rest of the software may
     323             :  * still be working on it.
     324             :  *
     325             :  * The function returns a client/server socket. This is the socket one can
     326             :  * use to communicate with the client that just connected to the server. This
     327             :  * descriptor can be written to or read from.
     328             :  *
     329             :  * This function is the one that applies the keepalive flag to the
     330             :  * newly accepted socket.
     331             :  *
     332             :  * \note
     333             :  * If you prevent SIGCHLD from stopping your code, you may want to allow it
     334             :  * when calling this function (that is, if you're interested in getting that
     335             :  * information immediately, otherwise it is cleaner to always block those
     336             :  * signals).
     337             :  * \note
     338             :  * For SIGCHLD, you may want to consider using the signal_child class which
     339             :  * takes care of the `waitpid()` and calls your callback at the time your
     340             :  * child process dies.
     341             :  *
     342             :  * \note
     343             :  * DO NOT use the shutdown() call since we may end up forking and using
     344             :  * that connection in the child.
     345             :  *
     346             :  * \note
     347             :  * If you want to have the FD_CLOEXEC flag set, make sure to call the
     348             :  * set_close_on_exec() function before you call the accept() function.
     349             :  *
     350             :  * \param[in] max_wait_ms  The maximum number of milliseconds to wait for
     351             :  *            a message. If set to -1 (the default), accept() will block
     352             :  *            indefinitely.
     353             :  *
     354             :  * \return A client socket descriptor, -1 if an error occurred, or
     355             :  *         -2 if it times out and max_wait is set.
     356             :  */
     357           0 : int tcp_server::accept(int const max_wait_ms)
     358             : {
     359             :     // auto-close?
     360           0 :     if(f_auto_close
     361           0 :     && f_accepted_socket != -1)
     362             :     {
     363             :         // if the close is interrupted, make sure we try again otherwise
     364             :         // we could lose that stream until next restart (this could happen
     365             :         // if you have SIGCHLD)
     366             :         //
     367           0 :         if(close(f_accepted_socket) == -1)
     368             :         {
     369           0 :             if(errno == EINTR)
     370             :             {
     371           0 :                 close(f_accepted_socket);
     372             :             }
     373             :         }
     374             :     }
     375           0 :     f_accepted_socket = -1;
     376             : 
     377           0 :     if( max_wait_ms > -1 )
     378             :     {
     379           0 :         pollfd fd;
     380           0 :         fd.events = POLLIN | POLLPRI | POLLRDHUP;
     381           0 :         fd.fd = f_socket;
     382           0 :         int const retval(poll(&fd, 1, max_wait_ms));
     383             : 
     384             : // on newer system each input of select() must be a distinct fd_set...
     385             : //        fd_set s;
     386             : //
     387             : //        FD_ZERO(&s);
     388             : //#pragma GCC diagnostic push
     389             : //#pragma GCC diagnostic ignored "-Wold-style-cast"
     390             : //        FD_SET(f_socket, &s);
     391             : //#pragma GCC diagnostic pop
     392             : //
     393             : //        struct timeval timeout;
     394             : //        timeout.tv_sec = max_wait_ms / 1000;
     395             : //        timeout.tv_usec = (max_wait_ms % 1000) * 1000;
     396             : //        int const retval = select(f_socket + 1, &s, nullptr, &s, &timeout);
     397             : 
     398           0 :         if( retval == -1 )
     399             :         {
     400             :             // error
     401             :             //
     402           0 :             return -1;
     403             :         }
     404           0 :         else if( retval == 0 )
     405             :         {
     406             :             // timeout
     407             :             //
     408           0 :             return -2;
     409             :         }
     410             :     }
     411             : 
     412             :     // accept the next connection
     413             :     //
     414           0 :     struct sockaddr_in accepted_addr = {};
     415           0 :     socklen_t addr_len(sizeof(accepted_addr));
     416           0 :     f_accepted_socket = ::accept4(
     417             :                   f_socket
     418             :                 , reinterpret_cast<struct sockaddr *>(&accepted_addr)
     419             :                 , &addr_len
     420           0 :                 , f_close_on_exec ? SOCK_CLOEXEC : 0);
     421             : 
     422             :     // mark the new connection with the SO_KEEPALIVE flag
     423             :     //
     424           0 :     if(f_accepted_socket != -1 && f_keepalive)
     425             :     {
     426             :         // if this fails, we ignore the error, but still log the event
     427             :         //
     428           0 :         int optval(1);
     429           0 :         socklen_t const optlen(sizeof(optval));
     430           0 :         if(setsockopt(f_accepted_socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) != 0)
     431             :         {
     432           0 :             SNAP_LOG_WARNING
     433             :                 << "tcp_server::accept(): an error occurred trying to mark"
     434             :                    " accepted socket with SO_KEEPALIVE."
     435             :                 << SNAP_LOG_SEND;
     436             :         }
     437             :     }
     438             : 
     439           0 :     return f_accepted_socket;
     440             : }
     441             : 
     442             : 
     443             : /** \brief Retrieve the last accepted socket descriptor.
     444             :  *
     445             :  * This function returns the last accepted socket descriptor as retrieved by
     446             :  * accept(). If accept() was never called or failed, then this returns -1.
     447             :  *
     448             :  * Note that it is possible that the socket was closed in between in which
     449             :  * case this value is going to be an invalid socket.
     450             :  *
     451             :  * \return The last accepted socket descriptor.
     452             :  */
     453           0 : int tcp_server::get_last_accepted_socket() const
     454             : {
     455           0 :     return f_accepted_socket;
     456             : }
     457             : 
     458             : 
     459             : 
     460           6 : } // namespace ed
     461             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13