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