Dia2Png Doxygen started
[senf.git] / Packets / Packet.hh
1 // $Id$
2 //
3 // Copyright (C) 2006 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.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 // TODO: Implement assign() method akin to reinterpret(). However,
24 // instead of using the data already present, assign() will replace
25 // the date of the current packet with the given Packet.
26
27 // TODO: Implement wrapping-constructor. Somehow we want to have a
28 // constructor, which allows creating a chain of packet interpreters
29 // with as little overhead as possible.
30
31 // TODO: Document the additional concrete Packet facade requirements
32 // explicitly and not only within the Parser requirements (check(),
33 // bytes() and min_bytes() members ...)
34
35 // TODO: Implement special container replacing vector which manages
36 // some headroom to allow efficient insertion of elements at the
37 // beginning. This really is just another type of deque
38 // implementation.
39
40
41 /** \mainpage The SENF Packet Library
42
43     \section arch Overall Architecture
44
45     The general Architecture of the Packet Framework (pkf for short)
46     is seperated into two components: The basic packet handling and
47     the parser framework.
48
49     The basic packet handling implements a packet interpreter
50     chain. Every packet is represented as a chain of interpreters
51     where each interpreter is a facade looking into the same
52     packet. Each interpreter will interpret a specific header of a
53     packet. For example, an ethernet frame might have an interpreter
54     chain consisting of EthernetPacket, IPPacket, UDPPacket and
55     DataPacket. Each of these interpreters will interpret a section of
56     the raw data bytes. The interpreter ranges overlap since every
57     packet also includes it's payload.
58
59     The parser framework is used to interpret the raw bytes of a
60     specific packet and parse the values present in that packet. For
61     example, Parse_Ethernet will parse the ethernet source MAC,
62     destination MAC and ethertype given any random access iterator to
63     the first byte of the ethernet frame. Parsers are extremely light
64     classes. They are temporary classes passed around by value. In
65     most cases, they are just comprised of a single pointer adorned
66     with type information.
67
68     \section handling Packet Handling
69
70     The packet handling is implemented within
71     satcom::pkf::Packet. This class is the baseclass to all packet
72     interpreter facades. To implement a new packet type, publically
73     derive from satcom::pkf::Packet and implement the virtual
74     interface (see the class documentation for details).
75
76     \section framework Parser Framework
77
78     The parser framework provides an abstract framwork to parse packet
79     oriented data. A Parser is a template class taking an arbitrary
80     iterator as input and allowing random access to data elements of
81     the interpreted type, like source and destination MAC of an
82     ethernet frame. The parser framework is to be used hierarchically
83     and recursively, the parser methods should return further parsers
84     which can return further parsers and so on.
85
86     The parser framework contains some basic parsers to be used to
87     build up more complex parsers:
88
89      - ParseInt.hh: Lots of parsers for integer numbers like
90        satcom::pkf::Parse_UInt8, for integer bitfields like
91        satcom::pkf::Parse_UIntField and satcom::pkf::Parse_Flag to
92        parse boolean flags.
93
94      - ParseArray.hh: The satcom::pkf::Parse_Array parser to parse
95        arbitrary fixed-size arrays of fixed-size elements (that is
96        sub-parsers).
97
98      - ParseVec.hh: The satcom::pkf::Parse_Vector parser to parse
99        dynamically sized arrays of fixed-size elements (that is
100        sub-parsers).
101
102     See satcom::pkf::ParserBase for further information.
103
104     \section stuff Other Utilities
105
106     The pkf also comprises some additional utilities to support the
107     development of packet classes. 
108
109     The satcom::pkf::PacketRegistry implements a registry of packets
110     keyed by an arbitrary type. The registry is used to find a packet
111     type given some kind of id (like the ethertype value from the
112     ethernet header). Together with it's support classes (especially
113     satcom::pkf::PacketRegistryMixin) this class greatly simplifies
114     implementing the needed table lookups.
115  */
116
117 /** \file
118     \brief Main packet interface
119  */
120
121 #ifndef HH_Packet_
122 #define HH_Packet_ 1
123
124 // Custom includes
125 #include <boost/utility.hpp> // for boost::noncopyable
126 #include <boost/cstdint.hpp>
127 #include <boost/shared_ptr.hpp>
128 #include <boost/intrusive_ptr.hpp>
129 #include <list>
130 #include <vector>
131 #include <iostream>
132
133 #include "Packet.mpp"
134 // ////////////////////////////hh.p////////////////////////////////////////
135
136 namespace satcom {
137 namespace pkf {
138     
139     namespace impl { template <class OtherPacket> class PkReg_EntryImpl; }
140     namespace impl { class PacketImpl; }
141
142     /** \brief Basic interface to all packet facades
143
144         \section packet_overview Overview
145         
146         This class is the base class of all Packets. It implements the
147         generic Packet interface and provides the packet management
148         framework. satcom::pkf::Packet manages the necessary memory
149         resources and controlls the chain of packet interpreters.
150
151         The Packet user always interfaces with the pkf via a Packet
152         derived class. This is the only external entity ever held by a
153         library user. The interface is implemented using a reference
154         counted smart pointer, so resource management is quasi
155         automatic.
156
157         \image html "../../structure.png" Overview
158         
159         Internally, every Packet references a PacketImpl instance which
160         manages the raw packet data and the interpreter list. This raw
161         data is interpreted by the concrete Packet derived class
162         according to the definition of that derived class's packet
163         type (i.e. EthernetPacket or UDPPacket).
164
165         Packet provides several interfaces:
166         
167         - Creation of Packet instances: create()
168
169         - Access to the chain of interpreters: next(), prev(), head(),
170           last(), find_next(), find_prev(), get_next(), get_prev(),
171           is(), as() and reinterpret()
172
173         - Access to the raw packet data: begin(), end(), size(),
174           insert() and erase()
175
176         - An interface to the derived class: v_nextInterpreter(),
177           v_finalize(), registerInterpreter()
178
179
180         \section packet_der Implementing new Packet facades
181
182         To implement a new Packet facade, publically derive from
183         Packet. You need to implement the following minimal interface:
184
185         - You need to provide a new #ptr typedef
186
187         - You have to implement v_nextInterpreter() and v_finalize()
188
189         - The constructor should be private
190
191         - You must make Packet a \c friend of the new Packet facade
192
193         - You must implement a static check() method which validates
194           a byte region as your new Packet
195
196         \code        
197             class ExamplePacket 
198                 : public satcom::pkf::Packet
199             {
200             public:
201                 typedef ptr_t<ExamplePacket>::ptr ptr;
202
203                 static bool check(Packet::iterator begin, Packet::iterator end)
204                 {
205                     // Validate, that the region [begin,end) can be
206                     // interpreted as an ExamplePacket without risking
207                     // memory access violations.
208                 }
209
210             private:
211                 template <class Arg>
212                 ExamplePacket(Arg arg [, other args ... ])
213                     : satcom::pkf::Packet(arg)
214                 {}
215
216                 virtual void v_nextInterpreter() const
217                 {
218                     // NextPacketType and header_length of course
219                     // depend on the packet type
220                     registerInterpreter<NextPacketType>(begin()+header_length, end());
221                 }
222
223                 virtual void v_finalize()
224                 {
225                     // calculate checksum etc
226                 }
227
228                 friend class satcom::pkf::Packet;
229             };
230         \endcode
231
232         Please do not implement the methods inline to not clutter up
233         the header file. This is done here in the example to simplify
234         it. If a class is to be registered in some
235         satcom:pkf::PacketRegistry, it must not take any additional
236         constructor parameters.
237
238         After having implemented the bare framework, the most comman
239         way to implement access to the packets specific data is to use
240         the parser framework by additionally inheriting a
241         corresponding parser. This also automatically implements the
242         check() method, which is provided by the Parser.
243
244         In the following example we only show the differences from the
245         previous example:
246
247         \code
248             class ExamplePacket
249                 : public satcom::pkf::Packet,
250                   public Parse_Example<satcom::pkf::Packet::iterator,
251                                        ExamplePacket>
252             {
253
254                 // check does not need to be implemented here, it is
255                 // inherited from the parser 
256
257             private:
258                 template <class InputIterator>
259                 ExamplePacket(InputIterator begin, InputIterator end)
260                     : satcom::pkf::Packet(begin,end)
261                 {}
262             };
263         \endcode
264
265         See the satcom::pkf::ParserBase Documentation for how to
266         implement Parse_Example.
267
268         The implementation of v_nextInterpreter most of the time
269         relies on some packet registry. This is simplified using the
270         satcom::pkf::PacketRegistryMixin class as follows. Again, we
271         only show the differences from the preceding Example:
272
273         \code
274             struct ExampleRegistry {
275                 type boost::uint16_t key_t;
276             };
277
278             class ExamplePacket
279                 : public satcom::pkf::Packet,
280                   public Parse_Example<satcom::pkf::Packet::iterator,
281                                        ExamplePacket>,
282                   public satcom::pkf::PacketRegistryMixin<ExampleRegistry,
283                                                           ExamplePacket>
284             {
285                 using satcom::pkf::Packet::registerInterpreter;
286                 using satcom::pkf::PacketRegsitryMixin<ExampleRegistry,ExamplePacket>::registerInterpreter;
287             private:
288                 virtual void v_nextInterpreter() const
289                 {
290                     // nextType() is defined in Parse_Example and
291                     // returns the key in the ExampleRegistry of the
292                     // next Packet.
293                     registerInterpreter(nextType(),begin()+header_length, end());
294                 }
295             };
296         \endcode
297
298         For further details on the packet registry, see
299         satcom::pkf::PacketRegistry.
300
301         \section packet_impl Implementation details
302
303         The Packet interface is implemented to minimize overhead as
304         far as possible without getting to complex. One area for
305         improvement ist the container class used to hold the raw
306         data. This currently is an \a std::vector. This could be
307         imporved by either allocating some headroom/tailroom in the
308         vector and using this when inserting data at the beginning or
309         end. Alternatively, a new container class (like the
310         satcom::lib::deque_list) could be used to support zero-copy
311         semantics.
312
313         At the moment, we leave the implementation at
314         std::vector. This container is very simple and especially it
315         can directly be sent out using the operating system since a \a
316         vector stores data at contiguous memory locations. An \a
317         std::deque could be used with \a writev(), however since we
318         have no access to the implementation details of the \a deque,
319         we cannot construct the \a writev() data structures.
320
321         The interpreter list managed by Packet is lazy, meaning packet
322         interpreter facades are added only when requestd by next(),
323         last() or find_next(). v_nextInterpreter() is called if
324         necessary by these methods to complete the interpreter chain.
325
326         To implement the automatic memory management, every Packet
327         facade is reference counted. Additionally, the number of
328         (indirect) references to PacketImpl is counted. This allows to
329         manage the PacketImpl instance automatically. To make this
330         work, it is necessary to ensure throughout the Packet code,
331         that the reference count of a Packet is not accidentally
332         decremented to zero. Also, the internal pointers from the
333         interpreter list to the Packet facades must not be
334         counted. They are therefore implemented differently (
335         boost::shared_ptr vs. boost::intrusive_ptr). The choice of
336         boost::intrusive_ptr for the externaly visible smart pointer
337         for all Packet facades is taken to reduce the overhead (an
338         intrusive_ptr is only the size of an ordinary pointer, a
339         smart_ptr has the size of two pointers).
340
341         \nosubgrouping
342       */
343     class Packet : boost::noncopyable
344     {
345     public:
346         ///\name Types
347         ///@{
348         typedef boost::uint8_t byte; //!< single byte datatype
349         ///@}
350
351     private:
352         ///\name Implementation
353         ///@{
354         // These types are implementation details. They are however
355         // needed to provide the correct typedefs for the user
356         // interface. Hiding these classes would incur a huge
357         // additional indirection overhead.
358
359         typedef std::vector<byte> raw_container;
360         typedef boost::shared_ptr<Packet> interpreter_list_ptr;
361         typedef std::list<satcom::pkf::Packet::interpreter_list_ptr> interpreter_list;
362         typedef unsigned refcount_t;
363
364         ///@}
365
366     public:
367
368         ///////////////////////////////////////////////////////////////////////////
369         ///\name Types
370         ///@{
371         
372         /** \brief smart pointer template for all Packet classes
373             
374             This struct is just a template typedef. It defines the
375             smart pointer used for all Packet classes.
376          */
377         template <class T> struct ptr_t { typedef boost::intrusive_ptr<T> ptr; };
378
379         /** \brief smart pointer to the Packet facades
380
381             Every derived class \e must redeclare this member for it's
382             derived type:
383             \code 
384                 typedef ptr_t<DerivedClass>::ptr ptr
385             \endcode
386          */
387         typedef ptr_t<Packet>::ptr ptr; 
388         typedef raw_container::iterator iterator; //!< raw data iterator
389         typedef raw_container::size_type size_type;
390         typedef raw_container::difference_type difference_type;
391
392         ///@}
393
394         // ////////////////////////////////////////////////////////////////////////
395
396         ///\name Creating packets
397         ///@{
398
399         /** \brief create new Packet
400             
401             This method is used to create a new Packet. All Packet
402             instances are created via this method, they are \e never
403             created directly from the Packet derived class.
404
405             \param OtherPacket Type of Packet to create, a Packet
406                     derived class
407             \param b begin iterator of byte range to create the Packet
408                     from
409             \param e corresponding end iterator
410             \return smart pointer to new packet
411             \throws TruncatedPacketException The data cannot be parsed
412                     securely (the data might be trunctated or just
413                     plain invalid)
414          */
415         template <class OtherPacket, class InputIterator>
416         static typename ptr_t<OtherPacket>::ptr create(InputIterator b, InputIterator e);
417
418         template <class OtherPacket>
419         static typename ptr_t<OtherPacket>::ptr create();
420
421         template <class OuterPacket>
422         static typename ptr_t<OuterPacket>::ptr create(Packet::ptr payload);
423
424         ///@}
425
426         ///\name Interpreter chain
427         ///@{
428         
429         /** \brief get next packet from the interpreter chain
430             \return smart pointer to next packet or 0 if last packet */
431         ptr next() const;
432         /** \brief get previous packet from the interpreter chain
433             \return smart pointer to previous packet or 0 if last packet */
434         ptr prev() const;
435         /** \brief first packet of the interpreter chain
436             \return smart pointer to first packet */
437         ptr head() const;
438         /** \brief get last packet of the interpreter chain
439             \return smart pointer to last packet */
440         ptr last() const;
441         
442         /** \brief first packet of given type after the current packet
443             \return smart pointer to first following packet of type \a
444                 OtherPacket or 0, if no such packet exists */
445         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr find_next() const;
446         /** \brief first packet of given type before the current packet
447             \return smart pointer to first preceding packet of type \a
448                 OtherPacket or 0, if no such packet exists */
449         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr find_prev() const;
450
451         /** \brief first packet of given type after the current packet
452             \return smart pointer to first following packet of type \a
453             OtherPacket. \e Assert's, that a packet of this type exists */
454         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr get_next() const;
455         /** \brief first packet of given type before the current packet
456             \return smart pointer to first preceding packet of type \a
457             OtherPacket. \e Assert's, that a packet of this type exists */
458         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr get_prev() const;
459
460         /** \brief check, wether the packet is of the given type
461             \return true, if packt is of type \a OtherPacket, false
462                 otherwise */
463         template <class OtherPacket> bool is() const; 
464         /** \brief cast packet pointer to the given type
465             \return a properly cast smart pointer if packet is of type
466                 \a OtherPacket. Otherwise return 0 */
467         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr as(); 
468
469         /** \brief replace current packet interpreter
470
471             This method will \e replace the current packet facade in
472             the interpreter list with a new interpreter given by \a
473             OtherPacket. 
474
475             \attention This invalidates the packet instance \e
476             this</b>. You must ensure, not to use the Packet instance
477             any further after this call
478
479             \return smart pointer to a \e new packet facade
480             \throws TruncatedPacketException there is not enough data
481                 to savely interpret the packet as the given type. The
482                 original packet is \e not invalidated
483          */
484         template <class OtherPacket>
485         typename ptr_t<OtherPacket>::ptr reinterpret();
486
487         ///@}
488
489         ///\name Raw packet data
490         ///@{
491
492         /** \brief begin interator of raw packet data
493             
494             This iterator allows access to the raw data interpreted by
495             the packet facade. This \e includes any header possibly
496             interpreted by the derived packet instance. To access the
497             payload of the packet, use next()->begin().
498
499             \return random access iterator to the begin of the raw
500                 data */
501         iterator begin() const;
502         /** \brief past-the-end iterator of raw packet data
503             
504             This iterator allows access to the raw data interpreted by
505             the packet facade. This \e includes any header possibly
506             interpreted by the derived packet instance. To access the
507             payload of the packet, use next()->end().
508
509             \return random access past-the-end iterator of the raw
510                 data */
511         iterator end() const;
512         /** \brief raw data size of packet
513             \return size of the raw data interpreted by this
514                 packet in bytes. This is \e not necessarily the size of
515                 the complete packet, use head()->size() for this. */
516         size_t size() const;
517
518         // Modifying the raw packet data
519
520         // FIXME: Make all data mutators protected
521
522         typedef enum { AUTO, BEFORE, INSIDE, OUTSIDE, AFTER } Whence;
523
524         /** \brief insert single byte \a v before pos
525
526             \attention The change will \e not be validated by the
527             derived packet instance. This method is mostly to be used
528             by the derived class implementation and their helper
529             classes. */
530         void insert(iterator pos, byte v, Whence whence = AUTO);
531         /** \brief insert \a n copies of byte \a v before pos
532
533             \attention The change will \e not be validated by the
534             derived packet instance. This method is mostly to be used
535             by the derived class implementation and their helper
536             classes. */
537         void insert(iterator pos, size_type n, byte v, Whence whence = AUTO);
538         /** \brief insert a copy of the given range before pos
539
540             \attention The change will \e not be validated by the
541             derived packet instance. This method is mostly to be used
542             by the derived class implementation and their helper
543             classes. */
544         template <class InputIterator> 
545         void insert(iterator pos, InputIterator f, InputIterator l, Whence whence = AUTO);
546
547         /** \brief erase single byte
548
549             \attention The change will \e not be validated by the
550             derived packet instance. This method is mostly to be used
551             by the derived class implementation and their helper
552             classes. */
553         void erase(iterator pos);
554         /** \brief erase range
555
556             \attention The change will \e not be validated by the
557             derived packet instance. This method is mostly to be used
558             by the derived class implementation and their helper
559             classes. */
560         void erase(iterator first, iterator last);
561
562         ///@}
563
564         void dump(std::ostream & os) const;
565
566     protected:
567         ///\name Derived class interface
568         ///@{
569
570         /** \brief create new interpreter facade for an existing packet
571             
572             This constructor is called, when a new interpreter is to
573             be added to the interpreter chain. The constructor is
574             called indirectly from registerInterpreter() or
575             reinterpret() via the derived classes template
576             constructor.
577          */
578         template <class Operation>
579         Packet(Operation const & arg);
580         virtual ~Packet();
581         
582     private:
583         /** \brief create next packet interpreter
584
585             This method is called by next(), last() or find_next() to
586             create any missing interpreters in the interpreter
587             chain. This method must be overridden in the derived class
588             to register the next packet interpreter in the interpreter
589             chain with the packet framework.
590
591             To register the new interpreter, use
592             registerInterpreter() to create the new Packet
593             instance. The new instance is automatically added to the
594             interpreter chain after the current interpreter.
595
596             See also satcom::pkf::PacketRegistryMixin on how to
597             use a Registry to find the next interpreters implementing
598             class.
599          */
600         virtual void v_nextInterpreter() const = 0;
601
602         /** \brief finalize packet for sending
603
604             This method is called by the packet framework to let the
605             interpreter facade do some final calculations/packet
606             cleanup before the packet is sent out or digested in some
607             other way. This is the place to calcaulate checksums and
608             such.
609
610             This method is autmatically called for all interpreters on
611             the interpreter chain.
612          */
613         virtual void v_finalize() = 0;
614
615         virtual void v_dump(std::ostream & os) const = 0;
616
617     protected:
618         /** \brief add interpreter to interpreter chain
619
620             This method is used by v_nextInterpreter() in the derived
621             classes to add a new interpreter to the interpreter
622             chain. This method will call \c OtherPacket's constructor
623             with the correct arguments and insert the new interpreter
624             into the interpreter list. This method is used, if no
625             further arguments are to be passed to the \c OtherPacket
626             constructor. If additional arguments are necessary, just
627             add them after \c end. The compiler will then choose the
628             correct overload to use.
629          */
630         template <class OtherPacket>
631         typename ptr_t<OtherPacket>::ptr registerInterpreter(
632             raw_container::iterator begin, raw_container::iterator end) const;
633         template <class OtherPacket, class A0>
634         typename ptr_t<OtherPacket>::ptr registerInterpreter(
635             raw_container::iterator begin, raw_container::iterator end,
636             A0 const & a0) const;
637
638 #       define BOOST_PP_ITERATION_PARAMS_1 (4, (2, 9, "Packets/Packet.mpp", 3))
639 #       include BOOST_PP_ITERATE()
640
641         ///@}
642
643     private:
644
645         ///\name Implementation
646         ///@{
647
648         void add_ref() const;
649         bool release();
650         bool unlink();
651
652         struct PacketOp_register;
653         friend class PacketOp_register;
654         void i_registerInterpreter(Packet * p) const;
655
656         struct PacketOp_replace;
657         friend class PacketOp_replace;
658         void i_replaceInterpreter(Packet * p);
659
660         struct PacketOp_set;
661         friend class PacketOp_set;
662         void i_setInterpreter(impl::PacketImpl * i);
663
664     private:
665         friend class impl::PacketImpl;
666         template <class OtherPacket> friend class impl::PkReg_EntryImpl;
667
668         impl::PacketImpl* impl_;
669         size_type begin_;
670         size_type end_;
671         interpreter_list::iterator self_;
672         mutable bool parsed_;
673         mutable refcount_t refcount_;
674
675         ///@}
676     };
677
678     /** \brief dump packet to stream
679         \related Packet */
680     // std::ostream & operator<<(std::ostream & os, Packet const & packet);
681
682     /** \brief smart pointer handling
683         \relates Packet */
684     void intrusive_ptr_add_ref(Packet const *);
685     /** \brief smart pointer handling
686         \relates Packet */
687     void intrusive_ptr_release(Packet *);
688
689     struct TruncatedPacketException : public std::exception
690     { virtual char const * what() const throw() { return "truncated packet"; } };
691
692 }}
693
694 // ////////////////////////////hh.e////////////////////////////////////////
695 #include "Packet.cci"
696 #include "Packet.ct"
697 #include "Packet.cti"
698
699 #include "Packet.mpp"
700 #endif
701
702 \f
703 // Local Variables:
704 // mode: c++
705 // c-file-style: "satcom"
706 // End: