PPI: Add missing TargetDgramWriter doku
[senf.git] / Packets / PacketType.hh
index 8e46eec..931ef4b 100644 (file)
@@ -1,6 +1,8 @@
-// Copyright (C) 2007 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// $Id$
+//
+// Copyright (C) 2007
+// 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
@@ -21,8 +23,8 @@
 /** \file
     \brief PacketType public header */
 
-#ifndef HH_PacketType_
-#define HH_PacketType_ 1
+#ifndef HH_SENF_Packets_PacketType_
+#define HH_SENF_Packets_PacketType_ 1
 
 // Custom includes
 #include <iostream>
@@ -36,7 +38,7 @@
 
 namespace senf {
 
-    /** \brief Helper baseclass implementing the PacketType interface
+    /** \brief Helper base-class implementing the PacketType interface
 
         This helper class maybe used when building a new PacketType. It provides a complete default
         implementations of this interface. To define a new PacketType, derive from this class and
@@ -88,7 +90,7 @@ namespace senf {
 
             static void finalize(packet p)
             {
-                // optionally complete the packet by generating autogenerated information
+                // optionally complete the packet by generating auto-generated information
                 // (like checksums)
             }
 
@@ -100,7 +102,9 @@ namespace senf {
         \endcode
 
         You may leave out any one of the members (you should however always define the \c
-        interpreter typedef member)
+        packet typedef member)
+
+        \ingroup packet_module
       */
     struct PacketTypeBase
     {
@@ -124,7 +128,7 @@ namespace senf {
                                         ///< Parser to parser packet fields
                                         /**< This typedef has to be set to the parser of the packet
                                              
-                                             The default is a VoidPacketParser which does not parser
+                                             The default is a VoidPacketParser which does not parse
                                              any field. */
 
         static size_type initSize();
@@ -136,7 +140,7 @@ namespace senf {
         static size_type initHeadSize();
                                         ///< Get size of new (empty) packet header
                                         /**< This function gives the index within a newly created,
-                                             empty packet where a subpacket is to be placed.
+                                             empty packet where a sub-packet is to be placed.
 
                                              The default implementation returns initSize(). 
                                              
@@ -152,7 +156,7 @@ namespace senf {
                                              packet. The new packet will have a size of at least
                                              initSize() but the size may well be larger. It is also
                                              possible for the packet to already have further
-                                             subpackets.
+                                             sub-packets.
 
                                              The default implementation does nothing. */
 
@@ -203,8 +207,8 @@ namespace senf {
         static void dump(packet p, std::ostream & os);
                                         ///< Dump packet data in readable form
                                         /**< The dump() function writes out a complete
-                                             representation of the packet. This is used formost for
-                                             debugging purposes. 
+                                             representation of the packet. This is used for most for
+                                             debugging purposes.
 
                                              The default implementation does nothing. */
     };
@@ -212,68 +216,152 @@ namespace senf {
 
     /** \brief Mixin to provide standard implementations for nextPacketRange and nextPacketType
 
-        This mixin class simplifies the definition of simple packets with fixed-size headers and/or
-        trailers. For this type of Packet, this mixin provides the nextPacketRange() and
-        nextPacketType() members:
+        This mixin class simplifies the definition of simple packets:
+        
+        \li The packets consist of three sections: The header, the payload and an optional trailer.
+        \li If the packet has a trailer, both the header and the trailer must have a fixed size.
+
+        This mixin provides the nextPacketRange() member as well as initSize() and init(). If you
+        additionally provide the optional \a Registry argument, PacketTypeMixin provides a simple
+        implementation of nextPacketType(). 
+
+        When using the PacketTypeMixin, the implementation of a packet is simplified to:
         \code
+        // Here 'SomeRegistryTag' is optional
         struct SimplePacketType 
-            : public senf::PacketTypeBase
-              pyblic senf:PacketTypeMixin<SimplePacketType, SomeRegistryTag>
+            : public senf::PacketTypeBase,
+              public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
         {
-            static interpreter::size_type initSize()
-            {
-                // This member is optional. If it is not defined, 'senf::init_size<parser>::value'
-                // will be returned.
+            typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
+            typedef senf::ConcretePacket<SimplePacketType> packet;
+            typedef SomePacketParser parser;
         
-                // The value returned is the length of the header if initHeadSize() is not defined.
-                // If initHeadSize is defined, this value is the combined size of the header
-                // and trailer while initHeadSize() will return the size of the header only.
-                return packet_size;
+            using mixin::nextPacketRange;
+            using mixin::nextPacketType;  // Only if the optional 'Registry' argument is provided
+            using mixin::initSize;
+            using mixin::init;
+
+            static key_t nextPacketKey(packet p)
+            {
+                // Return the key in the registry under which the next packet
+                // header is to be found. This member must be given if a Registry argument is
+                // passed to the PacketTypeMixin template.
+                return p->typeField();
             }
-        
+
+            static void finalize(packet p)
+            {
+                // Set the type field by querying the type of the next packet. This is an 
+                // optional assignment: If the key is not found, the value returned by 'key'
+                // is an empty optional and the assignment will be skipped.
+                p->typeField << key(p.next(senf::nothrow));
+
+                // optionally complete the packet by generating auto-generated information
+                // (like checksums)
+            }
+
+            static void dump(packet p, std::ostream & os)
+            {
+                // Write out a readable representation of the packet for debug purposes
+            }
+
             static interpreter::size_type initHeadSize()
             {
-                // This member is optional. It returns the header size if the packet has a
+                // This member is optional. It returns the \e fixed header size if the packet has a
                 // trailer.
                 return header_size;
             }
 
-            static registry_key_t nextPacketKey(packet p)
-            {
-                // Return the key in the registry under which the next packet
-                // header is to be found. This member must be given if a Registry argument is
-                // passed to the PacketTypeMixin template.
-                return i.fields().typeField();
+        };
+        \endcode
+
+        Most of the members are optional, which reduces the minimal implementation of a packet to:
+
+        \code
+        struct SimplePacketType 
+            : public senf::PacketTypeBase,
+              public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
+        {
+            typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
+            typedef senf::ConcretePacket<SimplePacketType> packet;
+            typedef SomePacketParser parser;
+        
+            using mixin::nextPacketRange;
+            using mixin::nextPacketType;            
+            using mixin::initSize;
+            using mixin::init;
+
+            // 'typeField()' is one of the fields defined in the parser which holds
+            // the next-header information
+
+            static key_t nextPacketKey(packet p) { return p->typeField(); }
+            static void finalize(packet p)       { p->typeField() << key(p.next(senf::nothrow)); }
+
+            static void dump(packet p) {
+                // should always be implemented although optional
             }
         };
         \endcode
+
+        \ingroup packet_module
      */
     template <class Self, class Registry=void>
     class PacketTypeMixin
     {
     public:
-        typedef typename Registry::key_t registry_key_t;
+        typedef typename Registry::key_t key_t;
+        typedef boost::optional<key_t> optional_key_t;
+
+        static optional_key_t key (Packet const & p); ///< Find key of packet from registry
+                                        /**< key() will query the registry to find the key of the
+                                             given packet. Whereas \c nextPacketKey() as implemented
+                                             by the mixin user will provide the registry key of the
+                                             next packet from information stored in the current
+                                             packets header, the key() member will look up the type
+                                             of packet \a p in the registry and return it's
+                                             key. 
+                                             
+                                             If either \a p is an in - valid() packet or the packet
+                                             type is not found in the registry, the returned
+                                             optional value will be empty. */
+
+        static PacketTypeBase::factory_t lookup (key_t key); ///< Lookup the key in the registry
+                                        /**< lookup() will query the registry and find the factory
+                                             for the given key. If the key cannot be found,
+                                             no_factory() will be returned. */
 
-        static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
-        static PacketInterpreterBase::factory_t      nextPacketType  (Packet p);
+        ///\name PacketType interface implementation
+        ///@{
+
+        static PacketInterpreterBase::optional_range nextPacketRange (Packet const & p);
+        static PacketInterpreterBase::factory_t      nextPacketType  (Packet const & p);
         static PacketInterpreterBase::size_type      initSize        ();
-        static void                                  init            (Packet p);
+        static void                                  init            (Packet const & p);
+        
+        ///@}
     };
 
+#   ifndef DOXYGEN
+
     template <class Self>
     class PacketTypeMixin<Self,void>
     {
     public:
-        static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
+        static PacketInterpreterBase::optional_range nextPacketRange (Packet const & p);
         static PacketInterpreterBase::size_type      initSize        ();
-        static void                                  init            (Packet p);
+        static void                                  init            (Packet const & p);
     };
 
+#   endif
+
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
+#endif
+#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketType_i_)
+#define HH_SENF_Packets_PacketType_i_
 #include "PacketType.cci"
-//#include "PacketType.ct"
+#include "PacketType.ct"
 #include "PacketType.cti"
 #endif
 
@@ -287,3 +375,4 @@ namespace senf {
 // compile-command: "scons -u test"
 // comment-column: 40
 // End:
+