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