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 Packet public header */
30 #include <boost/operators.hpp>
32 #include "../Utils/Exception.hh"
33 #include "../Utils/Tags.hh"
34 #include "../Utils/safe_bool.hh"
35 #include "PacketInterpreter.hh"
37 //#include "Packet.mpp"
38 ///////////////////////////////hh.p////////////////////////////////////////
42 /** \defgroup packet_module Packet Handling
44 The basic groundwork of the %Packet library is the packet handling:
46 \li The packet classes provide access to a chain of packet headers (more generically called
48 \li They automatically manage the required memory resources and the shared packet data.
50 \section packet_module_chain The Interpreter Chain
52 The central data structure for a packet is the interpreter chain
54 \image html structure.png The Interpreter Chain
56 This image depicts a packet with several headers. Each interpreter is responsible for a
57 specific sub-range of the complete packet. This range always \e includes the packets payload
58 (This is, why we call the data structure interpreter and not header: The interpreter is
59 responsible for interpreting a range of the packet according to a specific protocol), the
60 packet interpreters are nested inside each other.
62 For each interpreter, this structure automatically divides the packet into three areas (each
63 of which are optional): The header, the payload and the trailer. Every packet will have
64 either a header or a payload section while most don't have a trailer.
66 As user of the library you always interact with the chain through one (or more) of the
67 interpreters. The interpreter provides methods to traverse to the following or preceding
68 header (interpreter) and provides two levels of access to the packet data: Generic low-level
69 access in the form of an STL compatible sequence and access to the parsed fields which are
70 provided by the parser associated with the concrete packet type.
72 \section packet_module_management Resource Management
74 The interface to the packet library is provided using a handle class (\ref Packet for
75 generic, protocol agnostic access and \ref ConcretePacket derived from \ref Packet to access
76 a specific protocol). This handle automatically manages the resources associated with the
77 packet (the interpreter chain and the data storage holding the packet data). The resources
78 are automatically released when the last packet handle referencing a specific packet is
81 \implementation The packet chain is provided on two levels: The internal representation \ref
82 PacketInterpreterBase and \ref PacketInterpreter which are referenced by the Handle
83 classes \ref Packet and \ref ConcretePacket. \n
84 The internal representation classes are pertinent in the sense, that they exist
85 regardless of the existence of a handle referencing them (as long as the packet
86 exists). Still the interpreter chain is lazy and packet interpreters beside the first
87 are only created dynamically when accessed (this is implemented in the handle not in the
88 internal representation). \n
89 The packet interpreters make use of a pool allocator. This provides extremely efficient
90 creation and destruction of packet interpreter's and removes the dynamic memory
91 management overhead from the packet interpreter management. The packet implementation
92 class (\ref PacketImpl which holds the packet data itself) however is still dynamically
93 managed (however there is only a single instance for each packet).
96 template <class PackeType> class ConcretePacket;
98 ///\addtogroup packet_module
101 /** \brief Main %Packet class
103 %Packet is the main externally visible class of the packet library. %Packet is a handle into
104 the internal packet representation. From %Packet you may access the data of that specific
105 sub-packet/header/interpreter and navigate to the neighboring
106 sub-packets/headers/interpreters.
108 %Packet is protocol agnostic. This class only provides non-protocol dependent members. To
109 access the protocol specific features of a packet (like header fields) the ConcretePacket
110 class extending %Packet is provided.
112 \section packet_semantics Semantics
114 All operations accessing the data of \c this packet in some way will ignore any preceding
115 packets/headers/interpreters in the chain. It does not matter, whether a given packet is
116 taken from the middle or the beginning of the chain, all operations (except those explicitly
117 accessing the chain of course) should work the same.
119 This especially includes members like clone() or append(): clone() will clone \e only from
120 \c this packet until the end of the chain, append() will append the given packet \e ignoring
121 any possibly preceding packets/headers/interpreters.
123 In the same way, the data() member provides an STL-sequence compatible view of the packet
124 data. This only includes the data which is part of \c this packet including header, trailer
125 \e and payload but \e not the headers or trailers of packets \e before \c this packet in the
126 packet/header/interpreter chain (nonetheless, this data overlaps with the data of other
129 Several members are member templates taking an \a OtherPacket template parameter. This
130 parameter must be the ConcretePacket instantiation associated with some concrete packet type
131 (protocol). For each implemented protocol, typedefs should be provided for these
132 instantiations (Example: \ref EthernetPacket is a typedef for
133 \ref ConcretePacket < \ref EthernetPacketType >).
136 \ref ConcretePacket for the %type specific interface\n
137 \ref PacketData for the sequence interface\n
138 \ref packetparser for a specification of the parser interface
141 : public safe_bool<Packet>,
142 public boost::equality_comparable<Packet>
145 ///////////////////////////////////////////////////////////////////////////
148 typedef void type; ///< Type of the packet.
149 typedef senf::detail::packet::size_type size_type;
150 ///< Unsigned type to represent packet size
151 typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
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 in - 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 of \c this
167 packet. The returned packet will have the same data and
168 packet chain. It does however not share any data with
169 the original packet. */
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 /**< \throws InvalidPacketChainException if no next packet
189 Packet next(NoThrow_t) const;
190 ///< Get next packet in chain
191 /**< \returns in - valid() packet if no next packet
193 template <class OtherPacket> OtherPacket next() const;
194 ///< Get next packet in chain and cast to \a OtherPacket
195 /**< \throws std::bad_cast if the next() packet is not of
197 \throws InvalidPacketChainException if no next packet
199 template <class OtherPacket> OtherPacket next(NoThrow_t) const;
200 ///< Get next packet in chain and cast to \a OtherPacket
201 /**< \throws std::bad_cast if the next() packet is not of
203 \returns in - valid() packet if no next packet
205 template <class OtherPacket> OtherPacket find() const;
206 ///< Search chain forward for packet of type \a OtherPacket
207 /**< The search will start with the current packet.
208 \throws InvalidPacketChainException if no packet of
209 type \a OtherPacket can be found. */
210 template <class OtherPacket> OtherPacket find(NoThrow_t) const;
211 ///< Search chain forward for packet of type \a OtherPacket
212 /**< The search will start with the current packet.
213 \returns in - valid() packet if no packet of type \a
214 OtherPacket can be found. */
217 ///< Get previous packet in chain
218 /**< \throws InvalidPacketChainException if no previous
220 Packet prev(NoThrow_t) const;
221 ///< Get previous packet in chain
222 /**< \returns in - valid() packet if no previous packet
224 template <class OtherPacket> OtherPacket prev() const;
225 ///< Get previous packet in chain and cast to \a OtherPacket
226 /**< \throws std::bad_cast, if the previous packet is not of
228 \throws InvalidPacketChainException if no previous
230 template <class OtherPacket> OtherPacket prev(NoThrow_t) const;
231 ///< Get previous packet in chain and cast to \a OtherPacket
232 /**< \throws std::bad_cast, if the previous packet is not of
234 \returns in - valid() packet if no previous packet
236 template <class OtherPacket> OtherPacket rfind() const;
237 ///< Search chain backwards for packet of type \a OtherPacket
238 /**< The search will start with the current packet.
239 \throws InvalidPacketChainException if no packet of
240 type \a OtherPacket can be found. */
241 template <class OtherPacket> OtherPacket rfind(NoThrow_t) const;
242 ///< Search chain backwards for packet of type \a OtherPacket
243 /**< The search will start with the current packet.
244 \returns in - valid() packet if no packet of type \a
245 OtherPacket can be found. */
248 Packet first() const;
249 ///< Return first packet in chain
250 template <class OtherPacket> OtherPacket first() const;
251 ///< Return first packet in chain and cast
252 /**< \throws std::bad_cast if the first() packet is not of
253 type \a OtherPacket */
256 ///< Return last packet in chain
257 template <class OtherPacket> OtherPacket last() const;
258 ///< Return last packet in chain and cast
259 /**< \throws std::bad_cast if the last() packet is not of
260 type \a OtherPacket */
263 template <class OtherPacket> OtherPacket parseNextAs() const;
264 ///< Interpret payload of \c this as \a OtherPacket
265 /**< parseNextAs() will throw away the packet chain after
266 the current packet if necessary. It will then parse the
267 payload section of \c this packet as given by \a
268 OtherPacket. The new packet is added to the chain after
270 \returns new packet instance sharing the same data and
271 placed after \c this packet in the chain. */
272 Packet parseNextAs(factory_t factory) const;
273 ///< Interpret payload of \c this as \a factory type 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 factory. 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. */
282 template <class OtherPacket> bool is() const;
283 ///< Check, whether \c this packet is of the given type
284 template <class OtherPacket> OtherPacket as() const;
285 ///< Cast current packet to the given type
286 /**< This operations returns a handle to the same packet
287 header/interpreter however cast to the given
289 \throws std::bad_cast if the current packet is not of
290 type \a OtherPacket */
292 Packet append(Packet packet) const; ///< Append the given packet to \c this packet
293 /**< This operation will replace the payload section of \c
294 this packet with \a packet. This operation will replace
295 the packet chain after \c this packet with a clone of
296 \a packet and will replace the raw data of the payload
297 of \c this with the raw data of \a packet. \c this
298 packet will not share any date with \a packet.
299 \returns Packet handle to the cloned \a packet, placed
300 after \c this in the packet/header/interpreter
308 PacketData & data() const; ///< Access the packets raw data container
309 size_type size() const; ///< Return size of packet in bytes
310 /**< This size does \e not include the size of any preceding
311 headers/packets/interpreters. It does however include
312 \c this packets payload. */
316 ///\name Other methods
319 bool operator==(Packet other) const; ///< Check for packet identity
320 /**< Two packet handles compare equal if they really are the
321 same packet header in the same packet chain. */
322 bool boolean_test() const; ///< Check, whether the packet is valid()
324 bool valid() const; ///< Check, whether the packet is valid()
325 /**< An in - valid() packet does not allow any operation
326 except checking for validity and assignment. in -
327 valid() packets serve the same role as 0-pointers.
329 This is an alias for boolean_test() which is called
330 when using a packet in a boolean context. */
332 void finalize() const; ///< Update calculated fields
333 /**< This call will update all calculated fields of the
334 packet after it has been created or changed. This
335 includes checksums, payload size fields or other
336 fields, which can be set from other information in the
337 packet. Each concrete packet type should document,
338 which fields are set by finalize().
340 finalize() will automatically process all
341 packets/headers/interpreters from the end of the chain
342 backwards up to \c this. */
344 void dump(std::ostream & os) const; ///< Write out a printable packet representation
345 /**< This method is provided mostly to help debugging packet
346 problems. Each concrete packet should implement a dump
347 method writing out all fields of the packet in a
348 readable representation. dump() will call this member
349 for each packet/header/interpreter in the chain from \c
350 this packet up to the end of the chain. */
352 TypeIdValue typeId() const; ///< Get id of \c this packet
353 /**< This value is used e.g. in the packet registry to
354 associate packet types with other information.
355 \returns A type holding the same information as a
356 type_info object, albeit assignable */
357 factory_t factory() const; ///< Return factory instance of \c this packet
358 /**< The returned factory instance can be used to create new
359 packets of the given type without knowing the concrete
360 type of the packet. The value may be stored away for
361 later use if needed. */
366 explicit Packet(PacketInterpreterBase::ptr packet);
368 PacketInterpreterBase::ptr ptr() const;
371 Packet checkNext() const;
372 Packet checkLast() const;
374 PacketInterpreterBase::ptr packet_;
376 template <class PacketType>
377 friend class ConcretePacket;
378 friend class PacketParserBase;
381 /** \brief Protocol specific packet handle
383 The ConcretePacket template class extends Packet to provide protocol/packet type specific
384 aspects. These are packet constructors and access to the parsed packet fields.
386 The \c PacketType template argument to ConcretePacket is a protocol specific and internal
387 policy class which defines the protocol specific behavior. To access a specific type of
388 packet, the library provides corresponding typedefs of ConcretePacket < \a SomePacketType >
389 (e.g. \ref EthernetPacket as typedef for \ref ConcretePacket < \ref EthernetPacketType >).
391 The new members provided by ConcretePacket over packet are mostly comprised of the packet
392 constructors. These come in three major flavors:
394 \li The create() family of constructors will create completely new packets.
395 \li The createAfter() family of constructors will create new packets (with new data for the
396 packet) \e after a given existing packet.
397 \li The createBefore() family of constructors will create new packets (again with new data)
398 \e before a given existing packet.
400 Whereas create() will create a completely new packet with it's own chain and data storage,
401 createAfter() and createBefore() extend a packet with additional
402 headers/interpreters. createAfter() will set the payload of the given packet to the new
403 packet whereas createBefore() will create a new packet with the existing packet as it's
406 createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
407 replacing any possibly existing data whereas the latter will interpret the already \e
408 existing data as given by the type argument.
410 \see \ref PacketTypeBase for a specification of the interface to be provided by the \a
411 PacketType policy class.
413 template <class PacketType>
418 ///////////////////////////////////////////////////////////////////////////
421 typedef PacketType type;
422 typedef typename PacketType::parser Parser;
424 ///////////////////////////////////////////////////////////////////////////
425 ///\name Structors and default members
428 // default copy constructor
429 // default copy assignment
430 // default destructor
431 // no conversion constructors
433 ConcretePacket(); ///< Create uninitialized packet handle
434 /**< An uninitialized handle is not valid(). It does not
435 allow any operation except assignment and checking for
438 static factory_t factory(); ///< Return factory for packets of specific type
439 /**< This \e static member is like Packet::factory() for a
440 specific packet of type \a PacketType */
442 // Create completely new packet
444 static ConcretePacket create(); ///< Create default initialized packet
445 /**< The packet will be initialized to it's default empty
447 static ConcretePacket create(senf::NoInit_t); ///< Create uninitialized empty packet
448 /**< This will create a completely empty and uninitialized
449 packet with <tt>size() == 0</tt>.
450 \param[in] senf::noinit This parameter must always have the
451 value \c senf::noinit. */
452 static ConcretePacket create(size_type size); ///< Create default initialized packet
453 /**< This member will create a default initialized packet
454 with the given size. If the size parameter is smaller
455 than the minimum allowed packet size an exception will
457 \param[in] size Size of the packet to create in bytes.
458 \throws TruncatedPacketException if \a size is smaller
459 than the smallest permissible size for this type of
461 static ConcretePacket create(size_type size, senf::NoInit_t);
462 ///< Create uninitialized packet
463 /**< Creates an uninitialized (all-zero) packet of the exact
465 \param[in] size Size of the packet to create in bytes
466 \param[in] senf::noinit This parameter must always have the
467 value \c senf::noinit. */
468 template <class ForwardReadableRange>
469 static ConcretePacket create(ForwardReadableRange const & range);
470 ///< Create packet from given data
471 /**< The packet will be created from a copy of the given
472 data. The data from the range will be copied directly
473 into the packet representation. The data will \e not be
474 validated in any way.
476 href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
477 of data to construct packet from. */
479 // Create packet as new packet after a given packet
481 static ConcretePacket createAfter(Packet packet);
482 ///< Create default initialized packet after \a packet
483 /**< The packet will be initialized to it's default empty
484 state. It will be appended as next header/interpreter
485 after \a packet in that packets interpreter chain.
486 \param[in] packet Packet to append new packet to. */
487 static ConcretePacket createAfter(Packet packet, senf::NoInit_t);
488 ///< Create uninitialized empty packet after\a packet
489 /**< This will create a completely empty and uninitialized
490 packet with <tt>size() == 0</tt>. It will be appended
491 as next header/interpreter after \a packet in that
492 packets interpreter chain.
493 \param[in] packet Packet to append new packet to.
494 \param[in] senf::noinit This parameter must always have the
495 value \c senf::noinit. */
496 static ConcretePacket createAfter(Packet packet, size_type size);
497 ///< Create default initialized packet after \a packet
498 /**< This member will create a default initialized packet
499 with the given size. If the size parameter is smaller
500 than the minimum allowed packet size an exception will
501 be thrown. It will be appended as next
502 header/interpreter after \a packet in that packets
504 \param[in] packet Packet to append new packet to.
505 \param[in] size Size of the packet to create in bytes.
506 \throws TruncatedPacketException if \a size is smaller
507 than the smallest permissible size for this type of
509 static ConcretePacket createAfter(Packet packet, size_type size, senf::NoInit_t);
510 ///< Create uninitialized packet after \a packet
511 /**< Creates an uninitialized (all-zero) packet of the exact
512 given size. It will be appended as next
513 header/interpreter after \a packet in that packets
515 \param[in] packet Packet to append new packet to.
516 \param[in] size Size of the packet to create in bytes
517 \param[in] senf::noinit This parameter must always have the
518 value \c senf::noinit. */
519 template <class ForwardReadableRange>
520 static ConcretePacket createAfter(Packet packet,
521 ForwardReadableRange const & range);
522 ///< Create packet from given data after \a packet
523 /**< The packet will be created from a copy of the given
524 data. The data from the range will be copied directly
525 into the packet representation. The data will \e not be
526 validated in any way. It will be appended as next
527 header/interpreter after \a packet in that packets
529 \param[in] packet Packet to append new packet to.
531 href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
532 of data to construct packet from. */
534 // Create packet as new packet (header) before a given packet
536 static ConcretePacket createBefore(Packet packet);
537 ///< Create default initialized packet before \a packet
538 /**< The packet will be initialized to it's default empty
539 state. It will be prepended as previous
540 header/interpreter before \a packet in that packets
542 \param[in] packet Packet to prepend new packet to. */
543 static ConcretePacket createBefore(Packet packet, senf::NoInit_t);
544 ///< Create uninitialized empty packet before \a packet
545 /**< Creates a completely empty and uninitialized packet. It
546 will be prepended as previous header/interpreter before
547 \a packet in that packets interpreter chain.
548 \param[in] packet Packet to prepend new packet to. */
550 // Create a clone of the current packet
552 ConcretePacket clone() const;
555 ///////////////////////////////////////////////////////////////////////////
559 Parser * operator->() const; ///< Access packet fields
560 /**< This operator allows to access the parsed fields of the
561 packet using the notation <tt>packet->field()</tt>. The
562 fields of the packet are specified by the PacketType's
565 The members are not strictly restricted to simple field
566 access. The parser class may have any member which is
567 needed for full packet access (e.g. checksum validation
569 \see \ref packetparser for the parser interface. */
571 Parser parser() const; ///< Access packet field parser directly
572 /**< Access the parser of the packet. This is the same
573 object returned by the operator->() operator. The
574 operator however does not allow to access this object
575 itself, only it's members.
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