X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FPacketParser.hh;h=2b73860b2c32f9385fe8ffcc0dd1685b23f1638c;hb=c3e26baef92c53af9826c2af3bfe4f3570c634bd;hp=6c40b2f1fbb2826a55367530724e2dd9606e8dee;hpb=83df9651fac5af034774ff9314ee18eeb8a5ec2a;p=senf.git
diff --git a/Packets/PacketParser.hh b/Packets/PacketParser.hh
index 6c40b2f..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_
@@ -74,9 +152,7 @@
#include
#include "Utils/SafeBool.hh"
#include "PacketTypes.hh"
-#define HH_PacketData_DeclOnly
#include "PacketData.hh"
-#undef HH_PacketData_DeclOnly
#include "PacketParser.mpp"
///////////////////////////////hh.p////////////////////////////////////////
@@ -85,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.
@@ -284,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
@@ -297,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
@@ -311,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
@@ -327,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.
@@ -459,7 +559,7 @@ namespace senf {
\code
struct ExtendedParser : public BaseParser
{
- SENF_PACKET_PARSER_NO_INIT(ExtendedParser);
+ ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(senf::bytes(BaseParser(*this)),
( ... fields ... ) );
@@ -499,7 +599,7 @@ namespace senf {
\code
struct ExtendedParser : public BaseParser
{
- SENF_PACKET_PARSER_NO_INIT(ExtendedParser);
+ ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(BaseParser::fixed_bytes,
( ... fields ... ) );
@@ -518,6 +618,8 @@ namespace senf {
# define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(offset,fields) \
SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(offset,fields)
+ /** \brief Default parser parsing nothing
+ */
struct VoidPacketParser
: public PacketParserBase
{
@@ -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
@@ -582,6 +686,9 @@ namespace senf {
}
///////////////////////////////hh.e////////////////////////////////////////
+#endif
+#if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketParser_i_)
+#define HH_PacketParser_i_
#include "PacketParser.cci"
#include "PacketParser.ct"
#include "PacketParser.cti"
@@ -598,13 +705,3 @@ namespace senf {
// comment-column: 40
// End:
-// LocalWords: templated PacketParser defgroup packetparser PacketParsers li
-// LocalWords: EthernetParser ethertype UInt senf PacketParserBase tt
-// LocalWords: struct FooParser const init endcode ingroup param SomeParser
-// LocalWords: ethernet DefaultBundle EthernetPacket hh EthVLan UIntField CFI
-// LocalWords: VLanId OverlayField cfi vlanId accessor defaultInit bitfield
-// LocalWords: SomePacket SimpleVectorSizer packetparsermacros Fraunhofer std
-// LocalWords: hideinitializer Institut fuer offene Kommunikationssysteme STL
-// LocalWords: FOKUS Kompetenzzentrum Satelitenkommunikation SatCom Bund cerr
-// LocalWords: berlios dil Structors someField someVector someOtherField
-// LocalWords: TruncatedPacketException