Packets: Add introductory parse helper documentation
[senf.git] / Packets / ParseHelpers.hh
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief ParseHelpers public header */
25
26 #ifndef HH_ParseHelpers_
27 #define HH_ParseHelpers_ 1
28
29 #ifndef HH_Packets_
30 #error "Don't include 'ParseHelpers.hh' directly, include 'Packets.hh'"
31 #endif
32
33 // Custom includes
34
35 //#include "ParseHelpers.mpp"
36 #include "ParseHelpers.ih"
37 ///////////////////////////////hh.p////////////////////////////////////////
38
39 /** \defgroup packetparsermacros Helper macros for defining new packet parsers
40
41     To simplify the definition of simple packet parsers, several macros are provided. Before
42     using these macros you should familiarize yourself with the packet parser interface as
43     described in senf::PacketParserBase.
44
45     These macros simplify providing the above defined interface. A typical packet declaration
46     using these macros has the following form (This is a concrete example from the definition of
47     the ethernet packet in <tt>DefaultBundle/EthernetPacket.hh</tt>)
48
49     \code
50     struct Parse_EthVLan : public PacketParserBase
51     {
52     #   include SENF_FIXED_PARSER()
53
54         SENF_PARSER_BITFIELD( priority,  3, unsigned );
55         SENF_PARSER_BITFIELD( cfi,       1, bool     );
56         SENF_PARSER_BITFIELD( vlanId,   12, unsigned );
57
58         SENF_PARSER_FIELD( type, Parse_UInt16 );
59
60         SENF_PARSER_FINALIZE(Parse_EthVLan);
61     };
62     \endcode
63
64     The macros take care of the following:
65     \li They define the accessor functions returning parsers of the given type.
66     \li They automatically calculate the offset of the fields from the preceding fields.
67     \li The macros provide a definition for \c init() 
68     \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
69
70     You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined by
71     starting the packet with <tt>\#include SENF_FIXED_PARSER()</tt>, dynamically sized parsers start
72     with <tt>\#include SENF_PARSER()</tt>. The different members are implemented such that:
73
74     \li The needed parser constructor is defined
75     \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
76         of the fields.
77     \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
78         parsers) is defined to return the sum of the sizes of all fields.
79     \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
80         \c init_byte's of all fields
81
82     \section parserlanguage The Parser Macro micro-language
83
84     The macros provided to help implement collection parsers implement a very small declarative
85     language. This way of to think of the macros simplifies understanding, how the macros work.
86
87     Central to this language is the concept of <em>current offset</em>. The current offset is the
88     place (in bytes) from the beginning of the parser at which the next field will be added. Adding
89     fields to the parser will advance this offset by the size of the field added. Additional
90     commands allow to arbitrarily manipulate the current offset manually.
91
92     For fixed size parsers, the current offset is a single constant integral value, the number of
93     bytes from the parsers start. For dynamically sized parsers, the current offset really consists
94     of two values: One is the number of bytes from the parsers start, which however needs not be a
95     constant expression, the other value is the \c init_bytes value at this point, which is an
96     integral constant.
97
98     To demonstrate this functionality, here a more complex example (taken from MPEGDVBBundle and
99     then simplified by removing some fields)
100     \code
101     struct Parse_DSMCCSection : public PacketParserBase
102     {
103     #   include SENF_FIXED_PARSER()
104
105         SENF_PARSER_FIELD    ( table_id            , Parse_UInt8   );
106         
107         SENF_PARSER_BITFIELD ( ssi                 ,  1 , bool     );
108         SENF_PARSER_BITFIELD ( private_indicator   ,  1 , bool     );
109         SENF_PARSER_SKIP_BITS( 2 );
110         SENF_PARSER_BITFIELD ( sec_length          , 12 , unsigned );
111         
112         SENF_PARSER_FIELD    ( table_id_extension  , Parse_UInt16  );
113         
114         SENF_PARSER_FINALIZE( Parse_DSMCCSection );
115     };
116
117     struct Parse_DatagramSection : public Parse_DSMCCSection
118     {
119     #   include SENF_FIXED_PARSER()
120
121         SENF_PARSER_INHERIT( Parse_DSMCCSection );
122
123         SENF_PARSER_FIELD    ( mac_addr_4          , Parse_UInt8   );
124         SENF_PARSER_FIELD    ( mac_addr_3          , Parse_UInt8   );
125
126         SENF_PARSER_FINALIZE( Parse_DatagramSection );
127
128         // Parse table_id_extension as two bytes
129         SENF_PARSER_GOTO( table_id_extension );
130         SENF_PARSER_FIELD    ( mac_addr_6          , Parse_UInt8   );
131         SENF_PARSER_FIELD    ( mac_addr_5          , Parse_UInt8   );
132     };
133     \endcode
134
135     This code defines two parsers, the second of which is based on the first. Both are fixed size
136     parsers. The definition of \c Parse_DSMCCSection is straight forward (more on bit fields
137     below). 
138
139     The derived parser is a little bit more complex. It starts out the same defining itself as a
140     fixed size parser. Then the base class is imported. Among other things, this call sets the
141     current offset to the first byte after the base parser (the base parser need not be implemented
142     using the packet parser macros, it just needs to be a valid parser). The additional fields \c
143     mac_addr_4 and \c mac_addr_3 are defined. Then we finalize the parser declaration.
144
145     <em>After</em> \ref SENF_PARSER_FINALIZE we add two more fields but not at the end of the
146     parser. \ref SENF_PARSER_GOTO jumps back to a previously defined label or field. Since the base
147     parser \c Parse_DSMCCSection is defined using the packet parser macros, we can even jump to
148     labels or fields defined in the base parser. Here, we jump to the beginning of the \c
149     table_id_extension field. \c mac_addr_6 and \c mac_addr_5 are therefore defined starting at that
150     offset and therefore overlay the \c table_id_extension field.
151
152     \section parsermacroinit Parser initialization
153
154     \par ""
155         \ref SENF_FIXED_PARSER(), \ref SENF_PARSER(), \ref SENF_PARSER_INHERIT(), \ref
156         SENF_PARSER_INIT(), \ref SENF_PARSER_FINALIZE()
157
158     Every parser using the parser macros starts either with <tt>\#include SENF_PARSER()</tt> or with
159     <tt>\#include SENF_FIXED_PARSER()</tt>. This command sets the current offset to zero and defines
160     the type of parser to define.
161
162     A following optional \ref SENF_PARSER_INHERIT(\e base_class) is necessary if the parser does not
163     derive from senf::PacketParserBase. This call sets the base class and advances the current
164     offset to the end of the base parser.
165
166     \ref SENF_PARSER_INIT() is used to define the parser initialization code (the \c init()
167     member).
168
169     \ref SENF_PARSER_FINALIZE(\e class_name) is called to define the parsers constructor, the \c
170     init() member and to set the parsers size (\c fixed_bytes for fixed size parsers or \c bytes()
171     and \c init_bytes for dynamically sized parsers). It is valid to define further fields \e after
172     \ref SENF_PARSER_FINALIZE() has been called, however
173     \li Fields defined after \ref SENF_PARSER_FINALIZE() will \e not be initialized by \c
174         defaultInit() (and therefore not by the default provided \c init() member). This can be very
175         helpful when defining overlaying fields to avoid initializing some bytes multiple times.
176     \li The size of the parser is given by the current offset at the time of the \ref
177         SENF_PARSER_FINALIZE() call.
178
179     \section parsermacrofields Defining fields
180
181     \par ""
182         \ref SENF_PARSER_FIELD(), \ref SENF_PARSER_FIELD_RO(), \ref SENF_PARSER_PRIVATE_FIELD(),
183         \ref SENF_PARSER_PRIVATE_FIELD_RO(), SENF_PARSER_CUSTOM_FIELD()
184
185     There are quite a few commands available to define fields. All these macros do the same thing:
186     they define a field accessor plus some auxiliary symbols for the field:
187     \par ""
188         <em>type</em> <em>name</em><tt>()</tt> <tt>const</tt><br>
189         <tt>typedef</tt> <em>type</em> <em>name</em><tt>_t</tt><br>
190         <tt>size_type</tt> <tt>const</tt> <em>name</em><tt>_offset</tt><br>
191         &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>or</em><br>
192         &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<tt>size_type</tt> <em>name</em><tt>_offset()</tt> <tt>const</tt>
193     
194     Here \e type is the type of the field defined (the return value of the \e name() accessor) and
195     \e name is the field name. <em>name</em><tt>_offset</tt> gives the offset of the first byte of
196     the field from the start of the parser. This member is a constant for fixed size parser and a
197     member function for dynamically sized parsers. <em>name</em><tt>_t</tt> is just an alias for the
198     fields type (more precisely the return type of the <em>name</em>() accessor).
199
200     There are some properties the field defining macros might have. These properties are parts
201     of the macro name:
202
203     \par RO: Read only fields
204         Macros with \c RO in their name define read only fields. This is only possible, if the
205         field's parser is a value parser (that is, it must have a \c value_type typedef member and
206         must provide the \c value() accessor member function). In this case, the value returned from
207         the \e name() accessor member is not the parser but the parsers value and therefore it does
208         not allow assignment to the field.
209
210     \par PRIVATE: Fields private to the parser class 
211         A private field will not be accessible from the outside (it is made \c private to the parser
212         class). This is very handy when providing other accessor members to access a field in a
213         manner more suitable for the specific field, when combining several fields into a single
214         return value etc.
215
216     The field defining macros come in groups which members only differ in their properties:
217
218     \par Define standard fields:
219         \ref SENF_PARSER_FIELD(), \ref SENF_PARSER_FIELD_RO(), \ref SENF_PARSER_PRIVATE_FIELD(),
220         \ref SENF_PARSER_PRIVATE_FIELD_RO() define standard fields.
221
222     \par Define arbitrary custom field:
223         \ref SENF_PARSER_CUSTOM_FIELD()
224
225     See the documentation of each of these macros for a detailed description of the macro arguments
226     and usage. Bit-fields are handled in the following section.
227
228     \subsection parsermacrobitfields Bit-fields
229
230     \par "" 
231         \ref SENF_PARSER_BITFIELD(), \ref SENF_PARSER_BITFIELD_RO(), \ref
232         SENF_PARSER_PRIVATE_BITFIELD(), \ref SENF_PARSER_PRIVATE_BITFIELD_RO() \n
233
234     Bit-fields play a special role. They are quite frequent in packet definitions but don't fit into
235     the byte offset based parsing infrastructure defined so far. Since defining the correctly
236     parameterized Parse_IntField, Parse_UIntField and Parse_Flag typedefs is quite tedious, these
237     helper macros are provided.
238
239     It is important to recognize, that the current offset does \e not include the current bit
240     position. The current offset after defining a bit-field will be the first complete byte after
241     that bit-field. Only the bit-field macros additionally take care of the current bit position
242     which is reset automatically by any intervening non-bitfield command.
243
244     So bit-field commands will come in groups. Any group of consecutive bitfield commands defines a
245     set of consecutive bits. The group as a whole will always be considered to cover a fixed number
246     of complete bytes. If the group does not cover those bytes completely (there are some bit's left
247     at the end), those bit's will be skipped.
248
249     Since consecutive bit-field commands are aggregated into a single bit-field group, the offset of
250     all these bit-fields will be the offset of the \e beginning of the bit-field irrespective of the
251     number of bits parsed so far. Changing the offset to some bitfield using \ref SENF_PARSER_GOTO()
252     will therefore always go to the position at the beginning of this bitfield group. And since the
253     current offset does not include the bit position, the bit position will be 0, the first bit. You
254     may however break a bit-field group into two groups (at a byte boundary) by placing a \ref
255     SENF_PARSER_LABEL() command between the two groups.
256
257     The additional command \ref SENF_PARSER_SKIP_BITS() can be used to skip bit's between two
258     bit-fields.
259
260     \section parsermacrooffset Manipulating the current offset
261
262     \par ""
263         \ref SENF_PARSER_SKIP(), \ref SENF_PARSER_SKIP_BITS(), \ref SENF_PARSER_GOTO(), \ref
264         SENF_PARSER_GOTO_OFFSET(), \ref SENF_PARSER_LABEL()
265
266     To define more complex parsers, there are some macro commands which change the current offset. 
267
268     \ref SENF_PARSER_SKIP(\e bytes) will skip the given number of bytes. \ref
269     SENF_PARSER_SKIP_BITS(\e bits) will work within bitfield definition to skip that number of bits.
270
271     \ref SENF_PARSER_GOTO(\e label_or_field) will change the offset to the given field or label. The
272     following fields will therefore start at that offset and overlay any fields already defined.
273
274     \ref SENF_PARSER_GOTO_OFFSET(\e offset) will jump to the given byte offset from the start of the
275     parser.
276
277     \ref SENF_PARSER_LABEL(\e name) will define \e name as a label for the current offset which can
278     then later be referenced using \ref SENF_PARSER_GOTO(). This also defines
279     <em>name</em><tt>_offset</tt> as a constant or member (for fixed respectively dynamically sized
280     parsers).
281     
282     It is very important to recognize, that the size of the parser is defined by the current offset
283     <em>at the time \ref SENF_PARSER_FINALIZE() is called</em>. This allows to arbitrarily
284     manipulate the size of the parser by changing the current offset accordingly. For dynamically
285     sized parsers, the offset can even be any expression involving member function calls. See the
286     documentation of the respective macros for more details.
287
288     \ingroup packetparser
289  */
290 ///\ingroup packetparsermacros
291 ///\{
292
293 #define SENF_FIXED_PARSER()      SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_fixed_setup.hh)
294 #define SENF_PARSER()            SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_setup.hh)
295
296 #define SENF_PARSER_INHERIT      BOOST_PP_CAT(SENF_PARSER_INHERIT_,      SENF_PARSER_TYPE)
297
298 #define SENF_PARSER_FIELD        BOOST_PP_CAT(SENF_PARSER_FIELD_,        SENF_PARSER_TYPE)
299 #define SENF_PARSER_FIELD_RO     BOOST_PP_CAT(SENF_PARSER_FIELD_RO_,     SENF_PARSER_TYPE)
300 #define SENF_PARSER_BITFIELD     BOOST_PP_CAT(SENF_PARSER_BITFIELD_,     SENF_PARSER_TYPE)
301 #define SENF_PARSER_BITFIELD_RO  BOOST_PP_CAT(SENF_PARSER_BITFIELD_RO_,  SENF_PARSER_TYPE)
302 #define SENF_PARSER_CUSTOM_FIELD BOOST_PP_CAT(SENF_PARSER_CUSTOM_FIELD_, SENF_PARSER_TYPE)
303
304 #define SENF_PARSER_PRIVATE_FIELD       BOOST_PP_CAT(SENF_PARSER_P_FIELD_,       SENF_PARSER_TYPE)
305 #define SENF_PARSER_PRIVATE_FIELD_RO    BOOST_PP_CAT(SENF_PARSER_P_FIELD_RO_,    SENF_PARSER_TYPE)
306 #define SENF_PARSER_PRIVATE_BITFIELD    BOOST_PP_CAT(SENF_PARSER_P_BITFIELD_,    SENF_PARSER_TYPE)
307 #define SENF_PARSER_PRIVATE_BITFIELD_RO BOOST_PP_CAT(SENF_PARSER_P_BITFIELD_RO_, SENF_PARSER_TYPE)
308
309 #define SENF_PARSER_SKIP         BOOST_PP_CAT(SENF_PARSER_SKIP_,        SENF_PARSER_TYPE)
310 #define SENF_PARSER_SKIP_BITS    BOOST_PP_CAT(SENF_PARSER_SKIP_BITS_,   SENF_PARSER_TYPE)
311 #define SENF_PARSER_GOTO         BOOST_PP_CAT(SENF_PARSER_GOTO_,        SENF_PARSER_TYPE)
312 #define SENF_PARSER_GOTO_OFFSET  BOOST_PP_CAT(SENF_PARSER_GOTO_OFFSET_, SENF_PARSER_TYPE)
313 #define SENF_PARSER_LABEL        BOOST_PP_CAT(SENF_PARSER_LABEL_,       SENF_PARSER_TYPE)
314
315 /** \brief Define parser initialization routine
316
317     \code
318     SENF_PARSER_INIT() {
319         defaultInit();
320         foo() = 2;
321     }
322     \endcode
323     Defining the initialization code manually skips the automatic call of defaultInit(), which may
324     be performed manually. Should the initialization code be more complex, it should be placed into
325     a non-inline private member which is called from \ref SENF_PARSER_INIT()
326     
327     \hideinitializer
328  */
329 #define SENF_PARSER_INIT()       void init(int)
330
331 #define SENF_PARSER_FINALIZE     BOOST_PP_CAT(SENF_PARSER_FINALIZE_,    SENF_PARSER_TYPE)
332
333 ///\}
334
335 ///////////////////////////////hh.e////////////////////////////////////////
336 #endif
337 #if !defined(HH_Packets__decls_) && !defined(HH_ParseHelpers_i_)
338 #define HH_ParseHelpers_i_
339 //#include "ParseHelpers.cci"
340 //#include "ParseHelpers.ct"
341 //#include "ParseHelpers.cti"
342 #endif
343
344 \f
345 // Local Variables:
346 // mode: c++
347 // fill-column: 100
348 // comment-column: 40
349 // c-file-style: "senf"
350 // indent-tabs-mode: nil
351 // ispell-local-dictionary: "american"
352 // compile-command: "scons -u test"
353 // End: