LCOV - code coverage report
Current view: top level - eventdispatcher - tcp_server_client_connection.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 56.8 % 37 21
Test Date: 2025-05-30 15:24:13 Functions: 77.8 % 9 7
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2012-2024  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 3 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
      17              : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18              : 
      19              : /** \file
      20              :  * \brief Implementation of the Snap Communicator class.
      21              :  *
      22              :  * This class wraps the C poll() interface in a C++ object with many types
      23              :  * of objects:
      24              :  *
      25              :  * \li Server Connections; for software that want to offer a port to
      26              :  *     which clients can connect to; the server will call accept()
      27              :  *     once a new client connection is ready; this results in a
      28              :  *     Server/Client connection object
      29              :  * \li Client Connections; for software that want to connect to
      30              :  *     a server; these expect the IP address and port to connect to
      31              :  * \li Server/Client Connections; for the server when it accepts a new
      32              :  *     connection; in this case the server gets a socket from accept()
      33              :  *     and creates one of these objects to handle the connection
      34              :  *
      35              :  * Using the poll() function is the easiest and allows us to listen
      36              :  * on pretty much any number of sockets (on my server it is limited
      37              :  * at 16,768 and frankly over 1,000 we probably will start to have
      38              :  * real slowness issues on small VPN servers.)
      39              :  */
      40              : 
      41              : // self
      42              : //
      43              : #include    "eventdispatcher/tcp_server_client_connection.h"
      44              : 
      45              : #include    "eventdispatcher/exception.h"
      46              : 
      47              : 
      48              : // snaplogger
      49              : //
      50              : #include    <snaplogger/message.h>
      51              : 
      52              : 
      53              : // C++
      54              : //
      55              : #include    <cstring>
      56              : 
      57              : 
      58              : // C
      59              : //
      60              : #include    <arpa/inet.h>
      61              : #include    <netdb.h>
      62              : 
      63              : 
      64              : // last include
      65              : //
      66              : #include    <snapdev/poison.h>
      67              : 
      68              : 
      69              : 
      70              : namespace ed
      71              : {
      72              : 
      73              : 
      74              : 
      75              : /** \brief Create a client connection created from an accept().
      76              :  *
      77              :  * This constructor initializes a client connection from a socket
      78              :  * that we received from an accept() call.
      79              :  *
      80              :  * The destructor will automatically close that socket on destruction.
      81              :  *
      82              :  * \param[in] client  The client that accept() returned.
      83              :  */
      84           62 : tcp_server_client_connection::tcp_server_client_connection(tcp_bio_client::pointer_t client)
      85           62 :     : f_client(client)
      86              : {
      87           62 : }
      88              : 
      89              : 
      90              : /** \brief Make sure the socket gets released.
      91              :  *
      92              :  * This destructor makes sure that the socket gets closed.
      93              :  */
      94           62 : tcp_server_client_connection::~tcp_server_client_connection()
      95              : {
      96           62 :     close();
      97           62 : }
      98              : 
      99              : 
     100              : /** \brief Read data from the TCP server client socket.
     101              :  *
     102              :  * This function reads as much data up to the specified amount
     103              :  * in \p count. The read data is saved in \p buf.
     104              :  *
     105              :  * \param[in,out] buf  The buffer where the data gets read.
     106              :  * \param[in] count  The maximum number of bytes to read in buf.
     107              :  *
     108              :  * \return The number of bytes read or -1 if an error occurred.
     109              :  */
     110           95 : ssize_t tcp_server_client_connection::read(void * buf, std::size_t count)
     111              : {
     112           95 :     if(f_client == nullptr)
     113              :     {
     114            0 :         errno = EBADF;
     115            0 :         return -1;
     116              :     }
     117           95 :     return f_client->read(reinterpret_cast<char *>(buf), count);
     118              : }
     119              : 
     120              : 
     121              : /** \brief Write data to this connection's socket.
     122              :  *
     123              :  * This function writes up to \p count bytes of data from \p buf
     124              :  * to this connection's socket.
     125              :  *
     126              :  * \warning
     127              :  * This write function may not always write all the data you are
     128              :  * trying to send to the remote connection. If you want to make
     129              :  * sure that all your data is written to the other side,
     130              :  * you want to instead use the tcp_server_client_buffer_connection,
     131              :  * which overloads this write() function and saves the data to be
     132              :  * written to the socket in a buffer. The communicator run()-loop is
     133              :  * then responsible for sending all the data. However, that buffering
     134              :  * has no limit, so if you are sending large files, it is also not
     135              :  * a very good idea.
     136              :  *
     137              :  * \param[in] buf  The buffer of data to be written to the socket.
     138              :  * \param[in] count  The number of bytes the caller wants to write to the
     139              :  *                   connection.
     140              :  *
     141              :  * \return The number of bytes written to the socket or -1 if an error occurred.
     142              :  */
     143           40 : ssize_t tcp_server_client_connection::write(void const * buf, std::size_t count)
     144              : {
     145           40 :     if(f_client == nullptr)
     146              :     {
     147            0 :         errno = EBADF;
     148            0 :         return -1;
     149              :     }
     150           40 :     return f_client->write(reinterpret_cast<char const *>(buf), count);
     151              : }
     152              : 
     153              : 
     154              : /** \brief Close the socket of this connection.
     155              :  *
     156              :  * This function is automatically called whenever the object gets
     157              :  * destroyed (see destructor) or detects that the client closed
     158              :  * the network connection.
     159              :  *
     160              :  * Connections cannot be reopened.
     161              :  */
     162           68 : void tcp_server_client_connection::close()
     163              : {
     164           68 :     f_client.reset();
     165           68 : }
     166              : 
     167              : 
     168              : /** \brief Retrieve the socket of this connection.
     169              :  *
     170              :  * This function returns the socket defined in this connection.
     171              :  *
     172              :  * \return The socket file descriptor or -1 if the connection is closed.
     173              :  */
     174          575 : int tcp_server_client_connection::get_socket() const
     175              : {
     176          575 :     if(f_client == nullptr)
     177              :     {
     178              :         // client connection was closed
     179              :         //
     180           10 :         return -1;
     181              :     }
     182          564 :     return f_client->get_socket();
     183              : }
     184              : 
     185              : 
     186              : /** \brief Tell that we are always a reader.
     187              :  *
     188              :  * This function always returns true meaning that the connection is
     189              :  * always of a reader. In most cases this is safe because if nothing
     190              :  * is being written to you then poll() never returns so you do not
     191              :  * waste much time in have a TCP connection always marked as a
     192              :  * reader.
     193              :  *
     194              :  * \return The events to listen to for this connection.
     195              :  */
     196          110 : bool tcp_server_client_connection::is_reader() const
     197              : {
     198          110 :     return true;
     199              : }
     200              : 
     201              : 
     202              : /** \brief Retrieve a copy of the client's address.
     203              :  *
     204              :  * This function retrieves a copy of the client's address and returns it.
     205              :  *
     206              :  * \return A reference to the client's address.
     207              :  */
     208            0 : addr::addr const & tcp_server_client_connection::get_client_address() 
     209              : {
     210            0 :     if(f_client_address.is_default())
     211              :     {
     212            0 :         int const s(get_socket());
     213            0 :         if(s >= 0)
     214              :         {
     215            0 :             f_client_address.set_from_socket(s, false);
     216              :         }
     217              :     }
     218              : 
     219            0 :     return f_client_address;
     220              : }
     221              : 
     222              : 
     223              : /** \brief Retrieve the remote address information.
     224              :  *
     225              :  * This function can be used to retrieve the remove address and port
     226              :  * information as was specified on the constructor. These can be used
     227              :  * to find this specific connection at a later time or create another
     228              :  * connection.
     229              :  *
     230              :  * For example, you may get 192.168.2.17:4040.
     231              :  *
     232              :  * The function works even after the socket gets closed as we save
     233              :  * the remote address and port in a string just after the connection
     234              :  * was established.
     235              :  *
     236              :  * \warning
     237              :  * This function returns BOTH: the address and the port.
     238              :  *
     239              :  * \note
     240              :  * These parameters are the same as what was passed to the constructor,
     241              :  * only both will have been converted to numbers. So for example when
     242              :  * you used "localhost", here you get "::1" or "127.0.0.1" for the
     243              :  * address.
     244              :  *
     245              :  * \return The remote host address and connection port.
     246              :  */
     247            0 : addr::addr const & tcp_server_client_connection::get_remote_address()
     248              : {
     249              :     // TODO: somehow the port seems wrong (i.e. all connections return the same port)
     250              :     //       I changed this to do the getpeername() at the time you call the
     251              :     //       get_remote_address() and I use the addr::addr get_from_socket()
     252              :     //       so now it may work? I need to test it again
     253              :     //
     254            0 :     if(f_remote_address.is_default())
     255              :     {
     256            0 :         int const s(get_socket());
     257            0 :         if(s >= 0)
     258              :         {
     259            0 :             f_remote_address.set_from_socket(s, true);
     260              :         }
     261              :     }
     262              : 
     263            0 :     return f_remote_address;
     264              : }
     265              : 
     266              : 
     267              : } // namespace ed
     268              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions