Packets/80221Bundle: fix for TLVs to support latest version of the standard :-/
[senf.git] / Packets / 80221Bundle / TLVPacket.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 //     Thorsten Horstmann <tho@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 TLVPacket public header */
25
26 #ifndef HH_SENF_Packets_80221Bundle_TLVPacket_
27 #define HH_SENF_Packets_80221Bundle_TLVPacket_ 1
28
29 // Custom includes
30 #include <algorithm>
31 #include "../../Packets/Packets.hh"
32
33 //#include "TLVPacket.mpp"
34 ///////////////////////////////hh.p////////////////////////////////////////
35
36 namespace senf {
37
38     struct TLVLengthException : public senf::Exception
39     { 
40         TLVLengthException() 
41           : senf::Exception("TLVLengthException") {} 
42     };
43
44     
45     class DynamicTLVLengthParser 
46         : public detail::packet::IntParserOps<DynamicTLVLengthParser, boost::uint32_t>,
47           public PacketParserBase
48     {
49     public:
50         DynamicTLVLengthParser(data_iterator i, state_type s) : PacketParserBase(i,s) {}
51
52         typedef boost::uint32_t value_type;
53         static const size_type init_bytes = 1;
54         static value_type const min_value = 0;
55         static value_type const max_value = 4294967295u;
56
57         value_type value() const;
58         void value(value_type const & v);
59         
60         DynamicTLVLengthParser const & operator= (value_type other);
61         size_type bytes() const;
62         void init() const;
63
64 #       include SENF_PARSER()
65         SENF_PARSER_PRIVATE_FIELD ( length_field, UInt8Parser );
66         SENF_PARSER_GOTO( length_field );
67         SENF_PARSER_PRIVATE_BITFIELD ( extended_length_flag, 1,  bool     );
68         SENF_PARSER_PRIVATE_BITFIELD ( underflow_flag,       1,  bool     );
69         SENF_PARSER_PRIVATE_BITFIELD ( fixed_length_field,   6,  unsigned );
70
71         void shrink();
72         void maxValue(DynamicTLVLengthParser::value_type v);
73     private:
74         void resize(size_type size);
75     };  
76         
77
78     /** \brief Base class for TLV-Packet-Parsers
79      
80          BaseTLVPacketParser is the abstract base class for TLV-Packet-Parsers. It defines the
81          \ref type() field as an \ref senf::UInt8Parser and the \ref length() field as a 
82          DynamicTLVLengthParser. The length field is read-only. 
83          
84          To create your own \c TLVParser you have to inherit from BaseTLVPacketParser (don't 
85          forget \ref SENF_PARSER_INHERIT) and define the \c value field. In the following example 
86          the value is a vector of MacAddresses: 
87          \code
88          struct MacAddressesTLVParser : public BaseTLVPacketParser {
89          #   include SENF_PARSER()        
90              SENF_PARSER_INHERIT ( BaseTLVPacketParser );
91              SENF_PARSER_VECTOR  ( value, bytes(length), senf::MACAddressParser );
92              SENF_PARSER_FINALIZE( MacAddressesTLVParser );
93          };
94          
95          struct MacAddressesTLVPacketType : public PacketTypeBase {
96             typedef MacAddressesTLVParser parser;
97             ...
98             static void finalize(ConcretePacket<MacAddressesTLVPacketType> p) { 
99                 p->shrinkLength();
100             }
101          };
102          \endcode
103          
104          You have to adjust the maximum length value with the \ref maxLengthValue function 
105          before the length value is set. The default maximum value is 127. So, in the above
106          example adding more than 21 MACAddresses to the vector will throw a TLVLengthException
107          if you don't call \c macAddressesTLVPacket->maxLengthValue( \e some_value) before.
108          
109          \see DynamicTLVLengthParser \n
110            GenericTLVPacketParser \n
111      */
112     class BaseTLVPacketParser : public PacketParserBase
113     {
114     public:
115 #       include SENF_PARSER()
116         SENF_PARSER_FIELD    ( type,   UInt8Parser            );
117         SENF_PARSER_FIELD_RO ( length, DynamicTLVLengthParser );
118         SENF_PARSER_FINALIZE ( BaseTLVPacketParser            );
119         
120         /** \brief set maximum value of length field
121     
122             The size of the length field will be increased if necessary.
123             \param v maximum value of length field
124          */
125         void maxLengthValue(DynamicTLVLengthParser::value_type v) const {
126             length_().maxValue(v);
127         }
128         
129         /** \brief shrink size of length field to minimum
130     
131             The size of the length field will be decreased to minimum necessary to hold
132             the current length value.
133          */
134         void shrinkLength() { 
135             length_().shrink(); 
136         };
137         
138     protected:
139         /// return size of length field
140         size_type length_bytes() const { return length_().bytes(); };
141         /// set length field to given value
142         void length(DynamicTLVLengthParser::value_type &v) { length_() = v; };
143         /// resize the Packet after the length field to given size
144         senf::safe_data_iterator resizeValueField(DynamicTLVLengthParser::value_type size);
145     };
146
147         
148     /** \brief Parser for a generic TLV packet
149
150         \see GenericTLVPacketType
151      */
152     struct GenericTLVPacketParser : public BaseTLVPacketParser
153     {
154 #       include SENF_PARSER()        
155         SENF_PARSER_INHERIT  ( BaseTLVPacketParser    );
156         SENF_PARSER_SKIP     ( length(), 0            );
157         SENF_PARSER_FINALIZE ( GenericTLVPacketParser );
158         
159         SENF_PARSER_INIT() {
160             maxLengthValue( DynamicTLVLengthParser::max_value);
161         }
162         
163         senf::PacketInterpreterBase::range value() const;
164         
165         template <class ForwardReadableRange>
166         void value(ForwardReadableRange const &range);
167     };
168     
169     /** \brief Generic TLV packet
170
171         \par Packet type (typedef):
172             \ref GenericTLVPacket
173
174         \image html TLV.png
175         
176         \ingroup protocolbundle_80221
177      */
178     struct GenericTLVPacketType
179         : public PacketTypeBase,
180           public PacketTypeMixin<GenericTLVPacketType>
181     {
182 #ifndef DOXYGEN
183         typedef PacketTypeMixin<GenericTLVPacketType> mixin;
184 #endif
185         typedef ConcretePacket<GenericTLVPacketType> packet; ///< GenericTLV packet typedef
186         typedef GenericTLVPacketParser parser;               ///< typedef to the parser of GenericTLV packet
187
188         using mixin::nextPacketRange;
189         using mixin::init;
190         using mixin::initSize;
191         
192         /** \brief Dump given GenericTLVPacket in readable form to given output stream */
193         static void dump(packet p, std::ostream & os);  
194         static void finalize(packet p);  ///< Finalize packet.
195                                          /**< shrink size of length field to minimum 
196                                               \see BaseTLVPacketParser::shrinkLength() */
197         
198     };
199     
200     /** \brief GenericTLV packet typedef */
201     typedef ConcretePacket<GenericTLVPacketType> GenericTLVPacket;
202 }
203
204
205 ///////////////////////////////hh.e////////////////////////////////////////
206 #include "TLVPacket.cci"
207 #include "TLVPacket.ct"
208 //#include "TLVPacket.cti"
209 #endif
210
211 \f
212 // Local Variables:
213 // mode: c++
214 // fill-column: 100
215 // c-file-style: "senf"
216 // indent-tabs-mode: nil
217 // ispell-local-dictionary: "american"
218 // compile-command: "scons -u test"
219 // comment-column: 40
220 // End: