LCOV - code coverage report
Current view: top level - eventdispatcher - fd_connection.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 27 0.0 %
Date: 2019-08-08 02:52:36 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2019  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // This program is free software; you can redistribute it and/or modify
       4             : // it under the terms of the GNU General Public License as published by
       5             : // the Free Software Foundation; either version 2 of the License, or
       6             : // (at your option) any later version.
       7             : //
       8             : // This program is distributed in the hope that it will be useful,
       9             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      10             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      11             : // GNU General Public License for more details.
      12             : //
      13             : // You should have received a copy of the GNU General Public License
      14             : // along with this program; if not, write to the Free Software
      15             : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      16             : 
      17             : /** \file
      18             :  * \brief Implementation of the Snap Communicator class.
      19             :  *
      20             :  * This class wraps the C poll() interface in a C++ object with many types
      21             :  * of objects:
      22             :  *
      23             :  * \li Server Connections; for software that want to offer a port to
      24             :  *     which clients can connect to; the server will call accept()
      25             :  *     once a new client connection is ready; this results in a
      26             :  *     Server/Client connection object
      27             :  * \li Client Connections; for software that want to connect to
      28             :  *     a server; these expect the IP address and port to connect to
      29             :  * \li Server/Client Connections; for the server when it accepts a new
      30             :  *     connection; in this case the server gets a socket from accept()
      31             :  *     and creates one of these objects to handle the connection
      32             :  *
      33             :  * Using the poll() function is the easiest and allows us to listen
      34             :  * on pretty much any number of sockets (on my server it is limited
      35             :  * at 16,768 and frankly over 1,000 we probably will start to have
      36             :  * real slowness issues on small VPN servers.)
      37             :  */
      38             : 
      39             : // to get the POLLRDHUP definition
      40             : #ifndef _GNU_SOURCE
      41             : #define _GNU_SOURCE
      42             : #endif
      43             : 
      44             : 
      45             : // self
      46             : //
      47             : #include "eventdispatcher/fd_connection.h"
      48             : 
      49             : //#include "eventdispatcher/snap_communicator_dispatcher.h"
      50             : //
      51             : //
      52             : //// snaplogger lib
      53             : ////
      54             : //#include "snaplogger/message.h"
      55             : //
      56             : //
      57             : //// snapdev lib
      58             : ////
      59             : //#include "snapdev/not_reached.h"
      60             : //#include "snapdev/not_used.h"
      61             : //#include "snapdev/string_replace_many.h"
      62             : //
      63             : //
      64             : //// libaddr lib
      65             : ////
      66             : //#include "libaddr/addr_parser.h"
      67             : //
      68             : //
      69             : //// C++ lib
      70             : ////
      71             : //#include <sstream>
      72             : //#include <limits>
      73             : //#include <atomic>
      74             : 
      75             : 
      76             : // C lib
      77             : //
      78             : //#include <fcntl.h>
      79             : //#include <poll.h>
      80             : #include <unistd.h>
      81             : //#include <sys/eventfd.h>
      82             : //#include <sys/inotify.h>
      83             : //#include <sys/ioctl.h>
      84             : //#include <sys/resource.h>
      85             : //#include <sys/syscall.h>
      86             : //#include <sys/time.h>
      87             : 
      88             : 
      89             : // last include
      90             : //
      91             : #include <snapdev/poison.h>
      92             : 
      93             : 
      94             : 
      95             : 
      96             : namespace ed
      97             : {
      98             : 
      99             : 
     100             : 
     101             : /** \brief Initializes the file descriptor connection.
     102             :  *
     103             :  * This function creates a connection based on an existing file descriptor.
     104             :  * This is a class used to handle existing pipes or socket (opposed to other
     105             :  * implementations which create a pipe, open a socket, etc.) It is especially
     106             :  * useful if you want to listen to stdin and stdout. Use the `fileno()`
     107             :  * function to get the file descriptor and create a `snap_fd_connection`
     108             :  * object what that descriptor.
     109             :  *
     110             :  * The mode parameter defines how you are to use the file descriptor. In
     111             :  * other words, a socket that is read/write could be added to two different
     112             :  * `snap_fd_connection` objects: one to read and one to write, instead of
     113             :  * a single read/write object.
     114             :  *
     115             :  * Note that although you can say it's only going to be used in READ or
     116             :  * in WRITE mode, in all cases, make sure that the file is readable before
     117             :  * specifying READ or RW, and make sure that the file is writable before
     118             :  * specifying WRITE or RW.
     119             :  *
     120             :  * \note
     121             :  * It is important to note that the lifetime of the file desriptor is
     122             :  * not managed by this object. You are responsible for the descriptor to
     123             :  * stay valid as long as the connection is added to the snap_communicator
     124             :  * list of connections. If you want to close the connection, please first
     125             :  * remove the connection from the snap_communicator, destroy the connection,
     126             :  * then close the file descriptor.
     127             :  *
     128             :  * \note
     129             :  * It is possible to pass -1 (or any negative number) as the file
     130             :  * descriptor. In that case it is interpreted as "not a valid
     131             :  * file descriptor."
     132             :  *
     133             :  * \warning
     134             :  * If you are to use a read() or a write() that may block, make sure to
     135             :  * first set your file descriptor in non-blocking mode. If that's not
     136             :  * possible, then make sure to read or write only one byte at a time.
     137             :  * The loop will be slower, but you will avoid blocks which would
     138             :  * prevent the rest of the software from getting their own events.
     139             :  *
     140             :  * \param[in] fd  The file descriptor to handle.
     141             :  * \param[in] mode  The mode this descriptor is to be used by the connection.
     142             :  */
     143           0 : fd_connection::fd_connection(int fd, mode_t mode)
     144             :     : f_fd(fd)
     145           0 :     , f_mode(mode)
     146             : {
     147           0 : }
     148             : 
     149             : 
     150             : /** \brief Used to close the file descriptor.
     151             :  *
     152             :  * This function closes the file descript of this connection.
     153             :  *
     154             :  * The function is not called automatically as we mention in the
     155             :  * constructor, the function cannot just close the file descriptor
     156             :  * on its own so it is up to you to call this function or not.
     157             :  * It is not mandatory.
     158             :  *
     159             :  * The function does not verify to know whether the file descriptor
     160             :  * was already closed outside of this function. Although it is safe
     161             :  * to call this function multiple times, if you close the file
     162             :  * descriptor with other means, then calling this function may
     163             :  * end up closing another file...
     164             :  */
     165           0 : void fd_connection::close()
     166             : {
     167           0 :     if(f_fd != -1)
     168             :     {
     169           0 :         ::close(f_fd);
     170           0 :         f_fd = -1;
     171             :     }
     172           0 : }
     173             : 
     174             : 
     175             : /** \brief Used to mark the file descriptor as closed.
     176             :  *
     177             :  * This function marks the file descriptor as closed. Whether it is,
     178             :  * is your own concern. This is used to avoid a double close in
     179             :  * case some other function ends up calling close() and yet you
     180             :  * somehow closed the file descriptor (i.e. fclose(f) will do that
     181             :  * on you...)
     182             :  *
     183             :  * \code
     184             :  *      ...
     185             :  *      fclose(f);
     186             :  *      // tell connection that we've close the connection fd
     187             :  *      c->mark_closed();
     188             :  *      ...
     189             :  * \endcode
     190             :  *
     191             :  * Note that if you do not have any other copy of the file descriptor
     192             :  * and you call mark_closed() instead of close(), you will leak that
     193             :  * file descriptor.
     194             :  */
     195           0 : void fd_connection::mark_closed()
     196             : {
     197           0 :     f_fd = -1;
     198           0 : }
     199             : 
     200             : 
     201             : /** \brief Check whether this connection is a reader.
     202             :  *
     203             :  * If you created this file descriptor connection as a reader, then this
     204             :  * function returns true.
     205             :  *
     206             :  * A reader has a mode of FD_MODE_READ or FD_MODE_RW.
     207             :  *
     208             :  * \return true if the connection is considered to be a reader.
     209             :  */
     210           0 : bool fd_connection::is_reader() const
     211             : {
     212           0 :     return f_mode != mode_t::FD_MODE_WRITE && get_socket() != -1;
     213             : }
     214             : 
     215             : 
     216             : /** \brief Check whether this connection is a writer.
     217             :  *
     218             :  * If you created this file descriptor connection as a writer, then this
     219             :  * function returns true.
     220             :  *
     221             :  * A writer has a mode of FD_MODE_WRITE or FD_MODE_RW.
     222             :  *
     223             :  * \return true if the connection is considered to be a writer.
     224             :  */
     225           0 : bool fd_connection::is_writer() const
     226             : {
     227           0 :     return f_mode != mode_t::FD_MODE_READ && get_socket() != -1;
     228             : }
     229             : 
     230             : 
     231             : /** \brief Return the file descriptor ("socket").
     232             :  *
     233             :  * This function returns the file descriptor specified in the constructor.
     234             :  *
     235             :  * The current naming convention comes from the fact that the library
     236             :  * was first created for sockets.
     237             :  *
     238             :  * \return The connection file descriptor.
     239             :  */
     240           0 : int fd_connection::get_socket() const
     241             : {
     242           0 :     return f_fd;
     243             : }
     244             : 
     245             : 
     246             : /** \brief Read up data from the file descriptor.
     247             :  *
     248             :  * This function attempts to read up to \p count bytes of data from
     249             :  * this file descriptor. If that works to some extend, then the
     250             :  * data read will be saved in \p buf and the function returns
     251             :  * the number of bytes read.
     252             :  *
     253             :  * If no data can be read, the function may return -1 or 0.
     254             :  *
     255             :  * The file descriptor must be a reader or the function will always fail.
     256             :  *
     257             :  * \param[in] buf  The buffer where the data read is saved.
     258             :  * \param[in] count  The maximum number of bytes to read at once.
     259             :  */
     260           0 : ssize_t fd_connection::read(void * buf, size_t count)
     261             : {
     262             :     // WARNING: We MUST call the fd_connection version of the is_writer(),
     263             :     //          because the fd_buffer_connection::is_writer() also checks
     264             :     //          the f_output buffer which has unwanted side effects
     265             :     //
     266           0 :     if(!fd_connection::is_reader())
     267             :     {
     268           0 :         errno = EBADF;
     269           0 :         return -1;
     270             :     }
     271             : 
     272           0 :     return ::read(f_fd, buf, count);
     273             : }
     274             : 
     275             : 
     276             : /** \brief Write buffer data to the file descriptor.
     277             :  *
     278             :  * This function writes \p count bytes of data from \p buf to
     279             :  * the file descriptor attached to this connection.
     280             :  *
     281             :  * If the file descriptor is closed, then an error occurs and
     282             :  * the function returns -1.
     283             :  *
     284             :  * \note
     285             :  * If you setup the file descriptor in non-blocking mode, then the
     286             :  * function will return early if it cannot cache or immediately
     287             :  * send the specified data.
     288             :  *
     289             :  * \param[in] buf  A pointer to a buffer of data to write to the file.
     290             :  * \param[in] count  The number of bytes to write to the file.
     291             :  *
     292             :  * \return The number of bytes written to the file.
     293             :  */
     294           0 : ssize_t fd_connection::write(void const * buf, size_t count)
     295             : {
     296             :     // WARNING: We MUST call the fd_connection version of the is_writer(),
     297             :     //          because the fd_buffer_connection::is_writer() also checks
     298             :     //          the f_output buffer which has unwanted side effects
     299             :     //
     300           0 :     if(!fd_connection::is_writer())
     301             :     {
     302           0 :         errno = EBADF;
     303           0 :         return -1;
     304             :     }
     305             : 
     306           0 :     return ::write(f_fd, buf, count);
     307             : }
     308             : 
     309             : 
     310             : 
     311             : } // namespace ed
     312             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12