LCOV - code coverage report
Current view: top level - asiolink - io_asio_socket.h (source / functions) Hit Total Coverage
Test: report.info Lines: 1 7 14.3 %
Date: 2012-05-15 Functions: 0 14 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 6 0.0 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #ifndef __IO_ASIO_SOCKET_H
      16                 :            : #define __IO_ASIO_SOCKET_H 1
      17                 :            : 
      18                 :            : // IMPORTANT NOTE: only very few ASIO headers files can be included in
      19                 :            : // this file.  In particular, asio.hpp should never be included here.
      20                 :            : // See the description of the namespace below.
      21                 :            : #include <unistd.h>             // for some network system calls
      22                 :            : 
      23                 :            : #include <functional>
      24                 :            : #include <string>
      25                 :            : 
      26                 :            : #include <exceptions/exceptions.h>
      27                 :            : #include <coroutine.h>
      28                 :            : 
      29                 :            : #include <util/buffer.h>
      30                 :            : 
      31                 :            : #include <asiolink/io_error.h>
      32                 :            : #include <asiolink/io_socket.h>
      33                 :            : 
      34                 :            : namespace isc {
      35                 :            : namespace asiolink {
      36                 :            : 
      37                 :            : /// \brief Socket not open
      38                 :            : ///
      39                 :            : /// Thrown on an attempt to do read/write to a socket that is not open.
      40                 :          0 : class SocketNotOpen : public IOError {
      41                 :            : public:
      42                 :            :     SocketNotOpen(const char* file, size_t line, const char* what) :
      43 [ #  # ][ #  # ]:          0 :         IOError(file, line, what) {}
      44                 :            : };
      45                 :            : 
      46                 :            : /// \brief Error setting socket options
      47                 :            : ///
      48                 :            : /// Thrown if attempt to change socket options fails.
      49                 :          0 : class SocketSetError : public IOError {
      50                 :            : public:
      51                 :            :     SocketSetError(const char* file, size_t line, const char* what) :
      52                 :            :         IOError(file, line, what) {}
      53                 :            : };
      54                 :            : 
      55                 :            : /// \brief Buffer overflow
      56                 :            : ///
      57                 :            : /// Thrown if an attempt is made to receive into an area beyond the end of
      58                 :            : /// the receive data buffer.
      59                 :          0 : class BufferOverflow : public IOError {
      60                 :            : public:
      61                 :            :     BufferOverflow(const char* file, size_t line, const char* what) :
      62         [ #  # ]:          0 :         IOError(file, line, what) {}
      63                 :            : };
      64                 :            : 
      65                 :            : /// Forward declaration of an IOEndpoint
      66                 :            : class IOEndpoint;
      67                 :            : 
      68                 :            : 
      69                 :            : /// \brief I/O Socket with asynchronous operations
      70                 :            : ///
      71                 :            : /// This class is a wrapper for the ASIO socket classes such as
      72                 :            : /// \c ip::tcp::socket and \c ip::udp::socket.
      73                 :            : ///
      74                 :            : /// This is the basic IOSocket with additional operations - open, send, receive
      75                 :            : /// and close.  Depending on how the asiolink code develops, it may be a
      76                 :            : /// temporary class: its main use is to add the template parameter needed for
      77                 :            : /// the derived classes UDPSocket and TCPSocket but without changing the
      78                 :            : /// signature of the more basic IOSocket class.
      79                 :            : ///
      80                 :            : /// We may revisit this decision when we generalize the wrapper and more
      81                 :            : /// modules use it.  Also, at that point we may define a separate (visible)
      82                 :            : /// derived class for testing purposes rather than providing factory methods
      83                 :            : /// (i.e., getDummy variants below).
      84                 :            : ///
      85                 :            : /// \param C Template parameter identifying type of the callback object.
      86                 :            : 
      87                 :            : template <typename C>
      88                 :            : class IOAsioSocket : public IOSocket {
      89                 :            :     ///
      90                 :            :     /// \name Constructors and Destructor
      91                 :            :     ///
      92                 :            :     /// Note: The copy constructor and the assignment operator are
      93                 :            :     /// intentionally defined as private, making this class non-copyable.
      94                 :            :     //@{
      95                 :            : private:
      96                 :            :     IOAsioSocket(const IOAsioSocket<C>& source);
      97                 :            :     IOAsioSocket& operator=(const IOAsioSocket<C>& source);
      98                 :            : protected:
      99                 :            :     /// \brief The default constructor.
     100                 :            :     ///
     101                 :            :     /// This is intentionally defined as \c protected as this base class
     102                 :            :     /// should never be instantiated (except as part of a derived class).
     103                 :        212 :     IOAsioSocket() {}
     104                 :            : public:
     105                 :            :     /// The destructor.
     106                 :          0 :     virtual ~IOAsioSocket() {}
     107                 :            :     //@}
     108                 :            : 
     109                 :            :     /// \brief Return the "native" representation of the socket.
     110                 :            :     ///
     111                 :            :     /// In practice, this is the file descriptor of the socket for UNIX-like
     112                 :            :     /// systems so the current implementation simply uses \c int as the type of
     113                 :            :     /// the return value. We may have to need revisit this decision later.
     114                 :            :     ///
     115                 :            :     /// In general, the application should avoid using this method; it
     116                 :            :     /// essentially discloses an implementation specific "handle" that can
     117                 :            :     /// change the internal state of the socket (consider what would happen if
     118                 :            :     /// the application closes it, for example).  But we sometimes need to
     119                 :            :     /// perform very low-level operations that requires the native
     120                 :            :     /// representation.  Passing the file descriptor to a different process is
     121                 :            :     /// one example.  This method is provided as a necessary evil for such
     122                 :            :     /// limited purposes.
     123                 :            :     ///
     124                 :            :     /// This method never throws an exception.
     125                 :            :     ///
     126                 :            :     /// \return The native representation of the socket.  This is the socket
     127                 :            :     ///         file descriptor for UNIX-like systems.
     128                 :            :     virtual int getNative() const = 0;
     129                 :            : 
     130                 :            :     /// \brief Return the transport protocol of the socket.
     131                 :            :     ///
     132                 :            :     /// Currently, it returns \c IPPROTO_UDP for UDP sockets, and
     133                 :            :     /// \c IPPROTO_TCP for TCP sockets.
     134                 :            :     ///
     135                 :            :     /// This method never throws an exception.
     136                 :            :     ///
     137                 :            :     /// \return \c IPPROTO_UDP for UDP sockets, \c IPPROTO_TCP for TCP sockets
     138                 :            :     virtual int getProtocol() const = 0;
     139                 :            : 
     140                 :            :     /// \brief Is Open() synchronous?
     141                 :            :     ///
     142                 :            :     /// On a TCP socket, an "open" operation is a call to the socket's "open()"
     143                 :            :     /// method followed by a connection to the remote system: it is an
     144                 :            :     /// asynchronous operation.  On a UDP socket, it is just a call to "open()"
     145                 :            :     /// and completes synchronously.
     146                 :            :     ///
     147                 :            :     /// For TCP, signalling of the completion of the operation is done by
     148                 :            :     /// by calling the callback function in the normal way.  This could be done
     149                 :            :     /// for UDP (by posting en event on the event queue); however, that will
     150                 :            :     /// incur additional overhead in the most common case.  So we give the
     151                 :            :     /// caller the choice for calling this open() method synchronously or
     152                 :            :     /// asynchronously.
     153                 :            :     ///
     154                 :            :     /// Owing to the way that the stackless coroutines are implemented, we need
     155                 :            :     /// to know _before_ executing the "open" function whether or not it is
     156                 :            :     /// asynchronous.  So this method is called to provide that information.
     157                 :            :     ///
     158                 :            :     /// (The reason there is a need to know is because the call to open() passes
     159                 :            :     /// in the state of the coroutine at the time the call is made.  On an
     160                 :            :     /// asynchronous I/O, we need to set the state to point to the statement
     161                 :            :     /// after the call to open() _before_ we pass the corouine to the open()
     162                 :            :     /// call.  Unfortunately, the macros that set the state of the coroutine
     163                 :            :     /// also yield control - which we don't want to do if the open is
     164                 :            :     /// synchronous.  Hence we need to know before we make the call to open()
     165                 :            :     /// whether that call will complete asynchronously.)
     166                 :            :     virtual bool isOpenSynchronous() const = 0;
     167                 :            : 
     168                 :            :     /// \brief Open AsioSocket
     169                 :            :     ///
     170                 :            :     /// Opens the socket for asynchronous I/O.  The open will complete
     171                 :            :     /// synchronously on UCP or asynchronously on TCP (in which case a callback
     172                 :            :     /// will be queued).
     173                 :            :     ///
     174                 :            :     /// \param endpoint Pointer to the endpoint object.  This is ignored for
     175                 :            :     ///        a UDP socket (the target is specified in the send call), but
     176                 :            :     ///        should be of type TCPEndpoint for a TCP connection.
     177                 :            :     /// \param callback I/O Completion callback, called when the operation has
     178                 :            :     ///        completed, but only if the operation was asynchronous. (It is
     179                 :            :     ///        ignored on a UDP socket.)
     180                 :            :     virtual void open(const IOEndpoint* endpoint, C& callback) = 0;
     181                 :            : 
     182                 :            :     /// \brief Send Asynchronously
     183                 :            :     ///
     184                 :            :     /// This corresponds to async_send_to() for UDP sockets and async_send()
     185                 :            :     /// for TCP.  In both cases an endpoint argument is supplied indicating the
     186                 :            :     /// target of the send - this is ignored for TCP.
     187                 :            :     ///
     188                 :            :     /// \param data Data to send
     189                 :            :     /// \param length Length of data to send
     190                 :            :     /// \param endpoint Target of the send
     191                 :            :     /// \param callback Callback object.
     192                 :            :     virtual void asyncSend(const void* data, size_t length,
     193                 :            :                            const IOEndpoint* endpoint, C& callback) = 0;
     194                 :            : 
     195                 :            :     /// \brief Receive Asynchronously
     196                 :            :     ///
     197                 :            :     /// This corresponds to async_receive_from() for UDP sockets and
     198                 :            :     /// async_receive() for TCP.  In both cases, an endpoint argument is
     199                 :            :     /// supplied to receive the source of the communication.  For TCP it will
     200                 :            :     /// be filled in with details of the connection.
     201                 :            :     ///
     202                 :            :     /// \param data Buffer to receive incoming message
     203                 :            :     /// \param length Length of the data buffer
     204                 :            :     /// \param offset Offset into buffer where data is to be put.  Although the
     205                 :            :     ///        offset could be implied by adjusting "data" and "length"
     206                 :            :     ///        appropriately, using this argument allows data to be specified as
     207                 :            :     ///        "const void*" - the overhead of converting it to a pointer to a
     208                 :            :     ///        set of bytes is hidden away here.
     209                 :            :     /// \param endpoint Source of the communication
     210                 :            :     /// \param callback Callback object
     211                 :            :     virtual void asyncReceive(void* data, size_t length, size_t offset,
     212                 :            :                               IOEndpoint* endpoint, C& callback) = 0;
     213                 :            : 
     214                 :            :     /// \brief Processes received data
     215                 :            :     ///
     216                 :            :     /// In the IOFetch code, data is received into a staging buffer before being
     217                 :            :     /// copied into the target buffer.  (This is because (a) we don't know how
     218                 :            :     /// much data we will be receiving, so don't know how to size the output
     219                 :            :     /// buffer and (b) TCP data is preceded by a two-byte count field that needs
     220                 :            :     /// to be discarded before being returned to the user.)
     221                 :            :     ///
     222                 :            :     /// An additional consideration is that TCP data is not received in one
     223                 :            :     /// I/O - it may take a number of I/Os - each receiving any non-zero number
     224                 :            :     /// of bytes - to read the entire message.
     225                 :            :     ///
     226                 :            :     /// So the IOFetch code has to loop until it determines that all the data
     227                 :            :     /// has been read.  This is where this method comes in.  It has several
     228                 :            :     /// functions:
     229                 :            :     ///
     230                 :            :     /// - It checks if the received data is complete.
     231                 :            :     /// - If data is not complete, decides if the next set of data is to go into
     232                 :            :     ///   the start of the staging buffer or at some offset into it.  (This
     233                 :            :     ///   simplifies the case we could have in a TCP receive where the two-byte
     234                 :            :     ///   count field is received in one-byte chunks: we put off interpreting
     235                 :            :     ///   the count until we have all of it.  The alternative - copying the
     236                 :            :     ///   data to the output buffer and interpreting the count from there -
     237                 :            :     ///   would require moving the data in the output buffer by two bytes before
     238                 :            :     ///   returning it to the caller.)
     239                 :            :     /// - Copies data from the staging buffer into the output buffer.
     240                 :            :     ///
     241                 :            :     /// This functionality mainly applies to TCP receives.  For UDP, all the
     242                 :            :     /// data is received in one I/O, so this just copies the data into the
     243                 :            :     /// output buffer.
     244                 :            :     ///
     245                 :            :     /// \param staging Pointer to the start of the staging buffer.
     246                 :            :     /// \param length Amount of data in the staging buffer.
     247                 :            :     /// \param cumulative Amount of data received before the staging buffer is
     248                 :            :     ///        processed (this includes the TCP count field if appropriate).
     249                 :            :     ///        The value should be set to zero before the receive loop is
     250                 :            :     ///        entered, and it will be updated by this method as required.
     251                 :            :     /// \param offset Offset into the staging buffer where the next read should
     252                 :            :     ///        put the received data.  It should be set to zero before the first
     253                 :            :     ///        call and may be updated by this method.
     254                 :            :     /// \param expected Expected amount of data to be received.  This is
     255                 :            :     ///        really the TCP count field and is set to that value when enough
     256                 :            :     ///        of a TCP message is received.  It should be initialized to -1
     257                 :            :     ///        before the first read is executed.
     258                 :            :     /// \param outbuff Output buffer.  Data in the staging buffer may be copied
     259                 :            :     ///        to this output buffer in the call.
     260                 :            :     ///
     261                 :            :     /// \return true if the receive is complete, false if another receive is
     262                 :            :     ///         needed.  This is always true for UDP, but for TCP involves
     263                 :            :     ///         checking the amount of data received so far against the amount
     264                 :            :     ///         expected (as indicated by the two-byte count field).  If this
     265                 :            :     ///         method returns false, another read should be queued and data
     266                 :            :     ///         should be read into the staging buffer at offset given by the
     267                 :            :     ///         "offset" parameter.
     268                 :            :     virtual bool processReceivedData(const void* staging, size_t length,
     269                 :            :                                      size_t& cumulative, size_t& offset,
     270                 :            :                                      size_t& expected,
     271                 :            :                                      isc::util::OutputBufferPtr& outbuff) = 0;
     272                 :            : 
     273                 :            :     /// \brief Cancel I/O On AsioSocket
     274                 :            :     virtual void cancel() = 0;
     275                 :            : 
     276                 :            :     /// \brief Close socket
     277                 :            :     virtual void close() = 0;
     278                 :            : };
     279                 :            : 
     280                 :            : 
     281                 :            : #include "io_socket.h"
     282                 :            : 
     283                 :            : /// \brief The \c DummyAsioSocket class is a concrete derived class of
     284                 :            : /// \c IOAsioSocket that is not associated with any real socket.
     285                 :            : ///
     286                 :            : /// This main purpose of this class is tests, where it may be desirable to
     287                 :            : /// instantiate an \c IOAsioSocket object without involving system resource
     288                 :            : /// allocation such as real network sockets.
     289                 :            : ///
     290                 :            : /// \param C Template parameter identifying type of the callback object.
     291                 :            : 
     292                 :            : template <typename C>
     293                 :            : class DummyAsioSocket : public IOAsioSocket<C> {
     294                 :            : private:
     295                 :            :     DummyAsioSocket(const DummyAsioSocket<C>& source);
     296                 :            :     DummyAsioSocket& operator=(const DummyAsioSocket<C>& source);
     297                 :            : public:
     298                 :            :     /// \brief Constructor from the protocol number.
     299                 :            :     ///
     300                 :            :     /// The protocol must validly identify a standard network protocol.
     301                 :            :     /// For example, to specify TCP \c protocol must be \c IPPROTO_TCP.
     302                 :            :     ///
     303                 :            :     /// \param protocol The network protocol number for the socket.
     304                 :            :     DummyAsioSocket(const int protocol) : protocol_(protocol) {}
     305                 :            : 
     306                 :            :     /// \brief A dummy derived method of \c IOAsioSocket::getNative().
     307                 :            :     ///
     308                 :            :     /// \return Always returns -1 as the object is not associated with a real
     309                 :            :     /// (native) socket.
     310                 :            :     virtual int getNative() const { return (-1); }
     311                 :            : 
     312                 :            :     /// \brief A dummy derived method of \c IOAsioSocket::getProtocol().
     313                 :            :     ///
     314                 :            :     /// \return Protocol socket was created with
     315                 :            :     virtual int getProtocol() const { return (protocol_); }
     316                 :            : 
     317                 :            : 
     318                 :            :     /// \brief Is socket opening synchronous?
     319                 :            :     ///
     320                 :            :     /// \return true - it is for this class.
     321                 :            :     bool isOpenSynchronous() const {
     322                 :            :         return true;
     323                 :            :     }
     324                 :            : 
     325                 :            :     /// \brief Open AsioSocket
     326                 :            :     ///
     327                 :            :     /// A call that is a no-op on UDP sockets, this opens a connection to the
     328                 :            :     /// system identified by the given endpoint.
     329                 :            :     /// The endpoint and callback are unused.
     330                 :            :     ///
     331                 :            :     /// \return false indicating that the operation completed synchronously.
     332                 :            :     virtual bool open(const IOEndpoint*, C&) {
     333                 :            :         return (false);
     334                 :            :     }
     335                 :            : 
     336                 :            :     /// \brief Send Asynchronously
     337                 :            :     ///
     338                 :            :     /// Must be supplied as it is abstract in the base class.
     339                 :            :     /// This is unused.
     340                 :            :     virtual void asyncSend(const void*, size_t, const IOEndpoint*, C&) {
     341                 :            :     }
     342                 :            : 
     343                 :            :     /// \brief Receive Asynchronously
     344                 :            :     ///
     345                 :            :     /// Must be supplied as it is abstract in the base class.
     346                 :            :     /// The parameters are unused.
     347                 :            :     virtual void asyncReceive(void* data, size_t, size_t, IOEndpoint*, C&) {
     348                 :            :     }
     349                 :            : 
     350                 :            :     /// \brief Checks if the data received is complete.
     351                 :            :     ///
     352                 :            :     /// \param staging Unused
     353                 :            :     /// \param length Unused
     354                 :            :     /// \param cumulative Unused
     355                 :            :     /// \param offset Unused.
     356                 :            :     /// \param expected Unused.
     357                 :            :     /// \param outbuff Unused.
     358                 :            :     ///
     359                 :            :     /// \return Always true
     360                 :            :     virtual bool receiveComplete(const void* staging, size_t length,
     361                 :            :                                  size_t& cumulative, size_t& offset,
     362                 :            :                                  size_t& expected,
     363                 :            :                                  isc::util::OutputBufferPtr& outbuff)
     364                 :            :     {
     365                 :            :         return (true);
     366                 :            :     }
     367                 :            : 
     368                 :            : 
     369                 :            :     /// \brief Cancel I/O On AsioSocket
     370                 :            :     ///
     371                 :            :     /// Must be supplied as it is abstract in the base class.
     372                 :            :     virtual void cancel() {
     373                 :            :     }
     374                 :            : 
     375                 :            :     /// \brief Close socket
     376                 :            :     ///
     377                 :            :     /// Must be supplied as it is abstract in the base class.
     378                 :            :     virtual void close() {
     379                 :            :     }
     380                 :            : 
     381                 :            : private:
     382                 :            :     const int protocol_;
     383                 :            : };
     384                 :            : 
     385                 :            : } // namespace asiolink
     386                 :            : } // namespace isc
     387                 :            : 
     388                 :            : #endif // __IO_ASIO_SOCKET_H

Generated by: LCOV version 1.9