Skip to content
Snippets Groups Projects
SocketProtocol.hh 16.1 KiB
Newer Older
sbund's avatar
sbund committed
// $Id$
//
// Copyright (C) 2006
sbund's avatar
sbund committed
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
//     Stefan Bund <stefan.bund@fokus.fraunhofer.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/** \file
    \brief SocketProtocol and ConcreteSocketProtocol public header
    \idea We should optimize the protocol handling. Allocating a protocol instance for every socket
        body seems quite wasteful. We could derive SocketPolicy from SocketBody (probably privately,
        since private inheritance models more of 'has a' than 'is a'). This would allow to reduce
        the number of heap-allocations per socket to one which is good.
tho's avatar
tho committed
// The private inheritance idea should indeed work very well: We just need to change the
// implementations of body() and protocol() and that of the ProtocolClient/ServerSocketHandle
// constructors and the SocketBody constructor. The body and the protocol would still be visible
// like several instances because of the private inheritance but we would save the backwards
// pointer.

/** \defgroup protocol_group The Protocol Classes

    \htmlonly
    <map name="protocols">
      <area shape="rect" alt="SocketPolicy" href="structsenf_1_1SocketPolicy.html" title="SocketPolicy" coords="416,50,536,68" />
      <area shape="rect" alt="ConcreteSocketProtocol" href="classsenf_1_1ConcreteSocketProtocol.html" title="ConcreteSocketProtocol" coords="268,65,456,88" />
      <area shape="rect" alt="SocketProtocol" href="classsenf_1_1SocketProtocol.html" title="SocketProtocol" coords="1,2,120,26" />
      <area shape="rect" alt="BSDSocketProtocol" href="classsenf_1_1BSDSocketProtocol.html" title="BSDSocketProtocol" coords="124,118,276,143" />
      <area shape="rect" alt="AddressableBSDSocketProtocol" href="classsenf_1_1AddressableBSDSocketProtocol.html" title="AddressableBSDSocketProtocol" coords="82,200,314,224" />
      <area shape="rect" alt="IPv4Protocol" href="classsenf_1_1IPv4Protocol.html" title="IPv4Protocol" coords="149,272,252,296" />
      <area shape="rect" alt="IPv6Protocol" href="classsenf_1_1IPv6Protocol.html" title="IPv6Protocol" coords="149,335,251,359" />
      <area shape="rect" alt="TCPProtocol" href="classsenf_1_1TCPProtocol.html" title="TCPProtocol" coords="151,398,248,420" />
      <area shape="rect" alt="TCPv4SocketProtocol" href="classsenf_1_1TCPv4SocketProtocol.html" title="TCPv4SocketProtocol" coords="288,471,405,494" />
      <area shape="rect" alt="TCPv6SocketProtocol" href="classsenf_1_1TCPv6SocketProtocol.html" title="TCPv6SocketProtocol" coords="424,470,540,494" />
      <area shape="rect" alt="PacketProtocol" href="classsenf_1_1PacketProtocol.html" title="PacketProtocol" coords="560,469,680,495" />
    </map>
    <img src="Protocols.png" border="0" alt="Protocols" usemap="#protocols">
    \endhtmlonly
    The socket handle classes and templates only implement the most important socket API methods
    using the policy framework. To access the complete API, the protocol interface is
    provided. Access to the protocol interface is only possible via senf::ProtocolClientSocketHandle
    and senf::ProtocolServerSocketHandle which have the necessary \c protocol() member. This member
    returns a reference to the protocol class instance which contains members covering all the API
    functions (mostly setsockopt/getsockopt related calls but there may be more, this is completely
    up to the implementor of the protocol class) not found in the SocketHandle interface. The
    protocol interface is specific to the protocol. It's implementation is quite free. The standard
    protocols are implemented using a simple multiple-inheritance hierarchy as shown above.

    Since the protocol class is protocol specific (how intelligent ...), the protocol class also
    defines the \e complete socket policy to be used with it's protocol. Complete meaning, that
    every policy axis must be assigned it's the most specific (that is derived) policy class to be
    used with the protocol and that no policy axis is allowed to be left unspecified.
    \see
        \ref handle_group \n
        \ref policy_group

    \todo Complete the protocol interface implementations. Better distribution of members to
        protocol facets and more precise distribution of functionality among the facets.
 */

/** \defgroup concrete_protocol_group Protocol Implementations (Concrete Protocol Classes)
    \ingroup protocol_group

    Theese protocol classes define concrete and complete protocol implementations. They inherit from
    ConcreteSocketProtocol and are used with the ProtocolClientSocketHandle and
    ProtocolServerSocketHandle templates to instantiate socket handles. Appropriate typedefs are
    always provided.

    Every protocol defines both the protocol and the policy interface provided by that protocol. See
    the documentation of the protocol classes listed below for more information on the supported
    protocols. Every protocol class documents it's policy interface. Use the 'list all members' link
    of the protocol class to find the complete policy interface.
/** \defgroup protocol_facets_group Protocol Facets
    \ingroup protocol_group

    The protocol facets are classes used as building blocks to build concrete protocol classes. Each
    protocol facet will implement some functional part of the protocol interface. The protocol
    facets all inherit from SocketProtocol by public \e virtual inheritance. This ensures the
    accessibility of the socket body from all facets.
 */

sbund's avatar
sbund committed
#ifndef HH_SocketProtocol_
#define HH_SocketProtocol_ 1

// Custom includes
#include <boost/utility.hpp>
// Hrmpf ... I have tried very hard, but I just can't find a nice, generic way to clean
// up this include
#include "SocketHandle.ih"
sbund's avatar
sbund committed

//#include "SocketProtocol.mpp"
///////////////////////////////hh.p////////////////////////////////////////

    /// \addtogroup protocol_group
    /// @{
sbund's avatar
sbund committed

sbund's avatar
sbund committed
    class SocketPolicyBase;
sbund's avatar
sbund committed

    /** \brief Socket Protocol base class
        This is the base class of all socket protocol classes. Every protocol class must directly or
        indirectly inherit from SocketProtocol

        \attention SocketProtocol must \e always be inherited using public \e virtual inheritance.
    class SocketProtocol 
        : boost::noncopyable
sbund's avatar
sbund committed
    public:
        ///////////////////////////////////////////////////////////////////////////
        // Types

        ///////////////////////////////////////////////////////////////////////////
        ///\name Structors and default members
        ///@{

        SocketProtocol();
        virtual ~SocketProtocol() = 0;

        // default default constructor
sbund's avatar
sbund committed
        // no copy
        // no conversion constructors

        ///@}
        ///////////////////////////////////////////////////////////////////////////

        SocketBody & body() const;      ///< Access the socket body
                                        /**< \todo we don't need body(), we should better provide a
                                             handle() member which will return a simple FIleHandle
                                             object (we cannot return some other derived class since
                                             we don't know the Protocol or Policy at this point) */
sbund's avatar
sbund committed
        virtual SocketPolicyBase const & policy() const = 0;
                                        ///< Access the policy instance
sbund's avatar
sbund committed
        ///////////////////////////////////////////////////////////////////////////
sbund's avatar
sbund committed
        virtual std::auto_ptr<SocketProtocol> clone() const = 0;
                                        ///< Polymorphically return a copy of this protocol class
                                        /**< This member will create a new copy of the protocol
                                             class on the heap.
                                             \attention This member must be implemented in every \e
                                                 leaf protocol class to return a new instance of the
                                                 appropriate type. */
