Skip to content
Snippets Groups Projects
Commit 01889063 authored by g0dil's avatar g0dil
Browse files

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
parent 59da2a0c
No related branches found
No related tags found
No related merge requests found
// 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:
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
namespace senf { namespace senf {
///\addtogroup protocolbundle_default
///@{
struct MACAddress struct MACAddress
: boost::array<PacketParserBase::byte,6> : boost::array<PacketParserBase::byte,6>
{ {
...@@ -146,6 +149,8 @@ namespace senf { ...@@ -146,6 +149,8 @@ namespace senf {
}; };
typedef EthVLanPacketType::packet EthVLanPacket; typedef EthVLanPacketType::packet EthVLanPacket;
///@}
} }
......
// $Id$ // $Id: IpV4Packet.hh 307 2007-07-14 21:31:12Z g0dil $
// //
// Copyright (C) 2006 // Copyright (C) 2006
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
namespace senf { namespace senf {
///\addtogroup protocolbundle_default
///@{
struct Parse_IpV4 : public PacketParserBase struct Parse_IpV4 : public PacketParserBase
{ {
SENF_PACKET_PARSER_NO_INIT(Parse_IpV4); SENF_PACKET_PARSER_NO_INIT(Parse_IpV4);
...@@ -98,6 +101,7 @@ namespace senf { ...@@ -98,6 +101,7 @@ namespace senf {
typedef IpV4PacketType::packet IpV4Packet; typedef IpV4PacketType::packet IpV4Packet;
///@}
} }
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
namespace senf { namespace senf {
///\addtogroup protocolbundle_default
///@{
// See RFC2460 // See RFC2460
struct Parse_IpV6Extension_Fragment : public PacketParserBase struct Parse_IpV6Extension_Fragment : public PacketParserBase
{ {
...@@ -74,6 +77,8 @@ namespace senf { ...@@ -74,6 +77,8 @@ namespace senf {
}; };
typedef IpV6ExtensionType_Fragment::packet IpV6Extension_Fragment; typedef IpV6ExtensionType_Fragment::packet IpV6Extension_Fragment;
///@}
} }
///////////////////////////////hh.e//////////////////////////////////////// ///////////////////////////////hh.e////////////////////////////////////////
......
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
namespace senf { namespace senf {
///\addtogroup protocolbundle_default
///@{
// See RFC2460 // See RFC2460
struct Parse_IpV6 : public PacketParserBase struct Parse_IpV6 : public PacketParserBase
{ {
...@@ -88,6 +91,7 @@ namespace senf { ...@@ -88,6 +91,7 @@ namespace senf {
typedef IpV6PacketType::packet IpV6Packet; typedef IpV6PacketType::packet IpV6Packet;
///@}
} }
///////////////////////////////hh.e//////////////////////////////////////// ///////////////////////////////hh.e////////////////////////////////////////
......
// $Id$ // $Id: UDPPacket.hh 308 2007-07-14 22:31:20Z g0dil $
// //
// Copyright (C) 2006 // Copyright (C) 2006
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
namespace senf { namespace senf {
///\addtogroup protocolbundle_default
///@{
// See RFC768 // See RFC768
struct Parse_UDP : public PacketParserBase struct Parse_UDP : public PacketParserBase
{ {
...@@ -66,6 +69,8 @@ namespace senf { ...@@ -66,6 +69,8 @@ namespace senf {
}; };
typedef UDPPacketType::packet UDPPacket; typedef UDPPacketType::packet UDPPacket;
///@}
} }
......
...@@ -3,5 +3,4 @@ ...@@ -3,5 +3,4 @@
PROJECT_NAME = libPackets PROJECT_NAME = libPackets
TAGFILES = "$(TOPDIR)/Utils/doc/Utils.tag" TAGFILES = "$(TOPDIR)/Utils/doc/Utils.tag"
GENERATE_TAGFILE = doc/Packets.tag GENERATE_TAGFILE = doc/Packets.tag
#INPUT = . DefaultBundle RTPBundle INPUT = . DefaultBundle
INPUT = .
\ No newline at end of file
...@@ -2,104 +2,37 @@ ...@@ -2,104 +2,37 @@
\section arch Overall Architecture \section arch Overall Architecture
The general Architecture of the Packet Framework (pkf for short) The Packet library consists of several components:
is seperated into two components: The basic packet handling and
the parser framework. \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.
The basic packet handling implements a packet interpreter \li \ref packetparser provides the framework for interpreting packet data. It handles
chain. Every packet is represented as a chain of interpreters parsing the packet information into meaningful values.
where each interpreter is a facade looking into the same \li The \ref protocolbundles provide concrete implementations for interpreting packets of
packet. Each interpreter will interpret a specific header of a some protocol. The Protocol Bundles are built on top of the basic packet library.
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 parser framework contains some basic parsers to be used to /*
build up more complex parsers:
- ParseInt.hh: Lots of parsers for integer numbers like - ParseInt.hh: Lots of parsers for integer numbers like senf::Parse_UInt8, for integer
senf::Parse_UInt8, for integer bitfields like bitfields like senf::Parse_UIntField and senf::Parse_Flag to parse boolean flags.
senf::Parse_UIntField and senf::Parse_Flag to
parse boolean flags.
- ParseArray.hh: The senf::Parse_Array parser to parse - ParseArray.hh: The senf::Parse_Array parser to parse arbitrary fixed-size arrays of
arbitrary fixed-size arrays of fixed-size elements (that is fixed-size elements (that is sub-parsers).
sub-parsers).
- ParseVec.hh: The senf::Parse_Vector parser to parse - ParseVec.hh: The senf::Parse_Vector parser to parse dynamically sized arrays of fixed-size
dynamically sized arrays of fixed-size elements (that is elements (that is sub-parsers).
sub-parsers).
See senf::ParserBase for further information. See senf::ParserBase for further information.
\section stuff Other Utilities \section stuff Other Utilities
The pkf also comprises some additional utilities to support the The pkf also comprises some additional utilities to support the development of packet classes.
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.
\idea we need some better and automatic checking on data access The senf::PacketRegistry implements a registry of packets keyed by an arbitrary type. The
especially after data has changed. Idea 1: give the parser the registry is used to find a packet type given some kind of id (like the ethertype value from the
end iterator as additional member. Enforce, that all parsers ethernet header). Together with it's support classes (especially senf::PacketRegistryMixin) this
must ultimately be based on ParseInt and have ParseInt check class greatly simplifies implementing the needed table lookups.
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.
*/ */
......
...@@ -106,6 +106,7 @@ prefix_ bool senf::Packet::operator==(Packet other) ...@@ -106,6 +106,7 @@ prefix_ bool senf::Packet::operator==(Packet other)
prefix_ void senf::Packet::finalize() prefix_ void senf::Packet::finalize()
const const
{ {
last(); // Make sure the packet is complete
ptr()->finalize(); ptr()->finalize();
} }
......
...@@ -263,7 +263,7 @@ senf::ConcretePacket<PacketType>::clone() ...@@ -263,7 +263,7 @@ senf::ConcretePacket<PacketType>::clone()
// Field access // Field access
template <class PacketType> template <class PacketType>
prefix_ typename senf::ConcretePacket<PacketType>::interpreter::parser * prefix_ typename senf::ConcretePacket<PacketType>::type::parser *
senf::ConcretePacket<PacketType>::operator->() senf::ConcretePacket<PacketType>::operator->()
const const
{ {
......
...@@ -36,9 +36,98 @@ ...@@ -36,9 +36,98 @@
namespace senf { 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; 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 class Packet
: public SafeBool<Packet>, : public SafeBool<Packet>,
...@@ -48,15 +137,13 @@ namespace senf { ...@@ -48,15 +137,13 @@ namespace senf {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Types // Types
typedef void type; typedef void type; ///< Type of the packet.
typedef senf::detail::packet::iterator iterator; typedef senf::detail::packet::size_type size_type; ///< Unsigned type to represent packet size
typedef senf::detail::packet::const_iterator const_iterator; typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
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;
enum NoInit_t { noinit }; /// Special argument flag
/** Used in some ConcretePacket constructors */
enum NoInit_t { noinit };
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
///\name Structors and default members ///\name Structors and default members
...@@ -66,13 +153,23 @@ namespace senf { ...@@ -66,13 +153,23 @@ namespace senf {
// default copy assignment // default copy assignment
// default destructor // default destructor
Packet(); Packet(); ///< Create uninitialized packet handle
Packet clone() const; /**< 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 // conversion constructors
template <class PacketType> template <class PacketType>
Packet(ConcretePacket<PacketType> packet); 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 { ...@@ -80,56 +177,180 @@ namespace senf {
///\name Interpreter chain access ///\name Interpreter chain access
///@{ ///@{
Packet next() const; Packet next() const;
template <class OtherPacket> OtherPacket next() const; ///< Get next packet in chain
template <class OtherPacket> OtherPacket next(NoThrow_t) const; 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; 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; 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; Packet prev() const;
template <class OtherPacket> OtherPacket 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; 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; 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; 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; Packet first() const;
///< Return first packet in chain
template <class OtherPacket> OtherPacket first() const; 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; 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; Packet last() const;
///< Return last packet in chain
template <class OtherPacket> OtherPacket last() const; 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; 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; 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; 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; template <class OtherPacket> bool is() const;
///< Check, whether \c this packet is of the given type
template <class OtherPacket> OtherPacket as() const; template <class OtherPacket> OtherPacket as() const;
///< Cast current packet to the given type
Packet append(Packet packet) const; /**< 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 ///\name Data access
///@{ ///@{
PacketData & data() const; PacketData & data() const; ///< Access the packets raw data container
size_type size() const; 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 ///\name Other methods
///@{ ///@{
bool operator==(Packet other) const; bool operator==(Packet other) const; ///< Check for packet identity
bool boolean_test() const; /**< Two packet handles compare equal if they really are the
same packet header in the same packet chain. */
void finalize() const; bool boolean_test() const; ///< Check, whether the packet is valid()
/**< \see valid() */
void dump(std::ostream & os) const; 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; void finalize() const; ///< Update calculated fields
factory_t factory() const; /**< 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 { ...@@ -148,7 +369,37 @@ namespace senf {
friend class ConcretePacket; 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> template <class PacketType>
class ConcretePacket class ConcretePacket
...@@ -159,7 +410,6 @@ namespace senf { ...@@ -159,7 +410,6 @@ namespace senf {
// Types // Types
typedef PacketType type; typedef PacketType type;
typedef PacketInterpreter<PacketType> interpreter;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
///\name Structors and default members ///\name Structors and default members
...@@ -170,34 +420,122 @@ namespace senf { ...@@ -170,34 +420,122 @@ namespace senf {
// default destructor // default destructor
// no conversion constructors // 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 // Create completely new packet
static ConcretePacket create(); static ConcretePacket create(); ///< Create default initialized packet
static ConcretePacket create(NoInit_t); /**< The packet will be initialized to it's default empty
static ConcretePacket create(size_type size); state. */
static ConcretePacket create(size_type size, NoInit_t); 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> 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 // 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); 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); 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); 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> template <class ForwardReadableRange>
static ConcretePacket createAfter(Packet packet, static ConcretePacket createAfter(Packet packet,
ForwardReadableRange const & range); 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 // 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); 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 // Create a clone of the current packet
ConcretePacket clone() const; ConcretePacket clone() const;
...@@ -207,11 +545,23 @@ namespace senf { ...@@ -207,11 +545,23 @@ namespace senf {
// Field access // 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: protected:
private: private:
typedef PacketInterpreter<PacketType> interpreter;
ConcretePacket(typename interpreter::ptr packet_); ConcretePacket(typename interpreter::ptr packet_);
typename interpreter::ptr ptr() const; typename interpreter::ptr ptr() const;
...@@ -220,6 +570,8 @@ namespace senf { ...@@ -220,6 +570,8 @@ namespace senf {
friend class PacketInterpreter<PacketType>; friend class PacketInterpreter<PacketType>;
}; };
///@}
} }
///////////////////////////////hh.e//////////////////////////////////////// ///////////////////////////////hh.e////////////////////////////////////////
......
...@@ -164,8 +164,8 @@ BOOST_AUTO_UNIT_TEST(packet) ...@@ -164,8 +164,8 @@ BOOST_AUTO_UNIT_TEST(packet)
BOOST_CHECK( packet.factory() == FooPacket::factory() ); BOOST_CHECK( packet.factory() == FooPacket::factory() );
senf::Packet::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, senf::PacketData::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x81, 0x82, 0x83 }; 0x81, 0x82, 0x83 };
BarPacket::createAfter(packet,data); BarPacket::createAfter(packet,data);
BOOST_REQUIRE( packet.next() ); BOOST_REQUIRE( packet.next() );
...@@ -194,7 +194,7 @@ BOOST_AUTO_UNIT_TEST(packet) ...@@ -194,7 +194,7 @@ BOOST_AUTO_UNIT_TEST(packet)
BOOST_AUTO_UNIT_TEST(concretePacket) 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().size(), 4u );
BOOST_CHECK_EQUAL( FooPacket::create(FooPacket::noinit).size(), 0u ); BOOST_CHECK_EQUAL( FooPacket::create(FooPacket::noinit).size(), 0u );
......
No preview for this file type
...@@ -85,6 +85,12 @@ ...@@ -85,6 +85,12 @@
</xsl:call-template> </xsl:call-template>
</xsl: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:template match="table[descendant::td[@class='memItemLeft']]">
<xsl:call-template name="add-class"> <xsl:call-template name="add-class">
<xsl:with-param name="class">members</xsl:with-param> <xsl:with-param name="class">members</xsl:with-param>
...@@ -108,7 +114,7 @@ ...@@ -108,7 +114,7 @@
<xsl:with-param name="class">anchor</xsl:with-param> <xsl:with-param name="class">anchor</xsl:with-param>
</xsl:call-template> </xsl:call-template>
</xsl:template> </xsl:template>
<!-- Remove [external] references from the modules page --> <!-- 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 match="div[@id='content2']/ul/li[a/@class='elRef'][a/@doxygen][code/text()='[external]'][not(ul)]">
</xsl:template> </xsl:template>
......
...@@ -2,7 +2,7 @@ body { ...@@ -2,7 +2,7 @@ body {
padding: 0; padding: 0;
margin: 0; margin: 0;
font-family: Verdana, Arial, Helvetica, sans-serif; font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt; font-size: 10pt;
} }
#head { #head {
...@@ -21,8 +21,8 @@ body { ...@@ -21,8 +21,8 @@ body {
} }
#title2 { #title2 {
padding: 0 0 0 42px; padding: 0 0 0 42px;
max-width: 62em; max-width: 62em;
margin: 0 10px 0 0; margin: 0 10px 0 0;
} }
...@@ -40,49 +40,49 @@ body { ...@@ -40,49 +40,49 @@ body {
margin: 0 10px 0 100px; margin: 0 10px 0 100px;
padding: 4px 0 0 42px; padding: 4px 0 0 42px;
height: 18px; height: 18px;
max-width: 62em; max-width: 62em;
background-color: #EDE497; background-color: #EDE497;
color: #726921; color: #726921;
} }
#head h2 { #head h2 {
margin: 0; margin: 0;
padding: 0; padding: 0;
font-size: 13px; font-size: 13px;
font-weight: normal; font-weight: normal;
white-space: nowrap; white-space: nowrap;
} }
#head ul { #head ul {
display: inline; /* fr IE ... */ display: inline; /* fr IE ... */
font-size: 13px; font-size: 13px;
height: 0px; height: 0px;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
#head li { #head li {
list-style-type: none; list-style-type: none;
margin: 0 0 0 10px; margin: 0 0 0 10px;
padding: 0 10px 0 0; padding: 0 10px 0 0;
float: right; float: right;
border-right: 1px solid #726921; border-right: 1px solid #726921;
height: 14px; height: 14px;
} }
#head li:first-child { #head li:first-child {
border-right: none; border-right: none;
padding: 0; padding: 0;
} }
#head a { #head a {
font-weight: normal; font-weight: normal;
color: #726921; color: #726921;
} }
#head a:hover { #head a:hover {
background-color: #EDE497; background-color: #EDE497;
text-decoration: underline; text-decoration: underline;
} }
#search { #search {
...@@ -308,6 +308,11 @@ div.idea { ...@@ -308,6 +308,11 @@ div.idea {
border-left: 10px solid #AAAAAA; border-left: 10px solid #AAAAAA;
} }
dl.implementation {
color: #666666;
font-size: 9px;
}
table { table {
width: 100%; width: 100%;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment