8b116e6978cf0f0331387c80110b43e30678c369
[senf.git] / senf / Packets / Packet.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief Packet public header */
25
26 #ifndef HH_SENF_Packets_Packet_
27 #define HH_SENF_Packets_Packet_ 1
28
29 // Custom includes
30 #include <boost/operators.hpp>
31 #include <boost/utility.hpp>
32 #include <boost/type_traits/is_integral.hpp>
33 #include <senf/Utils/Tags.hh>
34 #include <senf/Utils/safe_bool.hh>
35 #include "PacketInterpreter.hh"
36
37 //#include "Packet.mpp"
38 ///////////////////////////////hh.p////////////////////////////////////////
39
40 namespace senf {
41
42     /** \defgroup packet_module Packet Handling
43
44         The basic groundwork of the %Packet library is the packet handling:
45
46         \li The packet classes provide access to a chain of packet headers (more generically called
47             interpreters).
48         \li They automatically manage the required memory resources and the shared packet data.
49
50         \section packet_module_chain The Interpreter Chain
51
52         The central data structure for a packet is the interpreter chain
53
54         \image html structure.png The Interpreter Chain
55
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.
61
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.
65
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.
71
72         \section packet_module_management Resource Management
73
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
79         destroyed.
80
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).
94      */
95
96     template <class PackeType> class ConcretePacket;
97
98     ///\addtogroup packet_module
99     ///@{
100
101     /** \brief Main %Packet class
102
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.
107
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.
111
112         \section packet_semantics Semantics
113
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.
118
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.
122
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
127         packets).
128
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 >).
134
135         \see
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
139      */
140     class Packet
141         : public safe_bool<Packet>,
142           public boost::equality_comparable<Packet>
143     {
144     public:
145         ///////////////////////////////////////////////////////////////////////////
146         // Types
147
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)
152
153         ///////////////////////////////////////////////////////////////////////////
154         ///\name Structors and default members
155         ///@{
156
157         // default copy constructor
158         // default copy assignment
159         // default destructor
160
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
164                                              validity. */
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,
168                                              annotations and packet chain. It does however not
169                                              share any data with the original packet. */
170
171         // conversion constructors
172
173         template <class PacketType>
174         Packet(ConcretePacket<PacketType> const & packet);
175                                         ///< Copy-construct Packet from ConcretePacket
176                                         /**< This constructor allows to convert an arbitrary
177                                              ConcretePacket into a general Packet, loosing the
178                                              protocol specific interface. */
179
180         ///@}
181         ///////////////////////////////////////////////////////////////////////////
182
183         ///\name Interpreter chain access
184         ///@{
185
186         Packet      next() const;       ///< Get next packet in chain
187                                         /**< \throws InvalidPacketChainException if no next packet
188                                              exists */
189         Packet      next(NoThrow_t) const; ///< Get next packet in chain
190                                         /**< \returns in - valid() packet if no next packet
191                                              exists */
192         template <class OtherPacket> OtherPacket next() const;
193                                         ///< Get next packet in chain and cast to \a OtherPacket
194                                         /**< \throws std::bad_cast if the next() packet is not of
195                                              type \a OtherPacket
196                                              \throws InvalidPacketChainException if no next packet
197                                                  exists */
198         template <class OtherPacket> OtherPacket next(NoThrow_t) const;
199                                         ///< Get next packet in chain and cast to \a OtherPacket
200                                         /**< \returns in - valid() packet if no next packet
201                                                  exists or if next() packet is not of
202                                                  type \a OtherPacket */
203         template <class OtherPacket> OtherPacket find() const;
204                                         ///< Search chain forward for packet of type \a OtherPacket
205                                         /**< The search will start with the current packet.
206                                              \throws InvalidPacketChainException if no packet of
207                                                  type \a OtherPacket can be found. */
208         template <class OtherPacket> OtherPacket find(NoThrow_t) const;
209                                         ///< Search chain forward for packet of type \a OtherPacket
210                                         /**< The search will start with the current packet.
211                                              \returns in - valid() packet if no packet of type \a
212                                                  OtherPacket can be found. */
213
214         Packet      prev() const;       ///< Get previous packet in chain
215                                         /**< \throws InvalidPacketChainException if no previous
216                                              packet exists */
217         Packet      prev(NoThrow_t) const; ///< Get previous packet in chain
218                                         /**< \returns in - valid() packet if no previous packet
219                                              exists */
220         template <class OtherPacket> OtherPacket prev() const;
221                                         ///< Get previous packet in chain and cast to \a OtherPacket
222                                         /**< \throws std::bad_cast, if the previous packet is not of
223                                              type \a OtherPacket
224                                              \throws InvalidPacketChainException if no previous
225                                                  packet exists */
226         template <class OtherPacket> OtherPacket prev(NoThrow_t) const;
227                                         ///< Get previous packet in chain and cast to \a OtherPacket
228                                         /**< \returns in - valid() packet if no previous packet
229                                                  exists or if the previous packet is not of
230                                                  type \a OtherPacket */
231         template <class OtherPacket> OtherPacket rfind() const;
232                                         ///< Search chain backwards for packet of type \a OtherPacket
233                                         /**< The search will start with the current packet.
234                                              \throws InvalidPacketChainException if no packet of
235                                                  type \a OtherPacket can be found. */
236         template <class OtherPacket> OtherPacket rfind(NoThrow_t) const;
237                                         ///< Search chain backwards for packet of type \a OtherPacket
238                                         /**< The search will start with the current packet.
239                                              \returns in - valid() packet if no packet of type \a
240                                                  OtherPacket can be found. */
241
242
243         Packet      first() const;      ///< Return first packet in chain
244         template <class OtherPacket> OtherPacket first() const;
245                                         ///< Return first packet in chain and cast
246                                         /**< \throws std::bad_cast if the first() packet is not of
247                                              type \a OtherPacket */
248
249         Packet      last() const;       ///< Return last packet in chain
250         template <class OtherPacket> OtherPacket last() const;
251                                         ///< Return last packet in chain and cast
252                                         /**< \throws std::bad_cast if the last() packet is not of
253                                              type \a OtherPacket  */
254
255
256         template <class OtherPacket> OtherPacket parseNextAs() const;
257                                         ///< Interpret payload of \c this as \a OtherPacket
258                                         /**< parseNextAs() will throw away the packet chain after
259                                              the current packet if necessary. It will then parse the
260                                              payload section of \c this packet as given by \a
261                                              OtherPacket. The new packet is added to the chain after
262                                              \c this.
263                                              \returns new packet instance sharing the same data and
264                                                  placed after \c this packet in the chain.
265                                              \throws InvalidPacketChainException if no next packet
266                                                  header is allowed (viz. nextPacketRange() of the
267                                                  the current PacketType returns no_range() ) */
268         Packet      parseNextAs(factory_t factory) const;
269                                         ///< Interpret payload of \c this as \a factory type packet
270                                         /**< parseNextAs() will throw away the packet chain after
271                                              the current packet if necessary. It will then parse the
272                                              payload section of \c this packet as given by \a
273                                              factory. The new packet is added to the chain after
274                                              \c this.
275                                              \returns new packet instance sharing the same data and
276                                                  placed after \c this packet in the chain.
277                                              \throws InvalidPacketChainException if no next packet
278                                                  header is allowed (viz. nextPacketRange() of the
279                                                  the current PacketType returns no_range() ) */
280
281         template <class OtherPacket> bool        is() const;
282                                         ///< Check, whether \c this packet is of the given type
283         template <class OtherPacket> OtherPacket as() const;
284                                         ///< Cast current packet to the given type
285                                         /**< This operations returns a handle to the same packet
286                                              header/interpreter however upcast to the given
287                                              ConcretePacket type which have been instantiated
288                                              before.
289                                              \throws std::bad_cast if the current packet is not of
290                                                  type \a OtherPacket */
291         template <class OtherPacket> OtherPacket as(NoThrow_t) const;
292                                         ///< Cast current packet to the given type
293                                         /**< This operations returns a handle to the same packet
294                                              header/interpreter however upcast to the given
295                                              ConcretePacket type which have been instantiated
296                                              before.
297                                              \warning You must make absolutely sure that the packet
298                                              is of the given type. If not, calling this member
299                                              crashes your program in a unkindly way. */
300
301         Packet append(Packet const & packet) const; ///< Append the given packet to \c this packet
302                                         /**< This operation will replace the payload section of \c
303                                              this packet with \a packet. This operation will replace
304                                              the packet chain after \c this packet with a clone of
305                                              \a packet and will replace the raw data of the payload
306                                              of \c this with the raw data of \a packet. \c this
307                                              packet will not share any data with \a packet.
308                                              \returns Packet handle to the cloned \a packet, placed
309                                                  after \c this in the packet/header/interpreter
310                                                  chain. */
311
312         void reparse() const;           ///< Reparse the payload the packet
313                                         /**< This member will throw away the packet chain after the
314                                              current packet. The payload will be reparsed
315                                              automatically when calling next() */
316         ///@}
317
318         ///\name Data access
319         ///@{
320
321         PacketData & data() const;      ///< Access the packets raw data container
322         size_type size() const;         ///< Return size of packet in bytes
323                                         /**< This size does \e not include the size of any preceding
324                                              headers/packets/interpreters. It does however include
325                                              \c this packets payload. */
326         ///@}
327
328         ///\name Annotations
329         ///@{
330
331         template <class Annotation>
332         Annotation & annotation();      ///< Get packet annotation
333                                         /**< This member will retrieve an arbitrary packet
334                                              annotation. Every annotation is identified by a unique
335                                              \a Annotation type. This type should \e always be a \c
336                                              struct.
337
338                                              \code
339                                              struct MyAnnotation {
340                                                  int value;
341                                              };
342
343                                              senf::Packet p (...);
344
345                                              p.annotation<MyAnnotation>().value = 1;
346                                              \endcode
347
348                                              Annotations are shared by all headers / interpreters
349                                              within a single packet chain.
350
351                                              If an annotation is \e not a POD type (more
352                                              specifically, if it's constructor or destructor is not
353                                              trivial including base classes and members), the \a
354                                              Annotation type \e must inherit from
355                                              senf::ComplexAnnotation. Failing to follow this rule
356                                              will result in undefined behavior and will probably
357                                              lead to a program crash.
358
359                                              \code
360                                              struct MyStringAnnotation : senf::ComplexAnnotation {
361                                                  std::string value;
362                                              };
363                                              \endcode
364                                              (This type is not POD since \c std::string is not POD)
365
366                                              \see \ref packet_usage_annotation
367
368                                              \implementation The annotation system is implemented
369                                                  quite efficiently since annotations are stored
370                                                  within a packet embedded vector of fixed size (the
371                                                  size is determined automatically at runtime by the
372                                                  number of different annotations
373                                                  used). Additionally, non-complex small annotations
374                                                  require no additional memory management (\c new /
375                                                  \c delete).
376
377                                              \idea Pool the annotation vectors: In the destructor
378                                                  swap the vector into a vector graveyard (swapping
379                                                  two vectors is an O(1) no allocation operation). In
380                                                  the constructor, if there is a vector in the
381                                                  graveyard, swap it in from there. Of course, it
382                                                  would be better to do away with the vector and just
383                                                  allocate the space together with the packet but
384                                                  that looks quite complicated to do ... especially
385                                                  considering that the packetimpl itself uses a pool.
386                                           */
387
388         template <class Annotation>
389         Annotation const & annotation() const; ///< Get packet annotation
390                                         /**< \see annotation() */
391
392         void clearAnnotations();        ///< Clear all packet annotations
393                                         /**< All packet annotations will be cleared. Afterwards
394                                              the annotations equates to a new created %packet.
395                                              \warning all references to existing complex
396                                              annotations become invalid. */
397         ///@}
398
399         ///\name Other methods
400         ///@{
401
402         bool operator==(Packet const & other) const; ///< Check for packet identity
403                                         /**< Two packet handles compare equal if they really are the
404                                              same packet header in the same packet chain. */
405         bool boolean_test() const;      ///< Check, whether the packet is valid()
406                                         /**< \see valid() */
407         bool valid() const;             ///< Check, whether the packet is valid()
408                                         /**< An in - valid() packet does not allow any operation
409                                              except checking for validity and assignment. in -
410                                              valid() packets serve the same role as 0-pointers.
411
412                                              This is an alias for boolean_test() which is called
413                                              when using a packet in a boolean context. */
414
415         void finalizeThis();            ///< Update calculated fields
416                                         /**< The finalize() family of members will update
417                                              calculated packet fields: checksums, size fields and so
418                                              on. This includes any field, which can be set from
419                                              other information in the packet. Each concrete packet
420                                              type should document, which fields are set by
421                                              finalize().
422
423                                              finalizeThis() will \e only process the current
424                                              header. Even if only changing fields in this protocol,
425                                              depending on the protocol it may not be enough to
426                                              finalize this header only. See the packet type
427                                              documentation. */
428
429         template <class Other>
430         void finalizeTo();              ///< Update calculated fields
431                                         /**< The finalize() family of members will update
432                                              calculated packet fields: checksums, size fields and so
433                                              on. This includes any field, which can be set from
434                                              other information in the packet. Each concrete packet
435                                              type should document, which fields are set by
436                                              finalize().
437
438                                              finalizeTo() will automatically process all
439                                              packets/headers/interpreters from the \e first
440                                              occurrence of packet type \a Other (beginning at \c
441                                              this packet searching forward towards deeper nested
442                                              packets) backwards up to \c this.
443
444                                              This call is equivalent to
445                                              \code
446                                                  p.finalizeTo(p.next<Other>())
447                                              \endcode */
448
449         void finalizeTo(Packet const & other);  ///< Update calculated fields
450                                         /**< The finalize() family of members will update
451                                              calculated packet fields: checksums, size fields and so
452                                              on. This includes any field, which can be set from
453                                              other information in the packet. Each concrete packet
454                                              type should document, which fields are set by
455                                              finalize().
456
457                                              finalizeTo(other) will automatically process all
458                                              packets/headers/interpreters beginning at \a other
459                                              backwards towards outer packets up to \c this. */
460
461         void finalizeAll();             ///< Update calculated fields
462                                         /**< The finalize() fammily of members will update
463                                              calculated packet fields: checksums, size fields and so
464                                              on. This includes any field, which can be set from
465                                              other information in the packet. Each concrete packet
466                                              type should document, which fields are set by
467                                              finalize().
468
469                                              finalizeAll() will automatically process all
470                                              packets/headers/interpreters from the end of the chain
471                                              (the most inner packet) backwards up to \c this.
472
473                                              This call is equivalent to
474                                              \code
475                                                  p.finalizeTo(p.last())
476                                              \endcode
477
478                                              Beware, that finalizeAll() will \e not finalize any
479                                              headers before \c this, it will \e only process inner
480                                              headers. */
481
482         void dump(std::ostream & os) const; ///< Write out a printable packet representation
483                                         /**< This method is provided mostly to help debugging packet
484                                              problems. Each concrete packet should implement a dump
485                                              method writing out all fields of the packet in a
486                                              readable representation. dump() will call this member
487                                              for each packet/header/interpreter in the chain from \c
488                                              this packet up to the end of the chain. */
489
490         TypeIdValue typeId() const;     ///< Get type of \c this packet
491                                         /**< This value is used e.g. in the packet registry to
492                                              associate packet types with other information.
493                                              \returns A type holding the same information as a
494                                              type_info object, albeit assignable */
495         factory_t factory() const;      ///< Return factory instance of \c this packet
496                                         /**< The returned factory instance can be used to create new
497                                              packets of the given type without knowing the concrete
498                                              type of the packet. The value may be stored away for
499                                              later use if needed. */
500
501         unsigned long id() const;       ///< Unique packet id
502                                         /**< Get a unique packet id. If two packets have the same
503                                              id, they share the internal data representation. */
504
505         bool is_shared() const;         ///< check if this packet shares data with any another packet handle.
506                                         /**< This method returns true if there is any other packet
507                                              handle pointing to any header in the packet chain. */
508
509         ///@}
510
511     protected:
512         explicit Packet(PacketInterpreterBase::ptr const & packet);
513
514         PacketInterpreterBase::ptr const & ptr() const;
515
516     private:
517         Packet getNext() const;
518         Packet getLast() const;
519
520         PacketInterpreterBase::ptr packet_;
521
522         template <class PacketType>
523         friend class ConcretePacket;
524         friend class PacketParserBase;
525     };
526
527     /** \brief Protocol specific packet handle
528
529         The ConcretePacket template class extends Packet to provide protocol/packet type specific
530         aspects. These are packet constructors and access to the parsed packet fields.
531
532         The \c PacketType template argument to ConcretePacket is a protocol specific and internal
533         policy class which defines the protocol specific behavior. To access a specific type of
534         packet, the library provides corresponding typedefs of ConcretePacket < \a SomePacketType >
535         (e.g. \ref EthernetPacket as typedef for \ref ConcretePacket < \ref EthernetPacketType >).
536
537         The new members provided by ConcretePacket over packet are mostly comprised of the packet
538         constructors. These come in three major flavors:
539
540         \li The create() family of constructors will create completely new packets.
541         \li The createAfter() family of constructors will create new packets (with new data for the
542             packet) \e after a given existing packet <em>thereby destroying and overwriting  any
543             possibly existing packets and data after the given packet</em>.
544         \li The createBefore() family of constructors will create new packets (again with new data)
545             \e before a given existing packet <em>thereby destroying and overwriting any possibly
546             existing packets and data before the given packet</em>.
547         \li The createInsertBefore() family of constructors will create new packets \e before a
548             given packet \e inserting them into the packet chain after any existing packets before
549             the given packet.
550
551         Whereas create() will create a completely new packet with it's own chain and data storage,
552         createAfter(), createBefore() and createInsertBefore() extend a packet with additional
553         headers/interpreters. createAfter() will set the payload of the given packet to the new
554         packet whereas createBefore() and createInsertBefore() will create a new packet with the
555         existing packet as it's payload.
556
557         createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
558         replacing any possibly existing data whereas the latter will interpret the already \e
559         existing data as given by the type argument.
560
561         \see \ref PacketTypeBase for a specification of the interface to be provided by the \a
562             PacketType policy class.
563      */
564     template <class PacketType>
565     class ConcretePacket
566         : public Packet
567     {
568     public:
569         ///////////////////////////////////////////////////////////////////////////
570         // Types
571
572         typedef PacketType type;
573         typedef typename PacketType::parser Parser;
574
575         ///////////////////////////////////////////////////////////////////////////
576         ///\name Structors and default members
577         ///@{
578
579         // default copy constructor
580         // default copy assignment
581         // default destructor
582         // no conversion constructors
583
584         ConcretePacket();               ///< Create uninitialized packet handle
585                                         /**< An uninitialized handle is not valid(). It does not
586                                              allow any operation except assignment and checking for
587                                              validity. */
588
589         static factory_t factory();     ///< Return factory for packets of specific type
590                                         /**< This \e static member is like Packet::factory() for a
591                                              specific packet of type \a PacketType */
592
593         // Create completely new packet
594
595         static ConcretePacket create(); ///< Create default initialized packet
596                                         /**< The packet will be initialized to it's default empty
597                                              state. */
598         static ConcretePacket create(senf::NoInit_t); ///< Create uninitialized empty packet
599                                         /**< This will create a completely empty and uninitialized
600                                              packet with <tt>size() == 0</tt>.
601                                              \param[in] senf::noinit This parameter must always have
602                                                  the value \c senf::noinit. */
603         static ConcretePacket create(size_type size); ///< Create default initialized packet
604                                         /**< This member will create a default initialized packet
605                                              with the given size. If the size parameter is smaller
606                                              than the minimum allowed packet size an exception will
607                                              be thrown.
608                                              \param[in] size Size of the packet to create in bytes.
609                                              \throws TruncatedPacketException if \a size is smaller
610                                                  than the smallest permissible size for this type of
611                                                  packet. */
612         static ConcretePacket create(size_type size, senf::NoInit_t);
613                                         ///< Create uninitialized packet
614                                         /**< Creates an uninitialized (all-zero) packet of the exact
615                                              given size.
616                                              \param[in] size Size of the packet to create in bytes
617                                              \param[in] senf::noinit This parameter must always have
618                                                  the value \c senf::noinit. */
619 #ifndef DOXYGEN
620         template <class ForwardReadableRange>
621         static ConcretePacket create(
622             ForwardReadableRange const & range,
623             typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0);
624 #else
625         template <class ForwardReadableRange>
626         static ConcretePacket create(ForwardReadableRange const & range);
627                                         ///< Create packet from given data
628                                         /**< The packet will be created from a copy of the given
629                                              data. The data from the range will be copied directly
630                                              into the packet representation. The data will \e not be
631                                              validated in any way.
632
633                                              \param[in] range <a href="http://www.boost.org/doc/libs/release/libs/range/index.html">Boost.Range</a>
634                                                  of data to construct packet from. */
635 #endif
636
637         // Create packet as new packet after a given packet
638
639         static ConcretePacket createAfter(Packet const & packet);
640                                         ///< Create default initialized packet after \a packet
641                                         /**< The packet will be initialized to it's default empty
642                                              state. It will be appended as next header/interpreter
643                                              after \a packet in that packets interpreter chain.
644                                              \param[in] packet Packet to append new packet to. */
645         static ConcretePacket createAfter(Packet const & packet, senf::NoInit_t);
646                                         ///< Create uninitialized empty packet after\a packet
647                                         /**< This will create a completely empty and uninitialized
648                                              packet with <tt>size() == 0</tt>. It will be appended
649                                              as next header/interpreter after \a packet in that
650                                              packets interpreter chain.
651                                              \param[in] packet Packet to append new packet to.
652                                              \param[in] senf::noinit This parameter must always have
653                                                  the value \c senf::noinit. */
654         static ConcretePacket createAfter(Packet const & packet, size_type size);
655                                         ///< Create default initialized packet after \a packet
656                                         /**< This member will create a default initialized packet
657                                              with the given size. If the size parameter is smaller
658                                              than the minimum allowed packet size an exception will
659                                              be thrown. It will be appended as next
660                                              header/interpreter after \a packet in that packets
661                                              interpreter chain.
662                                              \param[in] packet Packet to append new packet to.
663                                              \param[in] size Size of the packet to create in bytes.
664                                              \throws TruncatedPacketException if \a size is smaller
665                                                  than the smallest permissible size for this type of
666                                                  packet. */
667         static ConcretePacket createAfter(Packet const & packet, size_type size, senf::NoInit_t);
668                                         ///< Create uninitialized packet after \a packet
669                                         /**< Creates an uninitialized (all-zero) packet of the exact
670                                              given size.  It will be appended as next
671                                              header/interpreter after \a packet in that packets
672                                              interpreter chain.
673                                              \param[in] packet Packet to append new packet to.
674                                              \param[in] size Size of the packet to create in bytes
675                                              \param[in] senf::noinit This parameter must always have
676                                                  the value \c senf::noinit. */
677 #ifndef DOXYGEN
678         template <class ForwardReadableRange>
679         static ConcretePacket createAfter(
680             Packet const & packet,
681             ForwardReadableRange const & range,
682             typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0);
683 #else
684         template <class ForwardReadableRange>
685         static ConcretePacket createAfter(Packet const & packet,
686                                           ForwardReadableRange const & range);
687                                         ///< Create packet from given data after \a packet
688                                         /**< The packet will be created from a copy of the given
689                                              data. The data from the range will be copied directly
690                                              into the packet representation. The data will \e not be
691                                              validated in any way.  It will be appended as next
692                                              header/interpreter after \a packet in that packets
693                                              interpreter chain.
694                                              \param[in] packet Packet to append new packet to.
695                                              \param[in] range <a href="http://www.boost.org/doc/libs/release/libs/range/index.html">Boost.Range</a>
696                                                  of data to construct packet from. */
697 #endif
698
699         // Create packet as new packet (header) before a given packet
700
701         static ConcretePacket createBefore(Packet const & packet);
702                                         ///< Create default initialized packet before \a packet
703                                         /**< The packet will be initialized to it's default empty
704                                              state. It will be prepended as previous
705                                              header/interpreter before \a packet in that packets
706                                              interpreter chain.
707                                              \warning This constructor will destroy any existing
708                                                  headers before \a packet and replace them with the
709                                                  new header.
710                                              \param[in] packet Packet to prepend new packet to. */
711         static ConcretePacket createBefore(Packet const & packet, senf::NoInit_t);
712                                         ///< Create uninitialized empty packet before \a packet
713                                         /**< Creates a completely empty and uninitialized packet. It
714                                              will be prepended as previous header/interpreter before
715                                              \a packet in that packets interpreter chain.
716                                              \warning This constructor will destroy any existing
717                                                  headers before \a packet and replace them with the
718                                                  new header.
719                                              \param[in] packet Packet to prepend new packet to. */
720
721         static ConcretePacket createInsertBefore(Packet const & packet);
722                                         ///< Insert default initialized packet before \a packet
723                                         /**< The new packet header will be initialized to it' s
724                                              default empty state. It will be inserted into the
725                                              packet chain before \a packet.
726                                              \param[in] packet Packet before which to insert the new
727                                                  packet */
728         static ConcretePacket createInsertBefore(Packet const & packet, senf::NoInit_t);
729                                         ///< Insert uninitialized empty packet before \a packet
730                                         /**< Inserts a completely empty and unitialized packet
731                                              before \a packet into the header/interpreter chain.
732                                              \param[in] packet Packet before which to insert the new
733                                                  packet */
734
735         // Create a clone of the current packet
736
737         ConcretePacket clone() const;
738
739         ///@}
740         ///////////////////////////////////////////////////////////////////////////
741
742         // Field access
743
744         struct ParserProxy
745         {
746             ParserProxy(Parser const & p) : p_ (p) {}
747             Parser * operator->() { return &p_; }
748             Parser p_;
749         };
750
751         ParserProxy operator->() const;    ///< Access packet fields
752                                         /**< This operator allows to access the parsed fields of the
753                                              packet using the notation <tt>packet->field()</tt>. The
754                                              fields of the packet are specified by the PacketType's
755                                              \c parser member.
756
757                                              The members are not strictly restricted to simple field
758                                              access. The parser class may have any member which is
759                                              needed for full packet access (e.g. checksum validation
760                                              / recreation ...)
761                                              \see \ref packetparser for the %parser interface. */
762
763         Parser parser() const;          ///< Access packet field parser directly
764                                         /**< Access the parser of the packet. This is the same
765                                              object returned by the operator->() operator. The
766                                              operator however does not allow to access this object
767                                              itself, only it's members.
768                                              \see \ref packetparser for the %parser interface */
769
770     protected:
771
772     private:
773         typedef PacketInterpreter<PacketType> interpreter;
774
775         ConcretePacket(typename interpreter::ptr const & packet_);
776
777         interpreter * ptr() const;
778
779         friend class Packet;
780         friend class PacketInterpreter<PacketType>;
781     };
782
783     /** \brief Generic parser copying
784
785         This operator allows to copy the value of identical parsers. This operation does \e not
786         depend on the parsers detailed implementation, it will just replace the data bytes of the
787         target parser with those from the source packet.
788      */
789     template <class PacketType, class Parser>
790     Parser operator<<(Parser target, ConcretePacket<PacketType> const & packet);
791
792     ///@}
793
794 }
795
796 ///////////////////////////////hh.e////////////////////////////////////////
797 #endif
798 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_Packet_i_)
799 #define HH_SENF_Packets_Packet_i_
800 #include "Packet.cci"
801 #include "Packet.ct"
802 #include "Packet.cti"
803 #endif
804
805 \f
806 // Local Variables:
807 // mode: c++
808 // fill-column: 100
809 // c-file-style: "senf"
810 // indent-tabs-mode: nil
811 // ispell-local-dictionary: "american"
812 // compile-command: "scons -u test"
813 // comment-column: 40
814 // End:
815