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 Packet public header */
28 #include <boost/operators.hpp>
30 #include "../Utils/Exception.hh"
31 #include "../Utils/SafeBool.hh"
32 #include "PacketInterpreter.hh"
34 //#include "Packet.mpp"
35 ///////////////////////////////hh.p////////////////////////////////////////
39 /** \defgroup packet_module Packet Handling
41 The basic groundwork of the Packet library is the packet handling:
43 \li The packet classes provide access to a chain of packet headers (more generically called
45 \li They automatically manage the required memory resources and the shared packet data.
47 \section packet_module_chain The Interpreter Chain
49 The central data structure for a packet is the interpreter chain
51 \image html structure.png The Interpreter Chain
53 This image depicts a packet with several headers. Each interpreter is responsible for a
54 specific sub-range of the complete packet. This range always \e includes the packets payload
55 (This is, why we call the data structure interpreter and not header: The interpreter is
56 responsible for interpreting a range of the packet according to a specific protocol), the
57 packet interpreters are nested inside each other.
59 For each interpreter, this structure automatically divides the packet into three areas (each
60 of which are optional): The header, the payload and the trailer. Every packet will have
61 either a header or a payload section while most don't have a trailer.
63 As user of the library you always interact with the chain through one (or more) of the
64 interpreters. The interpreter provides methods to traverse to the following or preceding
65 header (interpreter) and provides two levels of access to the packet data: Generic low-level
66 access in the form of an STL compatible sequence and access to the parsed fields which are
67 provided by the parser associated with the concrete packet type.
69 \section packet_module_management Resource Management
71 The interface to the packet library is provided using a handle class (\ref Packet for
72 generic, protocol agnostic access and \ref ConcretePacket derived from \ref Packet to access
73 a specific protocol). This handle automatically manages the resources associated with the
74 packet (the interpreter chain and the data storage holding the packet data). The resources
75 are automatically released when the last packet handle referencing a specific packet is
78 \implementation The packet chain is provided on two levels: The internal representation \ref
79 PacketInterpreterBase and \ref PacketInterpreter which are referenced by the Handle
80 classes \ref Packet and \ref ConcretePacket. \n
81 The internal representation classes are pertinent in the sense, that they exist
82 regardless of the existence of a handle referencing them (as long as the packet
83 exists). Still the interpreter chain is lazy and packet interpreters beside the first
84 are only created dynamically when accessed (this is implemented in the handle not in the
85 internal representation). \n
86 The packet interpreters make use of a pool allocator. This provides extremely efficient
87 creation and destruction of packet interpreter's and removes the dynamic memory
88 management overhead from the packet interpreter management. The packet implementation
89 class (\ref PacketImpl which holds the packet data itself) however is still dynamically
90 managed (however there is only a single instance for each packet).
93 template <class PackeType> class ConcretePacket;
95 ///\addtogroup packet_module
98 /** \brief Main Packet class
100 Packet is the main externally visible class of the packet library. Packet is a handle into
101 the internal packet representation. From Packet you may access the data of that specific
102 sub-packet/header/interpreter and navigate to the neighboring
103 sub-packets/headers/interpreters.
105 Packet is protocol agnostic. This class only provides non-protocol dependent members. To
106 access the protocol specific features of a packet (like header fields) the ConcretePacket
107 class extending Packet is provided.
109 \section packet_semantics Semantics
111 All operations accessing the data of \c this packet in some way will ignore any preceding
112 packets/headers/interpreters in the chain. It does not matter, whether a given packet is
113 taken from the middle or the beginning of the chain, all operations (except those explicitly
114 accessing the chain of course) should work the same.
116 This especially includes members like clone() or append(): clone() will clone \e only from
117 \c this packet until the end of the chain, append() will append the given packet \e ignoring
118 any possibly preceding packets/headers/interpreters.
120 In the same way, the data() member provides an STL-sequence compatible view of the packet
121 data. This only includes the data which is part of \c this packet including header, trailer
122 \e and payload but \e not the headers or trailers of packets \e before \c this packet in the
123 packet/header/interpreter chain (nonetheless, this data overlaps with the data of other
126 Several members are member templates taking an \a OtherPacket template parameter. This
127 parameter must be the ConcretePacket instantiation associated with some concrete packet type
128 (protocol). For each implemented protocol, typedefs should be provided for these
129 instantiations (Example: \ref EthernetPacket is a typedef for
130 \ref ConcretePacket < \ref EthernetPacketType >).
133 \ref ConcretePacket for the type specific interface\n
134 \ref PacketData for the sequence interface\n
135 \ref packetparser for a specification of the parser interface
138 : public SafeBool<Packet>,
139 public boost::equality_comparable<Packet>
142 ///////////////////////////////////////////////////////////////////////////
145 typedef void type; ///< Type of the packet.
146 typedef senf::detail::packet::size_type size_type; ///< Unsigned type to represent packet size
147 typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
149 /// Special argument flag
150 /** Used in some ConcretePacket constructors */
151 enum NoInit_t { noinit };
153 ///////////////////////////////////////////////////////////////////////////
154 ///\name Structors and default members
157 // default copy constructor
158 // default copy assignment
159 // default destructor
161 Packet(); ///< Create uninitialized packet handle
162 /**< An uninitialized handle is not valid(). It does not
163 allow any operation except assignment and checking for
165 Packet clone() const; ///< Create copy packet
166 /**< clone() will create a complete copy the packet. The
167 returned packet will have the same data and packet
168 chain. It does however not share any data with the
171 // conversion constructors
173 template <class PacketType>
174 Packet(ConcretePacket<PacketType> packet); ///< Copy-construct Packet from ConcretePacket
175 /**< This constructor allows to convert an arbitrary
176 ConcretePacket into a general Packet, loosing the
177 protocol specific interface. */
180 ///////////////////////////////////////////////////////////////////////////
182 ///\name Interpreter chain access
186 ///< Get next packet in chain
187 /**< \returns in - valid() packet, if no next packet
189 template <class OtherPacket> OtherPacket next() const;
190 ///< Get next packet of given type in chain
191 /**< \throws InvalidPacketChainException if no such packet
193 template <class OtherPacket> OtherPacket next(NoThrow_t) const;
194 ///< Get next packet of given type in chain
195 /**< \param[in] nothrow This argument always has the value
197 \returns in - valid() packet, if no such packet is
199 template <class OtherPacket> OtherPacket findNext() const;
200 ///< Find next packet of given type in chain
201 /**< findNext() is like next(), it will however return \c
202 *this if it is of the given type.
203 \throws InvalidPacketChainException if no such packet
205 template <class OtherPacket> OtherPacket findNext(NoThrow_t) const;
206 ///< Find next packet of given type in chain
207 /**< findNext() is like next(), it will however return \c
208 *this if it is of the given type.
209 \param[in] nothrow This argument always has the value
211 \returns in - valid() packet, if no such packet is
216 ///< Get previous packet in chain
217 /**< \returns in - valid() packet, if no previous packet
219 template <class OtherPacket> OtherPacket prev() const;
220 ///< Get previous packet of given type in chain
221 /**< \throws InvalidPacketChainException if no such packet
223 template <class OtherPacket> OtherPacket prev(NoThrow_t) const;
224 ///< Get previous packet of given type in chain
225 /**< \param[in] nothrow This argument always has the value
227 \returns in - valid() packet, if no such packet is
229 template <class OtherPacket> OtherPacket findPrev() const;
230 ///< Find previous packet of given type in chain
231 /**< findPrev() is like prev(), it will however return \c
232 *this if it is of the type
233 \throws InvalidPacketChainException if no such packet
235 template <class OtherPacket> OtherPacket findPrev(NoThrow_t) const;
236 ///< Find previous packet of given type in chain
237 /**< findPrev() is like prev(), it will however return \c
238 *this if it is of the type
239 \param[in] nothrow This argument always has the value
241 \returns in - valid() packet, if no such packet is
245 Packet first() const;
246 ///< Return first packet in chain
247 template <class OtherPacket> OtherPacket first() const;
248 ///< Return first packet of given type in chain
249 /**< \throws InvalidPacketChainException if no such packet
251 template <class OtherPacket> OtherPacket first(NoThrow_t) const;
252 ///< Return first packet of given type in chain
253 /**< \param[in] nothrow This argument always has the value
255 \returns in - valid() packet, if no such packet is
259 ///< Return last packet in chain
260 template <class OtherPacket> OtherPacket last() const;
261 ///< Return last packet of given type in chain
262 /**< \throws InvalidPacketChainException if no such packet
264 template <class OtherPacket> OtherPacket last(NoThrow_t) const;
265 ///< Return last packet of given type in chain
266 /**< \param[in] nothrow This argument always has the value
268 \returns in - valid() packet, if no such packet is
272 template <class OtherPacket> OtherPacket parseNextAs() const;
273 ///< Parse payload as given by \a OtherPacket and add packet
274 /**< parseNextAs() will throw away the packet chain after
275 the current packet if necessary. It will then parse the
276 payload section of \c this packet as given by \a
277 OtherPacket. The new packet is added to the chain after
279 \returns new packet instance sharing the same data and
280 placed after \c this packet in the chain. */
281 Packet parseNextAs(factory_t factory) const;
282 ///< Parse payload as given by \a factory and add packet
283 /**< parseNextAs() will throw away the packet chain after
284 the current packet if necessary. It will then parse the
285 payload section of \c this packet as given by \a
286 OtherPacket. The new packet is added to the chain after
288 \returns new packet instance sharing the same data and
289 placed after \c this packet in the chain. */
290 template <class OtherPacket> bool is() const;
291 ///< Check, whether \c this packet is of the given type
292 template <class OtherPacket> OtherPacket as() const;
293 ///< Cast current packet to the given type
294 /**< This operations returns a handle to the same packet
295 header/interpreter however cast to the given
296 ConcretePacket type. <b>This conversion is
297 unchecked</b>. If the packet really is of a different
298 type, this will wreak havoc with the packet
299 data-structures. You can validate whether the
300 conversion is valid using is(). */
302 Packet append(Packet packet) const; ///< Append the given packet to \c this packet
303 /**< This operation will replace the payload section of \c
304 this packet with \a packet. This operation will replace
305 the packet chain after \c this packet with a clone of
306 \a packet and will replace the raw data of the payload
307 of \c this with the raw data if \a packet.
308 \returns Packet handle to the cloned \a packet, placed
309 after \c this in the packet/header/interpreter
317 PacketData & data() const; ///< Access the packets raw data container
318 size_type size() const; ///< Return size of packet in bytes
319 /**< This size does \e not include the size of any preceding
320 headers/packets/interpreters. It does however include
321 \c this packets payload. */
325 ///\name Other methods
328 bool operator==(Packet other) const; ///< Check for packet identity
329 /**< Two packet handles compare equal if they really are the
330 same packet header in the same packet chain. */
331 bool boolean_test() const; ///< Check, whether the packet is valid()
333 bool valid() const; ///< Check, whether the packet is valid()
334 /**< An in - valid() packet does not allow any operation
335 except checking for validity and assignment. in -
336 valid() packets serve the same role as 0-pointers.
338 This is an alias for boolean_test() which is called
339 when using a packet in a boolean context. */
341 void finalize() const; ///< Update calculated fields
342 /**< This call will update all calculated fields of the
343 packet after it has been created or changed. This
344 includes checksums, payload size fields or other
345 fields, which can be set from other information in the
346 packet. Each concrete packet type should document,
347 which fields are set by finalize().
349 finalize() will automatically process all
350 packets/headers/interpreters from the end of the chain
351 backwards up to \c this. */
353 void dump(std::ostream & os) const; ///< Write out a printable packet representation
354 /**< This method is provided mostly to help debugging packet
355 problems. Each concrete packet should implement a dump
356 method writing out all fields of the packet in a
357 readable representation. dump() will call this member
358 for each packet/header/interpreter in the chain from \c
359 this packet up to the end of the chain. */
361 TypeIdValue typeId() const; ///< Get id of \c this packet
362 /**< This value is used e.g. in the packet registry to
363 associate packet types with other information.
364 \returns A type holding the same information as a
365 type_info object, albeit assignable */
366 factory_t factory() const; ///< Return factory instance of \c this packet
367 /**< The returned factory instance can be used to create new
368 packets of the given type without knowing the concrete
369 type of the packet. The value may be stored away for
370 later use if needed. */
375 explicit Packet(PacketInterpreterBase::ptr packet);
377 PacketInterpreterBase::ptr ptr() const;
380 Packet checkNext() const;
381 Packet checkLast() const;
383 PacketInterpreterBase::ptr packet_;
385 template <class PacketType>
386 friend class ConcretePacket;
387 friend class PacketParserBase;
390 /** \brief Protocol specific packet handle
392 The ConcretePacket template class extends Packet to provide protocol/packet type specific
393 aspects. These are packet constructors and access to the parsed packet fields.
395 The \c PacketType template argument to ConcretePacket is a protocol specific and internal
396 policy class which defines the protocol specific behavior. To access a specific type of
397 packet, the library provides corresponding typedefs of ConcretePacket < \a SomePacketType >
398 (e.g. \ref EthernetPacket as typedef for \ref ConcretePacket < \ref EthernetPacketType >).
400 The new members provided by ConcretePacket over packet are mostly comprised of the packet
401 constructors. These come in three major flavors:
403 \li The create() family of constructors will create completely new packets.
404 \li The createAfter() family of constructors will create new packets (with new data for the
405 packet) \e after a given existing packet.
406 \li The createBefore() family of constructors will create new packets (again with new data)
407 \e before a given existing packet.
409 Whereas create() will create a completely new packet with it's own chain and data storage,
410 createAfter() and createBefore() extend a packet with additional
411 headers/interpreters. createAfter() will set the payload of the given packet to the new
412 packet whereas createBefore() will create a new packet with the existing packet as it's
415 createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
416 replacing any possibly existing data whereas the latter will interpret the already \e
417 existing data as given by the type argument.
419 \see \ref PacketTypeBase for a specification of the interface to be provided by the \a
420 PacketType policy class.
422 template <class PacketType>
427 ///////////////////////////////////////////////////////////////////////////
430 typedef PacketType type;
432 ///////////////////////////////////////////////////////////////////////////
433 ///\name Structors and default members
436 // default copy constructor
437 // default copy assignment
438 // default destructor
439 // no conversion constructors
441 ConcretePacket(); ///< Create uninitialized packet handle
442 /**< An uninitialized handle is not valid(). It does not
443 allow any operation except assignment and checking for
446 static factory_t factory(); ///< Return factory for packets of specific type
447 /**< This \e static member is like Packet::factory() for a
448 specific packet of type \a PacketType */
450 // Create completely new packet
452 static ConcretePacket create(); ///< Create default initialized packet
453 /**< The packet will be initialized to it's default empty
455 static ConcretePacket create(NoInit_t); ///< Create uninitialized empty packet
456 /**< This will create a completely empty and uninitialized
457 packet with <tt>size() == 0</tt>.
458 \param[in] noinit This parameter must always have the
459 value \c senf::noinit. */
460 static ConcretePacket create(size_type size); ///< Create default initialized packet
461 /**< This member will create a default initialized packet
462 with the given size. If the size parameter is smaller
463 than the minimum allowed packet size an exception will
465 \param[in] size Size of the packet to create in bytes.
466 \throws TruncatedPacketException if \a size is smaller
467 than the smallest permissible size for this type of
469 static ConcretePacket create(size_type size, NoInit_t); ///< Create uninitialized packet
470 /**< Creates an uninitialized (all-zero) packet of the exact
472 \param[in] size Size of the packet to create in bytes
473 \param[in] noinit This parameter must always have the
474 value \c senf::noinit. */
475 template <class ForwardReadableRange>
476 static ConcretePacket create(ForwardReadableRange const & range);
477 ///< Create packet from given data
478 /**< The packet will be created from a copy of the given
479 data. The data from the range will be copied directly
480 into the packet representation. The data will \e not be
481 validated in any way.
483 href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
484 of data to construct packet from. */
486 // Create packet as new packet after a given packet
488 static ConcretePacket createAfter(Packet packet);
489 ///< Create default initialized packet after \a packet
490 /**< The packet will be initialized to it's default empty
491 state. It will be appended as next header/interpreter
492 after \a packet in that packets interpreter chain.
493 \param[in] packet Packet to append new packet to. */
494 static ConcretePacket createAfter(Packet packet, NoInit_t);
495 ///< Create uninitialized empty packet after\a packet
496 /**< This will create a completely empty and uninitialized
497 packet with <tt>size() == 0</tt>. It will be appended
498 as next header/interpreter after \a packet in that
499 packets interpreter chain.
500 \param[in] packet Packet to append new packet to.
501 \param[in] noinit This parameter must always have the
502 value \c senf::noinit. */
503 static ConcretePacket createAfter(Packet packet, size_type size);
504 ///< Create default initialized packet after \a packet
505 /**< This member will create a default initialized packet
506 with the given size. If the size parameter is smaller
507 than the minimum allowed packet size an exception will
508 be thrown. It will be appended as next
509 header/interpreter after \a packet in that packets
511 \param[in] packet Packet to append new packet to.
512 \param[in] size Size of the packet to create in bytes.
513 \throws TruncatedPacketException if \a size is smaller
514 than the smallest permissible size for this type of
516 static ConcretePacket createAfter(Packet packet, size_type size, NoInit_t);
517 ///< Create uninitialized packet after \a packet
518 /**< Creates an uninitialized (all-zero) packet of the exact
519 given size. It will be appended as next
520 header/interpreter after \a packet in that packets
522 \param[in] packet Packet to append new packet to.
523 \param[in] size Size of the packet to create in bytes
524 \param[in] noinit This parameter must always have the
525 value \c senf::noinit. */
526 template <class ForwardReadableRange>
527 static ConcretePacket createAfter(Packet packet,
528 ForwardReadableRange const & range);
529 ///< Create packet from given data after \a packet
530 /**< The packet will be created from a copy of the given
531 data. The data from the range will be copied directly
532 into the packet representation. The data will \e not be
533 validated in any way. It will be appended as next
534 header/interpreter after \a packet in that packets
536 \param[in] packet Packet to append new packet to.
538 href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
539 of data to construct packet from. */
541 // Create packet as new packet (header) before a given packet
543 static ConcretePacket createBefore(Packet packet);
544 ///< Create default initialized packet before \a packet
545 /**< The packet will be initialized to it's default empty
546 state. It will be prepended as previous
547 header/interpreter before \a packet in that packets
549 \param[in] packet Packet to prepend new packet to. */
550 static ConcretePacket createBefore(Packet packet, NoInit_t);
551 ///< Create uninitialized empty packet before \a packet
552 /**< Creates a completely empty and uninitialized packet. It
553 will be prepended as previous header/interpreter before
554 \a packet in that packets interpreter chain.
555 \param[in] packet Packet to prepend new packet to. */
557 // Create a clone of the current packet
559 ConcretePacket clone() const;
562 ///////////////////////////////////////////////////////////////////////////
566 typename type::parser * operator->() const; ///< Access packet fields
567 /**< This operator allows to access the parsed fields of the
568 packet using the notation <tt>packet->field()</tt>. The
569 fields of the packet are specified by the PacketType's
572 The members are not strictly restricted to simple field
573 access. The parser class may have any member which is
574 needed for full packet access (e.g. checksum validation
576 \see \ref packetparser for the parser interface. */
581 typedef PacketInterpreter<PacketType> interpreter;
583 ConcretePacket(typename interpreter::ptr packet_);
585 typename interpreter::ptr ptr() const;
588 friend class PacketInterpreter<PacketType>;
595 ///////////////////////////////hh.e////////////////////////////////////////
597 #if !defined(HH_Packets__decls_) && !defined(HH_Packet_i_)
599 #include "Packet.cci"
601 #include "Packet.cti"
608 // c-file-style: "senf"
609 // indent-tabs-mode: nil
610 // ispell-local-dictionary: "american"
611 // compile-command: "scons -u test"
612 // comment-column: 40