From c97c06ad44aeb23febbe334f78530aba8d131b9d Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Wed, 1 Oct 2008 21:24:50 +0000 Subject: [PATCH] Packets: annotation facility --- Packets/Mainpage.dox | 36 +++++++++++++++------------------- Packets/Packet.hh | 44 ++++++++++++++++++++++++++++++++++++++++-- Packets/Packet.test.cc | 38 ++++++++++++++++++++++++++++++------ Packets/PacketImpl.cc | 4 ++-- Packets/PacketImpl.cci | 4 ++-- Packets/PacketImpl.cti | 16 +++++++-------- Packets/PacketImpl.hh | 44 +++++++++++++++++++++++++----------------- senf.dict | 30 ++++++++++++++++++++++++++++ 8 files changed, 157 insertions(+), 59 deletions(-) diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox index cfa8e30e9..817a45560 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<IPv4Packet>() // throws InvalidPacketChainException udp.prev() == ip // true - udp.prev<EthernetPacket>() // throws Inv + udp.prev<EthernetPacket>() // 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: <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> @@ -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 58264f8ff..e2e3c3fb1 100644 --- a/Packets/Packet.hh +++ b/Packets/Packet.hh @@ -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). + */ ///@} diff --git a/Packets/Packet.test.cc b/Packets/Packet.test.cc index b88993e4b..8c28f73b5 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<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_ diff --git a/Packets/PacketImpl.cc b/Packets/PacketImpl.cc index 5b5e12fe0..95b45cdaf 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<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 diff --git a/Packets/PacketImpl.cci b/Packets/PacketImpl.cci index 9b8a27723..1e0cad02d 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 21956f18c..1f2d79a74 100644 --- a/Packets/PacketImpl.cti +++ b/Packets/PacketImpl.cti @@ -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 diff --git a/Packets/PacketImpl.hh b/Packets/PacketImpl.hh index 1d1373f0c..92738a462 100644 --- a/Packets/PacketImpl.hh +++ b/Packets/PacketImpl.hh @@ -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" @@ -38,8 +39,28 @@ ///////////////////////////////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); diff --git a/senf.dict b/senf.dict index 42a609b91..1e116ff69 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 -- GitLab