From: g0dil Date: Wed, 1 Oct 2008 21:24:50 +0000 (+0000) Subject: Packets: annotation facility X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=51b10105e78a9ffee631223f50e63aa28bb5d2b4;p=senf.git Packets: annotation facility git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@921 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox index cfa8e30..817a455 100644 --- a/Packets/Mainpage.dox +++ b/Packets/Mainpage.dox @@ -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: @@ -42,27 +43,22 @@ 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 @@ -83,11 +79,11 @@ \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 @@ -167,7 +163,7 @@ udp.first() // throws InvalidPacketChainException udp.prev() == ip // true - udp.prev() // throws Inv + udp.prev() // throws InvalidPacketChainException \endcode \see \ref packet_module @@ -181,7 +177,7 @@ 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 @@ -518,7 +514,7 @@ Each Record is a composite with the following relevant fields: - +
nrSourcesIntegerNumber of sources in this record
nrOfSourcesIntegerNumber of sources in this record
sourcesVector of IPv6 AddressesMulticast sources
@@ -567,7 +563,7 @@ 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 diff --git a/Packets/Packet.hh b/Packets/Packet.hh index 58264f8..e2e3c3f 100644 --- a/Packets/Packet.hh +++ b/Packets/Packet.hh @@ -316,9 +316,49 @@ namespace senf { ///\name Annotations ///@{ - + template - 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().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). + */ ///@} diff --git a/Packets/Packet.test.cc b/Packets/Packet.test.cc index b88993e..8c28f73 100644 --- a/Packets/Packet.test.cc +++ b/Packets/Packet.test.cc @@ -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().value = 0xDEADBEEF ); - ComplexAnnotation & ca (packet.annotation()); - 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()); + ca.s = "dead beef"; + ca.i = 0x12345678; + SENF_CHECK_NO_THROW( packet.annotation().value = 0xDEADBEEF ); + + senf::Packet p2 (packet.next()); + + BOOST_CHECK_EQUAL( p2.annotation().value, 0xDEADBEEFu ); + BOOST_CHECK_EQUAL( p2.annotation().s, "dead beef" ); + BOOST_CHECK_EQUAL( p2.annotation().i, 0x12345678 ); + + BOOST_CHECK( senf::detail::AnnotationIndexer::Small ); + BOOST_CHECK( ! senf::detail::AnnotationIndexer::Small ); + BOOST_CHECK( ! senf::detail::AnnotationIndexer::Small ); + BOOST_CHECK( ! senf::detail::AnnotationIndexer::Small ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Packets/PacketImpl.cc b/Packets/PacketImpl.cc index 5b5e12f..95b45cd 100644 --- a/Packets/PacketImpl.cc +++ b/Packets/PacketImpl.cc @@ -47,8 +47,8 @@ prefix_ senf::detail::PacketImpl::~PacketImpl() Annotations::const_iterator const i_end (annotations_.end()); std::vector::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 diff --git a/Packets/PacketImpl.cci b/Packets/PacketImpl.cci index 9b8a277..1e0cad0 100644 --- a/Packets/PacketImpl.cci +++ b/Packets/PacketImpl.cci @@ -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 diff --git a/Packets/PacketImpl.cti b/Packets/PacketImpl.cti index 21956f1..1f2d79a 100644 --- a/Packets/PacketImpl.cti +++ b/Packets/PacketImpl.cti @@ -50,20 +50,18 @@ prefix_ unsigned senf::detail::AnnotationIndexer::index() // senf::detail::GetAnnotation template -prefix_ Annotation & senf::detail::GetAnnotation::get(AnnotationP * & p) +prefix_ Annotation & senf::detail::GetAnnotation::get(AnnotationEntry & e) { - if (!p) - p = new TAnnotationP(); - return static_cast< TAnnotationP* >(p)->annotation; + if (!e.p) + e.p = new TAnnotationP(); + return static_cast< TAnnotationP* >(e.p)->annotation; } -/* template -prefix_ Annotation & senf::detail::GetAnnotation::get(AnnotationP * & p) +prefix_ Annotation & senf::detail::GetAnnotation::get(AnnotationEntry & e) { - return * reinterpret_cast(p); + return * static_cast(static_cast(& e.i)); } -*/ /////////////////////////////////////////////////////////////////////////// // senf::detail::PacketImpl @@ -81,7 +79,7 @@ prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, F template 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 diff --git a/Packets/PacketImpl.hh b/Packets/PacketImpl.hh index 1d1373f..92738a4 100644 --- a/Packets/PacketImpl.hh +++ b/Packets/PacketImpl.hh @@ -30,6 +30,7 @@ #include #include #include +#include #include "../Utils/pool_alloc_mixin.hh" #include "PacketTypes.hh" #include "../Utils/singleton.hh" @@ -38,8 +39,28 @@ ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { + + struct ComplexAnnotation {}; + namespace detail { + struct AnnotationP + { + virtual ~AnnotationP(); + }; + + template + 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 - struct TAnnotationP - : public AnnotationP - { - Annotation annotation; + static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) + && ! boost::is_base_of::value); }; template ::Small> struct GetAnnotation { - static Annotation & get(AnnotationP * & p); + static Annotation & get(AnnotationEntry & e); }; -/* template struct GetAnnotation { - 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 Annotations; + typedef std::vector Annotations; Annotations annotations_; void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e); diff --git a/senf.dict b/senf.dict index 42a609b..1e116ff 100644 --- 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