LCOV - code coverage report
Current view: top level - server_common - socket_request.h (source / functions) Hit Total Coverage
Test: report.info Lines: 12 12 100.0 %
Date: 2012-05-15 Functions: 5 11 45.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 4 12 33.3 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  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 __SOCKET_REQUEST_H
      16                 :            : #define __SOCKET_REQUEST_H 1
      17                 :            : 
      18                 :            : #include <exceptions/exceptions.h>
      19                 :            : 
      20                 :            : #include <boost/noncopyable.hpp>
      21                 :            : #include <utility>
      22                 :            : #include <string>
      23                 :            : #include <stdint.h>
      24                 :            : 
      25                 :            : namespace isc {
      26                 :            : 
      27                 :            : namespace cc {
      28                 :            : class AbstractSession;
      29                 :            : };
      30                 :            : 
      31                 :            : namespace server_common {
      32                 :            : 
      33                 :            : /// \brief A singleton class for requesting sockets
      34                 :            : ///
      35                 :            : /// This class allows requesting sockets from the socket creator.
      36                 :            : ///
      37                 :            : /// It is considered to be a singleton - a class which is instantiated
      38                 :            : /// at most once in the whole application. This is because it makes no
      39                 :            : /// sense to have two of them.
      40                 :            : ///
      41                 :            : /// This is actually an abstract base class. There'll be one with
      42                 :            : /// hidden implementation and we expect the tests to create its own
      43                 :            : /// subclass when needed.
      44                 :            : ///
      45                 :            : /// \see socketRequestor function to access the object of this class.
      46                 :            : class SocketRequestor : boost::noncopyable {
      47                 :            : protected:
      48                 :            :     /// \brief Protected constructor
      49                 :            :     ///
      50                 :            :     /// The constructor is protected so this class is not created by accident
      51                 :            :     /// (which it can't anyway, as it has pure virtual methods, but just to
      52                 :            :     /// be sure).
      53                 :        125 :     SocketRequestor() {}
      54                 :            : 
      55                 :            : public:
      56                 :            :     /// \brief virtual destructor
      57                 :            :     ///
      58                 :            :     /// A virtual destructor, as we have virtual methods, to make sure it is
      59                 :            :     /// destroyed by the destructor of the subclass. This shouldn't matter, as
      60                 :            :     /// a singleton class wouldn't get destroyed, but just to be sure.
      61                 :        122 :     virtual ~ SocketRequestor() {}
      62                 :            : 
      63                 :            :     /// \brief A representation of received socket
      64                 :            :     ///
      65                 :            :     /// The pair holds two parts. The OS-level file descriptor acting as the
      66                 :            :     /// socket (you might want to use it directly with functions like recv,
      67                 :            :     /// or fill it into an asio socket). The other part is the token
      68                 :            :     /// representing the socket, which allows it to be given up again.
      69                 :            :     typedef std::pair<int, std::string> SocketID;
      70                 :            : 
      71                 :            :     /// \brief The protocol of requested socket
      72                 :            :     ///
      73                 :            :     /// This describes which protocol the socket should have when created.
      74                 :            :     enum Protocol {
      75                 :            :         UDP,
      76                 :            :         TCP
      77                 :            :     };
      78                 :            : 
      79                 :            :     /// \brief The share mode of the requested socket
      80                 :            :     ///
      81                 :            :     /// The socket creator is able to "borrow" the same socket to multiple
      82                 :            :     /// applications at once. However, it isn't always what is required. This
      83                 :            :     /// describes the restrains we want to have on our socket regarding the
      84                 :            :     /// sharing. Union of restriction of all requests on the given socket
      85                 :            :     /// is taken (so you still don't have to get your socket even if you
      86                 :            :     /// say SHARE_ANY, because someone else might already asked for the socket
      87                 :            :     /// with DONT_SHARE).
      88                 :            :     enum ShareMode {
      89                 :            :         DONT_SHARE, //< Request an exclusive ownership of the socket.
      90                 :            :         SHARE_SAME, //< It is possible to share the socket with anybody who
      91                 :            :                     //< provided the same share_name.
      92                 :            :         SHARE_ANY   //< Any sharing is allowed.
      93                 :            :     };
      94                 :            : 
      95                 :            :     /// \brief Exception when we can't manipulate a socket
      96                 :            :     ///
      97                 :            :     /// This is thrown if the other side doesn't want to comply to our
      98                 :            :     /// requests, like when we ask for a socket already held by someone
      99                 :            :     /// else or ask for nonsense (releasing a socket we don't own).
     100                 :         19 :     class SocketError : public Exception {
     101                 :            :     public:
     102                 :         25 :         SocketError(const char* file, size_t line, const char* what) :
     103 [ +  - ][ #  # ]:         33 :             Exception(file, line, what)
         [ +  - ][ #  # ]
     104                 :         25 :         { }
     105                 :            :     };
     106                 :            : 
     107                 :            :     /// \brief Exception when we can't return a requested socket, but we're
     108                 :            :     ///     sure we could return others
     109                 :            :     ///
     110                 :            :     /// This is thrown if the requested socket can't be granted, but it is only
     111                 :            :     /// that one socket, not that the system would be broken or anything. This
     112                 :            :     /// exception is a common base class for the concrete exceptions actually
     113                 :            :     /// thrown. You can safely keep using the SocketRequestor after this
     114                 :            :     /// exception (or anything derived from it) is thrown.
     115                 :            :     ///
     116                 :            :     /// \see ShareError
     117                 :            :     /// \see SocketAllocateError
     118                 :         10 :     class NonFatalSocketError : public SocketError {
     119                 :            :     public:
     120                 :            :         NonFatalSocketError(const char* file, size_t line, const char* what) :
     121 [ +  - ][ +  - ]:         22 :             SocketError(file, line, what)
     122                 :            :         { }
     123                 :            :     };
     124                 :            : 
     125                 :            :     /// \brief Exception when the socket is allocated by other bind10 module
     126                 :            :     ///    and it doesn't want to share it.
     127                 :            :     ///
     128                 :            :     /// This is thrown if a socket is requested and the socket is already
     129                 :            :     /// allocated by bind10, but other bind10 module(s) is using it and
     130                 :            :     /// the sharing parameters are incompatible (the socket can't be shared
     131                 :            :     /// between the module and our module).
     132                 :          2 :     class ShareError : public NonFatalSocketError {
     133                 :            :     public:
     134                 :            :         ShareError(const char* file, size_t line, const char* what) :
     135                 :          8 :             NonFatalSocketError(file, line, what)
     136                 :            :         { }
     137                 :            :     };
     138                 :            : 
     139                 :            :     /// \brief Exception when the operating system doesn't allow us to create
     140                 :            :     ///    the requested socket.
     141                 :            :     ///
     142                 :            :     /// This happens when the socket() or bind() call fails in the socket
     143                 :            :     /// creator. This can happen when the address/port pair is already taken
     144                 :            :     /// by a different application, the socket creator doesn't have enough
     145                 :            :     /// privileges, or for some kind of similar reason.
     146                 :          8 :     class SocketAllocateError : public NonFatalSocketError {
     147                 :            :     public:
     148                 :            :         SocketAllocateError(const char* file, size_t line, const char* what) :
     149                 :         20 :             NonFatalSocketError(file, line, what)
     150                 :            :         { }
     151                 :            :     };
     152                 :            : 
     153                 :            :     /// \brief Ask for a socket
     154                 :            :     ///
     155                 :            :     /// Asks the socket creator to give us a socket. The socket will be bound
     156                 :            :     /// to the given address and port.
     157                 :            :     ///
     158                 :            :     /// \param protocol specifies the protocol of the socket.  This must be
     159                 :            :     /// either UDP or TCP.
     160                 :            :     /// \param address to which the socket should be bound.
     161                 :            :     /// \param port the port to which the socket should be bound (native endian,
     162                 :            :     ///     not network byte order).
     163                 :            :     /// \param share_mode how the socket can be shared with other requests.
     164                 :            :     ///     This must be one of the defined values of ShareMode..
     165                 :            :     /// \param share_name the name of sharing group, relevant for SHARE_SAME
     166                 :            :     ///     (specified by us or someone else). If left empty (the default),
     167                 :            :     ///     the app_name parameter of initSocketRequestor is used. If that one
     168                 :            :     ///     is empty as well, it is accepted, but not recommended, as such
     169                 :            :     ///     a non-descriptive name has a high chance of collisions between
     170                 :            :     ///     applications. Note that you should provide a name (by share_name
     171                 :            :     ///     or app_name) even when you set it to DONT_SHARE (for logs and
     172                 :            :     ///     debugging) and you need to provide one with SHARE_SAME (to know
     173                 :            :     ///     what is same) and SHARE_ANY (someone else might want SHARE_SAME,
     174                 :            :     ///     so it would check against this)
     175                 :            :     /// \return the socket, as a file descriptor and token representing it on
     176                 :            :     ///     the socket creator side.
     177                 :            :     ///
     178                 :            :     /// To understand the modes better:
     179                 :            :     /// - If mode is DONT_SHARE, it succeeds if no one else has opened an FD
     180                 :            :     ///   for requested protocol, address and port.
     181                 :            :     /// - If mode is SHARE_SAME, it succeeds if all applications who opened an
     182                 :            :     ///   FD for the requested protocol, address and port provided the same
     183                 :            :     ///   share_name as this one and none of them had mode DONT_SHARE.
     184                 :            :     /// - If mode is SHARE_ANY, it succeeds if no applications who requested
     185                 :            :     ///   the same potocol, address and port provided DONT_SHARE and all the
     186                 :            :     ///   applications who provided SHARE_SAME also provided the same
     187                 :            :     ///   share_name as this process did.
     188                 :            :     ///
     189                 :            :     /// \throw InvalidParameter protocol or share_mode is invalid
     190                 :            :     /// \throw CCSessionError when we have a problem talking over the CC
     191                 :            :     ///     session.
     192                 :            :     /// \throw SocketError in case we have some other problems receiving the
     193                 :            :     ///     socket (eg. inconsistency in the protocol, the socket got stuck
     194                 :            :     ///     in the transport, etc). If the exception is not of the following
     195                 :            :     ///     derived ones, it usualy means something serious happened.
     196                 :            :     /// \throw SocketAllocateError if the other side can't create the socket.
     197                 :            :     /// \throw ShareError if the socket is used by other bind10 module and
     198                 :            :     ///     that one doesn't want to share it with us.
     199                 :            :     virtual SocketID requestSocket(Protocol protocol,
     200                 :            :                                    const std::string& address,
     201                 :            :                                    uint16_t port, ShareMode share_mode,
     202                 :            :                                    const std::string& share_name = "") = 0;
     203                 :            : 
     204                 :            :     /// \brief Tell the socket creator we no longer need the socket
     205                 :            :     ///
     206                 :            :     /// Releases the identified socket. This must be called *after*
     207                 :            :     /// the file descriptor was closed on our side. This will allow
     208                 :            :     /// the remote side to either give it to some other application
     209                 :            :     /// or close it, depending on the situation.
     210                 :            :     ///
     211                 :            :     /// \param token the token representing the socket, as received
     212                 :            :     ///     in the second part of the requestSocket result.
     213                 :            :     /// \throw CCSessionError when we have a problem talking over the CC
     214                 :            :     ///     session.
     215                 :            :     /// \throw SocketError in case the other side doesn't like the
     216                 :            :     ///     release (like we're trying to release a socket that doesn't
     217                 :            :     ///     belong to us or exist at all).
     218                 :            :     virtual void releaseSocket(const std::string& token) = 0;
     219                 :            : };
     220                 :            : 
     221                 :            : /// \brief Access the requestor object.
     222                 :            : ///
     223                 :            : /// This returns the singleton object for the Requestor.
     224                 :            : ///
     225                 :            : /// \return the active socket requestor object.
     226                 :            : /// \throw InvalidOperation if the object was not yet initialized.
     227                 :            : /// \see SocketRequestor::init to initialize the object.
     228                 :            : SocketRequestor& socketRequestor();
     229                 :            : 
     230                 :            : /// \brief Initialize the singleton object
     231                 :            : ///
     232                 :            : /// This creates the object that will be used to request sockets.
     233                 :            : /// It can be called only once per the life of application.
     234                 :            : ///
     235                 :            : /// \param session the CC session that'll be used to talk to the
     236                 :            : ///                socket creator.
     237                 :            : /// \param app_name default share name if one is not provided with
     238                 :            : ///                 requestSocket. You can leave this as empty string,
     239                 :            : ///                 but then you should provide a reasonably descriptive
     240                 :            : ///                 name to requestSocket. Empty names work like any others,
     241                 :            : ///                 but have a high chance of collisions, so it is recommended
     242                 :            : ///                 to avoid them and provide the name of the application
     243                 :            : ///                 here.
     244                 :            : /// \throw InvalidOperation when it is called more than once
     245                 :            : void initSocketRequestor(cc::AbstractSession& session,
     246                 :            :                          const std::string& app_name);
     247                 :            : 
     248                 :            : /// \brief Initialization for tests
     249                 :            : ///
     250                 :            : /// This is to support different subclasses in tests. It replaces
     251                 :            : /// the object used by socketRequestor() function by this one provided
     252                 :            : /// as parameter. The ownership is not taken, eg. it's up to the caller
     253                 :            : /// to delete it when necessary.
     254                 :            : ///
     255                 :            : /// This is not to be used in production applications. It is meant as
     256                 :            : /// an replacement of init.
     257                 :            : ///
     258                 :            : /// This never throws.
     259                 :            : ///
     260                 :            : /// \param requestor the object to be used. It can be NULL to reset to
     261                 :            : ///     an "virgin" state (which acts as if initTest or init was never
     262                 :            : ///     called before).
     263                 :            : void initTestSocketRequestor(SocketRequestor* requestor);
     264                 :            : 
     265                 :            : /// \brief Destroy the singleton instance
     266                 :            : ///
     267                 :            : /// Calling this function is not strictly necessary; the socket
     268                 :            : /// requestor is a singleton anyway. However, for some tests it
     269                 :            : /// is useful to destroy and recreate it, as well as for programs
     270                 :            : /// that want to be completely clean on exit.
     271                 :            : /// After this function has been called, all operations except init
     272                 :            : /// will fail.
     273                 :            : void cleanupSocketRequestor();
     274                 :            : 
     275                 :            : }
     276                 :            : }
     277                 :            : 
     278                 :            : #endif  // __SOCKET_REQUEST_H

Generated by: LCOV version 1.9