Merged revisions 262,264-265,267-282,284-298,300-311 via svnmerge from
[senf.git] / Packets / PacketType.hh
1 // Copyright (C) 2007 
2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 //     Stefan Bund <g0dil@berlios.de>
5 //
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.
10 //
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.
15 //
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.
20
21 /** \file
22     \brief PacketType public header */
23
24 #ifndef HH_PacketType_
25 #define HH_PacketType_ 1
26
27 // Custom includes
28 #include <iostream>
29 #include "PacketTypes.hh"
30 #include "PacketData.hh"
31 #include "PacketParser.hh"
32 #include "Packet.hh"
33
34 //#include "PacketType.mpp"
35 ///////////////////////////////hh.p////////////////////////////////////////
36
37 namespace senf {
38
39     /** \brief Helper baseclass implementing the PacketType interface
40
41         This helper class maybe used when building a new PacketType. It provides a complete default
42         implementations of this interface. To define a new PacketType, derive from this class and
43         implement the members you want to change.
44
45         \code
46         struct SomePacketType : public senf::PacketTypeBase
47         {
48             typedef senf::ConcretePacket<SomePacketType> packet;
49             typedef SomePacketParser parser;
50             
51             static size_type initSize()
52             {
53                 // This value can in most cases be taken from the parser
54                 return senf::init_size<parser>::value;
55             }
56
57             static size_type initHeadSize()
58             {
59                 // optional member. This is only needed, if the packet has header and trailer.
60                 return constant_initial_size_of_header
61             }
62
63             static void init(packet p)
64             {
65                 // Initialize a new packet by e.g. setting some fields. Should call
66                 // the packet parsers init() member
67                 p->init();
68                 p->some_field() = 1;
69             }
70
71             static optional_range nextPacketRange(packet p)
72             {
73                 if (have_next_packet)
74                     // return iterator range delimiting the packet, e.g.:
75                     return range(p.data()+begin_offset, p.data()+end_offset);
76                 else
77                     return no_range();
78             }
79
80             static factory_t nextPacketType(packet p)
81             {
82                 if (have_next_packet && know_next_packet_type)
83                     // \a NextPacket is the \c ConcretePacket instantiation of the next packet
84                     return NextPacket::factory();
85                 else
86                     return no_factory();
87             }
88
89             static void finalize(packet p)
90             {
91                 // optionally complete the packet by generating autogenerated information
92                 // (like checksums)
93             }
94
95             static void dump(packet p, std::ostream & os)
96             {
97                 // Write out a readable representation of the packet for debug purposes
98             }
99         }
100         \endcode
101
102         You may leave out any one of the members (you should however always define the \c
103         interpreter typedef member)
104       */
105     struct PacketTypeBase
106     {
107         typedef Packet packet;
108         
109         typedef senf::detail::packet::iterator iterator;
110         typedef senf::detail::packet::const_iterator const_iterator;
111         typedef senf::detail::packet::size_type size_type;
112         typedef senf::detail::packet::difference_type difference_type;
113         typedef senf::detail::packet::byte byte;
114
115         typedef PacketInterpreterBase::range range;
116         typedef PacketInterpreterBase::optional_range optional_range;
117         typedef PacketInterpreterBase::factory_t factory_t;
118
119         static optional_range no_range();
120         static factory_t no_factory();
121         template <class PacketType> static factory_t factory();
122
123         typedef VoidPacketParser parser;
124                                         ///< Parser to parser packet fields
125                                         /**< This typedef has to be set to the parser of the packet
126                                              
127                                              The default is a VoidPacketParser which does not parser
128                                              any field. */
129
130         static size_type initSize();
131                                         ///< Get size of new (empty) packet
132                                         /**< The default implementation returns 0.
133                                              \returns size that needs to be allocated to a newly
134                                              constructed packet */
135
136         static size_type initHeadSize();
137                                         ///< Get size of new (empty) packet header
138                                         /**< This function gives the index within a newly created,
139                                              empty packet where a subpacket is to be placed.
140
141                                              The default implementation returns initSize(). 
142                                              
143                                              \implementation Ok, it does not really return
144                                                  initSize(), it returns size_type(-1) which is
145                                                  interpreted to mean initSize(). It can't return
146                                                  initSize since initSize() is not (and can't be
147                                                  since it is static) virtual. */
148
149         static void init(packet p);
150                                         ///< Initialize new packet
151                                         /**< This member is called to initialize a just created new
152                                              packet. The new packet will have a size of at least
153                                              initSize() but the size may well be larger. It is also
154                                              possible for the packet to already have further
155                                              subpackets.
156
157                                              The default implementation does nothing. */
158
159         
160
161         static optional_range nextPacketRange(packet p);
162                                         ///< Get next packet placement
163                                         /**< nextPacketRange returns the iterator range where the
164                                              next packet (header) is placed within the current
165                                              packet.
166                                             
167                                              The default implementation always returns
168                                              <tt>no_range()</tt>.
169
170                                              \returns nextPacketRange must return
171                                              \li <tt>\ref interpreter::range(b,e)</tt> (where \a b
172                                                  and \a e are the iterators delimiting the next
173                                                  packet range) if the packet allows a next
174                                                  header. The returned range is allowed to be empty.
175                                              \li <tt>\ref interpreter::no_range()</tt> (a
176                                                  default constructed \c no_range instance) if
177                                                  no next header is allowed */
178
179         static factory_t nextPacketType(packet p);
180                                         ///< Get type of next packet
181                                         /**< nextPacketType retrieves the type of the next packet
182                                              returning a factory to create that packet.
183                                              
184                                              The default implementation always returns
185                                              <tt>no_factory()</tt>.
186
187                                              \returns factory to create next packet
188                                              \li <tt>interpreter::factory<OtherPacketType>()</tt> if
189                                                  the type of the packet can be determined
190                                              \li <tt>interpreter::no_factory()</tt> if the type of
191                                                  the packet cannot be determined or no next packet
192                                                  is supported */
193
194         static void finalize(packet p);
195                                         ///< Finalize packet
196                                         /**< finalize() will be called to complete a packet after it
197                                              has been modified. This function must calculate any
198                                              checksums, set size fields from the interpreter chain
199                                              etc. 
200                                              
201                                              The default implementation does nothing. */
202
203         static void dump(packet p, std::ostream & os);
204                                         ///< Dump packet data in readable form
205                                         /**< The dump() function writes out a complete
206                                              representation of the packet. This is used formost for
207                                              debugging purposes. 
208
209                                              The default implementation does nothing. */
210     };
211
212
213     /** \brief Mixin to provide standard implementations for nextPacketRange and nextPacketType
214
215         This mixin class simplifies the definition of simple packets with fixed-size headers and/or
216         trailers. For this type of Packet, this mixin provides the nextPacketRange() and
217         nextPacketType() members:
218         \code
219         struct SimplePacketType 
220             : public senf::PacketTypeBase
221               pyblic senf:PacketTypeMixin<SimplePacketType, SomeRegistryTag>
222         {
223             static interpreter::size_type initSize()
224             {
225                 // This member is optional. If it is not defined, 'senf::init_size<parser>::value'
226                 // will be returned.
227         
228                 // The value returned is the length of the header if initHeadSize() is not defined.
229                 // If initHeadSize is defined, this value is the combined size of the header
230                 // and trailer while initHeadSize() will return the size of the header only.
231                 return packet_size;
232             }
233         
234             static interpreter::size_type initHeadSize()
235             {
236                 // This member is optional. It returns the header size if the packet has a
237                 // trailer.
238                 return header_size;
239             }
240
241             static registry_key_t nextPacketKey(packet p)
242             {
243                 // Return the key in the registry under which the next packet
244                 // header is to be found. This member must be given if a Registry argument is
245                 // passed to the PacketTypeMixin template.
246                 return i.fields().typeField();
247             }
248         };
249         \endcode
250      */
251     template <class Self, class Registry=void>
252     class PacketTypeMixin
253     {
254     public:
255         typedef typename Registry::key_t registry_key_t;
256
257         static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
258         static PacketInterpreterBase::factory_t      nextPacketType  (Packet p);
259         static PacketInterpreterBase::size_type      initSize        ();
260         static void                                  init            (Packet p);
261     };
262
263     template <class Self>
264     class PacketTypeMixin<Self,void>
265     {
266     public:
267         static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
268         static PacketInterpreterBase::size_type      initSize        ();
269         static void                                  init            (Packet p);
270     };
271
272 }
273
274 ///////////////////////////////hh.e////////////////////////////////////////
275 #include "PacketType.cci"
276 //#include "PacketType.ct"
277 #include "PacketType.cti"
278 #endif
279
280 \f
281 // Local Variables:
282 // mode: c++
283 // fill-column: 100
284 // c-file-style: "senf"
285 // indent-tabs-mode: nil
286 // ispell-local-dictionary: "american"
287 // End: