4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
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 Packet public header */
30 #include <boost/operators.hpp>
32 #include "../Utils/Exception.hh"
33 #include "../Utils/safe_bool.hh"
34 #include "PacketInterpreter.hh"
36 //#include "Packet.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
41 /** \defgroup packet_module Packet Handling
43 The basic groundwork of the Packet library is the packet handling:
45 \li The packet classes provide access to a chain of packet headers (more generically called
47 \li They automatically manage the required memory resources and the shared packet data.
49 \section packet_module_chain The Interpreter Chain
51 The central data structure for a packet is the interpreter chain
53 \image html structure.png The Interpreter Chain
55 This image depicts a packet with several headers. Each interpreter is responsible for a
56 specific sub-range of the complete packet. This range always \e includes the packets payload
57 (This is, why we call the data structure interpreter and not header: The interpreter is
58 responsible for interpreting a range of the packet according to a specific protocol), the
59 packet interpreters are nested inside each other.
61 For each interpreter, this structure automatically divides the packet into three areas (each
62 of which are optional): The header, the payload and the trailer. Every packet will have
63 either a header or a payload section while most don't have a trailer.
65 As user of the library you always interact with the chain through one (or more) of the
66 interpreters. The interpreter provides methods to traverse to the following or preceding
67 header (interpreter) and provides two levels of access to the packet data: Generic low-level
68 access in the form of an STL compatible sequence and access to the parsed fields which are
69 provided by the parser associated with the concrete packet type.
71 \section packet_module_management Resource Management
73 The interface to the packet library is provided using a handle class (\ref Packet for
74 generic, protocol agnostic access and \ref ConcretePacket derived from \ref Packet to access
75 a specific protocol). This handle automatically manages the resources associated with the
76 packet (the interpreter chain and the data storage holding the packet data). The resources
77 are automatically released when the last packet handle referencing a specific packet is
80 \implementation The packet chain is provided on two levels: The internal representation \ref
81 PacketInterpreterBase and \ref PacketInterpreter which are referenced by the Handle
82 classes \ref Packet and \ref ConcretePacket. \n
83 The internal representation classes are pertinent in the sense, that they exist
84 regardless of the existence of a handle referencing them (as long as the packet
85 exists). Still the interpreter chain is lazy and packet interpreters beside the first
86 are only created dynamically when accessed (this is implemented in the handle not in the
87 internal representation). \n
88 The packet interpreters make use of a pool allocator. This provides extremely efficient
89 creation and destruction of packet interpreter's and removes the dynamic memory
90 management overhead from the packet interpreter management. The packet implementation
91 class (\ref PacketImpl which holds the packet data itself) however is still dynamically
92 managed (however there is only a single instance for each packet).
95 template <class PackeType> class ConcretePacket;
97 ///\addtogroup packet_module
100 /** \brief Main Packet class
102 Packet is the main externally visible class of the packet library. Packet is a handle into
103 the internal packet representation. From Packet you may access the data of that specific
104 sub-packet/header/interpreter and navigate to the neighboring
105 sub-packets/headers/interpreters.
107 Packet is protocol agnostic. This class only provides non-protocol dependent members. To
108 access the protocol specific features of a packet (like header fields) the ConcretePacket
109 class extending Packet is provided.
111 \section packet_semantics Semantics
113 All operations accessing the data of \c this packet in some way will ignore any preceding
114 packets/headers/interpreters in the chain. It does not matter, whether a given packet is
115 taken from the middle or the beginning of the chain, all operations (except those explicitly
116 accessing the chain of course) should work the same.
118 This especially includes members like clone() or append(): clone() will clone \e only from
119 \c this packet until the end of the chain, append() will append the given packet \e ignoring
120 any possibly preceding packets/headers/interpreters.
122 In the same way, the data() member provides an STL-sequence compatible view of the packet
123 data. This only includes the data which is part of \c this packet including header, trailer
124 \e and payload but \e not the headers or trailers of packets \e before \c this packet in the
125 packet/header/interpreter chain (nonetheless, this data overlaps with the data of other
128 Several members are member templates taking an \a OtherPacket template parameter. This
129 parameter must be the ConcretePacket instantiation associated with some concrete packet type
130 (protocol). For each implemented protocol, typedefs should be provided for these
131 instantiations (Example: \ref EthernetPacket is a typedef for
132 \ref ConcretePacket < \ref EthernetPacketType >).
135 \ref ConcretePacket for the type specific interface\n
136 \ref PacketData for the sequence interface\n
137 \ref packetparser for a specification of the parser interface
140 : public safe_bool<Packet>,
141 public boost::equality_comparable<Packet>
144 ///////////////////////////////////////////////////////////////////////////
147 typedef void type; ///< Type of the packet.
148 typedef senf::detail::packet::size_type size_type; ///< Unsigned type to represent packet size
149 typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
151 /// Special argument flag
152 /** Used in some ConcretePacket constructors */
153 enum NoInit_t { noinit };
155 ///////////////////////////////////////////////////////////////////////////
156 ///\name Structors and default members
159 // default copy constructor
160 // default copy assignment
161 // default destructor
163 Packet(); ///< Create uninitialized packet handle
164 /**< An uninitialized handle is not valid(). It does not
165 allow any operation except assignment and checking for
167 Packet clone() const; ///< Create copy packet
168 /**< clone() will create a complete copy the packet. The
169 returned packet will have the same data and packet
170 chain. It does however not share any data with the
173 // conversion constructors
175 template <class PacketType>
176 Packet(ConcretePacket<PacketType> packet); ///< Copy-construct Packet from ConcretePacket
177 /**< This constructor allows to convert an arbitrary
178 ConcretePacket into a general Packet, loosing the
179 protocol specific interface. */
182 ///////////////////////////////////////////////////////////////////////////
184 ///\name Interpreter chain access
188 ///< Get next packet in chain
189 /**< \returns in - valid() packet, if no next packet
191 template <class OtherPacket> OtherPacket next() const;
192 ///< Get next packet of given type in chain
193 /**< \throws InvalidPacketChainException if no such packet
195 template <class OtherPacket> OtherPacket next(NoThrow_t) const;
196 ///< Get next packet of given type in chain
197 /**< \param[in] nothrow This argument always has the value
199 \returns in - valid() packet, if no such packet is
201 template <class OtherPacket> OtherPacket findNext() const;
202 ///< Find next packet of given type in chain
203 /**< findNext() is like next(), it will however return \c
204 *this if it is of the given type.
205 \throws InvalidPacketChainException if no such packet
207 template <class OtherPacket> OtherPacket findNext(NoThrow_t) const;
208 ///< Find next packet of given type in chain
209 /**< findNext() is like next(), it will however return \c
210 *this if it is of the given type.
211 \param[in] nothrow This argument always has the value
213 \returns in - valid() packet, if no such packet is
218 ///< Get previous packet in chain
219 /**< \returns in - valid() packet, if no previous packet
221 template <class OtherPacket> OtherPacket prev() const;
222 ///< Get previous packet of given type in chain
223 /**< \throws InvalidPacketChainException if no such packet
225 template <class OtherPacket> OtherPacket prev(NoThrow_t) const;
226 ///< Get previous packet of given type in chain
227 /**< \param[in] nothrow This argument always has the value
229 \returns in - valid() packet, if no such packet is
231 template <class OtherPacket> OtherPacket findPrev() const;
232 ///< Find previous packet of given type in chain
233 /**< findPrev() is like prev(), it will however return \c
234 *this if it is of the type
235 \throws InvalidPacketChainException if no such packet
237 template <class OtherPacket> OtherPacket findPrev(NoThrow_t) const;
238 ///< Find previous packet of given type in chain
239 /**< findPrev() is like prev(), it will however return \c
240 *this if it is of the type
241 \param[in] nothrow This argument always has the value
243 \returns in - valid() packet, if no such packet is
247 Packet first() const;
248 ///< Return first packet in chain
249 template <class OtherPacket> OtherPacket first() const;
250 ///< Return first packet of given type in chain
251 /**< \throws InvalidPacketChainException if no such packet
253 template <class OtherPacket> OtherPacket first(NoThrow_t) const;
254 ///< Return first packet of given type in chain
255 /**< \param[in] nothrow This argument always has the value
257 \returns in - valid() packet, if no such packet is
261 ///< Return last packet in chain
262 template <class OtherPacket> OtherPacket last() const;
263 ///< Return last packet of given type in chain
264 /**< \throws InvalidPacketChainException if no such packet
266 template <class OtherPacket> OtherPacket last(NoThrow_t) const;
267 ///< Return last packet of given type in chain
268 /**< \param[in] nothrow This argument always has the value
270 \returns in - valid() packet, if no such packet is
274 template <class OtherPacket> OtherPacket parseNextAs() const;
275 ///< Parse payload as given by \a OtherPacket and add packet
276 /**< parseNextAs() will throw away the packet chain after
277 the current packet if necessary. It will then parse the
278 payload section of \c this packet as given by \a
279 OtherPacket. The new packet is added to the chain after
281 \returns new packet instance sharing the same data and
282 placed after \c this packet in the chain. */
283 Packet parseNextAs(factory_t factory) const;
284 ///< Parse payload as given by \a factory and add packet
285 /**< parseNextAs() will throw away the packet chain after
286 the current packet if necessary. It will then parse the
287 payload section of \c this packet as given by \a
288 OtherPacket. The new packet is added to the chain after
290 \returns new packet instance sharing the same data and
291 placed after \c this packet in the chain. */
292 template <class OtherPacket> bool is() const;
293 ///< Check, whether \c this packet is of the given type
294 template <class OtherPacket> OtherPacket as() const;
295 ///< Cast current packet to the given type
296 /**< This operations returns a handle to the same packet
297 header/interpreter however cast to the given
298 ConcretePacket type. <b>This conversion is
299 unchecked</b>. If the packet really is of a different
300 type, this will wreak havoc with the packet
301 data-structures. You can validate whether the
302 conversion is valid using is(). */
304 Packet append(Packet packet) const; ///< Append the given packet to \c this packet
305 /**< This operation will replace the payload section of \c
306 this packet with \a packet. This operation will replace
307 the packet chain after \c this packet with a clone of
308 \a packet and will replace the raw data of the payload
309 of \c this with the raw data if \a packet.
310 \returns Packet handle to the cloned \a packet, placed
311 after \c this in the packet/header/interpreter
319 PacketData & data() const; ///< Access the packets raw data container
320 size_type size() const; ///< Return size of packet in bytes
321 /**< This size does \e not include the size of any preceding
322 headers/packets/interpreters. It does however include
323 \c this packets payload. */
327 ///\name Other methods
330 bool operator==(Packet other) const; ///< Check for packet identity
331 /**< Two packet handles compare equal if they really are the
332 same packet header in the same packet chain. */
333 bool boolean_test() const; ///< Check, whether the packet is valid()
335 bool valid() const; ///< Check, whether the packet is valid()
336 /**< An in - valid() packet does not allow any operation
337 except checking for validity and assignment. in -
338 valid() packets serve the same role as 0-pointers.
340 This is an alias for boolean_test() which is called
341 when using a packet in a boolean context. */
343 void finalize() const; ///< Update calculated fields
344 /**< This call will update all calculated fields of the
345 packet after it has been created or changed. This
346 includes checksums, payload size fields or other
347 fields, which can be set from other information in the
348 packet. Each concrete packet type should document,
349 which fields are set by finalize().
351 finalize() will automatically process all
352 packets/headers/interpreters from the end of the chain
353 backwards up to \c this. */
355 void dump(std::ostream & os) const; ///< Write out a printable packet representation
356 /**< This method is provided mostly to help debugging packet
357 problems. Each concrete packet should implement a dump
358 method writing out all fields of the packet in a
359 readable representation. dump() will call this member
360 for each packet/header/interpreter in the chain from \c
361 this packet up to the end of the chain. */
363 TypeIdValue typeId() const; ///< Get id of \c this packet
364 /**< This value is used e.g. in the packet registry to
365 associate packet types with other information.
366 \returns A type holding the same information as a
367 type_info object, albeit assignable */
368 factory_t factory() const; ///< Return factory instance of \c this packet
369 /**< The returned factory instance can be used to create new
370 packets of the given type without knowing the concrete
371 type of the packet. The value may be stored away for
372 later use if needed. */
377 explicit Packet(PacketInterpreterBase::ptr packet);
379 PacketInterpreterBase::ptr ptr() const;
382 Packet checkNext() const;
383 Packet checkLast() const;
385 PacketInterpreterBase::ptr packet_;
387 template <class PacketType>
388 friend class ConcretePacket;
389 friend class PacketParserBase;
392 /** \brief Protocol specific packet handle
394 The ConcretePacket template class extends Packet to provide protocol/packet type specific
395 aspects. These are packet constructors and access to the parsed packet fields.
397 The \c PacketType template argument to ConcretePacket is a protocol specific and internal
398 policy class which defines the protocol specific behavior. To access a specific type of
399 packet, the library provides corresponding typedefs of ConcretePacket < \a SomePacketType >
400 (e.g. \ref EthernetPacket as typedef for \ref ConcretePacket < \ref EthernetPacketType >).
402 The new members provided by ConcretePacket over packet are mostly comprised of the packet
403 constructors. These come in three major flavors:
405 \li The create() family of constructors will create completely new packets.
406 \li The createAfter() family of constructors will create new packets (with new data for the
407 packet) \e after a given existing packet.
408 \li The createBefore() family of constructors will create new packets (again with new data)
409 \e before a given existing packet.
411 Whereas create() will create a completely new packet with it's own chain and data storage,
412 createAfter() and createBefore() extend a packet with additional
413 headers/interpreters. createAfter() will set the payload of the given packet to the new
414 packet whereas createBefore() will create a new packet with the existing packet as it's
417 createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
418 replacing any possibly existing data whereas the latter will interpret the already \e
419 existing data as given by the type argument.
421 \see \ref PacketTypeBase for a specification of the interface to be provided by the \a
422 PacketType policy class.
424 template <class PacketType>
429 ///////////////////////////////////////////////////////////////////////////
432 typedef PacketType type;
434 ///////////////////////////////////////////////////////////////////////////
435 ///\name Structors and default members
438 // default copy constructor
439 // default copy assignment
440 // default destructor
441 // no conversion constructors
443 ConcretePacket(); ///< Create uninitialized packet handle
444 /**< An uninitialized handle is not valid(). It does not
445 allow any operation except assignment and checking for
448 static factory_t factory(); ///< Return factory for packets of specific type
449 /**< This \e static member is like Packet::factory() for a
450 specific packet of type \a PacketType */
452 // Create completely new packet
454 static ConcretePacket create(); ///< Create default initialized packet
455 /**< The packet will be initialized to it's default empty
457 static ConcretePacket create(NoInit_t); ///< Create uninitialized empty packet
458 /**< This will create a completely empty and uninitialized
459 packet with <tt>size() == 0</tt>.
460 \param[in] noinit This parameter must always have the
461 value \c senf::noinit. */
462 static ConcretePacket create(size_type size); ///< Create default initialized packet
463 /**< This member will create a default initialized packet
464 with the given size. If the size parameter is smaller
465 than the minimum allowed packet size an exception will
467 \param[in] size Size of the packet to create in bytes.
468 \throws TruncatedPacketException if \a size is smaller
469 than the smallest permissible size for this type of
471 static ConcretePacket create(size_type size, NoInit_t); ///< Create uninitialized packet
472 /**< Creates an uninitialized (all-zero) packet of the exact
474 \param[in] size Size of the packet to create in bytes
475 \param[in] noinit This parameter must always have the
476 value \c senf::noinit. */
477 template <class ForwardReadableRange>
478 static ConcretePacket create(ForwardReadableRange const & range);
479 ///< Create packet from given data
480 /**< The packet will be created from a copy of the given
481 data. The data from the range will be copied directly
482 into the packet representation. The data will \e not be
483 validated in any way.
485 href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
486 of data to construct packet from. */
488 // Create packet as new packet after a given packet
490 static ConcretePacket createAfter(Packet packet);
491 ///< Create default initialized packet after \a packet
492 /**< The packet will be initialized to it's default empty
493 state. It will be appended as next header/interpreter
494 after \a packet in that packets interpreter chain.
495 \param[in] packet Packet to append new packet to. */
496 static ConcretePacket createAfter(Packet packet, NoInit_t);
497 ///< Create uninitialized empty packet after\a packet
498 /**< This will create a completely empty and uninitialized
499 packet with <tt>size() == 0</tt>. It will be appended
500 as next header/interpreter after \a packet in that
501 packets interpreter chain.
502 \param[in] packet Packet to append new packet to.
503 \param[in] noinit This parameter must always have the
504 value \c senf::noinit. */
505 static ConcretePacket createAfter(Packet packet, size_type size);
506 ///< Create default initialized packet after \a packet
507 /**< This member will create a default initialized packet
508 with the given size. If the size parameter is smaller
509 than the minimum allowed packet size an exception will
510 be thrown. It will be appended as next
511 header/interpreter after \a packet in that packets
513 \param[in] packet Packet to append new packet to.
514 \param[in] size Size of the packet to create in bytes.
515 \throws TruncatedPacketException if \a size is smaller
516 than the smallest permissible size for this type of
518 static ConcretePacket createAfter(Packet packet, size_type size, NoInit_t);
519 ///< Create uninitialized packet after \a packet
520 /**< Creates an uninitialized (all-zero) packet of the exact
521 given size. It will be appended as next
522 header/interpreter after \a packet in that packets
524 \param[in] packet Packet to append new packet to.
525 \param[in] size Size of the packet to create in bytes
526 \param[in] noinit This parameter must always have the
527 value \c senf::noinit. */
528 template <class ForwardReadableRange>
529 static ConcretePacket createAfter(Packet packet,
530 ForwardReadableRange const & range);
531 ///< Create packet from given data after \a packet
532 /**< The packet will be created from a copy of the given
533 data. The data from the range will be copied directly
534 into the packet representation. The data will \e not be
535 validated in any way. It will be appended as next
536 header/interpreter after \a packet in that packets
538 \param[in] packet Packet to append new packet to.
540 href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
541 of data to construct packet from. */
543 // Create packet as new packet (header) before a given packet
545 static ConcretePacket createBefore(Packet packet);
546 ///< Create default initialized packet before \a packet
547 /**< The packet will be initialized to it's default empty
548 state. It will be prepended as previous
549 header/interpreter before \a packet in that packets
551 \param[in] packet Packet to prepend new packet to. */
552 static ConcretePacket createBefore(Packet packet, NoInit_t);
553 ///< Create uninitialized empty packet before \a packet
554 /**< Creates a completely empty and uninitialized packet. It
555 will be prepended as previous header/interpreter before
556 \a packet in that packets interpreter chain.
557 \param[in] packet Packet to prepend new packet to. */
559 // Create a clone of the current packet
561 ConcretePacket clone() const;
564 ///////////////////////////////////////////////////////////////////////////
568 typename type::parser * operator->() const; ///< Access packet fields
569 /**< This operator allows to access the parsed fields of the
570 packet using the notation <tt>packet->field()</tt>. The
571 fields of the packet are specified by the PacketType's
574 The members are not strictly restricted to simple field
575 access. The parser class may have any member which is
576 needed for full packet access (e.g. checksum validation
578 \see \ref packetparser for the parser interface. */
583 typedef PacketInterpreter<PacketType> interpreter;
585 ConcretePacket(typename interpreter::ptr packet_);
587 typename interpreter::ptr ptr() const;
590 friend class PacketInterpreter<PacketType>;
597 ///////////////////////////////hh.e////////////////////////////////////////
599 #if !defined(HH_Packets__decls_) && !defined(HH_Packet_i_)
601 #include "Packet.cci"
603 #include "Packet.cti"
610 // c-file-style: "senf"
611 // indent-tabs-mode: nil
612 // ispell-local-dictionary: "american"
613 // compile-command: "scons -u test"
614 // comment-column: 40