4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief PacketType public header */
26 #ifndef HH_SENF_Packets_PacketType_
27 #define HH_SENF_Packets_PacketType_ 1
31 #include "PacketTypes.hh"
32 #include "PacketData.hh"
33 #include "PacketParser.hh"
36 //#include "PacketType.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
41 /** \brief Helper base-class implementing the PacketType interface
43 This helper class maybe used when building a new PacketType. It provides a complete default
44 implementations of this interface. To define a new PacketType, derive from this class and
45 implement the members you want to change.
48 struct SomePacketType : public senf::PacketTypeBase
50 typedef senf::ConcretePacket<SomePacketType> packet;
51 typedef SomePacketParser parser;
53 static size_type initSize()
55 // This value can in most cases be taken from the parser
56 return senf::init_size<parser>::value;
59 static size_type initHeadSize()
61 // optional member. This is only needed, if the packet has header and trailer.
62 return constant_initial_size_of_header
65 static void init(packet p)
67 // Initialize a new packet by e.g. setting some fields. Should call
68 // the packet parsers init() member
73 static optional_range nextPacketRange(packet p)
76 // return iterator range delimiting the packet, e.g.:
77 return range(p.data()+begin_offset, p.data()+end_offset);
82 static factory_t nextPacketType(packet p)
84 if (have_next_packet && know_next_packet_type)
85 // \a NextPacket is the \c ConcretePacket instantiation of the next packet
86 return NextPacket::factory();
91 static void finalize(packet p)
93 // optionally complete the packet by generating auto-generated information
97 static void dump(packet p, std::ostream & os)
99 // Write out a readable representation of the packet for debug purposes
104 You may leave out any one of the members (you should however always define the \c
105 packet typedef member)
107 \ingroup packet_module
109 struct PacketTypeBase
111 typedef Packet packet;
113 typedef senf::detail::packet::iterator iterator;
114 typedef senf::detail::packet::const_iterator const_iterator;
115 typedef senf::detail::packet::size_type size_type;
116 typedef senf::detail::packet::difference_type difference_type;
117 typedef senf::detail::packet::byte byte;
119 typedef PacketInterpreterBase::range range;
120 typedef PacketInterpreterBase::optional_range optional_range;
121 typedef PacketInterpreterBase::factory_t factory_t;
123 static optional_range no_range();
124 static factory_t no_factory();
125 template <class PacketType> static factory_t factory();
127 typedef VoidPacketParser parser;
128 ///< Parser to parser packet fields
129 /**< This typedef has to be set to the parser of the packet
131 The default is a VoidPacketParser which does not parse
134 static size_type initSize();
135 ///< Get size of new (empty) packet
136 /**< The default implementation returns 0.
137 \returns size that needs to be allocated to a newly
138 constructed packet */
140 static size_type initHeadSize();
141 ///< Get size of new (empty) packet header
142 /**< This function gives the index within a newly created,
143 empty packet where a sub-packet is to be placed.
145 The default implementation returns initSize().
147 \implementation Ok, it does not really return
148 initSize(), it returns size_type(-1) which is
149 interpreted to mean initSize(). It can't return
150 initSize since initSize() is not (and can't be
151 since it is static) virtual. */
153 static void init(packet p);
154 ///< Initialize new packet
155 /**< This member is called to initialize a just created new
156 packet. The new packet will have a size of at least
157 initSize() but the size may well be larger. It is also
158 possible for the packet to already have further
161 The default implementation does nothing. */
165 static optional_range nextPacketRange(packet p);
166 ///< Get next packet placement
167 /**< nextPacketRange returns the iterator range where the
168 next packet (header) is placed within the current
171 The default implementation always returns
174 \returns nextPacketRange must return
175 \li <tt>\ref interpreter::range(b,e)</tt> (where \a b
176 and \a e are the iterators delimiting the next
177 packet range) if the packet allows a next
178 header. The returned range is allowed to be empty.
179 \li <tt>\ref interpreter::no_range()</tt> (a
180 default constructed \c no_range instance) if
181 no next header is allowed */
183 static factory_t nextPacketType(packet p);
184 ///< Get type of next packet
185 /**< nextPacketType retrieves the type of the next packet
186 returning a factory to create that packet.
188 The default implementation always returns
189 <tt>no_factory()</tt>.
191 \returns factory to create next packet
192 \li <tt>interpreter::factory<OtherPacketType>()</tt> if
193 the type of the packet can be determined
194 \li <tt>interpreter::no_factory()</tt> if the type of
195 the packet cannot be determined or no next packet
198 static void finalize(packet p);
200 /**< finalize() will be called to complete a packet after it
201 has been modified. This function must calculate any
202 checksums, set size fields from the interpreter chain
205 The default implementation does nothing. */
207 static void dump(packet p, std::ostream & os);
208 ///< Dump packet data in readable form
209 /**< The dump() function writes out a complete
210 representation of the packet. This is used for most for
213 The default implementation does nothing. */
217 /** \brief Mixin to provide standard implementations for nextPacketRange and nextPacketType
219 This mixin class simplifies the definition of simple packets:
221 \li The packets consist of three sections: The header, the payload and an optional trailer.
222 \li If the packet has a trailer, both the header and the trailer must have a fixed size.
224 This mixin provides the nextPacketRange() member as well as initSize() and init(). If you
225 additionally provide the optional \a Registry argument, PacketTypeMixin provides a simple
226 implementation of nextPacketType().
228 When using the PacketTypeMixin, the implementation of a packet is simplified to:
230 // Here 'SomeRegistryTag' is optional
231 struct SimplePacketType
232 : public senf::PacketTypeBase,
233 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
235 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
236 typedef senf::ConcretePacket<SimplePacketType> packet;
237 typedef SomePacketParser parser;
239 using mixin::nextPacketRange;
240 using mixin::nextPacketType; // Only if the optional 'Registry' argument is provided
241 using mixin::initSize;
244 static key_t nextPacketKey(packet p)
246 // Return the key in the registry under which the next packet
247 // header is to be found. This member must be given if a Registry argument is
248 // passed to the PacketTypeMixin template.
249 return p->typeField();
252 static void finalize(packet p)
254 // Set the type field by querying the type of the next packet. This is an
255 // optional assignment: If the key is not found, the value returned by 'key'
256 // is an empty optional and the assignment will be skipped.
257 p->typeField << key(p.next(senf::nothrow));
259 // optionally complete the packet by generating auto-generated information
263 static void dump(packet p, std::ostream & os)
265 // Write out a readable representation of the packet for debug purposes
268 static interpreter::size_type initHeadSize()
270 // This member is optional. It returns the \e fixed header size if the packet has a
278 Most of the members are optional, which reduces the minimal implementation of a packet to:
281 struct SimplePacketType
282 : public senf::PacketTypeBase,
283 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
285 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
286 typedef senf::ConcretePacket<SimplePacketType> packet;
287 typedef SomePacketParser parser;
289 using mixin::nextPacketRange;
290 using mixin::nextPacketType;
291 using mixin::initSize;
294 // 'typeField()' is one of the fields defined in the parser which holds
295 // the next-header information
297 static key_t nextPacketKey(packet p) { return p->typeField(); }
298 static void finalize(packet p) { p->typeField() << key(p.next(senf::nothrow)); }
300 static void dump(packet p) {
301 // should always be implemented although optional
306 \ingroup packet_module
308 template <class Self, class Registry=void>
309 class PacketTypeMixin
312 typedef typename Registry::key_t key_t;
313 typedef boost::optional<key_t> optional_key_t;
315 static optional_key_t key (Packet const & p); ///< Find key of packet from registry
316 /**< key() will query the registry to find the key of the
317 given packet. Whereas \c nextPacketKey() as implemented
318 by the mixin user will provide the registry key of the
319 next packet from information stored in the current
320 packets header, the key() member will look up the type
321 of packet \a p in the registry and return it's
324 If either \a p is an in - valid() packet or the packet
325 type is not found in the registry, the returned
326 optional value will be empty. */
328 static PacketTypeBase::factory_t lookup (key_t key); ///< Lookup the key in the registry
329 /**< lookup() will query the registry and find the factory
330 for the given key. If the key cannot be found,
331 no_factory() will be returned. */
333 ///\name PacketType interface implementation
336 static PacketInterpreterBase::optional_range nextPacketRange (Packet const & p);
337 static PacketInterpreterBase::factory_t nextPacketType (Packet const & p);
338 static PacketInterpreterBase::size_type initSize ();
339 static void init (Packet const & p);
346 template <class Self>
347 class PacketTypeMixin<Self,void>
350 static PacketInterpreterBase::optional_range nextPacketRange (Packet const & p);
351 static PacketInterpreterBase::size_type initSize ();
352 static void init (Packet const & p);
359 ///////////////////////////////hh.e////////////////////////////////////////
361 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketType_i_)
362 #define HH_SENF_Packets_PacketType_i_
363 #include "PacketType.cci"
364 #include "PacketType.ct"
365 #include "PacketType.cti"
372 // c-file-style: "senf"
373 // indent-tabs-mode: nil
374 // ispell-local-dictionary: "american"
375 // compile-command: "scons -u test"
376 // comment-column: 40