bcf5c5ec7d4145a8de7e41fc2d60a725853c8ddb
[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 /** \file
24     \brief Main packet interface
25
26     \todo Implement assign() method akin to reinterpret(). However,
27     instead of using the data already present, assign() will replace
28     the date of the current packet with the given Packet.
29
30     \todo Implement wrapping-constructor. Somehow we want to have a
31     constructor, which allows creating a chain of packet interpreters
32     with as little overhead as possible.
33
34     \todo Document the additional concrete Packet facade requirements
35     explicitly and not only within the Parser requirements (check(),
36     bytes() and min_bytes() members ...)
37
38     \todo Implement special container replacing vector which manages
39     some headroom to allow efficient insertion of elements at the
40     beginning. This really is just another type of deque
41     implementation.
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         \fixme Make all data mutators protected
264
265         \nosubgrouping
266       */
267     class Packet : boost::noncopyable
268     {
269     public:
270         ///\name Types
271         ///@{
272         typedef boost::uint8_t byte; //!< single byte datatype
273         ///@}
274
275     private:
276         ///\name Implementation
277         ///@{
278         // These types are implementation details. They are however
279         // needed to provide the correct typedefs for the user
280         // interface. Hiding these classes would incur a huge
281         // additional indirection overhead.
282
283         typedef std::vector<byte> raw_container;
284         typedef boost::shared_ptr<Packet> interpreter_list_ptr;
285         typedef std::list<senf::Packet::interpreter_list_ptr> interpreter_list;
286         typedef unsigned refcount_t;
287
288         ///@}
289
290     public:
291
292         ///////////////////////////////////////////////////////////////////////////
293         ///\name Types
294         ///@{
295         
296         /** \brief smart pointer template for all Packet classes
297             
298             This struct is just a template typedef. It defines the
299             smart pointer used for all Packet classes.
300          */
301         template <class T> struct ptr_t { typedef boost::intrusive_ptr<T> ptr; };
302
303         /** \brief smart pointer to the Packet facades
304
305             Every derived class \e must redeclare this member for it's
306             derived type:
307             \code 
308                 typedef ptr_t<DerivedClass>::ptr ptr
309             \endcode
310          */
311         typedef ptr_t<Packet>::ptr ptr; 
312         typedef raw_container::iterator iterator; //!< raw data iterator
313         typedef raw_container::size_type size_type;
314         typedef raw_container::difference_type difference_type;
315
316         ///@}
317
318         // ////////////////////////////////////////////////////////////////////////
319
320         ///\name Creating packets
321         ///@{
322
323         /** \brief create new Packet
324             
325             This method is used to create a new Packet. All Packet
326             instances are created via this method, they are \e never
327             created directly from the Packet derived class.
328
329             \param OtherPacket Type of Packet to create, a Packet
330                     derived class
331             \param b begin iterator of byte range to create the Packet
332                     from
333             \param e corresponding end iterator
334             \return smart pointer to new packet
335             \throws TruncatedPacketException The data cannot be parsed
336                     securely (the data might be trunctated or just
337                     plain invalid)
338          */
339         template <class OtherPacket, class InputIterator>
340         static typename ptr_t<OtherPacket>::ptr create(InputIterator b, InputIterator e);
341
342         template <class OtherPacket>
343         static typename ptr_t<OtherPacket>::ptr create();
344
345         template <class OuterPacket>
346         static typename ptr_t<OuterPacket>::ptr create(Packet::ptr payload);
347
348         ///@}
349
350         ///\name Interpreter chain
351         ///@{
352         
353         /** \brief get next packet from the interpreter chain
354             \return smart pointer to next packet or 0 if last packet */
355         ptr next() const;
356         /** \brief get previous packet from the interpreter chain
357             \return smart pointer to previous packet or 0 if last packet */
358         ptr prev() const;
359         /** \brief first packet of the interpreter chain
360             \return smart pointer to first packet */
361         ptr head() const;
362         /** \brief get last packet of the interpreter chain
363             \return smart pointer to last packet */
364         ptr last() const;
365         
366         /** \brief first packet of given type after the current packet
367             \return smart pointer to first following packet of type \a
368                 OtherPacket or 0, if no such packet exists */
369         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr find_next() const;
370         /** \brief first packet of given type before the current packet
371             \return smart pointer to first preceding packet of type \a
372                 OtherPacket or 0, if no such packet exists */
373         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr find_prev() const;
374
375         /** \brief first packet of given type after the current packet
376             \return smart pointer to first following packet of type \a
377             OtherPacket. \e Assert's, that a packet of this type exists */
378         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr get_next() const;
379         /** \brief first packet of given type before the current packet
380             \return smart pointer to first preceding packet of type \a
381             OtherPacket. \e Assert's, that a packet of this type exists */
382         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr get_prev() const;
383
384         /** \brief check, wether the packet is of the given type
385             \return true, if packt is of type \a OtherPacket, false
386                 otherwise */
387         template <class OtherPacket> bool is() const; 
388         /** \brief cast packet pointer to the given type
389             \return a properly cast smart pointer if packet is of type
390                 \a OtherPacket. Otherwise return 0 */
391         template <class OtherPacket> typename ptr_t<OtherPacket>::ptr as(); 
392
393         /** \brief replace current packet interpreter
394
395             This method will \e replace the current packet facade in
396             the interpreter list with a new interpreter given by \a
397             OtherPacket. 
398
399             \attention This invalidates the packet instance \e
400             this. You must ensure, not to use the Packet instance any
401             further after this call
402
403             \return smart pointer to a \e new packet facade
404             \throws TruncatedPacketException there is not enough data
405                 to savely interpret the packet as the given type. The
406                 original packet is \e not invalidated
407          */
408         template <class OtherPacket>
409         typename ptr_t<OtherPacket>::ptr reinterpret();
410
411         ///@}
412
413         ///\name Raw packet data
414         ///@{
415
416         /** \brief begin interator of raw packet data
417             
418             This iterator allows access to the raw data interpreted by
419             the packet facade. This \e includes any header possibly
420             interpreted by the derived packet instance. To access the
421             payload of the packet, use next()->begin().
422
423             \return random access iterator to the begin of the raw
424                 data */
425         iterator begin() const;
426         /** \brief past-the-end iterator of raw packet data
427             
428             This iterator allows access to the raw data interpreted by
429             the packet facade. This \e includes any header possibly
430             interpreted by the derived packet instance. To access the
431             payload of the packet, use next()->end().
432
433             \return random access past-the-end iterator of the raw
434                 data */
435         iterator end() const;
436         /** \brief raw data size of packet
437             \return size of the raw data interpreted by this
438                 packet in bytes. This is \e not necessarily the size of
439                 the complete packet, use head()->size() for this. */
440         size_t size() const;
441
442         // Modifying the raw packet data
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: