LCOV - code coverage report
Current view: top level - eventdispatcher - local_dgram_base.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 58.3 % 36 21
Test Date: 2025-05-30 15:24:13 Functions: 42.9 % 7 3
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 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
      17              : // along with this program; if not, write to the Free Software
      18              : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19              : 
      20              : /** \file
      21              :  * \brief Event dispatch class.
      22              :  *
      23              :  * Class used to handle events.
      24              :  */
      25              : 
      26              : 
      27              : // self
      28              : //
      29              : #include    "eventdispatcher/local_dgram_base.h"
      30              : 
      31              : #include    "eventdispatcher/exception.h"
      32              : 
      33              : 
      34              : // C
      35              : //
      36              : #include    <sys/stat.h>
      37              : 
      38              : 
      39              : // last include
      40              : //
      41              : #include    <snapdev/poison.h>
      42              : 
      43              : 
      44              : 
      45              : 
      46              : namespace ed
      47              : {
      48              : 
      49              : 
      50              : 
      51              : /** \brief Initialize a UDP base object.
      52              :  *
      53              :  * This function initializes the UDP base object using the address and the
      54              :  * port as specified.
      55              :  *
      56              :  * The port is expected to be a host side port number (i.e. 59200).
      57              :  *
      58              :  * The \p addr parameter is a textual address. It may be an IPv4 or IPv6
      59              :  * address and it can represent a host name or an address defined with
      60              :  * just numbers. If the address cannot be resolved then an error occurs
      61              :  * and the constructor throws.
      62              :  *
      63              :  * \note
      64              :  * The socket is open in this process. If you fork() and exec() then the
      65              :  * socket gets closed by the operating system (i.e. close on exec()).
      66              :  *
      67              :  * \warning
      68              :  * We only make use of the first address found by getaddrinfo(). All
      69              :  * the other addresses are ignored.
      70              :  *
      71              :  * \todo
      72              :  * Add a constructor that supports a libaddr::addr object instead of
      73              :  * just a string address.
      74              :  *
      75              :  * \exception invalid_parameter
      76              :  * The \p addr parameter is empty or the port is out of the supported range.
      77              :  *
      78              :  * \exception runtime_error
      79              :  * The server could not be initialized properly. Either the address cannot be
      80              :  * resolved, the port is incompatible or not available, or the socket could
      81              :  * not be created.
      82              :  *
      83              :  * \param[in] address  The address to connect/listen to.
      84              :  * \param[in] sequential  Whether the packets have to be 100% sequential.
      85              :  * \param[in] close_on_exec  Whether the socket has to be closed on execve().
      86              :  */
      87            5 : local_dgram_base::local_dgram_base(
      88              :               addr::addr_unix const & address
      89              :             , bool sequential
      90            5 :             , bool close_on_exec)
      91            5 :     : f_address(address)
      92              : {
      93            5 :     int type(sequential ? SOCK_SEQPACKET : SOCK_DGRAM);
      94            5 :     if(close_on_exec)
      95              :     {
      96            5 :         type |= SOCK_CLOEXEC;
      97              :     }
      98              : 
      99            5 :     f_socket.reset(socket(AF_UNIX, type, 0));
     100            5 :     if(f_socket == nullptr)
     101              :     {
     102              :         throw runtime_error(
     103              :               "could not create socket for: \""
     104            0 :             + f_address.to_uri()
     105            0 :             + "\".");
     106              :     }
     107              : 
     108              :     // on Linux we can restrict the permissions immediately
     109              :     //
     110            5 :     fchmod(f_socket.get(), S_IRUSR | S_IWUSR);
     111              : 
     112              :     // get the "MTU" maximum size right away for
     113              :     //   (1) it is really fast; and
     114              :     //   (2) it is going to work right before a first write() but may not
     115              :     //       be if a write() was not yet fully processed
     116              :     //
     117            5 :     socklen_t optlen;
     118            5 :     optlen = sizeof(f_mtu_size);
     119            5 :     int const r(getsockopt(
     120           10 :               f_socket.get()
     121              :             , SOL_SOCKET
     122              :             , SO_SNDBUF
     123            5 :             , &f_mtu_size
     124            5 :             , &optlen));
     125            5 :     if(r != 0)
     126              :     {
     127              :         throw runtime_error(
     128              :               "could not retrieve \"MTU\" size for: \""
     129            0 :             + f_address.to_uri()
     130            0 :             + "\".");
     131              :     }
     132            5 : }
     133              : 
     134              : 
     135              : /** \brief The local datagram destructor.
     136              :  *
     137              :  * To avoid potential errors with virtual destruction, we have a virtual
     138              :  * destructor in this base class.
     139              :  */
     140            5 : local_dgram_base::~local_dgram_base()
     141              : {
     142            5 : }
     143              : 
     144              : 
     145              : /** \brief Retrieve a copy of the socket identifier.
     146              :  *
     147              :  * This function return the socket identifier as returned by the socket()
     148              :  * function. This can be used to change some flags.
     149              :  *
     150              :  * \return The socket used by this UDP client.
     151              :  */
     152           16 : int local_dgram_base::get_socket() const
     153              : {
     154           16 :     return f_socket.get();
     155              : }
     156              : 
     157              : 
     158              : /** \brief Set whether this UDP socket is to be used to broadcast messages.
     159              :  *
     160              :  * This function sets the BROADCAST flagon the socket. This is important
     161              :  * because by default it is expected that the socket is not used in
     162              :  * broadcast mode. This makes sure that was your intention.
     163              :  *
     164              :  * \note
     165              :  * We do not try to automatically set the flag for (1) the OS implementation
     166              :  * expects the end user application to systematically set the flag if
     167              :  * required and (2) it's complicated to know whether the address represents
     168              :  * the broadcast address (i.e. you need to get the info on the corresponding
     169              :  * interface to get the network mask, see whether the interface supports
     170              :  * broadcasting, etc.) We'll eventually implement that test in our
     171              :  * libaddr library one day. However, that would be a test we use in the
     172              :  * send() function to catch errors early (i.e. determine whether the
     173              :  * socket can be sent to in the current state).
     174              :  *
     175              :  * \param[in] state  Whether to set (true) or remove (false) the broadcast
     176              :  * flag on this Unix datagram socket.
     177              :  */
     178            0 : void local_dgram_base::set_broadcast(bool state)
     179              : {
     180            0 :     int const value(state ? 1 : 0);
     181            0 :     setsockopt(f_socket.get(), SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
     182            0 : }
     183              : 
     184              : 
     185              : /** \brief Retrieve the size of the MTU on that connection.
     186              :  *
     187              :  * The "MTU" of the AF_UNIX message is defined by the largest allocatable
     188              :  * page of memory. This is defined in this file:
     189              :  *
     190              :  * /proc/sys/net/core/wmem_max
     191              :  *
     192              :  * Note that to get the maximum size of your message, you want to use
     193              :  * the get_mss_size() instead. The MTU size is the entire packet including
     194              :  * headers.
     195              :  *
     196              :  * \return -1 if the MTU could not be retrieved, the MTU's size otherwise.
     197              :  */
     198            0 : int local_dgram_base::get_mtu_size() const
     199              : {
     200            0 :     return f_mtu_size;
     201              : }
     202              : 
     203              : 
     204              : /** \brief Determine the size of the data buffer we can use.
     205              :  *
     206              :  * This function gets the MTU and then subtract the possible header data
     207              :  * of the packet to 
     208              :  *
     209              :  * \return The size of the MMU, which is the MTU minus the headers.
     210              :  */
     211            0 : int local_dgram_base::get_mss_size() const
     212              : {
     213            0 :     int const mss(get_mtu_size());
     214            0 :     return mss < 32 ? -1 : mss - 32;      // it looks like the header uses 32 bytes
     215              : }
     216              : 
     217              : 
     218              : /** \brief Retrieve a copy of the address.
     219              :  *
     220              :  * This function returns a copy of the address as it was specified in the
     221              :  * constructor. This does not return a canonicalized version of the address.
     222              :  *
     223              :  * The address cannot be modified. If you need to send data on a different
     224              :  * address, create a new UDP client.
     225              :  *
     226              :  * \return A string with a copy of the constructor input address.
     227              :  */
     228            0 : addr::addr_unix local_dgram_base::get_address() const
     229              : {
     230            0 :     return f_address;
     231              : }
     232              : 
     233              : 
     234              : 
     235              : } // namespace ed
     236              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

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