Packets: Fix VariantParser invalid parser access bug
[senf.git] / Socket / SocketProtocol.hh
index 165d668..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>
+// 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
 
 /** \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.
  */
 
-// The private inheritance idea should indeed work very well: We just need to chnage the
+// 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
 
 /** \defgroup protocol_group The Protocol Classes
 
-    \image html Protocols.png
+     <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
     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
         \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)
     accessibility of the socket body from all facets.
  */
 
-#ifndef HH_SocketProtocol_
-#define HH_SocketProtocol_ 1
+#ifndef HH_SENF_Socket_SocketProtocol_
+#define HH_SENF_Socket_SocketProtocol_ 1
 
 // 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"
@@ -103,14 +108,15 @@ namespace senf {
 
     class SocketPolicyBase;
 
-    /** \brief Socket protocol base class
+    /** \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
+    class SocketProtocol 
+        : boost::noncopyable
     {
     public:
         ///////////////////////////////////////////////////////////////////////////
@@ -130,31 +136,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
-                                             deqpendent way, how many bytes are guarateed 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 +167,22 @@ 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 
+                                             \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
@@ -171,7 +192,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,51 +203,75 @@ 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 SPolicy> class ClientSocketHandle;
+    template <class SPolicy> class ServerSocketHandle;
 
-    /** \brief Concrete socket protocol implementation base class
+    /** \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.
+        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
-        (additnally) make use of multiple inheritance to combine a set of protocol facets into a
+        (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,
+        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>
+    template <class SocketPolicy, class Self>
     class ConcreteSocketProtocol
         : public virtual SocketProtocol
     {
@@ -250,12 +295,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_;
     };
 
     /// @}
@@ -274,4 +330,6 @@ namespace senf {
 // c-file-style: "senf"
 // indent-tabs-mode: nil
 // ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
 // End: