From 018890632a9a319335b03ccf4b5c5f3b9adf9109 Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Mon, 16 Jul 2007 19:21:05 +0000
Subject: [PATCH] Packets: BUGFIX: ensure complete interpreter chain in
 finalize() Packets: documentation: Mainpage, Packet, ConcretePacket Packets:
 Remove uneeded typedefs from public interface Packets/DefaultBundle: Move all
 documentation into special group doclib: Add special formating for
 implementation notes

---
 Packets/DefaultBundle/DefaultBundle.dox |  46 +++
 Packets/DefaultBundle/EthernetPacket.hh |   5 +
 Packets/DefaultBundle/IpV4Packet.hh     |   6 +-
 Packets/DefaultBundle/IpV6Extensions.hh |   5 +
 Packets/DefaultBundle/IpV6Packet.hh     |   4 +
 Packets/DefaultBundle/UDPPacket.hh      |   7 +-
 Packets/Doxyfile                        |   3 +-
 Packets/Mainpage.dox                    | 109 ++----
 Packets/Packet.cci                      |   1 +
 Packets/Packet.cti                      |   2 +-
 Packets/Packet.hh                       | 438 +++++++++++++++++++++---
 Packets/Packet.test.cc                  |   6 +-
 Packets/structure.dia                   | Bin 3580 -> 3794 bytes
 doclib/html-munge.xsl                   |   8 +-
 doclib/senf.css                         |  51 +--
 15 files changed, 528 insertions(+), 163 deletions(-)
 create mode 100644 Packets/DefaultBundle/DefaultBundle.dox

diff --git a/Packets/DefaultBundle/DefaultBundle.dox b/Packets/DefaultBundle/DefaultBundle.dox
new file mode 100644
index 000000000..5891ca81d
--- /dev/null
+++ b/Packets/DefaultBundle/DefaultBundle.dox
@@ -0,0 +1,46 @@
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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
+// 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.
+
+/** \defgroup protocolbundles Protocol Bundles
+
+    Each protocol bundle provides a collection of related concrete packet classes for a group of
+    related protocols.    
+ */
+
+/** \defgroup protocolbundle_default The Default Bundle
+
+    The default bundle combines a set of basic low level protocols like Ethernet or IP.
+
+    \ingroup protocolbundles
+ */
+
+
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// mode: flyspell
+// mode: auto-fill
+// ispell-local-dictionary: "american"
+// End:
diff --git a/Packets/DefaultBundle/EthernetPacket.hh b/Packets/DefaultBundle/EthernetPacket.hh
index f01dab2b1..126748896 100644
--- a/Packets/DefaultBundle/EthernetPacket.hh
+++ b/Packets/DefaultBundle/EthernetPacket.hh
@@ -36,6 +36,9 @@
 
 namespace senf {
 
+    ///\addtogroup protocolbundle_default
+    ///@{
+
     struct MACAddress
         : boost::array<PacketParserBase::byte,6>
     {
@@ -146,6 +149,8 @@ namespace senf {
     };
 
     typedef EthVLanPacketType::packet EthVLanPacket;
+
+    ///@}
 }
 
 
diff --git a/Packets/DefaultBundle/IpV4Packet.hh b/Packets/DefaultBundle/IpV4Packet.hh
index a38b59d42..e8879a2e1 100644
--- a/Packets/DefaultBundle/IpV4Packet.hh
+++ b/Packets/DefaultBundle/IpV4Packet.hh
@@ -1,4 +1,4 @@
-// $Id$
+// $Id: IpV4Packet.hh 307 2007-07-14 21:31:12Z g0dil $
 //
 // Copyright (C) 2006
 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
@@ -34,6 +34,9 @@
 
 namespace senf {
 
+    ///\addtogroup protocolbundle_default
+    ///@{
+
     struct Parse_IpV4 : public PacketParserBase
     {
         SENF_PACKET_PARSER_NO_INIT(Parse_IpV4);
@@ -98,6 +101,7 @@ namespace senf {
         
     typedef IpV4PacketType::packet IpV4Packet;
 
+    ///@}
 }
 
 
diff --git a/Packets/DefaultBundle/IpV6Extensions.hh b/Packets/DefaultBundle/IpV6Extensions.hh
index 79cc42acd..348a1a586 100644
--- a/Packets/DefaultBundle/IpV6Extensions.hh
+++ b/Packets/DefaultBundle/IpV6Extensions.hh
@@ -32,6 +32,9 @@
 
 namespace senf {
 
+    ///\addtogroup protocolbundle_default
+    ///@{
+
     // See RFC2460
     struct Parse_IpV6Extension_Fragment : public PacketParserBase
     {
@@ -74,6 +77,8 @@ namespace senf {
     };
 
     typedef IpV6ExtensionType_Fragment::packet IpV6Extension_Fragment;
+
+    ///@}
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
diff --git a/Packets/DefaultBundle/IpV6Packet.hh b/Packets/DefaultBundle/IpV6Packet.hh
index b40ab927a..0f1aafbf9 100644
--- a/Packets/DefaultBundle/IpV6Packet.hh
+++ b/Packets/DefaultBundle/IpV6Packet.hh
@@ -37,6 +37,9 @@
 
 namespace senf {
 
+    ///\addtogroup protocolbundle_default
+    ///@{
+
     // See RFC2460
     struct Parse_IpV6 : public PacketParserBase
     {
@@ -88,6 +91,7 @@ namespace senf {
 
     typedef IpV6PacketType::packet IpV6Packet;
 
+    ///@}
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
diff --git a/Packets/DefaultBundle/UDPPacket.hh b/Packets/DefaultBundle/UDPPacket.hh
index 047dc222b..26485486f 100644
--- a/Packets/DefaultBundle/UDPPacket.hh
+++ b/Packets/DefaultBundle/UDPPacket.hh
@@ -1,4 +1,4 @@
-// $Id$
+// $Id: UDPPacket.hh 308 2007-07-14 22:31:20Z g0dil $
 //
 // Copyright (C) 2006
 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
@@ -34,6 +34,9 @@
 
 namespace senf {
 
+    ///\addtogroup protocolbundle_default
+    ///@{
+
     // See RFC768
     struct Parse_UDP : public PacketParserBase
     {
@@ -66,6 +69,8 @@ namespace senf {
     };
 
     typedef UDPPacketType::packet UDPPacket;
+
+    ///@}
 }
 
 
diff --git a/Packets/Doxyfile b/Packets/Doxyfile
index 51fe456a3..0bacd5bf8 100644
--- a/Packets/Doxyfile
+++ b/Packets/Doxyfile
@@ -3,5 +3,4 @@
 PROJECT_NAME = libPackets
 TAGFILES = "$(TOPDIR)/Utils/doc/Utils.tag"
 GENERATE_TAGFILE = doc/Packets.tag
-#INPUT = . DefaultBundle RTPBundle
-INPUT = .
\ No newline at end of file
+INPUT = . DefaultBundle
diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox
index 44ba81f45..bb4aa52a1 100644
--- a/Packets/Mainpage.dox
+++ b/Packets/Mainpage.dox
@@ -2,104 +2,37 @@
 
     \section arch Overall Architecture
 
-    The general Architecture of the Packet Framework (pkf for short)
-    is seperated into two components: The basic packet handling and
-    the parser framework.
-
-    The basic packet handling implements a packet interpreter
-    chain. Every packet is represented as a chain of interpreters
-    where each interpreter is a facade looking into the same
-    packet. Each interpreter will interpret a specific header of a
-    packet. For example, an ethernet frame might have an interpreter
-    chain consisting of EthernetPacket, IPPacket, UDPPacket and
-    DataPacket. Each of these interpreters will interpret a section of
-    the raw data bytes. The interpreter ranges overlap since every
-    packet also includes it's payload.
-
-    The parser framework is used to interpret the raw bytes of a
-    specific packet and parse the values present in that packet. For
-    example, Parse_Ethernet will parse the ethernet source MAC,
-    destination MAC and ethertype given any random access iterator to
-    the first byte of the ethernet frame. Parsers are extremely light
-    classes. They are temporary classes passed around by value. In
-    most cases, they are just comprised of a single pointer adorned
-    with type information.
-
-    \section handling Packet Handling
-
-    The packet handling is implemented within
-    senf::Packet. This class is the baseclass to all packet
-    interpreter facades. To implement a new packet type, publically
-    derive from senf::Packet and implement the virtual
-    interface (see the class documentation for details).
-
-    \section framework Parser Framework
-
-    The parser framework provides an abstract framwork to parse packet
-    oriented data. A Parser is a template class taking an arbitrary
-    iterator as input and allowing random access to data elements of
-    the interpreted type, like source and destination MAC of an
-    ethernet frame. The parser framework is to be used hierarchically
-    and recursively, the parser methods should return further parsers
-    which can return further parsers and so on.
+    The Packet library consists of several components:
+    
+    \li The \ref packet_module manages the packet data and provides the framework for handling the
+        chain of packet headers. The visible interface is provided by the Packet class.
+    \li \ref packetparser provides the framework for interpreting packet data. It handles
+        parsing the packet information into meaningful values.
+    \li The \ref protocolbundles provide concrete implementations for interpreting packets of
+        some protocol. The Protocol Bundles are built on top of the basic packet library.
+ */
 
-    The parser framework contains some basic parsers to be used to
-    build up more complex parsers:
+/*    
 
-     - ParseInt.hh: Lots of parsers for integer numbers like
-       senf::Parse_UInt8, for integer bitfields like
-       senf::Parse_UIntField and senf::Parse_Flag to
-       parse boolean flags.
+     - ParseInt.hh: Lots of parsers for integer numbers like senf::Parse_UInt8, for integer
+       bitfields like senf::Parse_UIntField and senf::Parse_Flag to parse boolean flags.
 
-     - ParseArray.hh: The senf::Parse_Array parser to parse
-       arbitrary fixed-size arrays of fixed-size elements (that is
-       sub-parsers).
+     - ParseArray.hh: The senf::Parse_Array parser to parse arbitrary fixed-size arrays of
+       fixed-size elements (that is sub-parsers).
 
-     - ParseVec.hh: The senf::Parse_Vector parser to parse
-       dynamically sized arrays of fixed-size elements (that is
-       sub-parsers).
+     - ParseVec.hh: The senf::Parse_Vector parser to parse dynamically sized arrays of fixed-size
+       elements (that is sub-parsers).
 
     See senf::ParserBase for further information.
 
     \section stuff Other Utilities
 
-    The pkf also comprises some additional utilities to support the
-    development of packet classes.
-
-    The senf::PacketRegistry implements a registry of packets
-    keyed by an arbitrary type. The registry is used to find a packet
-    type given some kind of id (like the ethertype value from the
-    ethernet header). Together with it's support classes (especially
-    senf::PacketRegistryMixin) this class greatly simplifies
-    implementing the needed table lookups.
-
-    \todo The Packet Libarary really needs a refactoring of the public
-        interfaface ...
-
-    \idea Add the Handle-Body idiom to the mix with a PacketRef (or
-        HeaderRef or InterpreterRef or whatever class). This would
-        have members for all the API defined in Packet now. \c
-        operator-> would return a parser object to interpret the
-        data. This would make awayy with the inheritance relationship
-        ...
-
-    \idea Templating the parsers on the iterator type does not
-        introduce additional coupling (because of the inlining) but
-        looking at it after the fact it looks like severe overdesign
-        and it does introduce some problems (e.g. rebind and all this
-        entails). If we just implement all parsers for
-        Packet::byte_iterator they are no tmplates any more which
-        should simplify things a log.
+    The pkf also comprises some additional utilities to support the development of packet classes.
 
-    \idea we need some better and automatic checking on data access
-        especially after data has changed. Idea 1: give the parser the
-        end iterator as additional member. Enforce, that all parsers
-        must ultimately be based on ParseInt and have ParseInt check
-        against end() at construction time. Idea 2: add a dirty flag
-        to the interpreters. Set this flag whenever the packet is
-        changed and recall check() in operator-> of the PacketRef
-        object if the packet is dirty. Maybe we need both and make
-        them tunable.
+    The senf::PacketRegistry implements a registry of packets keyed by an arbitrary type. The
+    registry is used to find a packet type given some kind of id (like the ethertype value from the
+    ethernet header). Together with it's support classes (especially senf::PacketRegistryMixin) this
+    class greatly simplifies implementing the needed table lookups.
  */
 
 
diff --git a/Packets/Packet.cci b/Packets/Packet.cci
index 02e577208..7d2000626 100644
--- a/Packets/Packet.cci
+++ b/Packets/Packet.cci
@@ -106,6 +106,7 @@ prefix_ bool senf::Packet::operator==(Packet other)
 prefix_ void senf::Packet::finalize()
     const
 {
+    last(); // Make sure the packet is complete
     ptr()->finalize();
 }
 
diff --git a/Packets/Packet.cti b/Packets/Packet.cti
index 532c3b07b..a7d5a1500 100644
--- a/Packets/Packet.cti
+++ b/Packets/Packet.cti
@@ -263,7 +263,7 @@ senf::ConcretePacket<PacketType>::clone()
 // Field access
 
 template <class PacketType>
-prefix_ typename senf::ConcretePacket<PacketType>::interpreter::parser *
+prefix_ typename senf::ConcretePacket<PacketType>::type::parser *
 senf::ConcretePacket<PacketType>::operator->()
     const
 {
diff --git a/Packets/Packet.hh b/Packets/Packet.hh
index ae2c66e4e..0ef0cfdcb 100644
--- a/Packets/Packet.hh
+++ b/Packets/Packet.hh
@@ -36,9 +36,98 @@
 
 namespace senf {
 
+    /** \defgroup packet_module Packet Handling
+
+        The basic groundwork of the Packet library is the packet handling:
+
+        \li The packet classes provide access to a chain of packet headers (more generically called
+            interpreters).
+        \li They automatically manage the required memory resources and the shared packet data.
+
+        \section packet_module_chain The Interpreter Chain
+
+        The central data structure for a packet is the interpreter chain
+
+        \image html structure.png The Interpreter Chain
+
+        This image depicts a packet with several headers. Each interpreter is responsible for a
+        specific sub-range of the complete packet. This range always \e includes the packets payload
+        (This is, why we call the data structure interpreter and not header: The interpreter is
+        responsible for interpreting a range of the packet according to a specific protocol), the
+        packet interpreters are nested inside each other.
+    
+        For each interpreter, this structure automatically divides the packet into three areas (each
+        of which are optional): The header, the payload and the trailer. Every packet will have
+        either a header or a payload section while most don't have a trailer.
+
+        As user of the library you always interact with the chain through one (or more) of the
+        interpreters. The interpreter provides methods to traverse to the following or preceding
+        header (interpreter) and provides two levels of access to the packet data: Generic low-level
+        access in the form of an STL compatible sequence and access to the parsed fields which are
+        provided by the parser associated with the concrete packet type.
+
+        \section packet_module_management Resource Management
+
+        The interface to the packet library is provided using a handle class (\ref Packet for
+        generic, protocol agnostic access and \ref ConcretePacket derived from \ref Packet to access
+        a specific protocol). This handle automatically manages the resources associated with the
+        packet (the interpreter chain and the data storage holding the packet data). The resources
+        are automatically released when the last packet handle referencing a specific packet is
+        destroyed.
+
+        \implementation The packet chain is provided on two levels: The internal representation \ref
+            PacketInterpreterBase and \ref PacketInterpreter which are referenced by the Handle
+            classes \ref Packet and \ref ConcretePacket. \n
+            The internal representation classes are pertinent in the sense, that they exist
+            regardless of the existence of a handle referencing them (as long as the packet
+            exists). Still the interpreter chain is lazy and packet interpreters beside the first
+            are only created dynamically when accessed (this is implemented in the handle not in the
+            internal representation). \n
+            The packet interpreters make use of a pool allocator. This provides extremely efficient
+            creation and destruction of packet interpreter's and removes the dynamic memory
+            management overhead from the packet interpreter management. The packet implementation
+            class (\ref PacketImpl which holds the packet data itself) however is still dynamically
+            managed (however there is only a single instance for each packet).
+     */
+
     template <class PackeType> class ConcretePacket;
+
+    ///\addtogroup packet_module
+    ///@{
     
-    /** \brief
+    /** \brief Main Packet class
+
+        Packet is the main externally visible class of the packet library. Packet is a handle into
+        the internal packet representation. From Packet you may access the data of that specific
+        sub-packet/header/interpreter and navigate to the neighboring
+        sub-packets/headers/interpreters.
+
+        Packet is protocol agnostic. This class only provides non-protocol dependent members. To
+        access the protocol specific features of a packet (like header fields) the ConcretePacket
+        class extending Packet is povided.
+
+        \section packet_semantics Semantics
+        
+        All operations accessing the data of \c this packet in some way will ignore any preceding
+        packets/headers/interpreters in the chain. It does not matter, whether a given packet is
+        taken from the middle or the beginning of the chain, all operations (except those explicitly
+        accessing the chain of course) should work the same.
+        
+        This especially includes members like clone() or append(): clone() will clone \e only from
+        \c this packet until the end of the chain, append() will append the given packet \e ignoring
+        any possibly preceding packets/headers/interpreters.
+
+        In the same way, the data() member provides an STL-sequence compatible view of the packet
+        data. This only includes the data which is part of \c this packet including header, trailer
+        \e and payload but \e not the headers or trailers of packets \e before \c this packet in the
+        packet/header/interpreter chain (nonetheless, this data overlaps with the data of other
+        packets).
+
+        Several members are member templates taking an \a OtherPacket template parameter. This
+        parameter must be the ConcretePacket instantiation associated with some concrete packet type
+        (protocol). For each implemented protocol, typedefs should be provided for these
+        instantiations (Example: \ref EthernetPacket is a typedef for
+        \ref ConcretePacket < \ref EthernetPacketType >).
       */
     class Packet
         : public SafeBool<Packet>,
@@ -48,15 +137,13 @@ namespace senf {
         ///////////////////////////////////////////////////////////////////////////
         // Types
         
-        typedef void type;
-        typedef senf::detail::packet::iterator iterator;
-        typedef senf::detail::packet::const_iterator const_iterator;
-        typedef senf::detail::packet::size_type size_type;
-        typedef senf::detail::packet::difference_type difference_type;
-        typedef senf::detail::packet::byte byte;
-        typedef PacketInterpreterBase::factory_t factory_t;
+        typedef void type;              ///< Type of the packet.
+        typedef senf::detail::packet::size_type size_type; ///< Unsigned type to represent packet size
+        typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
 
-        enum NoInit_t { noinit };
+                                        /// Special argument flag
+                                        /** Used in some ConcretePacket constructors */
+        enum NoInit_t { noinit };       
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -66,13 +153,23 @@ namespace senf {
         // default copy assignment
         // default destructor
         
-        Packet();
-        Packet clone() const;
+        Packet();                       ///< Create uninitialized packet handle
+                                        /**< An uninitialized handle is not valid(). It does not
+                                             allow any operation except assignment and checking for
+                                             validity. */
+        Packet clone() const;           ///< Create copy packet
+                                        /**< clone() will create a complete copy the packet. The
+                                             returned packet will have the same data and packet
+                                             chain. It does however not share any data with the
+                                             original packet. */
 
         // conversion constructors
 
-        template <class PacketType>
-        Packet(ConcretePacket<PacketType> packet);
+        template <class PacketType>     
+        Packet(ConcretePacket<PacketType> packet); ///< Copy-construct Packet from ConcretePacket
+                                        /**< This constructor allows to convert an arbitrary
+                                             ConcretePacket into a general Packet, loosing the
+                                             protocol specific interface. */
 
         ///@}
         ///////////////////////////////////////////////////////////////////////////
@@ -80,56 +177,180 @@ namespace senf {
         ///\name Interpreter chain access
         ///@{
 
-                                     Packet      next() const;
-        template <class OtherPacket> OtherPacket next() const;
-        template <class OtherPacket> OtherPacket next(NoThrow_t) const;
+                                     Packet      next() const; 
+                                        ///< Get next packet in chain
+        template <class OtherPacket> OtherPacket next() const; 
+                                        ///< Get next packet of given type in chain
+                                        /**< \throws InvalidPacketChainException if no such packet
+                                             is found */
+        template <class OtherPacket> OtherPacket next(NoThrow_t) const; 
+                                        ///< Get next packet of given type in chain
+                                        /**< \param[in] nothrow This argument always has the value
+                                             \c senf::nothrow
+                                             \returns in-valid() packet, if no such packet is found */
         template <class OtherPacket> OtherPacket findNext() const;
+                                        ///< Find next packet of given type in chain
+                                        /**< findNext() is like next(), it will however return \c
+                                             *this if it is of the given type. 
+                                             \throws InvalidPacketChainException if no such packet
+                                                 is found */
         template <class OtherPacket> OtherPacket findNext(NoThrow_t) const;
+                                        ///< Find next packet of given type in chain
+                                        /**< findNext() is like next(), it will however return \c
+                                             *this if it is of the given type.
+                                             \param[in] nothrow This argument always has the value
+                                             \c senf::nothrow
+                                             \returns in-valid() packet, if no such packet is found */
+        
 
-                                     Packet      prev() const;
-        template <class OtherPacket> OtherPacket prev() const;
+                                     Packet      prev() const; 
+                                        ///< Get previous packet in chain
+        template <class OtherPacket> OtherPacket prev() const; 
+                                        ///< Get previous packet of given type in chain
+                                        /**< \throws InvalidPacketChainException if no such packet
+                                             is found */
         template <class OtherPacket> OtherPacket prev(NoThrow_t) const;
+                                        ///< Get previous packet of given type in chain
+                                        /**< \param[in] nothrow This argument always has the value
+                                             \c senf::nothrow
+                                             \returns in-valid() packet, if no such packet is found */
         template <class OtherPacket> OtherPacket findPrev() const;
+                                        ///< Find previous packet of given type in chain
+                                        /**< findPrev() is like prev(), it will however return \c
+                                             *this if it is of the type 
+                                             \throws InvalidPacketChainException if no such packet
+                                                 is found */
         template <class OtherPacket> OtherPacket findPrev(NoThrow_t) const;
+                                        ///< Find previous packet of given type in chain
+                                        /**< findPrev() is like prev(), it will however return \c
+                                             *this if it is of the type 
+                                             \param[in] nothrow This argument always has the value
+                                             \c senf::nothrow
+                                             \returns in-valid() packet, if no such packet is found */
+
 
                                      Packet      first() const;
+                                        ///< Return first packet in chain
         template <class OtherPacket> OtherPacket first() const;
+                                        ///< Return first packet of given type in chain
+                                        /**< \throws InvalidPacketChainException if no such packet
+                                             is found */
         template <class OtherPacket> OtherPacket first(NoThrow_t) const;
+                                        ///< Return first packet of given type in chain
+                                        /**< \param[in] nothrow This argument always has the value
+                                             \c senf::nothrow
+                                             \returns in-valid() packet, if no such packet is found */
 
                                      Packet      last() const;
+                                        ///< Return last packet in chain
         template <class OtherPacket> OtherPacket last() const;
+                                        ///< Return last packet of given type in chain
+                                        /**< \throws InvalidPacketChainException if no such packet
+                                             is found */
         template <class OtherPacket> OtherPacket last(NoThrow_t) const;
+                                        ///< Return last packet of given type in chain
+                                        /**< \param[in] nothrow This argument always has the value
+                                             \c senf::nothrow
+                                             \returns in-valid() packet, if no such packet is found */
 
 
         template <class OtherPacket> OtherPacket parseNextAs() const;
+                                        ///< Parse payload as given by \a OtherPacket and add packet
+                                        /**< parseNextAs() will throw away the packet chain after
+                                             the current packet if necessary. It will then parse the
+                                             payload section of \c this packet as given by \a
+                                             OtherPacket. The new packet is added to the chain after
+                                             \c this.
+                                             \returns new packet instance sharing the same data and
+                                                 placed after \c this packet in the chain. */
                                      Packet      parseNextAs(factory_t factory) const;
+                                        ///< Parse payload as given by \a factory and add packet
+                                        /**< parseNextAs() will throw away the packet chain after
+                                             the current packet if necessary. It will then parse the
+                                             payload section of \c this packet as given by \a
+                                             OtherPacket. The new packet is added to the chain after
+                                             \c this.
+                                             \returns new packet instance sharing the same data and
+                                                 placed after \c this packet in the chain. */
         template <class OtherPacket> bool        is() const;
+                                        ///< Check, whether \c this packet is of the given type
         template <class OtherPacket> OtherPacket as() const;
-
-        Packet append(Packet packet) const;
+                                        ///< Cast current packet to the given type
+                                        /**< This operations returns a handle to the same packet
+                                             header/interpreter however cast to the given
+                                             ConcretePacket type. <b>This conversion is
+                                             unchecked</b>. If the packet really is of a different
+                                             type, this will wreak havoc with the packet
+                                             data-structures. You can validate whether the
+                                             conversion is valid using is(). */
+
+        Packet append(Packet packet) const; ///< Append the given packet to \c this packet
+                                        /**< This operation will replace the payload section of \c
+                                             this packet with \a packet. This operation will replace
+                                             the packet chain after \c this packet with a clone of
+                                             \a packet and will replace the raw data of the payload
+                                             of \c this with the raw data if \a packet.
+                                             \returns Packet handle to the cloned \a packet, placed
+                                                 after \c this in the packet/header/interpreter
+                                                 chain. */
 
         ///@}
 
         ///\name Data access
         ///@{
 
-        PacketData & data() const;
-        size_type size() const;
+        PacketData & data() const;      ///< Access the packets raw data container
+        size_type size() const;         ///< Return size of packet in bytes
+                                        /**< This size does \e not include the size of any preceding
+                                             headers/packets/interpreters. It does however include
+                                             \c this packets payload. */
         
         ///@}
 
         ///\name Other methods
         ///@{
 
-        bool operator==(Packet other) const;
-        bool boolean_test() const;
-
-        void finalize() const;
-
-        void dump(std::ostream & os) const;
+        bool operator==(Packet other) const; ///< Check for packet identity
+                                        /**< Two packet handles compare equal if they really are the
+                                             same packet header in the same packet chain. */
+        bool boolean_test() const;      ///< Check, whether the packet is valid()
+                                        /**< \see valid() */
+        bool valid() const;             ///< Check, whether the packet is valid()
+                                        /**< An in-valid() packet does not allow any operation
+                                             except checking vor validity and assignment. in-valid()
+                                             packets serve the same role as 0-pointers. */
+        
 
-        TypeIdValue typeId() const;
-        factory_t factory() const;
+        void finalize() const;          ///< Update calculated fields
+                                        /**< This call will update all calculated fields of the
+                                             packet after it has been created or changed. This
+                                             includes checksums, payload size fields or other
+                                             fields, which can be set from other information in the
+                                             packet. Each concrete packet type should document,
+                                             which fields are set by finalize().
+
+                                             finalize() will automatically process all
+                                             packets/headers/interpreters from the end of the chain
+                                             backwards up to \c this. */
+
+        void dump(std::ostream & os) const; ///< Write out a printable packet representation
+                                        /**< This method is provided mostly to help debugging packet
+                                             problems. Each concrete packet should implement a dump
+                                             method writing out all fields of the packet in a
+                                             readable reresentation. dump() will call this member
+                                             for each packet/header/interpreter in the chain from \c
+                                             this packet up to the end of the chain. */
+
+        TypeIdValue typeId() const;     ///< Get id of \c this packet
+                                        /**< This value is used e.g. in the packet registry to
+                                             associate packet types with other information.
+                                             \returns A type holding the same information as a
+                                                 type_info object, albeit assignable */
+        factory_t factory() const;      ///< Return factory instance of \c this packet
+                                        /**< The returned factory instance can be used to create new
+                                             packets of the given type without knowing the concrete
+                                             type of the packet. The valid may be stored away for
+                                             later use if needed. */
         
         ///@}
 
@@ -148,7 +369,37 @@ namespace senf {
         friend class ConcretePacket;
     };
 
-    /** \brief
+    /** \brief Protocol specific packet handle
+
+        The ConcretePacket template class extends Packet to provide protocol/packet type specific
+        aspects. These are packet constructors and access to the parsed packet fields.
+
+        The \c PacketType template argument to ConcretePacket is a protocol specific and internal
+        policy class which defines the protocol specific behavior. To access a specific type of
+        packet, the library provides corresponding typedefs of ConcretePacket < \a SomePacketType >
+        (e.g. \ref EthernetPacket as typedef for \ref ConcretePacket < \ref EthernetPacketType >).
+
+        The new members provided by ConcretePacket over packet are mostly comprised of the packet
+        constructors. These come in three major flavors:
+        
+        \li The create() family of constructors will create completely new packets.
+        \li The createAfter() family of constructors will create new packets (with new data for the
+            packet) \e after a given existing packet.
+        \li The createBefore()  family of constructors will create new packets (again with new data)
+            \e before a given existing packet.
+        
+        Whereas create() will create a completely new packet with it's own chain and data storage,
+        createAfter() and createBefore() extend a packet with additional
+        headers/interpreters. createAfter() will set the payload of the given packet to the new
+        packet whereas createBefore() will create a new packet with the existing packet as it's
+        payload. 
+
+        createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
+        replacing any possibly existing data whereas the latter will interpret the already \e
+        existing data as given by the type argument.
+        
+        \see \ref PacketTypeBase for a specification of the interface to be provided by the \a
+            PacketType policy class.
       */
     template <class PacketType>
     class ConcretePacket 
@@ -159,7 +410,6 @@ namespace senf {
         // Types
         
         typedef PacketType type;
-        typedef PacketInterpreter<PacketType> interpreter;
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -170,34 +420,122 @@ namespace senf {
         // default destructor
         // no conversion constructors
 
-        ConcretePacket();
+        ConcretePacket();               ///< Create uninitialized packet handle
+                                        /**< An uninitialized handle is not valid(). It does not
+                                             allow any operation except assignment and checking for
+                                             validity. */
 
-        static factory_t factory();
+        static factory_t factory();     ///< Return factory for packets of specific type
+                                        /**< This \e static member is like Packet::factory() for a
+                                             specific packet of type \a PacketType */
 
         // Create completely new packet
 
-        static ConcretePacket create();
-        static ConcretePacket create(NoInit_t);
-        static ConcretePacket create(size_type size);
-        static ConcretePacket create(size_type size, NoInit_t);
+        static ConcretePacket create(); ///< Create default initialized packet
+                                        /**< The packet will be initialized to it's default empty
+                                             state. */
+        static ConcretePacket create(NoInit_t); ///< Create uninitialized empty packet
+                                        /**< This will create a completely empty and uninitialized
+                                             packet with <tt>size() == 0</tt>.
+                                             \param[in] noinit This parameter must always have the
+                                                 value \c senf::noinit. */
+        static ConcretePacket create(size_type size); ///< Create default initialized packet
+                                        /**< This member will create a default initialized packet
+                                             with the given size. If the size parameter is smaller
+                                             than the minimum allowed packet size an exception will
+                                             be thrown.
+                                             \param[in] size Size of the packet to create in bytes.
+                                             \throws TruncatedPacketException if \a size is smaller
+                                                 than the smallest permissible size for this type of
+                                                 packet. */
+        static ConcretePacket create(size_type size, NoInit_t); ///< Create uninitialized packet
+                                        /**< Creates an uninitialized (all-zero) packet of the exact
+                                             given size. 
+                                             \param[in] size Size of the packet to create in bytes
+                                             \param[in] noinit This parameter must always have the
+                                                 value \c senf::noinit. */
         template <class ForwardReadableRange>
-        static ConcretePacket create(ForwardReadableRange const & range);
+        static ConcretePacket create(ForwardReadableRange const & range); 
+                                        ///< Create packet from given data
+                                        /**< The packet will be created from a copy of the given
+                                             data. The data from the range will be copied directly
+                                             into the packet representation. The data will \e not be
+                                             validated in any way.
+                                             \param[in] range <a
+                                                 href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
+                                                 of data to construct packet from. */
 
         // Create packet as new packet after a given packet
 
-        static ConcretePacket createAfter(Packet packet);
+        static ConcretePacket createAfter(Packet packet); 
+                                        ///< Create default initialized packet after \a packet
+                                        /**< The packet will be initialized to it's default empty
+                                             state. It will be appended as next header/interpreter
+                                             after \a packet in that packets interpreter chain.
+                                             \param[in] packet Packet to append new packet to. */
         static ConcretePacket createAfter(Packet packet, NoInit_t);
+                                        ///< Create uninitialized empty packet after\a packet
+                                        /**< This will create a completely empty and uninitialized
+                                             packet with <tt>size() == 0</tt>. It will be appended
+                                             as next header/interpreter after \a packet in that
+                                             packets interpreter chain.
+                                             \param[in] packet Packet to append new packet to.
+                                             \param[in] noinit This parameter must always have the
+                                                 value \c senf::noinit. */
         static ConcretePacket createAfter(Packet packet, size_type size);
+                                        ///< Create default initializzed packet after \a packet
+                                        /**< This member will create a default initialized packet
+                                             with the given size. If the size parameter is smaller
+                                             than the minimum allowed packet size an exception will
+                                             be thrown. It will be appended as next
+                                             header/interpreter after \a packet in that packets
+                                             interpreter chain.
+                                             \param[in] packet Packet to append new packet to.
+                                             \param[in] size Size of the packet to create in bytes.
+                                             \throws TruncatedPacketException if \a size is smaller
+                                                 than the smallest permissible size for this type of
+                                                 packet. */
         static ConcretePacket createAfter(Packet packet, size_type size, NoInit_t);
+                                        ///< Create uninitialized packet after \a packet
+                                        /**< Creates an uninitialized (all-zero) packet of the exact
+                                             given size.  It will be appended as next
+                                             header/interpreter after \a packet in that packets
+                                             interpreter chain.
+                                             \param[in] packet Packet to append new packet to.
+                                             \param[in] size Size of the packet to create in bytes
+                                             \param[in] noinit This parameter must always have the
+                                                 value \c senf::noinit. */
         template <class ForwardReadableRange>
         static ConcretePacket createAfter(Packet packet, 
                                           ForwardReadableRange const & range);
+                                        ///< Create packet from given data after \a packet
+                                        /**< The packet will be created from a copy of the given
+                                             data. The data from the range will be copied directly
+                                             into the packet representation. The data will \e not be
+                                             validated in any way.  It will be appended as next
+                                             header/interpreter after \a packet in that packets
+                                             interpreter chain.
+                                             \param[in] packet Packet to append new packet to.
+                                             \param[in] range <a
+                                                 href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
+                                                 of data to construct packet from. */
 
         // Create packet as new packet (header) before a given packet
 
-        static ConcretePacket createBefore(Packet packet);
+        static ConcretePacket createBefore(Packet packet); 
+                                        ///< Create default initialized packet before \a packet
+                                        /**< The packet will be initialized to it's default empty
+                                             state. It will be prepended as previous
+                                             header/interpreter before \a packet in that packets
+                                             interpreter chain.
+                                             \param[in] packet Packet to prepend new packet to. */
         static ConcretePacket createBefore(Packet packet, NoInit_t);
-
+                                        ///< Create uninitialized empty packet before \a packet
+                                        /**< Creates a completely empty and uninitialized packet. It
+                                             will be prepended as previous header/interpreter before
+                                             \a packet in that packets interpreter chain.
+                                             \param[in] packet Packet to prepend new packet to. */
+        
         // Create a clone of the current packet
 
         ConcretePacket clone() const;
@@ -207,11 +545,23 @@ namespace senf {
 
         // Field access
 
-        typename interpreter::parser * operator->() const;
+        typename type::parser * operator->() const; ///< Access packet fields
+                                        /**< This operator allows to access the parsed fields of the
+                                             packet using the notation <tt>packet->field()</tt>. The
+                                             fields of the packet are specified by the PacketType's
+                                             \c parser member. 
+
+                                             The members are not strictly restricted to simple field
+                                             access. The parser class may have any member which is
+                                             needed for full packet access (e.g. checksum validation
+                                             / recreation ...)
+                                             \see \ref packetparser for the parser interface. */
 
     protected:
 
     private:
+        typedef PacketInterpreter<PacketType> interpreter;
+
         ConcretePacket(typename interpreter::ptr packet_);
         
         typename interpreter::ptr ptr() const;
@@ -220,6 +570,8 @@ namespace senf {
         friend class PacketInterpreter<PacketType>;
     };
 
+    ///@}
+
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
diff --git a/Packets/Packet.test.cc b/Packets/Packet.test.cc
index 60b2bd2c4..509039e06 100644
--- a/Packets/Packet.test.cc
+++ b/Packets/Packet.test.cc
@@ -164,8 +164,8 @@ BOOST_AUTO_UNIT_TEST(packet)
 
     BOOST_CHECK( packet.factory() == FooPacket::factory() );
 
-    senf::Packet::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                  0x81, 0x82, 0x83 };
+    senf::PacketData::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                      0x81, 0x82, 0x83 };
 
     BarPacket::createAfter(packet,data);
     BOOST_REQUIRE( packet.next() );
@@ -194,7 +194,7 @@ BOOST_AUTO_UNIT_TEST(packet)
 
 BOOST_AUTO_UNIT_TEST(concretePacket)
 {
-    FooPacket::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+    senf::PacketData::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
 
     BOOST_CHECK_EQUAL( FooPacket::create().size(), 4u );
     BOOST_CHECK_EQUAL( FooPacket::create(FooPacket::noinit).size(), 0u );
diff --git a/Packets/structure.dia b/Packets/structure.dia
index f6ea11fe5968bc8b1d87ba7965db9210d7149a2f..6a316810fdd9a7e7117d2819c36441078f830cc2 100644
GIT binary patch
literal 3794
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

literal 3580
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

diff --git a/doclib/html-munge.xsl b/doclib/html-munge.xsl
index d36e315ad..671373ca5 100644
--- a/doclib/html-munge.xsl
+++ b/doclib/html-munge.xsl
@@ -85,6 +85,12 @@
     </xsl:call-template>
   </xsl:template>
 
+  <xsl:template match="dl[dt/b/text()='Implementation note:']">
+    <xsl:call-template name="add-class">
+      <xsl:with-param name="class">implementation</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+
   <xsl:template match="table[descendant::td[@class='memItemLeft']]">
     <xsl:call-template name="add-class">
       <xsl:with-param name="class">members</xsl:with-param>
@@ -108,7 +114,7 @@
       <xsl:with-param name="class">anchor</xsl:with-param>
     </xsl:call-template>
   </xsl:template>
-
+  
   <!-- Remove [external] references from the modules page -->
   <xsl:template match="div[@id='content2']/ul/li[a/@class='elRef'][a/@doxygen][code/text()='[external]'][not(ul)]">
   </xsl:template>
diff --git a/doclib/senf.css b/doclib/senf.css
index 12a3f3e25..250dadcf7 100644
--- a/doclib/senf.css
+++ b/doclib/senf.css
@@ -2,7 +2,7 @@ body {
         padding: 0;
         margin: 0;
         font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 10pt;
+        font-size: 10pt;
 }
 
 #head {
@@ -21,8 +21,8 @@ body {
 }
 
 #title2 {
-	padding: 0 0 0 42px;
-	max-width: 62em;
+        padding: 0 0 0 42px;
+        max-width: 62em;
         margin: 0 10px 0 0;
 }
 
@@ -40,49 +40,49 @@ body {
         margin: 0 10px 0 100px;
         padding: 4px 0 0 42px;
         height: 18px;
-	max-width: 62em;
+        max-width: 62em;
         background-color: #EDE497;
         color: #726921;
 }
 
 #head h2 {
-	margin: 0;
-	padding: 0;
-	font-size: 13px;
+        margin: 0;
+        padding: 0;
+        font-size: 13px;
         font-weight: normal;
         white-space: nowrap;
 }
 
 #head ul { 
-	display: inline; /* für IE ... */
-	font-size: 13px;
-	height: 0px;
-	margin: 0;
-	padding: 0;
+        display: inline; /* für IE ... */
+        font-size: 13px;
+        height: 0px;
+        margin: 0;
+        padding: 0;
 }
 
 #head li { 
-	list-style-type: none;
-	margin: 0 0 0 10px;
-	padding: 0 10px 0 0;
-	float: right;
-	border-right: 1px solid #726921;
-	height: 14px;
+        list-style-type: none;
+        margin: 0 0 0 10px;
+        padding: 0 10px 0 0;
+        float: right;
+        border-right: 1px solid #726921;
+        height: 14px;
 }
 
 #head li:first-child { 
-	border-right: none;
-	padding: 0;
+        border-right: none;
+        padding: 0;
 }
 
 #head a { 
-	font-weight: normal;
+        font-weight: normal;
         color: #726921;
 }
 
 #head a:hover { 
-	background-color: #EDE497;
-	text-decoration: underline;
+        background-color: #EDE497;
+        text-decoration: underline;
 }
 
 #search {
@@ -308,6 +308,11 @@ div.idea {
         border-left: 10px solid #AAAAAA;
 }
 
+dl.implementation {
+        color: #666666;
+        font-size: 9px;
+}
+
 table {
         width: 100%;
 }
-- 
GitLab