2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.be>
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
28 <em>by value</em>, they can be understood as pointers into the packet data with added type
29 information providing parsing functions.
31 Packet parsers are \e only used within the packet framework. You should never allocate a new
32 parser instance directly, you should the Packet library let that do for you (either by having
33 the parser as a packet parser in a packet type or by having a member in the packet parser which
34 allocates the parser as a sub-parser).
36 Parsers are built hierarchically. A high-level parser will return other parsers when accessing
37 an element (Example: Asking an EthernetParser for the ethertype field by calling the parsers \c
38 type() member will return an \c UInt16 parser). The lowest level building blocks then return the
39 values. This hierarchical structure greatly simplifies building complex parsers.
41 Since parsers are very lightweight and are passed by value, packet fields are accessed using the
42 corresponding accessor method:
47 // Assign new value to an integer parser
50 // Write out above value
51 std::cerr << p->someField() << "\n";
53 // Use the generic parser-assignment operator '<<' to copy field values
54 p->someVector()[1].someOtherField() << q->someField();
55 p->someVector() << q->someVector()
58 Here \c someField(), \c someOtherField() and \c someVector() are accessor methods named after
59 the field name. Each returns a parser object. Simple parsers can be used like their
60 corresponding basic type (e.g. a Parse_UInt16 field can be used like an unsigned integer), more
61 complex parsers provide type specific access members. Assigning a value to a parser will change
62 the underlying representation (the packet data).
64 Parsers can be grouped into several categories. These categories are not all defined rigorously
65 but are nevertheless helpful when working with the parsers:
66 \li <em>\ref parserimpl_value</em> provide the lowest level parsers (e.g. senf::Parse_UInt16 which
67 returns an integer value).
68 \li <em>\ref parserimpl_collection</em> are parsers which model a collection of sub-elements like
69 senf::Parse_List or senf::Parse_Vector.
70 \li <em>\ref parserimpl_composite</em> collect several fields of arbitrary type into a new
71 parser. Parsers defined using the \ref packetparsermacros fall under this category.
72 \li <em>\ref parserimpl_packet</em> are used to define a packet type.
74 \warning Parsers are like iterators: They are invalidated <em>whenever the size of the packet's
75 data is changed</em>. You should not store a parser anywhere. If you want to keep a parser
76 reference, use the senf::SafePacketParser wrapper. You still will need to take extra care to
77 ensure the parser is not invalidated.
79 \section parserimpl Packet parser categories
81 Every parser is derived from senf::PacketParserBase. This class provides the necessary
82 housekeeping information and provides the parsers with access to the data. You may in principle
83 define arbitrary methods as parser members (e.g. methods to calculate a checksum, methods
84 processing fields in some way and so on). You should however be very wary to access data outside
85 the range assigned to the packet (the range starting at \c i() and with a size of senf::bytes()
88 Each parser type has specific features
90 \subsection parserimpl_value Value parsers
92 For a parser \a SomeParser to be a value parser, the following expressions must be valid:
94 // SomeParser must have a 'value_type', The 'value_type' must be default constructible, copy
95 // constructible and assignable
96 SomeParser::value_type v;
98 // An instance of 'SomeParser' must have a 'value' member which returns a value which may be
99 // assigned to a variable of type 'value_type'
100 v = p.someParserField().value()
102 // It must be possible to assign a new value using the 'value' member
103 p.someParserField().value(v)
106 If at all possible, the 'value_type' should not reference the packet data using iterators or
107 pointers, it should hold a copy of the value (it's Ok for \c value() to return such a reference
108 as long as assigning it to a \c value_type variable will copy the value).
112 \subsection parserimpl_collection Collection parsers
114 A collection parser \a SomeParser should model STL containers. The parsers themselves will
115 probably only // provide a reduced interface, but the collection parser should have a \c
116 collection member which is a wrapper providing the full interface.
118 SomeParser::container c (p.someParserField());
121 You will probably only very seldom need to implement a completely new collection
122 parser. Instead, you can rely on senf::Parse_Vector or senf::Parse_List and implement new
127 \subsection parserimpl_composite Composite parsers
129 If possible, composite parsers should be implemented using the \ref packetparsermacros. In
130 addition to the normal parser requirements, these macros ensure, that for each field,
131 <em>fieldname</em><tt>_t</tt> is a typedef for the fields parser and
132 <em>fieldname</em><tt>_offset</tt> is the offset of the field in bytes from the beginning of the
133 parser (either a constant for fixed size parsers or a member function for dynamically sized
134 parsers). When defining composite parsers without the help of the \ref packetparsermacros, you
135 should provide those same members.
137 \subsection parserimpl_packet Packet parsers
139 Packet parsers are composite parsers with relaxed requirements. Since a packet parser will never
140 be used as a sub-parser (it will not be used within another composite parser or as value type in
141 a collection parser), the value returned by senf::bytes for this parser must not necessarily
142 cover the complete packet (e.g. if the packet has a trailer, the trailer will live outside the
143 range given by senf::bytes). You may define any member you want to have in your packets field
144 interface. These members may access the packet data in any way. You just need to ensure, that
145 the integration into the packet-type is correct (the senf::PacketTypeMixin will by default use
146 senf::bytes() to find the end of the header).
151 #ifndef HH_PacketParser_
152 #define HH_PacketParser_ 1
155 #include <boost/utility/enable_if.hpp>
156 #include <boost/type_traits.hpp>
157 #include <boost/optional.hpp>
158 #include "../Utils/safe_bool.hh"
159 #include "PacketTypes.hh"
160 #include "PacketData.hh"
161 #include "ParseHelpers.hh"
163 //#include "PacketParser.mpp"
164 ///////////////////////////////hh.p////////////////////////////////////////
170 /** \brief Parser Base class
172 Parsers come in two flavors: fixed and dynamically sized parsers. A <em>fixed size
173 parser</em> has a constant size, it will always parse a fixed number of bytes. The low-level
174 'final' parsers (like the integer parsers) are fixed size parsers as are composite parsers
175 built up only of fixed-size fields.
177 A <em>dynamically sized</em> parser on the other hand infers it's size from the contents of
178 the data parsed. Any parser containing at least one dynamically sized sub-parser will itself
179 be dynamically sized.
181 Both kinds of parser need to derive from PacketParserBase and implement several required
182 members. Which members to implement depends on the parsers flavor. There are two ways how to
184 \li If the parser just consists of sequence of consecutive fields (sub-parsers), the \ref
185 packetparsermacros provide a simple yet flexible way to define a packet parser.
186 \li In more complex cases, you need to implement the necessary members manually.
188 This documentation is about the manual implementation. You should nevertheless read through
189 this to understand, what above macros are doing.
191 The following example documents the interface (which must be) provided by a parser:
193 struct FooParser : public PacketParserBase
195 FooParser(data_iterator i, state_type s) : PacketParserBase(i,s) {}
197 // If this parser has a fixed size, you must define this size here This definition
198 // allows the parser to be used within the list, vector and array parsers static
199 static const size_type fixed_bytes = some_constant_size;
201 // If the parser does not have a fixed size, you must implement the bytes() member to
202 // return the size. ONLY EVER DEFINE ONE OF fixed_bytes OR bytes().
203 size_type bytes() const;
205 // If you define bytes(), you also need to define the init_bytes. This is the number
206 // of bytes to allocate when creating a new object
207 static const size_type init_bytes = some_constant_size;
209 // You also may define an init() member. This will be called to initialize a newly
210 // created data object. The default implementation just does nothing.
213 // ////////////////////////////////////////////////////////////////////////
215 // Add here members returning (sub-)parsers for the fields. The 'parse' member is
216 // used to construct the sub-parsers. This member either takes an iterator to the
217 // data to be parsed or just an offset in bytes.
219 senf::Parse_UInt16 type() const { return parse<Parse_UInt16>( 0 ); }
220 senf::Parse_UInt16 size() const { return parse<Parse_UInt16>( 2 ); }
224 You should never call the \c bytes() member of a parser directly. Instead you should use the
225 freestanding senf::bytes() function. This function will return the correct size irrespective
226 of the parsers flavor. You may access \c fixed_bytes directly, however be aware that this
227 will restrict your code to fixed size parsers (which depending on the circumstances may be
228 exactly what you want).
230 In the same way, don't access \c init_bytes directly, always use the senf::init_bytes
231 meta-function class which correctly supports fixed size parsers.
233 \ingroup packetparser
235 class PacketParserBase
238 ///////////////////////////////////////////////////////////////////////////
241 typedef detail::packet::iterator data_iterator; ///< Raw data iterator type
242 typedef detail::packet::size_type size_type; ///< Unsigned integral type
243 typedef detail::packet::difference_type difference_type; ///< Signed integral type
244 typedef detail::packet::byte byte; ///< Unsigned 8bit value, the raw value type
245 typedef PacketData * state_type; ///< Type of the 'state' parameter
246 typedef PacketParserBase parser_base_type; ///< Base type of the next parser
248 ///////////////////////////////////////////////////////////////////////////
249 ///\name Structors and default members
252 // no default constructor
254 // default destructor
255 // no conversion constructors
258 ///////////////////////////////////////////////////////////////////////////
260 data_iterator i() const; ///< Return beginning of data to parse
261 /**< The parser is expected to interpret the data beginning
262 here. The size of the interpreted is given by
263 <tt>senf::bytes(</tt><em>parser
264 instance</em><tt>)</tt>. */
265 state_type state() const; ///< Return state of this parser
266 /**< The value returned should be interpreted as an opaque
267 value provided just to be forwarded to other
269 PacketData & data() const; ///< Access the packets raw data container
270 /**< This member will return the raw data container holding
271 the data which is parsed by \c this parser. */
273 void init() const; ///< Default implementation
274 /**< This is just an empty default
275 implementation. Re-implement this member in your own
276 parsers if needed. */
279 PacketParserBase(data_iterator i, state_type s); ///< Standard constructor
280 /**< This is the constructor used by most parsers. The
281 parameters are just forwarded from the derived classes
282 constructor parameters. */
283 PacketParserBase(data_iterator i, state_type s, size_type size);
284 ///< Size checking constructor
285 /**< In addition to the standard constructor, this
286 constructor will validate, that there is enough data in
287 the raw data container to parse \a size bytes after \a
290 This constructor is called by all 'final' parsers
291 (e.g. the integer parsers) and \e only by those
292 parsers. Most parsers do \e not check the validity of
293 the iterator, this is delayed until the very last
294 parser. This allows to partial parse truncated
297 \throw TruncatedPacketException if the raw data
298 container does not hold at least \a size bytes
299 beginning at \a i. */
301 bool check(size_type size) const; ///< Check size of data container
302 /**< \returns \c true, if the data container holds at least
303 \a size beginning at i(), \c false otherwise. */
304 void validate(size_type size) const; ///< Validate size of data container
305 /**< \throws TruncatedPacketException if the raw data
306 container does not hold at least \a size bytes
309 template <class Parser> Parser parse(data_iterator i) const; ///< Create sub-parser
310 /**< Creates a new instance of \a Parser to parse data
311 beginning at \a i. Automatically passes \a state() to
313 template <class Parser> Parser parse(size_type n) const; ///< Create sub-parser
314 /**< Creates a new instance of \a Parser to parse data
315 * beginning at i()<tt> + </tt>\a n. Automatically passes \a
316 state() to the new parser. */
318 void defaultInit() const; ///< Default implementation
319 /**< This is just an empty default
320 implementation. Re-implement this member in your own
321 parsers if needed. */
323 Packet packet() const; ///< Get packet this parser is parsing from
324 /**< \important This member should only be used from packet
325 parsers when access to previous or following packets is
326 needed e.g. for calculating checksums etc. */
329 data_iterator end() const;
334 template <class Parser> friend class SafePacketParser;
337 /** \brief Return raw size parsed by the given parser object
339 This function will either call <tt>p.bytes()</tt> or return <tt>Parser::fixed_bytes</tt>
340 depending on the type of parser.
342 The value returned does \e not take into account the amount of data actually available. So
343 you always need to validate this value against the packet size if you directly access the
344 data. The standard low-level parses all do this check automatically to guard against
347 \param[in] p Parser object to check
348 \returns number of bytes this parser expects to parser
349 \ingroup packetparser
351 template <class Parser>
352 PacketParserBase::size_type bytes(Parser p);
354 namespace detail { template <class Parser> class ParserInitBytes; }
356 /** \brief Return number of bytes to allocate to new object of given type
358 This meta-function is called like
360 senf::init_bytes<SomeParser>::value
363 This expression evaluates to a compile-time constant integral expression of type
364 senf::PacketParserBase::size_type. This meta-function will return \c Parser::fixed_bytes or
365 \c Parser::init_bytes depending on the type of parser.
367 \param[in] Parser The Parser to return init_bytes for
368 \returns Number of bytes to allocate to the new object
369 \ingroup packetparser
371 template <class Parser>
372 struct init_bytes : public detail::ParserInitBytes<Parser>
376 template <class Parser>
377 typename boost::enable_if<
378 boost::is_base_of<PacketParserBase, Parser>,
380 operator<<(Parser target, Parser source);
382 /** \brief Generic parser copying
385 This operator allows to copy the values of identical parsers. This operation does \e not
386 depend on the parsers detailed implementation, it will just replace the data bytes of the
387 target parser with those from the source parser. This allows to easily copy around complex
388 packet substructures.
390 This operation is different from the ordinary assignment operator: It does not change the \a
391 target parser, it changes the data referenced by the \a target parser.
393 \ingroup packetparser
395 template <class Parser>
396 Parser operator<<(Parser target, Parser source);
400 template <class Parser, class Value>
401 typename boost::enable_if_c <
402 boost::is_base_of<PacketParserBase, Parser>::value
403 && ! boost::is_base_of<PacketParserBase, Value>::value,
405 operator<<(Parser target, Value const & value);
407 /** \brief Generic parser value assignment
409 This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
410 value<tt>)</tt> member. This operator allows to use a common syntax for assigning values or
413 \ingroup packetparser
415 template <class Parser, class Value>
416 Parser operator<<(Parser target, Value const & value);
420 template <class Parser, class Value>
421 typename boost::enable_if_c <
422 boost::is_base_of<PacketParserBase, Parser>::value
423 && ! boost::is_base_of<PacketParserBase, Value>::value,
425 operator<<(Parser target, boost::optional<Value> const & value);
427 /** \brief Generic parser value assignment
429 This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
430 value<tt>)</tt> member. This special version allows to assign optional values: IF the
431 optional value is not set, the assignment will be skipped.
433 This operator allows to use a common syntax for assigning values or parsers to a parser.
435 \ingroup packetparser
437 template <class Parser, class Value>
438 Parser operator<<(Parser target, boost::optional<Value> const & value);
441 /** \brief Default parser parsing nothing
443 struct VoidPacketParser
444 : public PacketParserBase
446 # include SENF_FIXED_PARSER()
447 SENF_PARSER_FINALIZE(VoidPacketParser);
450 /** \brief Iterator re-validating Parser wrapper
452 An ordinary parser will be invalidated whenever the raw data container's size is
453 changed. This can complicate some algorithms considerably.
455 This wrapper will update the parsers iterator (the value returned by the i() member) on
456 every access. This ensures that the iterator will stay valid.
458 \attention Beware however, if you insert or remove data before the safe wrapper, the
459 location will \e not be updated accordingly and therefore the parser will be
462 Additionally a SafePacketParser has an uninitialized state. The only allowed operations in
463 this state are the boolean test for validity and assigning another parser.
465 \ingroup packetparser
467 template <class Parser>
468 class SafePacketParser
469 : public safe_bool< SafePacketParser<Parser> >
472 ///////////////////////////////////////////////////////////////////////////
475 ///////////////////////////////////////////////////////////////////////////
476 ///\name Structors and default members
479 // default copy constructor
480 // default copy assignment
481 // default destructor
482 SafePacketParser(); ///< Create an empty uninitialized SafePacketParser
484 // conversion constructors
485 SafePacketParser(Parser parser); ///< Initialize SafePacketParser from \a parser
487 SafePacketParser & operator=(Parser parser); ///< Assign \a parser to \c this
490 ///////////////////////////////////////////////////////////////////////////
492 Parser operator*() const; ///< Access the stored parser
493 /**< On every access, the stored parsers iterator will be
494 updated / re-validated. */
495 Parser const * operator->() const; ///< Access the stored parser
496 /**< On every access, the stored parsers iterator will be
497 updated / re-validated. */
498 bool boolean_test() const; ///< Check validity
503 mutable boost::optional<Parser> parser_;
504 senf::safe_data_iterator i_;
509 ///////////////////////////////hh.e////////////////////////////////////////
511 #if !defined(HH_Packets__decls_) && !defined(HH_PacketParser_i_)
512 #define HH_PacketParser_i_
513 #include "PacketParser.cci"
514 #include "PacketParser.ct"
515 #include "PacketParser.cti"
522 // c-file-style: "senf"
523 // indent-tabs-mode: nil
524 // ispell-local-dictionary: "american"
525 // compile-command: "scons -u test"
526 // comment-column: 40