From: g0dil Date: Mon, 16 Jul 2007 19:21:05 +0000 (+0000) Subject: Packets: BUGFIX: ensure complete interpreter chain in finalize() X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=64e170521a221effc1ba11a0544f753544d03bac;p=senf.git 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 git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@315 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/DefaultBundle/DefaultBundle.dox b/Packets/DefaultBundle/DefaultBundle.dox new file mode 100644 index 0000000..5891ca8 --- /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 +// +// 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 f01dab2..1267488 100644 --- a/Packets/DefaultBundle/EthernetPacket.hh +++ b/Packets/DefaultBundle/EthernetPacket.hh @@ -36,6 +36,9 @@ namespace senf { + ///\addtogroup protocolbundle_default + ///@{ + struct MACAddress : boost::array { @@ -146,6 +149,8 @@ namespace senf { }; typedef EthVLanPacketType::packet EthVLanPacket; + + ///@} } diff --git a/Packets/DefaultBundle/IpV4Packet.hh b/Packets/DefaultBundle/IpV4Packet.hh index a38b59d..e8879a2 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 79cc42a..348a1a5 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 b40ab92..0f1aafb 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 047dc22..2648548 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 51fe456..0bacd5b 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 44ba81f..bb4aa52 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 02e5772..7d20006 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 532c3b0..a7d5a15 100644 --- a/Packets/Packet.cti +++ b/Packets/Packet.cti @@ -263,7 +263,7 @@ senf::ConcretePacket::clone() // Field access template -prefix_ typename senf::ConcretePacket::interpreter::parser * +prefix_ typename senf::ConcretePacket::type::parser * senf::ConcretePacket::operator->() const { diff --git a/Packets/Packet.hh b/Packets/Packet.hh index ae2c66e..0ef0cfd 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 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, @@ -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 - Packet(ConcretePacket packet); + template + Packet(ConcretePacket 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 OtherPacket next() const; - template OtherPacket next(NoThrow_t) const; + Packet next() const; + ///< Get next packet in chain + template OtherPacket next() const; + ///< Get next packet of given type in chain + /**< \throws InvalidPacketChainException if no such packet + is found */ + template 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 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 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 OtherPacket prev() const; + Packet prev() const; + ///< Get previous packet in chain + template OtherPacket prev() const; + ///< Get previous packet of given type in chain + /**< \throws InvalidPacketChainException if no such packet + is found */ template 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 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 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 OtherPacket first() const; + ///< Return first packet of given type in chain + /**< \throws InvalidPacketChainException if no such packet + is found */ template 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 OtherPacket last() const; + ///< Return last packet of given type in chain + /**< \throws InvalidPacketChainException if no such packet + is found */ template 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 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 bool is() const; + ///< Check, whether \c this packet is of the given type template 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. This conversion is + unchecked. 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 ConcretePacket @@ -159,7 +410,6 @@ namespace senf { // Types typedef PacketType type; - typedef PacketInterpreter 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 size() == 0. + \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 - 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 Boost.Range + 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 size() == 0. 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 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 Boost.Range + 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 packet->field(). 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 interpreter; + ConcretePacket(typename interpreter::ptr packet_); typename interpreter::ptr ptr() const; @@ -220,6 +570,8 @@ namespace senf { friend class PacketInterpreter; }; + ///@} + } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Packets/Packet.test.cc b/Packets/Packet.test.cc index 60b2bd2..509039e 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 f6ea11f..6a31681 100644 Binary files a/Packets/structure.dia and b/Packets/structure.dia differ diff --git a/doclib/html-munge.xsl b/doclib/html-munge.xsl index d36e315..671373c 100644 --- a/doclib/html-munge.xsl +++ b/doclib/html-munge.xsl @@ -85,6 +85,12 @@ + + + implementation + + + members @@ -108,7 +114,7 @@ anchor - + diff --git a/doclib/senf.css b/doclib/senf.css index 12a3f3e..250dadc 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%; }