sbund's avatar
sbund committed
        virtual unsigned available() const = 0;
                                        ///< Return number of bytes available for reading without
                                        ///< blocking
                                        /**< This member will check in a (very, sigh) protocol
tho's avatar
tho committed
                                             dependent way, how many bytes are guaranteed to be
                                             readable from the socket without blocking even if the
                                             socket is blocking. If the socket does not support
                                             reading (viz. NotReadablePolicy is set), this member
                                             should always return \c 0.*/

        virtual bool eof() const = 0;   ///< Check for end-of-file condition
                                        /**< This is another check which (like available()) is
                                             extremely protocol dependent. This member will return
                                             \c true only, if at end-of-file. If the protocol does
                                             not support the notion of EOF, this member should
                                             always return \c false. */

        virtual void close() const;           ///< Close socket
                                        /**< This override will automatically \c shutdown() the
                                             socket whenever it is closed.
                                             \throws senf::SystemException */
        virtual void terminate() const;       ///< Forcibly close socket
                                        /**< This override will automatically \c shutdown() the
                                           socket whenever it is called. Additionally it will
                                           disable SO_LINGER to ensure, that v_terminate will not
                                           block. Like the overriden method, this member will ignore
                                           failures and will never throw. It therefore safe to be
                                           called from a destructor. */

        virtual void state(SocketStateMap & map, unsigned lod) const;
                                        ///< Return socket state information
                                        /**< This member is called to add state information to the
                                             status \a map. The protocol map should provide as
                                             detailed information as possible. The amount of
                                             information to be added to the map is selected by the
                                             \a lod value with a default value of 0. The
                                             interpretation of the \a lod value is completely
                                             implementation defined.

                                             Every class derived from SocketProtocol should
                                             reimplement state(). The reimplemented method should
                                             call (all) baseclass-implementations of this
                                             member.

                                             The \a map Argument is a map which associates
                                             std:string keys with std:string-like values. The map
                                             keys are interpreted as hierarchical strings with '.'
                                             as a separator (like hostnames or struct or class
                                             members). They are automatically sorted correctly.

                                             The values are std:string with one additional feature:
                                             they allow assignment or conversion from *any* type as
                                             long as that type is streamable. This simplifies
                                             assigning non-string values to the map:

                                             \code
                                               map["socket.protocol.ip.address"] = peer();
                                               map["socket.protocol.tcp.backlog"] = backlog();
                                             \endcode

                                             This will work even if peer() returns an ip-address
                                             object or backlog() returns an integer. The values are
                                             automatically converted to their string representation.

                                             The operator "+=" also has been reimplemented to
                                             simplify adding multiple values to a single entry: It
                                             will automatically add a ", " separator if the string
                                             is non-empty. */
sbund's avatar
sbund committed

    protected:

    private:
        // backpointer to owning SocketBody instance
        SocketBody * body_;
        friend class SocketBody;
sbund's avatar
sbund committed

    /** \brief Concrete Socket Protocol implementation base class

        ConcreteSocketProtocol is the base class of a concrete socket protocol implementation. The
        final protocol class must inherit from ConcreteSocketProtocol. The template argument \a
        SocketPolicy must be set to the complete socket policy of the protocol.

        A protocol implementation may define the protocol interface directly. It can also
tho's avatar
tho committed
        (additionally) make use of multiple inheritance to combine a set of protocol facets into a
        specific protocol implementation (i.e. TCPv4SocketProtocol inherits from
        ConcreteSocketProtocol and from the protocol facets IPv4Protocol, TCPProtocol,
        BSDSocketProtocol and AddressableBSDSocketProtocol). The protocol facets are not concrete
        protocols themselves, they are combined to build concrete protocols. This structure will
        remove a lot of code duplication. It is important to ensure, that the protocol facets do not
        overlap, since otherwise there will be problems resolving overlapping members.
tho's avatar
tho committed
        
        \doc init_client init_server
sbund's avatar
sbund committed
    template <class SocketPolicy>
    class ConcreteSocketProtocol
        : public virtual SocketProtocol
sbund's avatar
sbund committed
    {
    public:
        ///////////////////////////////////////////////////////////////////////////
        // Types

        typedef SocketPolicy Policy;    ///< The protocols policy
sbund's avatar
sbund committed

        ///////////////////////////////////////////////////////////////////////////
        ///\name Structors and default members
        ///@{

        ~ConcreteSocketProtocol() = 0;

        // no default constructor
        // no copy
        // no conversion constructors

        ///@}
        ///////////////////////////////////////////////////////////////////////////

        Policy const & policy() const;

    protected:

    private:
        Policy policy_;

    };

sbund's avatar
sbund committed

///////////////////////////////hh.e////////////////////////////////////////
#include "SocketProtocol.cci"
//#include "SocketProtocol.ct"
#include "SocketProtocol.cti"
#endif


// Local Variables:
// mode: c++
// fill-column: 100
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// comment-column: 40
sbund's avatar
sbund committed
// End: