X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FPacketParser.hh;h=2b73860b2c32f9385fe8ffcc0dd1685b23f1638c;hb=c3e26baef92c53af9826c2af3bfe4f3570c634bd;hp=631bf10f915736700f0796cabcbba485d9f8b80b;hpb=d084c02e4914da4fa1a4098a33d704f69e8bdedd;p=senf.git
diff --git a/Packets/PacketParser.hh b/Packets/PacketParser.hh
index 631bf10..2b73860 100644
--- a/Packets/PacketParser.hh
+++ b/Packets/PacketParser.hh
@@ -28,6 +28,11 @@
by value, they can be understood as pointers into the packet data with added type
information providing parsing functions.
+ Packet parsers are \e only used within the packet framework. You should never allocate a new
+ parser instance directly, you should the Packet library let that do for you (either by having
+ the parser as a packet parser in a packet type or by having a member in the packet parser which
+ allocates the parser as a sub-parser).
+
Parsers are built hierarchically. A high-level parser will return other parsers when accessing
an element (Example: Asking an EthernetParser for the ethertype field by calling the parsers \c
type() member will return an \c UInt16 parser). The lowest level building blocks then return the
@@ -56,13 +61,86 @@
complex parsers provide type specific access members. Assigning a value to a parser will change
the underlying representation (the packet data).
- More complex parsers (especially those representing a collection of values) provide an
- additional wrapper class for mutating access (e.g. Parse_Vector provides a container wrapper
- with am STL compatible random-access sequence interface). See the documentation of the specific
- parser for the wrapper specification.
+ Parsers can be grouped into several categories. These categories are not all defined rigorously
+ but are nevertheless helpful when working with the parsers:
+ \li Value parsers provide the lowest level parsers (e.g. senf::Parse_UInt16 which
+ returns an integer value).
+ \li Collection parsers are parsers which model a collection of sub-elements like
+ senf::Parse_List or senf::Parse_Vector.
+ \li Composite parsers collect several fields of arbitrary type into a new
+ parser. Parsers defined using the \ref packetparsermacros fall under this category.
+ \li Packet parsers are used to define a packet type.
+
+ \warning Parsers are like iterators: They are invalidated whenever the size of the packet's
+ data is changed. You should not store a parser anywhere. If you want to keep a parser
+ reference, use the senf::SafePacketParser wrapper. You still will need to take extra care to
+ ensure the parser is not invalidated.
+
+ \section parserimpl Packet parser categories
Every parser is derived from senf::PacketParserBase. This class provides the necessary
- housekeeping information and provides the parsers with access to the data.
+ housekeeping information and provides the parsers with access to the data. You may in principle
+ define arbitrary methods as parser members (e.g. methods to calculate a checksum, methods
+ processing fields in some way and so on). You should however be very wary to access data outside
+ the range assigned to the packet (the range starting at \c i() and with a size of senf::bytes()
+ bytes).
+
+ Each parser type has specific features
+
+ \subsection parserimpl_value Value parsers
+
+ For a parser \a SomeParser to be a value parser, the following expressions must be valid:
+ \code
+ // SomeParser must have a 'value_type', The 'value_type' must be default constructible, copy
+ // constructible and assignable
+ SomeParser::value_type v;
+
+ // An instance of 'SomeParser' must have a 'value' member which returns a value which may be
+ // assigned to a variable of type 'value_type'
+ v = p.someParserField().value()
+
+ // It must be possible to assign a new value using the 'value' member
+ p.someParserField().value(v)
+ \endcode
+
+ If at all possible, the 'value_type' should not reference the packet data using iterators or
+ pointers, it should hold a copy of the value (it's Ok for \c value() to return such a reference
+ as long as assigning it to a \c value_type variable will copy the value).
+
+ \subsection parserimpl_collection Collection parsers
+
+ A collection parser \a SomeParser should model STL containers. The parsers themselves will
+ probably only // provide a reduced interface, but the collection parser should have a \c
+ collection member which is a wrapper providing the full interface.
+ \code
+ SomeParser::container c (p.someParserField());
+ \endcode
+
+ You will probably only very seldom need to implement a completely new collection
+ parser. Instead, you can rely on senf::Parse_Vector or senf::Parse_List and implement new
+ polcies.
+
+ \subsection parserimpl_composite Composite parsers
+
+ If possible, composite parsers should be implemented using the \ref packetparsermacros. In
+ addition to the normal parser requirements, these macros ensure, that for each field,
+ fieldname_t is a typedef for the fields parser and
+ fieldname_offset is the offset of the field in bytes from the beginning of the
+ parser (either a constant for fixed size parsers or a member function for dynamically sized
+ parsers). When defining composite parsers without the help of the \ref packetparsermacros, you
+ should provide those same members.
+
+ \subsection parserimpl_packet Packet parsers
+
+ Packet parsers are composite parsers with relaxed requirements. Since a packet parser will never
+ be used as a sub-parser (it will not be used within another composite parser or as value type in
+ a collection parser), the value returned by senf::bytes for this parser must not necessarily
+ cover the complete packet (e.g. if the packet has a trailer, the trailer will live outside the
+ range given by senf::bytes). You may define any member you want to have in your packets field
+ interface. These members may access the packet data in any way. You just need to ensure, that
+ the integration into the packet-type is correct (the senf::PacketTypeMixin will by default use
+ senf::bytes() to find the end of the header).
+
*/
#ifndef HH_PacketParser_
@@ -83,7 +161,7 @@ namespace senf {
/** \brief Parser Base class
- Parsers come in two favors: fixed and dynamically sized parsers. A fixed size
+ Parsers come in two flavors: fixed and dynamically sized parsers. A fixed size
parser has a constant size, it will always parse a fixed number of bytes. The low-level
'final' parsers (like the integer parsers) are fixed size parsers as are composite parsers
built up only of fixed-size fields.
@@ -282,6 +360,13 @@ namespace senf {
struct init_bytes : public detail::ParserInitBytes
{};
+# ifndef DOXYGEN
+ template
+ typename boost::enable_if<
+ boost::is_base_of,
+ Parser >::type
+ operator<<(Parser target, Parser source);
+# else
/** \brief Generic parser copying
This operator allows to copy the values of identical parsers. This operation does \e not
@@ -295,11 +380,17 @@ namespace senf {
\ingroup packetparser
*/
template
- typename boost::enable_if<
- boost::is_base_of,
- Parser >::type
- operator<<(Parser target, Parser source);
+ Parser operator<<(Parser target, Parser source);
+# endif
+# ifndef DOXYGEN
+ template
+ typename boost::enable_if_c <
+ boost::is_base_of::value
+ && ! boost::is_base_of::value,
+ Parser >::type
+ operator<<(Parser target, Value const & value);
+# else
/** \brief Generic parser value assignment
This operator allows to assign a value to parsers which implement a value(\a
@@ -309,11 +400,8 @@ namespace senf {
\ingroup packetparser
*/
template
- typename boost::enable_if_c <
- boost::is_base_of::value
- && ! boost::is_base_of::value,
- Parser >::type
- operator<<(Parser target, Value const & value);
+ Parser operator<<(Parser target, Value const & value);
+# endif
/** \defgroup packetparsermacros Helper macros for defining new packet parsers
@@ -325,10 +413,24 @@ namespace senf {
using these macros has the following form (This is a concrete example from the definition of
the ethernet packet in DefaultBundle/EthernetPacket.hh)
- \dontinclude EthernetPacket.hh
- \skipline struct Parse_EthVLan : public PacketParserBase
- \until };
-
+ \code
+ struct Parse_EthVLan : public PacketParserBase
+ {
+ typedef Parse_UIntField < 0, 3 > Parse_Priority;
+ typedef Parse_Flag < 3 > Parse_CFI;
+ typedef Parse_UIntField < 4, 16 > Parse_VLanId;
+ typedef Parse_UInt16 Parse_Type;
+
+ SENF_PACKET_PARSER_INIT(Parse_EthVLan);
+
+ SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(
+ ((OverlayField)( priority, Parse_Priority ))
+ ((OverlayField)( cfi, Parse_CFI ))
+ ((Field )( vlanId, Parse_VLanId ))
+ ((Field )( type, Parse_Type )) );
+ };
+ \endcode
+
The macros take care of the following:
\li They define the accessor functions returning parsers of the given type.
\li They automatically calculate the offset of the fields from the preceding fields.
@@ -536,8 +638,10 @@ namespace senf {
location will \e not be updated accordingly and therefore the parser will be
invalid.
- Additionally a SafePacketparser has an uninitialized state. The only allowed operations in
+ Additionally a SafePacketParser has an uninitialized state. The only allowed operations in
this state are the boolean test for validity and assigning another parser.
+
+ \ingroup packetparser
*/
template
class SafePacketParser