2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.de>
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 \brief PacketParser public header */
24 /** \defgroup packetparser The PacketParser facility
26 The PacketParser facility provides a framework to implement very lightweight classes which parse
27 the raw content of a packet into meaningful values. PacketParsers are always passed around by
28 value, they can be understood as pointers into the data structure with added type information
29 providing parsing functions.
31 Parsers are built hirarchically. A high-level parser will return other parsers when returning
32 some element (Example: Asking an EthernetParser for the ethertype field by calling the parsers
33 \c type() member will return an UInt16 parser). The lowest level building blocks then return the
34 values. This hierarchical structure greatly simplifies building complex parsers.
36 Every parser is derived from senf::PacketParserBase. This parser provides the necessary
37 housekeeping information and provides the parsers with access to the data.
39 The PacketParser facility predefines several parsers to be used as building blocks in defining
40 more complex parsers (integer parsers, several parsers for repetitive constructs)
43 #ifndef HH_PacketParser_
44 #define HH_PacketParser_ 1
47 #include <boost/utility/enable_if.hpp>
48 #include <boost/type_traits.hpp>
49 #include <boost/optional.hpp>
50 #include "Utils/SafeBool.hh"
51 #include "PacketTypes.hh"
52 #define HH_PacketData_DeclOnly
53 #include "PacketData.hh"
54 #undef HH_PacketData_DeclOnly
56 #include "PacketParser.mpp"
57 ///////////////////////////////hh.p////////////////////////////////////////
61 /** \brief Parser Baseclass
63 To implement a packet parser, you need to derive from PacketParserBase and implement several
64 required members. There are two ways how to do this.
65 \li If the parser just consists of a simple sequence of consecutive fields, the
66 SENF_PACKET_PARESR_DEFINE_FIELDS and SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS macros
67 provide a simple an convenient way to define the packet
68 \li In more complex cases, you need to implement the necessary members manually.
70 The following example documents the interface (which must be) provided by a parser.
72 struct FooParser : public PacketParserBase
74 FooParser(data_iterator i, state_type s) : PacketParserBase(i,s) {}
76 // If this parser has a fixed size, you must define this size here This definition
77 // allows the parser to be used within the list, vector and array parsers static
78 static const size_type fixed_bytes = some_constant_size;
80 // If the parser does not have a fixed size, you must implement the bytes() member to
81 // return the size. ONLY EVER DEFINE ONE OF fixed_bytes OR bytes().
82 size_type bytes() const;
84 // If you define bytes(), you also need to define the init_bytes. This is the number
85 // of bytes to allocate when creating a new object
86 static const size_type init_bytes = some_constant_size;
88 // You also mey define an init() member. This will be called to initialize a newly
89 // created data object. The default implementation just does nothing.
92 // ////////////////////////////////////////////////////////////////////////
94 // Add here members returning (sub-)parsers for the fields. The 'parse' member is
95 // used to construct the sub-parsers. This member either takes an iterator to the
96 // data to be parsed or just an offset in bytes.
98 senf::Parse_UInt16 type() const { return parse<Parse_UInt16>( 0 ); }
99 senf::Parse_UInt16 size() const { return parse<Parse_UInt16>( 2 ); }
103 You should never call the \c bytes() member of a parser directly. Instead you should use the
104 freestanding senf::bytes() functon. This function will return the correct size even for
105 fixed-size parsers. You may access \c fixed_bytes directly, however be aware that this will
106 restrict your code to fixed size parsers (which depending on the circumstances may be
107 exactly what you want).
109 In the same way, dont access \c init_bytes directly, always use the senf::init_bytes
110 metafunction class which will correctly support fixed size parsers.
112 \ingroup packetparser
114 class PacketParserBase
117 ///////////////////////////////////////////////////////////////////////////
120 typedef detail::packet::iterator data_iterator;
121 typedef detail::packet::size_type size_type;
122 typedef detail::packet::difference_type difference_type;
123 typedef detail::packet::byte byte;
124 typedef PacketData * state_type;
126 ///////////////////////////////////////////////////////////////////////////
127 ///\name Structors and default members
130 // no default constructor
132 // default destructor
133 // no conversion constructors
136 ///////////////////////////////////////////////////////////////////////////
138 data_iterator i() const;
139 state_type state() const;
140 PacketData & data() const;
145 PacketParserBase(data_iterator i, state_type s);
146 PacketParserBase(data_iterator i, state_type s, size_type size);
148 bool check(size_type size);
149 void validate(size_type size);
151 template <class Parser> Parser parse(data_iterator i) const;
152 template <class Parser> Parser parse(size_type n) const;
154 void defaultInit() const;
162 template <class Parser> friend class SafePacketParser;
165 /** \brief Return raw size parsed by the given parser object
167 This function will either call <tt>p.bytes()</tt> or return <tt>Parser::fixed_bytes</tt>
168 depending on the type of parser.
170 The value returned does \e not take into account the amount of data actually available. So
171 you always need to validate this value against the packet size if you directly access the
172 data. The standard low-level parses all do this check automatically to guard against
175 \param[in] p Parser object to check
176 \returns number of bytes this parser expects to parser
177 \ingroup packetparser
179 template <class Parser>
180 PacketParserBase::size_type bytes(Parser p);
182 namespace detail { template <class Parser> class ParserInitBytes; }
184 /** \brief Return number of bytes to allocate to new object of given type
186 This metafcuntion is called like
188 senf::init_bytes<SomeParser>::value
191 This expression evaluates to a compile-time constant itegral expression of type
192 senf::PacketParserBase::size_type. This metafunction will return \c Parser::fixed_bytes or
193 \c Parser::init_bytes depending on the type of parser.
195 \param[in] Parser Parser to return init_bytes for
196 \returns Number of bytes to allocate to the new object
197 \ingroup packetparser
199 template <class Parser>
200 struct init_bytes : public detail::ParserInitBytes<Parser>
203 template <class Parser>
204 typename boost::enable_if<
205 boost::is_base_of<PacketParserBase, Parser>,
207 operator<<(Parser target, Parser source);
209 template <class Parser, class Value>
210 typename boost::enable_if_c <
211 boost::is_base_of<PacketParserBase, Parser>::value
212 && ! boost::is_base_of<PacketParserBase, Value>::value,
214 operator<<(Parser target, Value const & value);
216 /** \defgroup packetparsermacros Helper macros for defining new packet parsers
218 To simplify the definition of simple packet parsers, several macros are provided. Before
219 using these macros you should familarize yourself with the packet parser interface as
220 described in senf::PacketParserBase.
222 These macros simplify providing the above defined interface. A typical packet declaration
223 using these macros has the following form (This is a concrete example from the definition of
224 the ethernet packet in <tt>DefaultBundle//EthernetPacket.hh</tt>)
226 struct Parse_EthVLan : public senf::PacketParserBase
228 SENF_PACKET_PARSER_INIT(Parse_EthVLan);
230 // ////////////////////////////////////////////////////////////////////////
232 typedef senf::Parse_UIntField < 0, 3 > Parse_Priority;
233 typedef senf::Parse_Flag < 3 > Parse_CFI;
234 typedef senf::Parse_UIntField < 4, 16 > Parse_VLanId;
235 typedef senf::Parse_UInt16 Parse_Type;
237 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(
238 ((OverlayField)( priority, Parse_Priority ))
239 ((OverlayField)( cfi, Parse_CFI ))
240 ((Field )( vlanId, Parse_VLanId ))
241 ((Field )( type, Parse_Type ))
246 The macros take care of the following:
247 \li They define the accessor functions returning parsers of the given type.
248 \li They automatically calculate the offset of the fields from the preceding fields.
249 \li The macros provide a definition for \c init()
250 \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
252 You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined
253 using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined
254 using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such
257 \li The needed parser constructor is defined
258 \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
260 \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
261 parsers) is defined to return the sum of the sizes of all fields.
262 \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
263 \c init_size's of all fields
265 The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref
266 SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a
267 (boost preprocessor style) sequence of field definitions where each field definition
268 provides the builder macro to use and the name and type of the field to define:
270 SENF_PACKET_PARSER_DEFINE[_FIXED]_FIELDS(
271 (( <builder> )( <name>, <type> ))
276 The \a builder argument selects, how the field is defined
277 \li <tt>Field</tt> defines a field and increments the current position by the size of the
279 \li <tt>OverlayField</tt> defines a field like <tt>Field</tt> but does \e not increment the
280 position. In the above example, this is used to overlay the different bitfield parsers:
281 All overlaying bitfield parser except the last one (the one with the highest bit
282 numbers) is marked as OverlayField.
284 The \a name argument defines the name of the accessor method.
286 The \a type argument is the parser to return for that field. Since none of the arguments may
287 contain a komma, <em>This argument cannot be a template</em>. Always use typedefs to access
288 tempalte parsers as shown above.
290 The \ref SENF_PACKET_PARSER_INIT makro defines the constructor and the \c init() member. If
291 you want to provide your own \c init() implementation, use \ref
292 SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call
293 \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can
294 set up the field values as needed:
296 struct SomePacket : public senf::PacketParserBase
298 SENF_PACKET_PARSER_NO_INIT(SomePacket);
300 typedef senf::Parse_UInt8 Parse_Type;
301 typedef senf::Parse_Vector< senf::Parse_UInt32,
302 senf::SimpleVectorSizer<senf::Parse_UInt16>
305 SENF_PACKET_PARSER_DEFINE_FIELDS(
306 ((Field)( type, Parse_Type ))
307 ((Field)( elements, Parse_Elements ))
313 elements().push_back(0x01020304u);
318 \ingroup packetparser
321 /** \brief Define initialization members of a parser
323 This macro defines the packet parser constructor and the \c init() member. \c init() is
324 defined to just call \c defaultInit() which is defined by the other macros to call \c init()
325 on each of the parsers fields.
327 \ingroup packetparsermacros
330 # define SENF_PACKET_PARSER_INIT(name) \
331 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {} \
332 void init() const { defaultInit(); }
334 /** \brief Define initialization mebers of a parser except init()
336 This macro is like SENF_PACKET_PARSER_INIT but does \e not define \c init(). This allows you
337 to provide your own implementation. You should call \c defaultInit() first before
338 initializing your data fields.
340 \ingroup packetparsermacros
343 # define SENF_PACKET_PARSER_NO_INIT(name) \
344 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {}
346 /** \brief Define fields for a dynamically sized parser
348 Define the fields as specified in \a fields. This macro supports dynamically sized
349 subfields, the resulting parser will be dynamically sized.
351 \ingroup packetparsermacros
354 # define SENF_PACKET_PARSER_DEFINE_FIELDS(fields) \
355 SENF_PACKET_PARSER_I_DEFINE_FIELDS(fields)
357 /** \brief Define fields for a fixed size parser
359 Define the fields as specified in \a fields. This macro only supports fixed size
360 subfields, the resulting parser will also be a fixed size parser.
362 \ingroup packetparsermacros
365 # define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(fields) \
366 SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(fields)
368 struct VoidPacketParser
369 : public PacketParserBase
371 SENF_PACKET_PARSER_INIT(VoidPacketParser);
376 template <class Parser>
377 class SafePacketParser
378 : public SafeBool< SafePacketParser<Parser> >
381 ///////////////////////////////////////////////////////////////////////////
384 ///////////////////////////////////////////////////////////////////////////
385 ///\name Structors and default members
388 // default default constructor
389 // default copy constructor
390 // default copy assignment
391 // default destructor
394 // conversion constructors
395 SafePacketParser(Parser parser);
397 SafePacketParser & operator=(Parser parser);
400 ///////////////////////////////////////////////////////////////////////////
402 Parser operator*() const;
403 Parser const * operator->() const;
404 bool boolean_test() const;
409 mutable boost::optional<Parser> parser_;
410 senf::safe_data_iterator i_;
415 ///////////////////////////////hh.e////////////////////////////////////////
416 #include "PacketParser.cci"
417 #include "PacketParser.ct"
418 #include "PacketParser.cti"
425 // c-file-style: "senf"
426 // indent-tabs-mode: nil
427 // ispell-local-dictionary: "american"