Socket: Move protocol into the socket body (as private base class) and allow non...
[senf.git] / Socket / SocketProtocol.hh
index 25316de..50301f9 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>
+// 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
 
 /** \defgroup protocol_group The Protocol Classes
 
-    \image html Protocols.png
+    \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
@@ -50,9 +65,9 @@
     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 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.
+    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
 
 // Custom includes
 #include <boost/utility.hpp>
-/** \fixme this is not nice. 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"
@@ -110,7 +126,8 @@ namespace senf {
 
         \attention SocketProtocol must \e always be inherited using public \e virtual inheritance.
      */
-    class SocketProtocol : boost::noncopyable
+    class SocketProtocol 
+        : boost::noncopyable
     {
     public:
         ///////////////////////////////////////////////////////////////////////////
@@ -130,31 +147,30 @@ namespace senf {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        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) */
         virtual SocketPolicyBase const & policy() const = 0;
-                                        ///< Access the policy instance
+        ///< Access the policy instance
 
         ///////////////////////////////////////////////////////////////////////////
         // Virtual interface
 
-        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. */
         virtual unsigned available() const = 0;
-                                        ///< Return number of bytes available for reading without
-                                        ///< blocking
+                                        ///< Return (maximum) number of bytes available for reading
+                                        ///< without < blocking
                                         /**< This member will check in a (very, sigh) protocol
-                                             dependent way, how many bytes are guaranteed to be
-                                             readable from the socket without blocking even if the
-                                             socket is blocking. */
+                                             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
@@ -162,6 +178,20 @@ namespace senf {
                                              \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 is 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
@@ -171,7 +201,7 @@ namespace senf {
                                              \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
@@ -182,34 +212,55 @@ namespace senf {
                                              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();
+                                                 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. */
+                                             
+                                             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 Policy> class ClientSocketHandle;
+    template <class Policy> class ServerSocketHandle;
 
     /** \brief Concrete Socket Protocol implementation base class
 
@@ -228,7 +279,7 @@ namespace senf {
         
         \doc init_client init_server
      */
-    template <class SocketPolicy>
+    template <class SocketPolicy, class Self>
     class ConcreteSocketProtocol
         : public virtual SocketProtocol
     {
@@ -252,12 +303,23 @@ 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_;
     };
 
     /// @}
@@ -276,4 +338,6 @@ namespace senf {
 // c-file-style: "senf"
 // indent-tabs-mode: nil
 // ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
 // End: