X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FPacketParser.hh;h=543ba9c7a2d76ff6ee25f4244311728e2ea427d1;hb=ac86c2bb40746fbedf70a19af3307e5da642b04a;hp=c6a38e82a4844f23915aa838f9a91e4362572ead;hpb=a18d131c38ffe7178ea4736ed3f584125e9903ae;p=senf.git diff --git a/Packets/PacketParser.hh b/Packets/PacketParser.hh index c6a38e8..543ba9c 100644 --- a/Packets/PacketParser.hh +++ b/Packets/PacketParser.hh @@ -107,6 +107,8 @@ 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). + \see parseint + \subsection parserimpl_collection Collection parsers A collection parser \a SomeParser should model STL containers. The parsers themselves will @@ -120,6 +122,8 @@ parser. Instead, you can rely on senf::Parse_Vector or senf::Parse_List and implement new policies. + \see parsecollection + \subsection parserimpl_composite Composite parsers If possible, composite parsers should be implemented using the \ref packetparsermacros. In @@ -154,11 +158,14 @@ #include "../Utils/SafeBool.hh" #include "PacketTypes.hh" #include "PacketData.hh" +#include "ParseHelpers.hh" -#include "PacketParser.mpp" +//#include "PacketParser.mpp" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { + + class Packet; /** \brief Parser Base class @@ -238,6 +245,7 @@ namespace senf { typedef detail::packet::difference_type difference_type; ///< Signed integral type typedef detail::packet::byte byte; ///< Unsigned 8bit value, the raw value type typedef PacketData * state_type; ///< Type of the 'state' parameter + typedef PacketParserBase parser_base_type; ///< Base type of the next parser /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -292,10 +300,10 @@ namespace senf { container does not hold at least \a size bytes beginning at \a i. */ - bool check(size_type size); ///< Check size of data container + bool check(size_type size) const; ///< Check size of data container /**< \returns \c true, if the data container holds at least \a size beginning at i(), \c false otherwise. */ - void validate(size_type size); ///< Validate size of data container + void validate(size_type size) const; ///< Validate size of data container /**< \throws TruncatedPacketException if the raw data container does not hold at least \a size bytes beginning at i(). */ @@ -314,8 +322,13 @@ namespace senf { implementation. Re-implement this member in your own parsers if needed. */ + Packet packet() const; ///< Get packet this parser is parsing from + /**< \important This member should only be used from packet + parsers when access to previous or following packets is + needed e.g. for calculating checksums etc. */ + private: - data_iterator end(); + data_iterator end() const; data_iterator i_; PacketData * data_; @@ -427,227 +440,13 @@ namespace senf { Parser operator<<(Parser target, boost::optional const & value); # endif - /** \defgroup packetparsermacros Helper macros for defining new packet parsers - - To simplify the definition of simple packet parsers, several macros are provided. Before - using these macros you should familiarize yourself with the packet parser interface as - described in senf::PacketParserBase. - - These macros simplify providing the above defined interface. A typical packet declaration - using these macros has the following form (This is a concrete example from the definition of - the ethernet packet in DefaultBundle/EthernetPacket.hh) - - \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. - \li The macros provide a definition for \c init() - \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed. - - You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined - using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined - using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such - that: - - \li The needed parser constructor is defined - \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each - of the fields. - \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size - parsers) is defined to return the sum of the sizes of all fields. - \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the - \c init_size's of all fields - - The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref - SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a - (boost preprocessor style) sequence of field definitions where each field definition - provides the builder macro to use and the name and type of the field to define: - \code - SENF_PACKET_PARSER_DEFINE[_FIXED]_FIELDS( - (( )( , )) - ... - ) - \endcode - - For each field, this command will define - \li A method \a name() returning an instance of the \a type parser - \li \a name_t as a typedef for \a type, the fields value - \li \a name_offset to give the offset of the field from the beginning of the - parser. If the parser is a fixed size parser, this will be a static constant, otherwise - it will be a method. - - The \a builder argument selects, how the field is defined - \li Field defines a field and increments the current position by the size of the - field - \li OverlayField defines a field like Field but does \e not increment the - position. In the above example, this is used to overlay the different bitfield parsers: - All overlaying bitfield parser except the last one (the one with the highest bit - numbers) is marked as OverlayField. - - The \a name argument defines the name of the accessor method. - - The \a type argument is the parser to return for that field. Since none of the arguments may - contain a comma, This argument cannot be a multi-parameter template. Always use - typedefs to access templated parsers as shown above. - - The \ref SENF_PACKET_PARSER_INIT macro defines the constructor and the \c init() member. If - you want to provide your own \c init() implementation, use \ref - SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call - \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can - set up the field values as needed: - \code - struct SomePacket : public senf::PacketParserBase - { - SENF_PACKET_PARSER_NO_INIT(SomePacket); - - typedef senf::Parse_UInt8 Parse_Type; - typedef senf::Parse_Vector< senf::Parse_UInt32, - senf::SimpleVectorSizer - > Parse_Elements; - - SENF_PACKET_PARSER_DEFINE_FIELDS( - ((Field)( type, Parse_Type )) - ((Field)( elements, Parse_Elements )) - ); - - void init() const { - defaultInit(); - type() = 0x01; - elements().push_back(0x01020304u); - } - } - \endcode - - \ingroup packetparser - */ - - /** \brief Define initialization members of a parser - - This macro defines the packet parser constructor and the \c init() member. \c init() is - defined to just call \c defaultInit() which is defined by the other macros to call \c init() - on each of the parsers fields. - - \ingroup packetparsermacros - \hideinitializer - */ -# define SENF_PACKET_PARSER_INIT(name) \ - name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {} \ - void init() const { defaultInit(); } - - /** \brief Define initialization members of a parser except init() - - This macro is like SENF_PACKET_PARSER_INIT but does \e not define \c init(). This allows you - to provide your own implementation. You should call \c defaultInit() first before - initializing your data fields. - - \ingroup packetparsermacros - \hideinitializer - */ -# define SENF_PACKET_PARSER_NO_INIT(name) \ - name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {} - - /** \brief Define fields for a dynamically sized parser - - Define the fields as specified in \a fields. This macro supports dynamically sized - subfields, the resulting parser will be dynamically sized. - - \ingroup packetparsermacros - \hideinitializer - */ -# define SENF_PACKET_PARSER_DEFINE_FIELDS(fields) \ - SENF_PACKET_PARSER_I_DEFINE_FIELDS(0,fields) - - /** \brief Define fields for a dynamically sized parser (with offset) - - Define the fields as specified in \a fields. This macro supports dynamically sized - subfields, the resulting parser will be dynamically sized. - - The \a offset argument gives the byte offset at which to start parsing the fields. This - helps defining extended parser deriving from a base parser: - \code - struct ExtendedParser : public BaseParser - { - ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {} - - SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(senf::bytes(BaseParser(*this)), - ( ... fields ... ) ); - - void init() { - BaseParser::init(); - defaultInit(); - // other init code - } - } - \endcode - - \ingroup packetparsermacros - \hideinitializer - */ -# define SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(offset,fields) \ - SENF_PACKET_PARSER_I_DEFINE_FIELDS(offset,fields) - - /** \brief Define fields for a fixed size parser - - Define the fields as specified in \a fields. This macro only supports fixed size - subfields, the resulting parser will also be a fixed size parser. - - \ingroup packetparsermacros - \hideinitializer - */ -# define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(fields) \ - SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(0,fields) - - /** \brief Define fields for a fixed size parser - - Define the fields as specified in \a fields. This macro only supports fixed size - subfields, the resulting parser will also be a fixed size parser. - - The \a offset argument gives the byte offset at which to start parsing the fields. This - helps defining extended parser deriving from a base parser: - \code - struct ExtendedParser : public BaseParser - { - ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {} - - SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(BaseParser::fixed_bytes, - ( ... fields ... ) ); - - void init() { - BaseParser::init(); - defaultInit(); - // other init code - } - } - \endcode - - \ingroup packetparsermacros - \hideinitializer - */ -# 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 { - SENF_PACKET_PARSER_INIT(VoidPacketParser); +# include SENF_FIXED_PARSER() + SENF_PARSER_FINALIZE(VoidPacketParser); }; /** \brief Iterator re-validating Parser wrapper @@ -711,7 +510,7 @@ namespace senf { ///////////////////////////////hh.e//////////////////////////////////////// #endif -#if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketParser_i_) +#if !defined(HH_Packets__decls_) && !defined(HH_PacketParser_i_) #define HH_PacketParser_i_ #include "PacketParser.cci" #include "PacketParser.ct"