Packets: Fix VariantParser invalid parser access bug
[senf.git] / Socket / SocketProtocol.hh
index 008716e..7590312 100644 (file)
@@ -1,9 +1,9 @@
 // $Id$
 //
-// Copyright (C) 2006 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-//     Stefan Bund <stefan.bund@fokus.fraunhofer.de>
+// Copyright (C) 2006
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.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
 // Free Software Foundation, Inc.,
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
-#ifndef HH_SocketProtocol_
-#define HH_SocketProtocol_ 1
+/** \file
+    \brief SocketProtocol and ConcreteSocketProtocol public header
+ */
+
+// 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
+
+     <div class="diamap" name="Protocols">
+     <span coords="0,0,118,25">\ref SocketProtocol</span>
+     <span coords="139,381,279,407">\ref UNSocketProtocol</span>
+     <span coords="527,412,693,438">\ref PacketSocketProtocol</span>
+     <span coords="214,49,471,86">\ref ConcreteSocketProtocol</span>
+     <span coords="135,112,283,137">\ref BSDSocketProtocol</span>
+     <span coords="114,258,304,284">\ref DatagramSocketProtocol</span>
+     <span coords="136,320,281,346">\ref TCPSocketProtocol</span>
+     <span coords="395,446,604,472">\ref UNDatagramSocketProtocol</span>
+     <span coords="89,189,329,215">\ref AddressableBSDSocketProtocol</span>
+     <span coords="282,481,444,507">\ref TCPv4SocketProtocol</span>
+     </div>
+     \htmlonly <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
+ */
+
+/** \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.
+ */
+
+#ifndef HH_SENF_Socket_SocketProtocol_
+#define HH_SENF_Socket_SocketProtocol_ 1
 
 // Custom includes
 #include <boost/utility.hpp>
-// FIXME: this is really bad. The includes and predefs should be restructured
+// Hrmpf ... I have tried very hard, but I just can't find a nice, generic way to clean
+// up this include
 #include "SocketHandle.ih"
 
 //#include "SocketProtocol.mpp"
 
 namespace senf {
 
+    /// \addtogroup protocol_group
+    /// @{
 
     class SocketPolicyBase;
 
-    class SocketProtocol : boost::noncopyable
+    /** \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
     {
     public:
         ///////////////////////////////////////////////////////////////////////////
@@ -56,26 +136,142 @@ namespace senf {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        SocketBody & body() const;
         virtual SocketPolicyBase const & policy() const = 0;
-        
+        ///< Access the policy instance
+
         ///////////////////////////////////////////////////////////////////////////
         // Virtual interface
 
-        virtual std::auto_ptr<SocketProtocol> clone() const = 0;
         virtual unsigned available() const = 0;
-        virtual bool eof() const = 0;
+                                        ///< Return (maximum) number of bytes available for reading
+                                        ///< without < blocking
+                                        /**< This member will check in a (very, sigh) protocol
+                                             dependent way, how many bytes may be read from a socket
+                                             in a single (non-blocking) read operation. If the
+                                             socket does not support reading (viz. NotReadablePolicy
+                                             is set), this member should always return \c 0.
+                                             
+                                             Depending on the protocol, it may not be possible to
+                                             return a good value. In this case, an upper bound may
+                                             be returned (e.g.: When reading from a socket which
+                                             returns ethernet frames, returning 1500 from
+                                             available() is ok). However, this should only be done
+                                             as a last resort. Also beware, that this number should
+                                             not be too large since the socket layer will always
+                                             need to allocate that number of bytes for the data to
+                                             be read. */
+
+        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 
+                                             \fixme Move into (at least) BSDSOcketProtocol */
+        
+        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 is therefore safe to be
+                                             called from a destructor. 
+                                             \fixme Move into (at least) BSDSocketProtocol */
+
         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.
+                                             
+                                             Additionally, if the slot the date is written to is not
+                                             empty, the <tt>\<\<</tt> operator will add add a comma
+                                             as separator. */
 
     protected:
+        FileHandle fh() const;          ///< Get a FileHandle for this instance
+                                        /**< This member will re turn a FileHandle instance for this
+                                             protocol instance. You may cast this FileHandle
+                                             instance to a ClientSocketHandle / ServerSocketHandle
+                                             as long as you know some of the socket policy using
+                                             static_socket_cast or dynamic_socket_cast */
+
+        int fd() const;                 ///< Get file descriptor
+                                        /**< Returns the file descriptor this protocol instance
+                                             references. This is the same as <tt>fh().fd()</tt> but
+                                             is implemented here since it is needed so often. */
+
+        void fd(int) const;             ///< Initialize file descriptor
+                                        /**< Assigns the file descriptor to the file handle, this
+                                             protocol instance references. Only valid, if the file
+                                             handle has not yet been assigned any descriptor (To
+                                             change the file descriptor association later, use \c
+                                             ::dup2()). */
 
     private:
-        // backpointer to owning SocketBody instance
-        SocketBody * body_;
-        friend class SocketBody; 
-   };
+        virtual std::auto_ptr<SocketBody> clone(bool isServer) const = 0;
+        virtual std::auto_ptr<SocketBody> clone(int fd, bool isServer) const = 0;
+        virtual SocketBody & body() const = 0;
+
+        friend class SocketBody;
+    };
+    
+    template <class SPolicy> class ClientSocketHandle;
+    template <class SPolicy> class ServerSocketHandle;
+
+    /** \brief Concrete Socket Protocol implementation base class
 
-    template <class SocketPolicy>
+        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 Self is the name
+        of the final protocol class which inherits this class.
+
+        A protocol implementation may define the protocol interface directly. It can also
+        (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 IPv4SocketProtocol, TCPSocketProtocol,
+        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.
+        
+        \doc init_client init_server
+     */
+    template <class SocketPolicy, class Self>
     class ConcreteSocketProtocol
         : public virtual SocketProtocol
     {
@@ -83,7 +279,7 @@ namespace senf {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
-        typedef SocketPolicy Policy;
+        typedef SocketPolicy Policy;    ///< The protocols policy
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -99,14 +295,26 @@ namespace senf {
         ///////////////////////////////////////////////////////////////////////////
 
         Policy const & policy() const;
-
+        
     protected:
+        ClientSocketHandle<Policy> clientHandle() const; 
+                                        ///< Get client handle for associated socket
+                                        /**< Returns a client handle for the socket associated with
+                                             this protocol instance */
+        ServerSocketHandle<Policy> serverHandle() const;
+                                        ///< Get server handle for associated socket
+                                        /**< Returns a server handle for the socket associated with
+                                             this protocol instance */
 
     private:
-        Policy policy_;
+        virtual std::auto_ptr<SocketBody> clone(bool isServer) const;
+        virtual std::auto_ptr<SocketBody> clone(int fd, bool isServer) const;
+        virtual SocketBody & body() const;
 
+        Policy policy_;
     };
 
+    /// @}
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
@@ -118,5 +326,10 @@ namespace senf {
 \f
 // 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
 // End: