Packets: annotation facility
g0dil [Wed, 1 Oct 2008 21:24:50 +0000 (21:24 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@921 270642c3-0616-0410-b53a-bc976706d245

Packets/Mainpage.dox
Packets/Packet.hh
Packets/Packet.test.cc
Packets/PacketImpl.cc
Packets/PacketImpl.cci
Packets/PacketImpl.cti
Packets/PacketImpl.hh
senf.dict

index cfa8e30..817a455 100644 (file)
@@ -28,7 +28,8 @@
     \autotoc
 
     
-    \section packet_intro_arch Overall Architecture
+    \section packet_intro_arch Introduction
+    \seechapter \ref packet_arch
 
     The Packet library consists of several components:
     
     All these components work together to provide a hopefully simple and intuitive interface to
     packet parsing and creation.
 
-    \see \ref packet_arch
 
-
-    \section packet_intro_usage Using the packet library
+    \section packet_intro_usage Tutorial
+    \seechapter \ref packet_usage 
 
     This chapter discusses the usage of the packet library from a high level view. 
 
-    \see \ref packet_usage 
-
     
-    \section packet_intro_parser Parsing packet data
+    \section packet_intro_api The packet API
 
-    This chapter goes into more detail discussing the usage of packet parsers. 
-    
-    \li categorizing packet parsers
-    \li reading and writing values
-    \li using complex parsers
+    The packet library API is divided into three areas
 
-    \see \ref packetparser
+    \li the \ref senf::PacketData API for accessing the raw data container
+    \li the packet interpreter chain providing \ref packet_module
+    \li and \ref packetparser which provides access to protocol specific packet fields.
 
-    
+   
     \section protocolbundles Supported packet types (protocols)
 
     Each protocol bundle provides a collection of related concrete packet classes for a group of
 
     
     \section packet_intro_new Defining new packet types
+    \seechapter \ref packet_new
 
     The packet library provides the framework which allows to define arbitrary packet types. There
-    is quite some information needed to completely specify a specific type of paceket.
+    is quite some information needed to completely specify a specific type of packet.
 
-    \see \ref packet_new
  */
 
 /** \page packet_arch Overall Packet library Architecture
     udp.first<IPv4Packet>()            // throws InvalidPacketChainException
 
     udp.prev() == ip                   // true
-    udp.prev<EthernetPacket>()         // throws Inv
+    udp.prev<EthernetPacket>()         // throws InvalidPacketChainException
     \endcode
     
     \see \ref packet_module
 
     To access this information, we need to use a protocol specific handle, the senf::ConcretePacket
     which takes as a template argument the specific type of packet to be interpreted. This allows us
-    to easily interpret or create packets. Here an example on how to create a new Etheret / IP / UDP
+    to easily interpret or create packets. Here an example on how to create a new Ethernet / IP / UDP
     / Payload packet interpreter chain:
 
     \code
     Each Record is a composite with the following relevant fields:
 
     <table class="fields">
-    <tr><td>nrSources</td><td>Integer</td><td>Number of sources in this record</td></tr>
+    <tr><td>nrOfSources</td><td>Integer</td><td>Number of sources in this record</td></tr>
     <tr><td>sources</td><td>Vector of IPv6 Addresses</td><td>Multicast sources</td></tr>
     </table>
     
     for (MLDv2ReportPacket::Parser::records_t::container::iterator i (records.begin());
          i != records.end(); ++i) {
         // Allocate a collection wrapper for the multicast address record
-        typedef MLDv2ReportPackte::Parser::records_t::value_type::sources_t Sources;
+        typedef MLDv2ReportPacket::Parser::records_t::value_type::sources_t Sources;
         Sources::container sources (i->sources());
         
         // Iterate over the sources in this record
index 58264f8..e2e3c3f 100644 (file)
@@ -316,9 +316,49 @@ namespace senf {
 
         ///\name Annotations
         ///@{
-        
+
         template <class Annotation>
-        Annotation & annotation();
+        Annotation & annotation();      ///< Get packet annotation
+                                        /**< This member will retrieve an arbitrary packet
+                                             annotation. Every annotation is identified by a unique
+                                             \a Annotation type. This type should \e always be a \c
+                                             struct.
+
+                                             \code
+                                             struct MyAnnotation {
+                                                 int value;
+                                             };
+
+                                             senf::Packet p (...);
+                                            
+                                             p.annotation<MyAnnotation>().value = 1;
+                                             \endcode
+                                             
+                                             Annotations are shared by all headers / interpreters
+                                             within a single packet chain.
+
+                                             If an annotation is \e not a POD type (more
+                                             specifically, if it's constructor or destructor is not
+                                             trivial), the \a Annotation type \e must inherit from
+                                             senf::ComplexAnnotation. Failing to follow this rule
+                                             will result in undefined behavior and will probably
+                                             lead to a program crash.
+
+                                             \code
+                                             struct MyStringAnnotation : senf::ComplexAnnotation {
+                                                 std::string value;
+                                             };
+                                             \endcode
+
+                                             \implementation The annotation system is implemented
+                                                 quite efficiently since annotations are stored
+                                                 within a packet embedded vector of fixed size (the
+                                                 size is determined automatically at runtime by the
+                                                 number of different annotations
+                                                 used). Additionally, non-complex small annotations
+                                                 require no additional memory management (\c new /
+                                                 \c delete).
+                                          */
 
         ///@}
 
index b88993e..8c28f73 100644 (file)
@@ -110,14 +110,22 @@ namespace {
     }
 
     struct IntAnnotation {
-        int value;
+        unsigned value;
+    };
+    
+    struct LargeAnnotation {
+        char value[32];
     };
 
-    struct ComplexAnnotation {
+    struct ComplexAnnotation : senf::ComplexAnnotation
+    {
         std::string s;
         int i;
     };
 
+    struct ComplexEmptyAnnotation : senf::ComplexAnnotation
+    {};
+
 }
 
 BOOST_AUTO_UNIT_TEST(packet)
@@ -125,10 +133,6 @@ BOOST_AUTO_UNIT_TEST(packet)
     senf::Packet packet (FooPacket::create());
     BarPacket::createAfter(packet);
 
-    SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
-    ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
-    ca.s = "dead beef";
-    ca.i = 0x12345678;
     BOOST_REQUIRE( packet );
     BOOST_CHECK( packet.next() );
     BOOST_CHECK( ! packet.next().next(senf::nothrow) );
@@ -247,6 +251,28 @@ BOOST_AUTO_UNIT_TEST(concretePacket)
     BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
 }
 
+BOOST_AUTO_UNIT_TEST(packetAnnotation)
+{
+    senf::Packet packet (FooPacket::create());
+    BarPacket::createAfter(packet);
+
+    ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
+    ca.s = "dead beef";
+    ca.i = 0x12345678;
+    SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
+
+    senf::Packet p2 (packet.next());
+
+    BOOST_CHECK_EQUAL( p2.annotation<IntAnnotation>().value, 0xDEADBEEFu );
+    BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "dead beef" );
+    BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, 0x12345678 );
+
+    BOOST_CHECK( senf::detail::AnnotationIndexer<IntAnnotation>::Small );
+    BOOST_CHECK( ! senf::detail::AnnotationIndexer<LargeAnnotation>::Small );
+    BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexAnnotation>::Small );
+    BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexEmptyAnnotation>::Small );
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 5b5e12f..95b45cd 100644 (file)
@@ -47,8 +47,8 @@ prefix_ senf::detail::PacketImpl::~PacketImpl()
     Annotations::const_iterator const i_end (annotations_.end());
     std::vector<bool>::iterator small (AnnotationIndexerBase::small().begin());
     for (; i != i_end; ++i, ++small)
-        if (! *small && *i)
-            delete *i;
+        if (! *small && i->p)
+            delete i->p;
 }
 
 // This function has a problem being inlined. Somehow, often when calling this, the size of the 
index 9b8a277..1e0cad0 100644 (file)
@@ -72,11 +72,11 @@ prefix_ senf::detail::AnnotationP::~AnnotationP()
 // senf::detail::PacketImpl
 
 prefix_ senf::detail::PacketImpl::PacketImpl()
-    : refcount_(0), annotations_(AnnotationIndexerBase::maxAnnotations, 0)
+    : refcount_(0), annotations_(AnnotationIndexerBase::maxAnnotations)
 {}
 
 prefix_ senf::detail::PacketImpl::PacketImpl(size_type size, byte initValue)
-    : refcount_(0), data_(size,initValue), annotations_(AnnotationIndexerBase::maxAnnotations, 0)
+    : refcount_(0), data_(size,initValue), annotations_(AnnotationIndexerBase::maxAnnotations)
 {}
 
 // rerference/memory management
index 21956f1..1f2d79a 100644 (file)
@@ -50,20 +50,18 @@ prefix_ unsigned senf::detail::AnnotationIndexer<Annotation>::index()
 // senf::detail::GetAnnotation<Annotation,Small>
 
 template <class Annotation, bool Small>
-prefix_ Annotation & senf::detail::GetAnnotation<Annotation,Small>::get(AnnotationP * & p)
+prefix_ Annotation & senf::detail::GetAnnotation<Annotation,Small>::get(AnnotationEntry & e)
 {
-    if (!p)
-        p = new TAnnotationP<Annotation>();
-    return static_cast< TAnnotationP<Annotation>* >(p)->annotation;
+    if (!e.p)
+        e.p = new TAnnotationP<Annotation>();
+    return static_cast< TAnnotationP<Annotation>* >(e.p)->annotation;
 }
 
-/*
 template <class Annotation>
-prefix_ Annotation & senf::detail::GetAnnotation<Annotation, true>::get(AnnotationP * & p)
+prefix_ Annotation & senf::detail::GetAnnotation<Annotation, true>::get(AnnotationEntry & e)
 {
-    return * reinterpret_cast<Annotation*>(p);
+    return * static_cast<Annotation*>(static_cast<void*>(& e.i));
 }
-*/
 
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::PacketImpl
@@ -81,7 +79,7 @@ prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, F
 
 template <class InputIterator>
 prefix_ senf::detail::PacketImpl::PacketImpl(InputIterator first, InputIterator last)
-    : refcount_(0), data_(first,last), annotations_(AnnotationIndexerBase::maxAnnotations, 0)
+    : refcount_(0), data_(first,last), annotations_(AnnotationIndexerBase::maxAnnotations)
 {}
 
 // Annotations
index 1d1373f..92738a4 100644 (file)
@@ -30,6 +30,7 @@
 #include <memory>
 #include <vector>
 #include <boost/utility.hpp>
+#include <boost/type_traits/is_base_of.hpp>
 #include "../Utils/pool_alloc_mixin.hh"
 #include "PacketTypes.hh"
 #include "../Utils/singleton.hh"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
+
+    struct ComplexAnnotation {};
+
 namespace detail {
 
+    struct AnnotationP
+    {
+        virtual ~AnnotationP();
+    };
+
+    template <class Annotation>
+    struct TAnnotationP
+        : public AnnotationP
+    {
+        Annotation annotation;
+    };
+
+    union AnnotationEntry {
+        AnnotationP * p;
+        unsigned long long i;
+    };
+
     struct AnnotationIndexerBase
     {
         static unsigned maxAnnotations;
@@ -54,34 +75,21 @@ namespace detail {
         AnnotationIndexer();
         unsigned index_;
         static unsigned index();
-        static bool const Small = (sizeof(Annotation) <= sizeof(void*));
-    };
-
-    struct AnnotationP
-    {
-        virtual ~AnnotationP();
-    };
-
-    template <class Annotation>
-    struct TAnnotationP
-        : public AnnotationP
-    {
-        Annotation annotation;
+        static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) 
+                                   && ! boost::is_base_of<ComplexAnnotation, Annotation>::value);
     };
 
     template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
     struct GetAnnotation
     {
-        static Annotation & get(AnnotationP * & p);
+        static Annotation & get(AnnotationEntry & e);
     };
 
-/*
     template <class Annotation>
     struct GetAnnotation<Annotation, true>
     {
-        static Annotation & get(AnnotationP * & p);
+        static Annotation & get(AnnotationEntry & e);
     };
-*/
 
     /** \brief Internal: Packet data storage
 
@@ -171,7 +179,7 @@ namespace detail {
         raw_container data_;
         interpreter_list interpreters_;
         
-        typedef std::vector<AnnotationP*> Annotations;
+        typedef std::vector<AnnotationEntry> Annotations;
         Annotations annotations_;
 
         void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
index 42a609b..1e116ff 100644 (file)
--- a/senf.dict
+++ b/senf.dict
@@ -13,6 +13,7 @@ addr
 AddressingPolicy
 AddressingPolicyBase
 AddressParser
+addrs
 addtogroup
 aListCollection
 alloc
@@ -25,6 +26,7 @@ args
 argTokens
 ArgumentToken
 argv
+ArrayParser
 async
 attr
 Augustin
@@ -78,6 +80,7 @@ ConnectedRawV
 ConnectedUDPv
 const
 copyable
+cout
 CPPDEFINES
 CPPPATH
 createAfter
@@ -113,6 +116,9 @@ doxygen
 DSENF
 DSMCCSection
 dt
+DTCP
+DTCPHelloPacket
+DVB
 ElementParser
 enableChecksum
 endcode
@@ -134,6 +140,7 @@ errorNumber
 eth
 ethernet
 EthernetPacket
+EthernetPacketParser
 EthernetPacketType
 EthernetParser
 ethertype
@@ -155,11 +162,15 @@ ExampleVectorPolicy
 EXC
 ExceptionMixin
 ExtendedParser
+fbipList
+FBIPList
+fbips
 FFFF
 FileBody
 filebody
 FileHandle
 FileTarget
+finalizeAll
 findNext
 findPrev
 fixedcolumn
@@ -200,6 +211,7 @@ hostname
 hostnames
 howto
 HowTo
+HowTos
 hpp
 href
 htm
@@ -243,6 +255,7 @@ IpTypes
 IpV
 ipv
 IPv
+ipVersion
 IPX
 isock
 iter
@@ -269,6 +282,7 @@ LinkScope
 linux
 ListB
 ListN
+ListParser
 ListPolicy
 localAddr
 localhost
@@ -286,6 +300,10 @@ mem
 memberfn
 mixin
 mkdir
+mld
+MLDv
+MPEG
+mpegdvb
 MPEGDVBBundle
 mpp
 multicast
@@ -310,6 +328,7 @@ nc
 netcat
 NETwork
 newpacket
+NewPacket
 NextPacket
 nextPacketKey
 nextPacketRange
@@ -321,6 +340,8 @@ NodeCreateTraits
 noinit
 noroute
 nothrow
+nrOfRecords
+nrOfSources
 nUsing
 ob
 ObjectDirectory
@@ -403,6 +424,7 @@ protocolType
 ptr
 PUSHD
 py
+QueryPacket
 QueueingDiscipline
 queueSize
 RateFilter
@@ -420,6 +442,7 @@ registerPacket
 registerPacketType
 registerSomePacket
 RegistrationProxy
+ReportPacket
 repos
 rerference
 rfc
@@ -437,6 +460,7 @@ ScopedDirectory
 ScopeId
 screenshot
 sec
+seechapter
 seekable
 senf
 senfscons
@@ -518,6 +542,7 @@ STL
 strerror
 struct
 structors
+subsubsection
 svn
 svnbook
 svnroot
@@ -542,6 +567,7 @@ TunTapSocketHandle
 TypeA
 TypeB
 typeField
+UDLR
 udp
 UDPPacket
 udpReader
@@ -558,14 +584,18 @@ unthrottled
 unthrottles
 unthrottling
 Utils
+valueParser
+ValueParser
 var
 varadd
 varattr
 varchange
 varChanged
 VariableAttributor
+VariantParser
 varro
 VectorN
+VectorParser
 Ver
 vlanId
 VLanId