2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
22 \brief PacketType public header */
24 #ifndef HH_PacketType_
25 #define HH_PacketType_ 1
29 #include "PacketTypes.hh"
30 #include "PacketData.hh"
31 #include "PacketParser.hh"
34 //#include "PacketType.mpp"
35 ///////////////////////////////hh.p////////////////////////////////////////
39 /** \brief Helper base-class implementing the PacketType interface
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.
46 struct SomePacketType : public senf::PacketTypeBase
48 typedef senf::ConcretePacket<SomePacketType> packet;
49 typedef SomePacketParser parser;
51 static size_type initSize()
53 // This value can in most cases be taken from the parser
54 return senf::init_size<parser>::value;
57 static size_type initHeadSize()
59 // optional member. This is only needed, if the packet has header and trailer.
60 return constant_initial_size_of_header
63 static void init(packet p)
65 // Initialize a new packet by e.g. setting some fields. Should call
66 // the packet parsers init() member
71 static optional_range nextPacketRange(packet p)
74 // return iterator range delimiting the packet, e.g.:
75 return range(p.data()+begin_offset, p.data()+end_offset);
80 static factory_t nextPacketType(packet p)
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();
89 static void finalize(packet p)
91 // optionally complete the packet by generating auto-generated information
95 static void dump(packet p, std::ostream & os)
97 // Write out a readable representation of the packet for debug purposes
102 You may leave out any one of the members (you should however always define the \c
103 packet typedef member)
105 \ingroup packet_module
107 struct PacketTypeBase
109 typedef Packet packet;
111 typedef senf::detail::packet::iterator iterator;
112 typedef senf::detail::packet::const_iterator const_iterator;
113 typedef senf::detail::packet::size_type size_type;
114 typedef senf::detail::packet::difference_type difference_type;
115 typedef senf::detail::packet::byte byte;
117 typedef PacketInterpreterBase::range range;
118 typedef PacketInterpreterBase::optional_range optional_range;
119 typedef PacketInterpreterBase::factory_t factory_t;
121 static optional_range no_range();
122 static factory_t no_factory();
123 template <class PacketType> static factory_t factory();
125 typedef VoidPacketParser parser;
126 ///< Parser to parser packet fields
127 /**< This typedef has to be set to the parser of the packet
129 The default is a VoidPacketParser which does not parse
132 static size_type initSize();
133 ///< Get size of new (empty) packet
134 /**< The default implementation returns 0.
135 \returns size that needs to be allocated to a newly
136 constructed packet */
138 static size_type initHeadSize();
139 ///< Get size of new (empty) packet header
140 /**< This function gives the index within a newly created,
141 empty packet where a sub-packet is to be placed.
143 The default implementation returns initSize().
145 \implementation Ok, it does not really return
146 initSize(), it returns size_type(-1) which is
147 interpreted to mean initSize(). It can't return
148 initSize since initSize() is not (and can't be
149 since it is static) virtual. */
151 static void init(packet p);
152 ///< Initialize new packet
153 /**< This member is called to initialize a just created new
154 packet. The new packet will have a size of at least
155 initSize() but the size may well be larger. It is also
156 possible for the packet to already have further
159 The default implementation does nothing. */
163 static optional_range nextPacketRange(packet p);
164 ///< Get next packet placement
165 /**< nextPacketRange returns the iterator range where the
166 next packet (header) is placed within the current
169 The default implementation always returns
172 \returns nextPacketRange must return
173 \li <tt>\ref interpreter::range(b,e)</tt> (where \a b
174 and \a e are the iterators delimiting the next
175 packet range) if the packet allows a next
176 header. The returned range is allowed to be empty.
177 \li <tt>\ref interpreter::no_range()</tt> (a
178 default constructed \c no_range instance) if
179 no next header is allowed */
181 static factory_t nextPacketType(packet p);
182 ///< Get type of next packet
183 /**< nextPacketType retrieves the type of the next packet
184 returning a factory to create that packet.
186 The default implementation always returns
187 <tt>no_factory()</tt>.
189 \returns factory to create next packet
190 \li <tt>interpreter::factory<OtherPacketType>()</tt> if
191 the type of the packet can be determined
192 \li <tt>interpreter::no_factory()</tt> if the type of
193 the packet cannot be determined or no next packet
196 static void finalize(packet p);
198 /**< finalize() will be called to complete a packet after it
199 has been modified. This function must calculate any
200 checksums, set size fields from the interpreter chain
203 The default implementation does nothing. */
205 static void dump(packet p, std::ostream & os);
206 ///< Dump packet data in readable form
207 /**< The dump() function writes out a complete
208 representation of the packet. This is used for most for
211 The default implementation does nothing. */
215 /** \brief Mixin to provide standard implementations for nextPacketRange and nextPacketType
217 This mixin class simplifies the definition of simple packets with fixed-size (!) headers
218 and/or trailers. For this type of Packet, this mixin provides the nextPacketRange()
219 member. If you additionally provide the optional \a Registry argument, PacketTypeMixin
220 provides a simple implementation of nextPacketType. When using the PacketTypeMixin, the
221 implementation of a packet is simplified to:
223 // Here 'SomeRegistryTag' is optional
224 struct SimplePacketType
225 : public senf::PacketTypeBase,
226 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
228 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
229 typedef senf::ConcretePacket<SimplePacketType> packet;
230 typedef SomePacketParser parser;
232 using mixin::nextPacketRange;
233 // Only if the optional 'Registry' argument is provided
234 using mixin::nextPacketType;
235 // Only if using the default implementation
236 using mixin::initSize;
237 // Only if using the default implementation
240 static interpreter::size_type initSize()
242 // This member is optional. If it is not defined, 'senf::init_size<parser>::value'
245 // The value returned is the length of the header if initHeadSize() is not defined.
246 // If initHeadSize is defined, this value is the combined size of the header
247 // and trailer while initHeadSize() will return the size of the header only.
251 static interpreter::size_type initHeadSize()
253 // This member is optional. It returns the header size if the packet has a
258 static void init(packet p)
260 // This member is optional. The default implementation calls the parsers init()
264 static registry_key_t nextPacketKey(packet p)
266 // Return the key in the registry under which the next packet
267 // header is to be found. This member must be given if a Registry argument is
268 // passed to the PacketTypeMixin template.
269 return p->typeField();
272 static void finalize(packet p)
274 // Set the type field by querying the type of the next packet. This is an
275 // optional assignment: If the key is not found, the value returned by 'key'
276 // is an empty optional and the assignment will be skipped.
277 p->typeField << key(p.next());
279 // optionally complete the packet by generating auto-generated information
283 static void dump(packet p, std::ostream & os)
285 // Write out a readable representation of the packet for debug purposes
290 Most of the members are optional, which reduces the implementation of a fixed-sized header
291 packet with no trailer and a simple next-packet header to
294 struct SimplePacketType
295 : public senf::PacketTypeBase,
296 public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
298 typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
299 typedef senf::ConcretePacket<SimplePacketType> packet;
300 typedef SomePacketParser parser;
302 using mixin::nextPacketRange;
303 using mixin::nextPacketType;
304 using mixin::initSize;
307 static registry_key_t nextPacketKey(packet p)
308 { return p->typeField(); }
312 If needed, you may additionally add a \c finalize() member. You also should add a \c dump()
313 member to help debugging but both members are optional.
315 \ingroup packet_module
317 template <class Self, class Registry=void>
318 class PacketTypeMixin
321 typedef typename Registry::key_t registry_key_t;
322 typedef boost::optional<registry_key_t> optional_registry_key_t;
324 static optional_registry_key_t key (Packet p); ///< Find key of packet from registry
325 /**< key() will query the registry to find the key of the
326 given packet. Whereas \c nextPacketKey() as implemented
327 by the mixin user will provide the registry key of the
328 next packet from information stored in the current
329 packets header, the key() member will look up the type
330 of packet \a p in the registry and return it's
333 If either \a p is an in - valid() packet or the packet
334 type is not found in the registry, the returned
335 optional value will be empty. */
337 ///\name PacketType interface implementation
340 static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
341 static PacketInterpreterBase::factory_t nextPacketType (Packet p);
342 static PacketInterpreterBase::size_type initSize ();
343 static void init (Packet p);
350 template <class Self>
351 class PacketTypeMixin<Self,void>
354 static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
355 static PacketInterpreterBase::size_type initSize ();
356 static void init (Packet p);
363 ///////////////////////////////hh.e////////////////////////////////////////
365 #if !defined(HH_Packets__decls_) && !defined(HH_PacketType_i_)
366 #define HH_PacketType_i_
367 #include "PacketType.cci"
368 //#include "PacketType.ct"
369 #include "PacketType.cti"
376 // c-file-style: "senf"
377 // indent-tabs-mode: nil
378 // ispell-local-dictionary: "american"
379 // compile-command: "scons -u test"
380 // comment-column: 40