Packets/80221Bundle: enhanced error message in MIHBaseTLVParser::validateType()
[senf.git] / senf / Packets / 80221Bundle / TLVParser.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Thorsten Horstmann <tho@berlios.de>
27
28 /** \file
29     \brief TLVParser non-inline non-template implementation */
30
31 #include "TLVParser.hh"
32 //#include "TLVParser.ih"
33
34 // Custom includes
35 #include <senf/Utils/hexdump.hh>
36 #include <senf/Utils/Format.hh>
37 #include "Exceptions.hh"
38
39 #define prefix_
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41
42 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHFSrcIdTLVParser );
43 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHFDstIdTLVParser );
44 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHStatusTLVParser );
45 SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHValidTimeIntervalTLVParser );
46
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
48 // MIHBaseTLVParser
49
50 prefix_ void senf::MIHBaseTLVParser::validateType(boost::uint8_t expectedType)
51     const
52 {
53     if (! check( 1 + senf::bytes(length_()) + length()) )
54         throw InvalidMIHPacketException("truncated TLV.") << " Type: " << unsigned(type())
55             << ", size:" << 1 + senf::bytes(length_()) + length()
56             << ", available: " << std::distance(i(), data().end());
57     if (type() != expectedType)
58         throw InvalidMIHPacketException("wrong TLV type. expected ") << unsigned(expectedType) << " got " << unsigned(type());
59 }
60
61 prefix_ void senf::MIHBaseTLVParser::validateTypeLength(boost::uint8_t expectedType, MIHTLVLengthParser::value_type expectedLength)
62     const
63 {
64     validateType( expectedType);
65     if (length() != expectedLength)
66         throw InvalidMIHPacketException("invalid length in TLV.") << " Type: " << unsigned(type());
67 }
68
69 //-/////////////////////////////////////////////////////////////////////////////////////////////////
70 // senf::MIHBaseListTLVParser
71
72 prefix_ void senf::MIHBaseListTLVParser::maxListSize(MIHTLVLengthParser::value_type maxl)
73     const
74 {
75     protect(), listSize_().capacity( maxl);
76     maxLength( maxl + senf::bytes(listSize_()));
77 }
78
79 //-/////////////////////////////////////////////////////////////////////////////////////////////////
80 // senf::MIHFIdTLVParser
81
82 prefix_ void senf::MIHFIdTLVParser::dump(std::ostream & os)
83     const
84 {
85     senf::format::IndentHelper indent;
86     os << indent << "type:   " << unsigned (type()) << std::endl
87        << indent << "length: " << unsigned (length()) << std::endl
88        << indent << "value:\n";
89     std::string src_mihfId (valueAsString());
90     hexdump(src_mihfId.begin(), src_mihfId.end(), os);
91 }
92
93 prefix_ void senf::MIHFIdTLVParser::finalize()
94 {
95     protect(), idLength_().finalize();
96     length_() << idLength() + senf::bytes(idLength_());
97     MIHBaseTLVParser::finalize();
98 }
99
100 prefix_ void senf::MIHFIdTLVParser::maxIdLength(boost::uint8_t maxl)
101     const
102 {
103     // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
104     if (maxl > 253)
105         throw std::length_error("maximum length of a MIHF_ID is 253 octets");
106     protect(), idLength_().capacity( maxl);
107     maxLength( maxl + senf::bytes(idLength_()));
108 }
109
110 prefix_ senf::safe_data_iterator senf::MIHFIdTLVParser::resizeValueField(
111         MIHTLVLengthParser::value_type size)
112 {
113     MIHTLVLengthParser::value_type current_length ( idLength());
114     idLength_() << size;
115     length_() << size + idLength_().bytes();
116
117     safe_data_iterator si (data(), valueBegin());
118     if (current_length > size)
119         data().erase( si, boost::next(si, current_length-size));
120     else
121         data().insert( si, size-current_length, 0);
122     return si;
123 }
124
125 prefix_ void senf::MIHFIdTLVParser::value(std::string const & id)
126 {
127     size_type str_size (id.size());
128     // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
129     if (str_size > 253)
130         throw std::length_error("maximum length of a MIHF_ID is 253 octets");
131     safe_data_iterator si = resizeValueField( str_size);
132     std::copy( id.begin(), id.end(), si);
133 }
134
135 prefix_ void senf::MIHFIdTLVParser::value(senf::MACAddress const & addr)
136 {
137     safe_data_iterator si = resizeValueField(6*2);
138     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
139 }
140
141 prefix_ void senf::MIHFIdTLVParser::value(senf::INet4Address const & addr)
142 {
143     safe_data_iterator si = resizeValueField(4*2);
144     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
145 }
146
147 prefix_ void senf::MIHFIdTLVParser::value(senf::INet6Address const & addr)
148 {
149     safe_data_iterator si = resizeValueField(16*2);
150     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
151 }
152
153 prefix_ void senf::MIHFIdTLVParser::value(senf::EUI64 const & addr)
154 {
155     safe_data_iterator si = resizeValueField(8*2);
156     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
157 }
158
159 prefix_ void senf::MIHFIdTLVParser::value( MIHFId const & id)
160 {
161     boost::apply_visitor( ValueSetterVisitor(*this), id);
162 }
163
164 prefix_ senf::MIHFId senf::MIHFIdTLVParser::valueAs(MIHFId::Type type)
165     const
166 {
167     if (length() == 0) return MIHFId();
168     switch (type) {
169     case MIHFId::MulticastType:
170         return MIHFId();
171     case MIHFId::MACAddress:
172         return MIHFId( valueAsMACAddress());
173     case MIHFId::INet4Address:
174         return MIHFId( valueAsINet4Address());
175     case MIHFId::INet6Address:
176         return MIHFId( valueAsINet6Address());
177     case MIHFId::String:
178         return MIHFId( valueAsString());
179     case MIHFId::EUI64:
180         return MIHFId( valueAsEUI64());
181     }
182     return MIHFId();
183 }
184
185
186 //-/////////////////////////////////////////////////////////////////////////////////////////////////
187 // senf::MIHFSrcIdTLVParser
188
189 prefix_ void senf::MIHFSrcIdTLVParser::dump(std::ostream & os)
190     const
191 {
192     senf::format::IndentHelper indent;
193     os << indent << "source MIHF_Id TLV:\n";
194     MIHFIdTLVParser::dump(os);
195 }
196
197 prefix_ void senf::MIHFSrcIdTLVParser::validate()
198     const
199 {
200     validateType( typeId);
201 }
202
203
204 //-/////////////////////////////////////////////////////////////////////////////////////////////////
205 // senf::MIHFDstIdTLVParser
206
207 prefix_ void senf::MIHFDstIdTLVParser::dump(std::ostream & os)
208     const
209 {
210     senf::format::IndentHelper indent;
211     os << indent << "destination MIHF_Id TLV:\n";
212     MIHFIdTLVParser::dump(os);
213 }
214
215 prefix_ void senf::MIHFDstIdTLVParser::validate()
216     const
217 {
218     validateType( typeId);
219 }
220
221 //-/////////////////////////////////////////////////////////////////////////////////////////////////
222 // senf::MIHStatusTLVParser
223
224 prefix_ void senf::MIHStatusTLVParser::dump(std::ostream & os)
225     const
226 {
227     senf::format::IndentHelper indent;
228     os << indent << "Status TLV:" << std::endl;
229     indent.increase();
230     os << indent <<   "type:   " << unsigned( type()) << std::endl
231        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
232        << indent <<   "value:  " << unsigned( value());
233     switch (value()) {
234     case Success:
235         os << " (Success)" << std::endl;
236         return;
237     case UnspecifiedFailure:
238         os << " (Unspecified Failure)" << std::endl;
239         return;
240     case Rejected:
241         os << " (Rejected)" << std::endl;
242         return;
243     case AuthorizationFailure:
244         os << " (Authorization Failure)" << std::endl;
245         return;
246     case NetworkError:
247         os << " (Network Error)" << std::endl;
248         return;
249     }
250     os << " (???; invalid value!)" << std::endl;
251 }
252
253 prefix_ void senf::MIHStatusTLVParser::validate()
254     const
255 {
256     validateTypeLength( typeId, 1);
257     if (value() >= 4)
258         throw InvalidMIHPacketException("invalid value in MIHStatusTLV ") << unsigned( value());
259 }
260
261 //-/////////////////////////////////////////////////////////////////////////////////////////////////
262 // senf::MIHRegisterReqCodeTLVParser
263
264 prefix_ void senf::MIHRegisterReqCodeTLVParser::dump(std::ostream & os)
265     const
266 {
267     senf::format::IndentHelper indent;
268     os << indent << "Register Request Code TLV:" << std::endl;
269     indent.increase();
270     os << indent <<   "type:   " << unsigned( type()) << std::endl
271        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
272        << indent <<   "value:  " << unsigned( value());
273     switch (value()) {
274     case Registration:
275         os << " (Registration)" << std::endl;
276         return;
277     case ReRegistration:
278         os << " (Re-Registration)" << std::endl;
279         return;
280     }
281     os << " (???; invalid value!)" << std::endl;
282 }
283
284 prefix_ void senf::MIHRegisterReqCodeTLVParser::validate()
285     const
286 {
287     validateTypeLength( typeId, 1);
288     if (value() >= 2)
289         throw InvalidMIHPacketException("invalid value in MIHRegisterReqCodeTLV ") << unsigned( value());
290 }
291
292 //-/////////////////////////////////////////////////////////////////////////////////////////////////
293 // senf::MIHValidTimeIntervalTLVParser
294
295 prefix_ void senf::MIHValidTimeIntervalTLVParser::dump(std::ostream & os)
296     const
297 {
298     senf::format::IndentHelper indent;
299     os << indent << "Valid Time Interval TLV:" << std::endl;
300     indent.increase();
301     os << indent <<   "type:   " << unsigned( type()) << std::endl
302        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
303        << indent <<   "value:  " << unsigned( value())
304        << ( value()==0 ? " (infinite)" : " seconds") << std::endl;
305 }
306
307 prefix_ void senf::MIHValidTimeIntervalTLVParser::validate()
308     const
309 {
310     validateTypeLength( typeId, 4);
311 }
312
313 //-/////////////////////////////////////////////////////////////////////////////////////////////////
314 // senf::MIHTLVLengthParser
315
316 prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::value() const
317 {
318     switch (bytes() ) {
319     case 1:
320         return length_field().value();
321     case 2:
322         return parse<UInt8Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
323     case 3:
324         return parse<UInt16Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
325     case 4:
326         return parse<UInt24Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
327     case 5:
328         return parse<UInt32Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
329     default:
330         throw( MIHTLVLengthException());
331     };
332 }
333
334 prefix_ void senf::MIHTLVLengthParser::value(value_type const & v)
335 {
336     switch (bytes() ) {
337     case 1:
338         if (v > 128) throw( MIHTLVLengthException());
339         length_field() = v;
340         return;
341     case 2:
342         if (v > UInt8Parser::max_value + 128) throw( MIHTLVLengthException());
343         parse<UInt8Parser>(1) = v - (v>128 ? 128 : 0);
344         break;
345     case 3:
346         if (v > UInt16Parser::max_value + 128) throw( MIHTLVLengthException());
347         parse<UInt16Parser>(1) = v - (v>128 ? 128 : 0);
348         break;;
349     case 4:
350         if (v > UInt24Parser::max_value + 128) throw( MIHTLVLengthException());
351         parse<UInt24Parser>(1) = v - (v>128 ? 128 : 0);
352         break;
353     case 5:
354         parse<UInt32Parser>(1) = v - (v>128 ? 128 : 0);
355         break;
356     default:
357         throw( MIHTLVLengthException());
358     };
359     underflow_flag() = (v <= 128);
360 }
361
362 prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::capacity()
363     const
364 {
365     switch (bytes() ) {
366     case 1:
367         return 128;
368     case 2:
369         return UInt8Parser::max_value + 128;
370     case 3:
371         return UInt16Parser::max_value + 128;
372     case 4:
373         return UInt24Parser::max_value + 128;
374     case 5:
375         return UInt32Parser::max_value;
376     default:
377         throw( MIHTLVLengthException());
378     };
379 }
380
381 prefix_ senf::MIHTLVLengthParser const & senf::MIHTLVLengthParser::operator= (value_type other)
382 {
383     value(other);
384     return *this;
385 }
386
387 prefix_ void senf::MIHTLVLengthParser::init() const
388 {
389     defaultInit();
390     extended_length_flag() = false;
391 }
392
393 prefix_ void senf::MIHTLVLengthParser::finalize()
394 {
395     value_type v = value();
396     size_type b = bytes();
397     if (v <= 128) {
398         if (b != 1) resize_(1);
399         return;
400     }
401     if (v <= UInt8Parser::max_value + 128) {
402         if (b != 2) resize_(2);
403         return;
404     }
405     if (v <= UInt16Parser::max_value + 128) {
406         if (b != 3) resize_(3);
407         return;
408     }
409     if (v <= UInt24Parser::max_value + 128 ) {
410         if (b != 4) resize_(4);
411         return;
412     }
413     if (b != 5) resize_(5);
414 }
415
416 prefix_ void senf::MIHTLVLengthParser::capacity(MIHTLVLengthParser::value_type v)
417 {
418     if (v <= 128)
419         return;
420     size_type b = bytes();
421     if (v <= UInt8Parser::max_value + 128) {
422         if (b < 2) resize_(2);
423         return;
424     }
425     if (v <= UInt16Parser::max_value + 128) {
426         if (b < 3) resize_(3);
427         return;
428     }
429     if (v <= UInt24Parser::max_value + 128) {
430         if (b < 4) resize_(4);
431         return;
432     }
433     if (b < 5) resize_(5);
434 }
435
436 prefix_ void senf::MIHTLVLengthParser::resize_(size_type size)
437 {
438     value_type v = value();
439     resize(bytes(), size);
440     if (size > 1) {
441         extended_length_flag() = true;
442         fixed_length_field() = size - 1;
443     } else {
444         extended_length_flag() = false;
445     }
446     value(v);
447 }
448
449
450 //-/////////////////////////////////////////////////////////////////////////////////////////////////
451 #undef prefix_
452
453 \f
454 // Local Variables:
455 // mode: c++
456 // fill-column: 100
457 // c-file-style: "senf"
458 // indent-tabs-mode: nil
459 // ispell-local-dictionary: "american"
460 // compile-command: "scons -u test"
461 // comment-column: 40
462 // End: