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_PacketType_
27 #define HH_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 with fixed-size (!) headers
220 and/or trailers. For this type of Packet, this mixin provides the nextPacketRange()
221 member. If you additionally provide the optional \a Registry argument, PacketTypeMixin
222 provides a simple implementation of nextPacketType. When using the PacketTypeMixin, the
223 implementation of a packet is simplified to:
225 // Here 'SomeRegistryTag' is optional
226 struct SimplePacketType
227 : public senf::PacketTypeBase,
228 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
230 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
231 typedef senf::ConcretePacket<SimplePacketType> packet;
232 typedef SomePacketParser parser;
234 using mixin::nextPacketRange;
235 // Only if the optional 'Registry' argument is provided
236 using mixin::nextPacketType;
237 // Only if using the default implementation
238 using mixin::initSize;
239 // Only if using the default implementation
242 static interpreter::size_type initSize()
244 // This member is optional. If it is not defined, 'senf::init_size<parser>::value'
247 // The value returned is the length of the header if initHeadSize() is not defined.
248 // If initHeadSize is defined, this value is the combined size of the header
249 // and trailer while initHeadSize() will return the size of the header only.
253 static interpreter::size_type initHeadSize()
255 // This member is optional. It returns the header size if the packet has a
260 static void init(packet p)
262 // This member is optional. The default implementation calls the parsers init()
266 static registry_key_t nextPacketKey(packet p)
268 // Return the key in the registry under which the next packet
269 // header is to be found. This member must be given if a Registry argument is
270 // passed to the PacketTypeMixin template.
271 return p->typeField();
274 static void finalize(packet p)
276 // Set the type field by querying the type of the next packet. This is an
277 // optional assignment: If the key is not found, the value returned by 'key'
278 // is an empty optional and the assignment will be skipped.
279 p->typeField << key(p.next());
281 // optionally complete the packet by generating auto-generated information
285 static void dump(packet p, std::ostream & os)
287 // Write out a readable representation of the packet for debug purposes
292 Most of the members are optional, which reduces the implementation of a fixed-sized header
293 packet with no trailer and a simple next-packet header to
296 struct SimplePacketType
297 : public senf::PacketTypeBase,
298 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
300 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
301 typedef senf::ConcretePacket<SimplePacketType> packet;
302 typedef SomePacketParser parser;
304 using mixin::nextPacketRange;
305 using mixin::nextPacketType;
306 using mixin::initSize;
309 static registry_key_t nextPacketKey(packet p)
310 { return p->typeField(); }
314 If needed, you may additionally add a \c finalize() member. You also should add a \c dump()
315 member to help debugging but both members are optional.
317 \ingroup packet_module
319 template <class Self, class Registry=void>
320 class PacketTypeMixin
323 typedef typename Registry::key_t registry_key_t;
324 typedef boost::optional<registry_key_t> optional_registry_key_t;
326 static optional_registry_key_t key (Packet p); ///< Find key of packet from registry
327 /**< key() will query the registry to find the key of the
328 given packet. Whereas \c nextPacketKey() as implemented
329 by the mixin user will provide the registry key of the
330 next packet from information stored in the current
331 packets header, the key() member will look up the type
332 of packet \a p in the registry and return it's
335 If either \a p is an in - valid() packet or the packet
336 type is not found in the registry, the returned
337 optional value will be empty. */
339 ///\name PacketType interface implementation
342 static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
343 static PacketInterpreterBase::factory_t nextPacketType (Packet p);
344 static PacketInterpreterBase::size_type initSize ();
345 static void init (Packet p);
352 template <class Self>
353 class PacketTypeMixin<Self,void>
356 static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
357 static PacketInterpreterBase::size_type initSize ();
358 static void init (Packet p);
365 ///////////////////////////////hh.e////////////////////////////////////////
367 #if !defined(HH_Packets__decls_) && !defined(HH_PacketType_i_)
368 #define HH_PacketType_i_
369 #include "PacketType.cci"
370 //#include "PacketType.ct"
371 #include "PacketType.cti"
378 // c-file-style: "senf"
379 // indent-tabs-mode: nil
380 // ispell-local-dictionary: "american"
381 // compile-command: "scons -u test"
382 // comment-column: 40