4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief PacketType public header */
31 #ifndef HH_SENF_Packets_PacketType_
32 #define HH_SENF_Packets_PacketType_ 1
36 #include "PacketTypes.hh"
37 #include "PacketData.hh"
38 #include "PacketParser.hh"
41 //#include "PacketType.mpp"
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
46 /** \brief Helper base-class implementing the PacketType interface
48 This helper class maybe used when building a new PacketType. It provides a complete default
49 implementations of this interface. To define a new PacketType, derive from this class and
50 implement the members you want to change.
53 struct SomePacketType : public senf::PacketTypeBase
55 typedef senf::ConcretePacket<SomePacketType> packet;
56 typedef SomePacketParser parser;
58 static size_type initSize()
60 // This value can in most cases be taken from the parser
61 return senf::init_size<parser>::value;
64 static size_type initHeadSize()
66 // optional member. This is only needed, if the packet has header and trailer.
67 return constant_initial_size_of_header
70 static void init(packet p)
72 // Initialize a new packet by e.g. setting some fields. Should call
73 // the packet parsers init() member
78 static optional_range nextPacketRange(packet p)
81 // return iterator range delimiting the packet, e.g.:
82 return range(p.data()+begin_offset, p.data()+end_offset);
87 static factory_t nextPacketType(packet p)
89 if (have_next_packet && know_next_packet_type)
90 // \a NextPacket is the \c ConcretePacket instantiation of the next packet
91 return NextPacket::factory();
96 static void finalize(packet p)
98 // optionally complete the packet by generating auto-generated information
102 static void dump(packet p, std::ostream & os)
104 // Write out a readable representation of the packet for debug purposes
109 You may leave out any one of the members (you should however always define the \c
110 packet typedef member)
112 \ingroup packet_module
114 struct PacketTypeBase
116 typedef Packet packet;
118 typedef senf::detail::packet::iterator iterator;
119 typedef senf::detail::packet::const_iterator const_iterator;
120 typedef senf::detail::packet::size_type size_type;
121 typedef senf::detail::packet::difference_type difference_type;
122 typedef senf::detail::packet::byte byte;
124 typedef PacketInterpreterBase::range range;
125 typedef PacketInterpreterBase::optional_range optional_range;
126 typedef PacketInterpreterBase::factory_t factory_t;
128 static optional_range no_range();
129 static factory_t no_factory();
130 template <class PacketType> static factory_t factory();
132 typedef VoidPacketParser parser;
133 ///< Parser to parser packet fields
134 /**< This typedef has to be set to the parser of the packet
136 The default is a VoidPacketParser which does not parse
139 static size_type initSize();
140 ///< Get size of new (empty) packet
141 /**< The default implementation returns 0.
142 \returns size that needs to be allocated to a newly
143 constructed packet */
145 static size_type initHeadSize();
146 ///< Get size of new (empty) packet header
147 /**< This function gives the index within a newly created,
148 empty packet where a sub-packet is to be placed.
150 The default implementation returns initSize().
152 \implementation Ok, it does not really return
153 initSize(), it returns size_type(-1) which is
154 interpreted to mean initSize(). It can't return
155 initSize since initSize() is not (and can't be
156 since it is static) virtual. */
158 static void init(packet p);
159 ///< Initialize new packet
160 /**< This member is called to initialize a just created new
161 packet. The new packet will have a size of at least
162 initSize() but the size may well be larger. It is also
163 possible for the packet to already have further
166 The default implementation does nothing. */
170 static optional_range nextPacketRange(packet p);
171 ///< Get next packet placement
172 /**< nextPacketRange returns the iterator range where the
173 next packet (header) is placed within the current
176 The default implementation always returns
179 \returns nextPacketRange must return
180 \li <tt>\ref interpreter::range(b,e)</tt> (where \a b
181 and \a e are the iterators delimiting the next
182 packet range) if the packet allows a next
183 header. The returned range is allowed to be empty.
184 \li <tt>\ref interpreter::no_range()</tt> (a
185 default constructed \c no_range instance) if
186 no next header is allowed */
188 static factory_t nextPacketType(packet p);
189 ///< Get type of next packet
190 /**< nextPacketType retrieves the type of the next packet
191 returning a factory to create that packet.
193 The default implementation always returns
194 <tt>no_factory()</tt>.
196 \returns factory to create next packet
197 \li <tt>interpreter::factory<OtherPacketType>()</tt> if
198 the type of the packet can be determined
199 \li <tt>interpreter::no_factory()</tt> if the type of
200 the packet cannot be determined or no next packet
203 static void finalize(packet p);
205 /**< finalize() will be called to complete a packet after it
206 has been modified. This function must calculate any
207 checksums, set size fields from the interpreter chain
210 The default implementation does nothing. */
212 static void dump(packet p, std::ostream & os);
213 ///< Dump packet data in readable form
214 /**< The dump() function writes out a complete
215 representation of the packet. This is used for most for
218 The default implementation does nothing. */
222 /** \brief Mixin to provide standard implementations for nextPacketRange and nextPacketType
224 This mixin class simplifies the definition of simple packets:
226 \li The packets consist of three sections: The header, the payload and an optional trailer.
227 \li If the packet has a trailer, both the header and the trailer must have a fixed size.
229 This mixin provides the nextPacketRange() member as well as initSize() and init(). If you
230 additionally provide the optional \a Registry argument, PacketTypeMixin provides a simple
231 implementation of nextPacketType().
233 When using the PacketTypeMixin, the implementation of a packet is simplified to:
235 // Here 'SomeRegistryTag' is optional
236 struct SimplePacketType
237 : public senf::PacketTypeBase,
238 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
240 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
241 typedef senf::ConcretePacket<SimplePacketType> packet;
242 typedef SomePacketParser parser;
244 using mixin::nextPacketRange;
245 using mixin::nextPacketType; // Only if the optional 'Registry' argument is provided
246 using mixin::initSize;
249 static key_t nextPacketKey(packet p)
251 // Return the key in the registry under which the next packet
252 // header is to be found. This member must be given if a Registry argument is
253 // passed to the PacketTypeMixin template.
254 return p->typeField();
257 static void finalize(packet p)
259 // Set the type field by querying the type of the next packet. This is an
260 // optional assignment: If the key is not found, the value returned by 'key'
261 // is an empty optional and the assignment will be skipped.
262 p->typeField << key(p.next(senf::nothrow));
264 // optionally complete the packet by generating auto-generated information
268 static void dump(packet p, std::ostream & os)
270 // Write out a readable representation of the packet for debug purposes
273 static interpreter::size_type initHeadSize()
275 // This member is optional. It returns the \e fixed header size if the packet has a
283 Most of the members are optional, which reduces the minimal implementation of a packet to:
286 struct SimplePacketType
287 : public senf::PacketTypeBase,
288 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
290 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
291 typedef senf::ConcretePacket<SimplePacketType> packet;
292 typedef SomePacketParser parser;
294 using mixin::nextPacketRange;
295 using mixin::nextPacketType;
296 using mixin::initSize;
299 // 'typeField()' is one of the fields defined in the parser which holds
300 // the next-header information
302 static key_t nextPacketKey(packet p) { return p->typeField(); }
303 static void finalize(packet p) { p->typeField() << key(p.next(senf::nothrow)); }
305 static void dump(packet p) {
306 // should always be implemented although optional
311 \ingroup packet_module
313 template <class Self, class Registry=void>
314 class PacketTypeMixin
317 typedef typename Registry::key_t key_t;
318 typedef boost::optional<key_t> optional_key_t;
320 static optional_key_t key (Packet const & p); ///< Find key of packet from registry
321 /**< key() will query the registry to find the key of the
322 given packet. Whereas \c nextPacketKey() as implemented
323 by the mixin user will provide the registry key of the
324 next packet from information stored in the current
325 packets header, the key() member will look up the type
326 of packet \a p in the registry and return it's
329 If either \a p is an in - valid() packet or the packet
330 type is not found in the registry, the returned
331 optional value will be empty. */
333 static PacketTypeBase::factory_t lookup (key_t key); ///< Lookup the key in the registry
334 /**< lookup() will query the registry and find the factory
335 for the given key. If the key cannot be found,
336 no_factory() will be returned. */
338 ///\name PacketType interface implementation
341 static PacketInterpreterBase::optional_range nextPacketRange (ConcretePacket<Self> const & p);
342 static PacketInterpreterBase::factory_t nextPacketType (ConcretePacket<Self> const & p);
343 static PacketInterpreterBase::size_type initSize ();
344 static void init (ConcretePacket<Self> const & p);
351 template <class Self>
352 class PacketTypeMixin<Self,void>
355 static PacketInterpreterBase::optional_range nextPacketRange (ConcretePacket<Self> const & p);
356 static PacketInterpreterBase::size_type initSize ();
357 static void init (ConcretePacket<Self> const & p);
364 //-/////////////////////////////////////////////////////////////////////////////////////////////////
366 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketType_i_)
367 #define HH_SENF_Packets_PacketType_i_
368 #include "PacketType.cci"
369 #include "PacketType.ct"
370 #include "PacketType.cti"
377 // c-file-style: "senf"
378 // indent-tabs-mode: nil
379 // ispell-local-dictionary: "american"
380 // compile-command: "scons -u test"
381 // comment-column: 40