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