f08a996a87bf4fa760ed9246ad9519476af3b1f0
[senf.git] / 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_Packet_
27 #define HH_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 "../Utils/Exception.hh"
34 #include "../Utils/Tags.hh"
35 #include "../Utils/safe_bool.hh"
36 #include "PacketInterpreter.hh"
37
38 //#include "Packet.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
40
41 namespace senf {
42
43     /** \defgroup packet_module Packet Handling
44
45         The basic groundwork of the %Packet library is the packet handling:
46
47         \li The packet classes provide access to a chain of packet headers (more generically called
48             interpreters).
49         \li They automatically manage the required memory resources and the shared packet data.
50
51         \section packet_module_chain The Interpreter Chain
52
53         The central data structure for a packet is the interpreter chain
54
55         \image html structure.png The Interpreter Chain
56
57         This image depicts a packet with several headers. Each interpreter is responsible for a
58         specific sub-range of the complete packet. This range always \e includes the packets payload
59         (This is, why we call the data structure interpreter and not header: The interpreter is
60         responsible for interpreting a range of the packet according to a specific protocol), the
61         packet interpreters are nested inside each other.
62     
63         For each interpreter, this structure automatically divides the packet into three areas (each
64         of which are optional): The header, the payload and the trailer. Every packet will have
65         either a header or a payload section while most don't have a trailer.
66
67         As user of the library you always interact with the chain through one (or more) of the
68         interpreters. The interpreter provides methods to traverse to the following or preceding
69         header (interpreter) and provides two levels of access to the packet data: Generic low-level
70         access in the form of an STL compatible sequence and access to the parsed fields which are
71         provided by the parser associated with the concrete packet type.
72
73         \section packet_module_management Resource Management
74
75         The interface to the packet library is provided using a handle class (\ref Packet for
76         generic, protocol agnostic access and \ref ConcretePacket derived from \ref Packet to access
77         a specific protocol). This handle automatically manages the resources associated with the
78         packet (the interpreter chain and the data storage holding the packet data). The resources
79         are automatically released when the last packet handle referencing a specific packet is
80         destroyed.
81
82         \implementation The packet chain is provided on two levels: The internal representation \ref
83             PacketInterpreterBase and \ref PacketInterpreter which are referenced by the Handle
84             classes \ref Packet and \ref ConcretePacket. \n
85             The internal representation classes are pertinent in the sense, that they exist
86             regardless of the existence of a handle referencing them (as long as the packet
87             exists). Still the interpreter chain is lazy and packet interpreters beside the first
88             are only created dynamically when accessed (this is implemented in the handle not in the
89             internal representation). \n
90             The packet interpreters make use of a pool allocator. This provides extremely efficient
91             creation and destruction of packet interpreter's and removes the dynamic memory
92             management overhead from the packet interpreter management. The packet implementation
93             class (\ref PacketImpl which holds the packet data itself) however is still dynamically
94             managed (however there is only a single instance for each packet).
95      */
96
97     template <class PackeType> class ConcretePacket;
98
99     ///\addtogroup packet_module
100     ///@{
101     
102     /** \brief Main %Packet class
103
104         %Packet is the main externally visible class of the packet library. %Packet is a handle into
105         the internal packet representation. From %Packet you may access the data of that specific
106         sub-packet/header/interpreter and navigate to the neighboring
107         sub-packets/headers/interpreters.
108
109         %Packet is protocol agnostic. This class only provides non-protocol dependent members. To
110         access the protocol specific features of a packet (like header fields) the ConcretePacket
111         class extending %Packet is provided.
112
113         \section packet_semantics Semantics
114         
115         All operations accessing the data of \c this packet in some way will ignore any preceding
116         packets/headers/interpreters in the chain. It does not matter, whether a given packet is
117         taken from the middle or the beginning of the chain, all operations (except those explicitly
118         accessing the chain of course) should work the same.
119         
120         This especially includes members like clone() or append(): clone() will clone \e only from
121         \c this packet until the end of the chain, append() will append the given packet \e ignoring
122         any possibly preceding packets/headers/interpreters.
123
124         In the same way, the data() member provides an STL-sequence compatible view of the packet
125         data. This only includes the data which is part of \c this packet including header, trailer
126         \e and payload but \e not the headers or trailers of packets \e before \c this packet in the
127         packet/header/interpreter chain (nonetheless, this data overlaps with the data of other
128         packets).
129
130         Several members are member templates taking an \a OtherPacket template parameter. This
131         parameter must be the ConcretePacket instantiation associated with some concrete packet type
132         (protocol). For each implemented protocol, typedefs should be provided for these
133         instantiations (Example: \ref EthernetPacket is a typedef for
134         \ref ConcretePacket < \ref EthernetPacketType >).
135
136         \see 
137             \ref ConcretePacket for the %type specific interface\n
138             \ref PacketData for the sequence interface\n
139             \ref packetparser for a specification of the parser interface
140       */
141     class Packet
142         : public safe_bool<Packet>,
143           public boost::equality_comparable<Packet>
144     {
145     public:
146         ///////////////////////////////////////////////////////////////////////////
147         // Types
148         
149         typedef void type;              ///< Type of the packet.
150         typedef senf::detail::packet::size_type size_type;
151                                         ///< Unsigned type to represent packet size
152         typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
153
154         ///////////////////////////////////////////////////////////////////////////
155         ///\name Structors and default members
156         ///@{
157
158         // default copy constructor
159         // default copy assignment
160         // default destructor
161         
162         Packet();                       ///< Create uninitialized packet handle
163                                         /**< An uninitialized handle is in - valid(). It does not
164                                              allow any operation except assignment and checking for
165                                              validity. */
166         Packet clone() const;           ///< Create copy packet
167                                         /**< clone() will create a complete copy of \c this
168                                              packet. The returned packet will have the same data and
169                                              packet chain. It does however not share any data with
170                                              the original packet. */
171
172         // conversion constructors
173
174         template <class PacketType>     
175         Packet(ConcretePacket<PacketType> packet); ///< 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; 
187                                         ///< Get next packet in chain
188                                         /**< \throws InvalidPacketChainException if no next packet 
189                                              exists */
190                                      Packet      next(NoThrow_t) const; 
191                                         ///< Get next packet in chain
192                                         /**< \returns in - valid() packet if no next packet 
193                                              exists */
194         template <class OtherPacket> OtherPacket next() const; 
195                                         ///< Get next packet in chain and cast to \a OtherPacket
196                                         /**< \throws std::bad_cast if the next() packet is not of
197                                              type \a OtherPacket
198                                              \throws InvalidPacketChainException if no next packet
199                                                  exists */
200         template <class OtherPacket> OtherPacket next(NoThrow_t) const; 
201                                         ///< Get next packet in chain and cast to \a OtherPacket
202                                         /**< \throws std::bad_cast if the next() packet is not of
203                                              type \a OtherPacket
204                                              \returns in - valid() packet if no next packet
205                                                  exists */
206         template <class OtherPacket> OtherPacket find() const;
207                                         ///< Search chain forward for packet of type \a OtherPacket
208                                         /**< The search will start with the current packet.
209                                              \throws InvalidPacketChainException if no packet of
210                                                  type \a OtherPacket can be found. */
211         template <class OtherPacket> OtherPacket find(NoThrow_t) const;
212                                         ///< Search chain forward for packet of type \a OtherPacket
213                                         /**< The search will start with the current packet.
214                                              \returns in - valid() packet if no packet of type \a
215                                                  OtherPacket can be found. */
216         
217                                      Packet      prev() const; 
218                                         ///< Get previous packet in chain
219                                         /**< \throws InvalidPacketChainException if no previous
220                                              packet exists */
221                                      Packet      prev(NoThrow_t) const; 
222                                         ///< Get previous packet in chain
223                                         /**< \returns in - valid() packet if no previous packet
224                                              exists */
225         template <class OtherPacket> OtherPacket prev() const; 
226                                         ///< Get previous packet in chain and cast to \a OtherPacket
227                                         /**< \throws std::bad_cast, if the previous packet is not of
228                                              type \a OtherPacket
229                                              \throws InvalidPacketChainException if no previous
230                                                  packet exists */
231         template <class OtherPacket> OtherPacket prev(NoThrow_t) const; 
232                                         ///< Get previous packet in chain and cast to \a OtherPacket
233                                         /**< \throws std::bad_cast, if the previous packet is not of
234                                              type \a OtherPacket
235                                              \returns in - valid() packet if no previous packet 
236                                                  exists */
237         template <class OtherPacket> OtherPacket rfind() const;
238                                         ///< Search chain backwards for packet of type \a OtherPacket
239                                         /**< The search will start with the current packet.
240                                              \throws InvalidPacketChainException if no packet of
241                                                  type \a OtherPacket can be found. */
242         template <class OtherPacket> OtherPacket rfind(NoThrow_t) const;
243                                         ///< Search chain backwards for packet of type \a OtherPacket
244                                         /**< The search will start with the current packet.
245                                              \returns in - valid() packet if no packet of type \a
246                                                  OtherPacket can be found. */
247
248
249                                      Packet      first() const;
250                                         ///< Return first packet in chain
251         template <class OtherPacket> OtherPacket first() const;
252                                         ///< Return first packet in chain and cast
253                                         /**< \throws std::bad_cast if the first() packet is not of
254                                              type \a OtherPacket */
255
256                                      Packet      last() const;
257                                         ///< Return last packet in chain
258         template <class OtherPacket> OtherPacket last() const;
259                                         ///< Return last packet in chain and cast
260                                         /**< \throws std::bad_cast if the last() packet is not of
261                                              type \a OtherPacket  */
262
263
264         template <class OtherPacket> OtherPacket parseNextAs() const;
265                                         ///< Interpret payload of \c this as \a OtherPacket
266                                         /**< parseNextAs() will throw away the packet chain after
267                                              the current packet if necessary. It will then parse the
268                                              payload section of \c this packet as given by \a
269                                              OtherPacket. The new packet is added to the chain after
270                                              \c this.
271                                              \returns new packet instance sharing the same data and
272                                                  placed after \c this packet in the chain. */
273                                      Packet      parseNextAs(factory_t factory) const;
274                                         ///< Interpret payload of \c this as \a factory type packet
275                                         /**< parseNextAs() will throw away the packet chain after
276                                              the current packet if necessary. It will then parse the
277                                              payload section of \c this packet as given by \a
278                                              factory. The new packet is added to the chain after
279                                              \c this.
280                                              \returns new packet instance sharing the same data and
281                                                  placed after \c this packet in the chain. */
282
283         template <class OtherPacket> bool        is() const;
284                                         ///< Check, whether \c this packet is of the given type
285         template <class OtherPacket> OtherPacket as() const;
286                                         ///< Cast current packet to the given type
287                                         /**< This operations returns a handle to the same packet
288                                              header/interpreter however cast to the given
289                                              ConcretePacket type.
290                                              \throws std::bad_cast if the current packet is not of
291                                                  type \a OtherPacket */
292
293         Packet append(Packet packet) const; ///< Append the given packet to \c this packet
294                                         /**< This operation will replace the payload section of \c
295                                              this packet with \a packet. This operation will replace
296                                              the packet chain after \c this packet with a clone of
297                                              \a packet and will replace the raw data of the payload
298                                              of \c this with the raw data of \a packet. \c this
299                                              packet will not share any date with \a packet.
300                                              \returns Packet handle to the cloned \a packet, placed
301                                                  after \c this in the packet/header/interpreter
302                                                  chain. */
303
304         ///@}
305
306         ///\name Data access
307         ///@{
308
309         PacketData & data() const;      ///< Access the packets raw data container
310         size_type size() const;         ///< Return size of packet in bytes
311                                         /**< This size does \e not include the size of any preceding
312                                              headers/packets/interpreters. It does however include
313                                              \c this packets payload. */
314         
315         ///@}
316
317         ///\name Other methods
318         ///@{
319
320         bool operator==(Packet other) const; ///< Check for packet identity
321                                         /**< Two packet handles compare equal if they really are the
322                                              same packet header in the same packet chain. */
323         bool boolean_test() const;      ///< Check, whether the packet is valid()
324                                         /**< \see valid() */
325         bool valid() const;             ///< Check, whether the packet is valid()
326                                         /**< An in - valid() packet does not allow any operation
327                                              except checking for validity and assignment. in -
328                                              valid() packets serve the same role as 0-pointers. 
329                                              
330                                              This is an alias for boolean_test() which is called
331                                              when using a packet in a boolean context. */
332
333         void finalize() const;          ///< Update calculated fields
334                                         /**< This call will update all calculated fields of the
335                                              packet after it has been created or changed. This
336                                              includes checksums, payload size fields or other
337                                              fields, which can be set from other information in the
338                                              packet. Each concrete packet type should document,
339                                              which fields are set by finalize().
340
341                                              finalize() will automatically process all
342                                              packets/headers/interpreters from the end of the chain
343                                              backwards up to \c this. */
344
345         void dump(std::ostream & os) const; ///< Write out a printable packet representation
346                                         /**< This method is provided mostly to help debugging packet
347                                              problems. Each concrete packet should implement a dump
348                                              method writing out all fields of the packet in a
349                                              readable representation. dump() will call this member
350                                              for each packet/header/interpreter in the chain from \c
351                                              this packet up to the end of the chain. */
352
353         TypeIdValue typeId() const;     ///< Get id of \c this packet
354                                         /**< This value is used e.g. in the packet registry to
355                                              associate packet types with other information.
356                                              \returns A type holding the same information as a
357                                                  type_info object, albeit assignable */
358         factory_t factory() const;      ///< Return factory instance of \c this packet
359                                         /**< The returned factory instance can be used to create new
360                                              packets of the given type without knowing the concrete
361                                              type of the packet. The value may be stored away for
362                                              later use if needed. */
363         
364         ///@}
365
366     protected:
367         explicit Packet(PacketInterpreterBase::ptr packet);
368
369         PacketInterpreterBase::ptr ptr() const;
370
371     private:
372         Packet checkNext() const;
373         Packet checkLast() const;
374         
375         PacketInterpreterBase::ptr packet_;
376         
377         template <class PacketType>
378         friend class ConcretePacket;
379         friend class PacketParserBase;
380     };
381
382     /** \brief Protocol specific packet handle
383
384         The ConcretePacket template class extends Packet to provide protocol/packet type specific
385         aspects. These are packet constructors and access to the parsed packet fields.
386
387         The \c PacketType template argument to ConcretePacket is a protocol specific and internal
388         policy class which defines the protocol specific behavior. To access a specific type of
389         packet, the library provides corresponding typedefs of ConcretePacket < \a SomePacketType >
390         (e.g. \ref EthernetPacket as typedef for \ref ConcretePacket < \ref EthernetPacketType >).
391
392         The new members provided by ConcretePacket over packet are mostly comprised of the packet
393         constructors. These come in three major flavors:
394         
395         \li The create() family of constructors will create completely new packets.
396         \li The createAfter() family of constructors will create new packets (with new data for the
397             packet) \e after a given existing packet.
398         \li The createBefore()  family of constructors will create new packets (again with new data)
399             \e before a given existing packet.
400         
401         Whereas create() will create a completely new packet with it's own chain and data storage,
402         createAfter() and createBefore() extend a packet with additional
403         headers/interpreters. createAfter() will set the payload of the given packet to the new
404         packet whereas createBefore() will create a new packet with the existing packet as it's
405         payload. 
406
407         createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
408         replacing any possibly existing data whereas the latter will interpret the already \e
409         existing data as given by the type argument.
410         
411         \see \ref PacketTypeBase for a specification of the interface to be provided by the \a
412             PacketType policy class.
413       */
414     template <class PacketType>
415     class ConcretePacket 
416         : public Packet
417     {
418     public:
419         ///////////////////////////////////////////////////////////////////////////
420         // Types
421         
422         typedef PacketType type;
423         typedef typename PacketType::parser Parser;
424
425         ///////////////////////////////////////////////////////////////////////////
426         ///\name Structors and default members
427         ///@{
428
429         // default copy constructor
430         // default copy assignment
431         // default destructor
432         // no conversion constructors
433
434         ConcretePacket();               ///< Create uninitialized packet handle
435                                         /**< An uninitialized handle is not valid(). It does not
436                                              allow any operation except assignment and checking for
437                                              validity. */
438
439         static factory_t factory();     ///< Return factory for packets of specific type
440                                         /**< This \e static member is like Packet::factory() for a
441                                              specific packet of type \a PacketType */
442
443         // Create completely new packet
444
445         static ConcretePacket create(); ///< Create default initialized packet
446                                         /**< The packet will be initialized to it's default empty
447                                              state. */
448         static ConcretePacket create(senf::NoInit_t); ///< Create uninitialized empty packet
449                                         /**< This will create a completely empty and uninitialized
450                                              packet with <tt>size() == 0</tt>.
451                                              \param[in] senf::noinit This parameter must always have the
452                                                  value \c senf::noinit. */
453         static ConcretePacket create(size_type size); ///< Create default initialized packet
454                                         /**< This member will create a default initialized packet
455                                              with the given size. If the size parameter is smaller
456                                              than the minimum allowed packet size an exception will
457                                              be thrown.
458                                              \param[in] size Size of the packet to create in bytes.
459                                              \throws TruncatedPacketException if \a size is smaller
460                                                  than the smallest permissible size for this type of
461                                                  packet. */
462         static ConcretePacket create(size_type size, senf::NoInit_t); 
463                                         ///< Create uninitialized packet
464                                         /**< Creates an uninitialized (all-zero) packet of the exact
465                                              given size. 
466                                              \param[in] size Size of the packet to create in bytes
467                                              \param[in] senf::noinit This parameter must always have the
468                                                  value \c senf::noinit. */
469 #ifndef DOXYGEN
470         template <class ForwardReadableRange>
471         static ConcretePacket create(
472             ForwardReadableRange const & range,
473             typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0); 
474 #else
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.
482                                              \param[in] range <a
483                                                  href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
484                                                  of data to construct packet from. */
485 #endif
486
487         // Create packet as new packet after a given packet
488
489         static ConcretePacket createAfter(Packet packet); 
490                                         ///< Create default initialized packet after \a packet
491                                         /**< The packet will be initialized to it's default empty
492                                              state. It will be appended as next header/interpreter
493                                              after \a packet in that packets interpreter chain.
494                                              \param[in] packet Packet to append new packet to. */
495         static ConcretePacket createAfter(Packet packet, senf::NoInit_t);
496                                         ///< Create uninitialized empty packet after\a packet
497                                         /**< This will create a completely empty and uninitialized
498                                              packet with <tt>size() == 0</tt>. It will be appended
499                                              as next header/interpreter after \a packet in that
500                                              packets interpreter chain.
501                                              \param[in] packet Packet to append new packet to.
502                                              \param[in] senf::noinit This parameter must always have the
503                                                  value \c senf::noinit. */
504         static ConcretePacket createAfter(Packet packet, size_type size);
505                                         ///< Create default initialized packet after \a packet
506                                         /**< This member will create a default initialized packet
507                                              with the given size. If the size parameter is smaller
508                                              than the minimum allowed packet size an exception will
509                                              be thrown. It will be appended as next
510                                              header/interpreter after \a packet in that packets
511                                              interpreter chain.
512                                              \param[in] packet Packet to append new packet to.
513                                              \param[in] size Size of the packet to create in bytes.
514                                              \throws TruncatedPacketException if \a size is smaller
515                                                  than the smallest permissible size for this type of
516                                                  packet. */
517         static ConcretePacket createAfter(Packet packet, size_type size, senf::NoInit_t);
518                                         ///< Create uninitialized packet after \a packet
519                                         /**< Creates an uninitialized (all-zero) packet of the exact
520                                              given size.  It will be appended as next
521                                              header/interpreter after \a packet in that packets
522                                              interpreter chain.
523                                              \param[in] packet Packet to append new packet to.
524                                              \param[in] size Size of the packet to create in bytes
525                                              \param[in] senf::noinit This parameter must always have the
526                                                  value \c senf::noinit. */
527 #ifndef DOXYGEN
528         template <class ForwardReadableRange>
529         static ConcretePacket createAfter(
530             Packet packet, 
531             ForwardReadableRange const & range,
532             typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0);
533 #else
534         template <class ForwardReadableRange>
535         static ConcretePacket createAfter(Packet packet, 
536                                           ForwardReadableRange const & range);
537                                         ///< Create packet from given data after \a packet
538                                         /**< The packet will be created from a copy of the given
539                                              data. The data from the range will be copied directly
540                                              into the packet representation. The data will \e not be
541                                              validated in any way.  It will be appended as next
542                                              header/interpreter after \a packet in that packets
543                                              interpreter chain.
544                                              \param[in] packet Packet to append new packet to.
545                                              \param[in] range <a
546                                                  href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
547                                                  of data to construct packet from. */
548 #endif
549
550         // Create packet as new packet (header) before a given packet
551
552         static ConcretePacket createBefore(Packet packet); 
553                                         ///< Create default initialized packet before \a packet
554                                         /**< The packet will be initialized to it's default empty
555                                              state. It will be prepended as previous
556                                              header/interpreter before \a packet in that packets
557                                              interpreter chain.
558                                              \param[in] packet Packet to prepend new packet to. */
559         static ConcretePacket createBefore(Packet packet, senf::NoInit_t);
560                                         ///< Create uninitialized empty packet before \a packet
561                                         /**< Creates a completely empty and uninitialized packet. It
562                                              will be prepended as previous header/interpreter before
563                                              \a packet in that packets interpreter chain.
564                                              \param[in] packet Packet to prepend new packet to. */
565         
566         // Create a clone of the current packet
567
568         ConcretePacket clone() const;
569
570         ///@}
571         ///////////////////////////////////////////////////////////////////////////
572
573         // Field access
574
575         Parser * operator->() const;    ///< Access packet fields
576                                         /**< This operator allows to access the parsed fields of the
577                                              packet using the notation <tt>packet->field()</tt>. The
578                                              fields of the packet are specified by the PacketType's
579                                              \c parser member. 
580
581                                              The members are not strictly restricted to simple field
582                                              access. The parser class may have any member which is
583                                              needed for full packet access (e.g. checksum validation
584                                              / recreation ...)
585                                              \see \ref packetparser for the parser interface. */
586
587         Parser parser() const;          ///< Access packet field parser directly
588                                         /**< Access the parser of the packet. This is the same
589                                              object returned by the operator->() operator. The
590                                              operator however does not allow to access this object
591                                              itself, only it's members.
592                                              \see \ref packetparser for the parser interface */
593
594     protected:
595
596     private:
597         typedef PacketInterpreter<PacketType> interpreter;
598
599         ConcretePacket(typename interpreter::ptr packet_);
600         
601         typename interpreter::ptr ptr() const;
602
603         friend class Packet;
604         friend class PacketInterpreter<PacketType>;
605     };
606
607     ///@}
608
609 }
610
611 ///////////////////////////////hh.e////////////////////////////////////////
612 #endif
613 #if !defined(HH_Packets__decls_) && !defined(HH_Packet_i_)
614 #define HH_Packet_i_
615 #include "Packet.cci"
616 #include "Packet.ct"
617 #include "Packet.cti"
618 #endif
619
620 \f
621 // Local Variables:
622 // mode: c++
623 // fill-column: 100
624 // c-file-style: "senf"
625 // indent-tabs-mode: nil
626 // ispell-local-dictionary: "american"
627 // compile-command: "scons -u test"
628 // comment-column: 40
629 // End:
630