LCOV - code coverage report
Current view: top level - eventdispatcher - pipe_connection.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 35 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             : // self
      40             : //
      41             : #include "eventdispatcher/pipe_connection.h"
      42             : 
      43             : #include "eventdispatcher/exception.h"
      44             : 
      45             : 
      46             : // C lib
      47             : //
      48             : #include <unistd.h>
      49             : #include <sys/socket.h>
      50             : 
      51             : 
      52             : // last include
      53             : //
      54             : #include <snapdev/poison.h>
      55             : 
      56             : 
      57             : 
      58             : 
      59             : namespace ed
      60             : {
      61             : 
      62             : 
      63             : 
      64             : /** \brief Initializes the pipe connection.
      65             :  *
      66             :  * This function creates the pipes that are to be used to connect
      67             :  * two processes (these are actually Unix sockets). These are
      68             :  * used whenever you fork() so the parent process can very quickly
      69             :  * communicate with the child process using complex messages just
      70             :  * like you do between services and Snap Communicator.
      71             :  *
      72             :  * \warning
      73             :  * The sockets are opened in a non-blocking state. However, they are
      74             :  * not closed when you call fork() since they are to be used across
      75             :  * processes.
      76             :  *
      77             :  * \warning
      78             :  * You need to create a new snap_pipe_connection each time you want
      79             :  * to create a new child.
      80             :  *
      81             :  * \exception snap_communicator_initialization_error
      82             :  * This exception is raised if the pipes (socketpair) cannot be created.
      83             :  */
      84           0 : pipe_connection::pipe_connection()
      85             : {
      86           0 :     if(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, f_socket) != 0)
      87             :     {
      88             :         // pipe could not be created
      89           0 :         throw event_dispatcher_initialization_error("somehow the pipes used for a two way pipe connection could not be created.");
      90             :     }
      91             : 
      92           0 :     f_parent = getpid();
      93           0 : }
      94             : 
      95             : 
      96             : /** \brief Make sure to close the pipes.
      97             :  *
      98             :  * The destructor ensures that the pipes get closed.
      99             :  *
     100             :  * They may already have been closed if a broken pipe was detected.
     101             :  */
     102           0 : pipe_connection::~pipe_connection()
     103             : {
     104           0 :     close();
     105           0 : }
     106             : 
     107             : 
     108             : /** \brief Read data from this pipe connection.
     109             :  *
     110             :  * This function reads up to count bytes from this pipe connection.
     111             :  *
     112             :  * The function makes sure to use the correct socket for the calling
     113             :  * process (i.e. depending on whether this is the parent or child.)
     114             :  *
     115             :  * Just like the system read(2) function, errno is set to the error
     116             :  * that happened when the function returns -1.
     117             :  *
     118             :  * \param[in] buf  A pointer to a buffer of data.
     119             :  * \param[in] count  The number of bytes to read from the pipe connection.
     120             :  *
     121             :  * \return The number of bytes read from this pipe socket, or -1 on errors.
     122             :  */
     123           0 : ssize_t pipe_connection::read(void * buf, size_t count)
     124             : {
     125           0 :     int const s(get_socket());
     126           0 :     if(s == -1)
     127             :     {
     128           0 :         errno = EBADF;
     129           0 :         return -1;
     130             :     }
     131           0 :     return ::read(s, buf, count);
     132             : }
     133             : 
     134             : 
     135             : /** \brief Write data to this pipe connection.
     136             :  *
     137             :  * This function writes count bytes to this pipe connection.
     138             :  *
     139             :  * The function makes sure to use the correct socket for the calling
     140             :  * process (i.e. depending on whether this is the parent or child.)
     141             :  *
     142             :  * Just like the system write(2) function, errno is set to the error
     143             :  * that happened when the function returns -1.
     144             :  *
     145             :  * \param[in] buf  A pointer to a buffer of data.
     146             :  * \param[in] count  The number of bytes to write to the pipe connection.
     147             :  *
     148             :  * \return The number of bytes written to this pipe socket, or -1 on errors.
     149             :  */
     150           0 : ssize_t pipe_connection::write(void const * buf, size_t count)
     151             : {
     152           0 :     int const s(get_socket());
     153           0 :     if(s == -1)
     154             :     {
     155           0 :         errno = EBADF;
     156           0 :         return -1;
     157             :     }
     158           0 :     if(buf != nullptr && count > 0)
     159             :     {
     160           0 :         return ::write(s, buf, count);
     161             :     }
     162           0 :     return 0;
     163             : }
     164             : 
     165             : 
     166             : /** \brief Close the sockets.
     167             :  *
     168             :  * This function closes the pair of sockets managed by this
     169             :  * pipe connection object.
     170             :  *
     171             :  * After this call, the pipe connection is closed and cannot be
     172             :  * used anymore. The read and write functions will return immediately
     173             :  * if called.
     174             :  */
     175           0 : void pipe_connection::close()
     176             : {
     177           0 :     if(f_socket[0] != -1)
     178             :     {
     179           0 :         ::close(f_socket[0]);
     180           0 :         ::close(f_socket[1]);
     181           0 :         f_socket[0] = -1;
     182           0 :         f_socket[1] = -1;
     183             :     }
     184           0 : }
     185             : 
     186             : 
     187             : /** \brief Pipe connections accept reads.
     188             :  *
     189             :  * This function returns true meaning that the pipe connection can be
     190             :  * used to read data.
     191             :  *
     192             :  * \return true since a pipe connection is a reader.
     193             :  */
     194           0 : bool pipe_connection::is_reader() const
     195             : {
     196           0 :     return true;
     197             : }
     198             : 
     199             : 
     200             : /** \brief This function returns the pipe we want to listen on.
     201             :  *
     202             :  * This function returns the file descriptor of one of the two
     203             :  * sockets. The parent process returns the descriptor of socket
     204             :  * number 0. The child process returns the descriptor of socket
     205             :  * number 1.
     206             :  *
     207             :  * \note
     208             :  * If the close() function was called, this function returns -1.
     209             :  *
     210             :  * \return A pipe descriptor to listen on with poll().
     211             :  */
     212           0 : int pipe_connection::get_socket() const
     213             : {
     214           0 :     if(f_parent == getpid())
     215             :     {
     216           0 :         return f_socket[0];
     217             :     }
     218             : 
     219           0 :     return f_socket[1];
     220             : }
     221             : 
     222             : 
     223             : 
     224             : 
     225             : 
     226             : 
     227             : 
     228             : } // namespace ed
     229             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12