Packets/80221Bundle: renamed MIHTLVLengthParser to MIHLengthParser
[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, MIHLengthParser::value_type expectedLength)
62     const
63 {
64     validateType( expectedType);
65     if (length() != expectedLength)
66         throw InvalidMIHPacketException("invalid length in TLV.") << " Type: " << unsigned(type())
67                 << ", expected length: " << expectedLength << " got " << length();
68 }
69
70 //-/////////////////////////////////////////////////////////////////////////////////////////////////
71 // senf::MIHBaseListTLVParser
72
73 prefix_ void senf::MIHBaseListTLVParser::maxListSize(MIHLengthParser::value_type maxl)
74     const
75 {
76     protect(), listSize_().capacity( maxl);
77     maxLength( maxl + senf::bytes(listSize_()));
78 }
79
80 //-/////////////////////////////////////////////////////////////////////////////////////////////////
81 // senf::MIHFIdTLVParser
82
83 prefix_ void senf::MIHFIdTLVParser::dump(std::ostream & os)
84     const
85 {
86     senf::format::IndentHelper indent;
87     os << indent << "type:   " << unsigned (type()) << std::endl
88        << indent << "length: " << unsigned (length()) << std::endl
89        << indent << "value:\n";
90     std::string src_mihfId (valueAsString());
91     hexdump(src_mihfId.begin(), src_mihfId.end(), os);
92 }
93
94 prefix_ void senf::MIHFIdTLVParser::finalize()
95 {
96     protect(), idLength_().finalize();
97     length_() << idLength() + senf::bytes(idLength_());
98     MIHBaseTLVParser::finalize();
99 }
100
101 prefix_ void senf::MIHFIdTLVParser::maxIdLength(boost::uint8_t maxl)
102     const
103 {
104     // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
105     if (maxl > 253)
106         throw std::length_error("maximum length of a MIHF_ID is 253 octets");
107     protect(), idLength_().capacity( maxl);
108     maxLength( maxl + senf::bytes(idLength_()));
109 }
110
111 prefix_ senf::safe_data_iterator senf::MIHFIdTLVParser::resizeValueField(
112         MIHLengthParser::value_type size)
113 {
114     MIHLengthParser::value_type current_length ( idLength());
115     idLength_() << size;
116     length_() << size + idLength_().bytes();
117
118     safe_data_iterator si (data(), valueBegin());
119     if (current_length > size)
120         data().erase( si, boost::next(si, current_length-size));
121     else
122         data().insert( si, size-current_length, 0);
123     return si;
124 }
125
126 prefix_ void senf::MIHFIdTLVParser::value(std::string const & id)
127 {
128     size_type str_size (id.size());
129     // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
130     if (str_size > 253)
131         throw std::length_error("maximum length of a MIHF_ID is 253 octets");
132     safe_data_iterator si = resizeValueField( str_size);
133     std::copy( id.begin(), id.end(), si);
134 }
135
136 prefix_ void senf::MIHFIdTLVParser::value(senf::MACAddress const & addr)
137 {
138     safe_data_iterator si = resizeValueField(6*2);
139     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
140 }
141
142 prefix_ void senf::MIHFIdTLVParser::value(senf::INet4Address const & addr)
143 {
144     safe_data_iterator si = resizeValueField(4*2);
145     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
146 }
147
148 prefix_ void senf::MIHFIdTLVParser::value(senf::INet6Address const & addr)
149 {
150     safe_data_iterator si = resizeValueField(16*2);
151     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
152 }
153
154 prefix_ void senf::MIHFIdTLVParser::value(senf::EUI64 const & addr)
155 {
156     safe_data_iterator si = resizeValueField(8*2);
157     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
158 }
159
160 prefix_ void senf::MIHFIdTLVParser::value( MIHFId const & id)
161 {
162     boost::apply_visitor( ValueSetterVisitor(*this), id);
163 }
164
165 prefix_ senf::MIHFId senf::MIHFIdTLVParser::valueAs(MIHFId::Type type)
166     const
167 {
168     if (length() == 0) return MIHFId();
169     switch (type) {
170     case MIHFId::MulticastType:
171         return MIHFId();
172     case MIHFId::MACAddress:
173         return MIHFId( valueAsMACAddress());
174     case MIHFId::INet4Address:
175         return MIHFId( valueAsINet4Address());
176     case MIHFId::INet6Address:
177         return MIHFId( valueAsINet6Address());
178     case MIHFId::String:
179         return MIHFId( valueAsString());
180     case MIHFId::EUI64:
181         return MIHFId( valueAsEUI64());
182     }
183     return MIHFId();
184 }
185
186
187 //-/////////////////////////////////////////////////////////////////////////////////////////////////
188 // senf::MIHFSrcIdTLVParser
189
190 prefix_ void senf::MIHFSrcIdTLVParser::dump(std::ostream & os)
191     const
192 {
193     senf::format::IndentHelper indent;
194     os << indent << "source MIHF_Id TLV:\n";
195     MIHFIdTLVParser::dump(os);
196 }
197
198 prefix_ void senf::MIHFSrcIdTLVParser::validate()
199     const
200 {
201     validateType( typeId);
202 }
203
204
205 //-/////////////////////////////////////////////////////////////////////////////////////////////////
206 // senf::MIHFDstIdTLVParser
207
208 prefix_ void senf::MIHFDstIdTLVParser::dump(std::ostream & os)
209     const
210 {
211     senf::format::IndentHelper indent;
212     os << indent << "destination MIHF_Id TLV:\n";
213     MIHFIdTLVParser::dump(os);
214 }
215
216 prefix_ void senf::MIHFDstIdTLVParser::validate()
217     const
218 {
219     validateType( typeId);
220 }
221
222 //-/////////////////////////////////////////////////////////////////////////////////////////////////
223 // senf::MIHStatusTLVParser
224
225 prefix_ void senf::MIHStatusTLVParser::dump(std::ostream & os)
226     const
227 {
228     senf::format::IndentHelper indent;
229     os << indent << "Status TLV:" << std::endl;
230     indent.increase();
231     os << indent <<   "type:   " << unsigned( type()) << std::endl
232        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
233        << indent <<   "value:  " << unsigned( value());
234     switch (value()) {
235     case Success:
236         os << " (Success)" << std::endl;
237         return;
238     case UnspecifiedFailure:
239         os << " (Unspecified Failure)" << std::endl;
240         return;
241     case Rejected:
242         os << " (Rejected)" << std::endl;
243         return;
244     case AuthorizationFailure:
245         os << " (Authorization Failure)" << std::endl;
246         return;
247     case NetworkError:
248         os << " (Network Error)" << std::endl;
249         return;
250     }
251     os << " (???; invalid value!)" << std::endl;
252 }
253
254 prefix_ void senf::MIHStatusTLVParser::validate()
255     const
256 {
257     validateTypeLength( typeId, 1);
258     if (value() >= 4)
259         throw InvalidMIHPacketException("invalid value in MIHStatusTLV ") << unsigned( value());
260 }
261
262 //-/////////////////////////////////////////////////////////////////////////////////////////////////
263 // senf::MIHRegisterReqCodeTLVParser
264
265 prefix_ void senf::MIHRegisterReqCodeTLVParser::dump(std::ostream & os)
266     const
267 {
268     senf::format::IndentHelper indent;
269     os << indent << "Register Request Code TLV:" << std::endl;
270     indent.increase();
271     os << indent <<   "type:   " << unsigned( type()) << std::endl
272        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
273        << indent <<   "value:  " << unsigned( value());
274     switch (value()) {
275     case Registration:
276         os << " (Registration)" << std::endl;
277         return;
278     case ReRegistration:
279         os << " (Re-Registration)" << std::endl;
280         return;
281     }
282     os << " (???; invalid value!)" << std::endl;
283 }
284
285 prefix_ void senf::MIHRegisterReqCodeTLVParser::validate()
286     const
287 {
288     validateTypeLength( typeId, 1);
289     if (value() >= 2)
290         throw InvalidMIHPacketException("invalid value in MIHRegisterReqCodeTLV ") << unsigned( value());
291 }
292
293 //-/////////////////////////////////////////////////////////////////////////////////////////////////
294 // senf::MIHValidTimeIntervalTLVParser
295
296 prefix_ void senf::MIHValidTimeIntervalTLVParser::dump(std::ostream & os)
297     const
298 {
299     senf::format::IndentHelper indent;
300     os << indent << "Valid Time Interval TLV:" << std::endl;
301     indent.increase();
302     os << indent <<   "type:   " << unsigned( type()) << std::endl
303        << indent <<   "length: " << unsigned( length()) << " byte(s)" << std::endl
304        << indent <<   "value:  " << unsigned( value())
305        << ( value()==0 ? " (infinite)" : " seconds") << std::endl;
306 }
307
308 prefix_ void senf::MIHValidTimeIntervalTLVParser::validate()
309     const
310 {
311     validateTypeLength( typeId, 4);
312 }
313
314 //-/////////////////////////////////////////////////////////////////////////////////////////////////
315 // senf::MIHLengthParser
316
317 prefix_ senf::MIHLengthParser::value_type senf::MIHLengthParser::value() const
318 {
319     switch (bytes() ) {
320     case 1:
321         return length_field().value();
322     case 2:
323         return parse<UInt8Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
324     case 3:
325         return parse<UInt16Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
326     case 4:
327         return parse<UInt24Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
328     case 5:
329         return parse<UInt32Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
330     default:
331         throw( MIHLengthException());
332     };
333 }
334
335 prefix_ void senf::MIHLengthParser::value(value_type const & v)
336 {
337     switch (bytes() ) {
338     case 1:
339         if (v > 128) throw( MIHLengthException());
340         length_field() = v;
341         return;
342     case 2:
343         if (v > UInt8Parser::max_value + 128) throw( MIHLengthException());
344         parse<UInt8Parser>(1) = v - (v>128 ? 128 : 0);
345         break;
346     case 3:
347         if (v > UInt16Parser::max_value + 128) throw( MIHLengthException());
348         parse<UInt16Parser>(1) = v - (v>128 ? 128 : 0);
349         break;;
350     case 4:
351         if (v > UInt24Parser::max_value + 128) throw( MIHLengthException());
352         parse<UInt24Parser>(1) = v - (v>128 ? 128 : 0);
353         break;
354     case 5:
355         parse<UInt32Parser>(1) = v - (v>128 ? 128 : 0);
356         break;
357     default:
358         throw( MIHLengthException());
359     };
360     underflow_flag() = (v <= 128);
361 }
362
363 prefix_ senf::MIHLengthParser::value_type senf::MIHLengthParser::capacity()
364     const
365 {
366     switch (bytes() ) {
367     case 1:
368         return 128;
369     case 2:
370         return UInt8Parser::max_value + 128;
371     case 3:
372         return UInt16Parser::max_value + 128;
373     case 4:
374         return UInt24Parser::max_value + 128;
375     case 5:
376         return UInt32Parser::max_value;
377     default:
378         throw( MIHLengthException());
379     };
380 }
381
382 prefix_ senf::MIHLengthParser const & senf::MIHLengthParser::operator= (value_type other)
383 {
384     value(other);
385     return *this;
386 }
387
388 prefix_ void senf::MIHLengthParser::init() const
389 {
390     defaultInit();
391     extended_length_flag() = false;
392 }
393
394 prefix_ void senf::MIHLengthParser::finalize()
395 {
396     value_type v = value();
397     size_type b = bytes();
398     if (v <= 128) {
399         if (b != 1) resize_(1);
400         return;
401     }
402     if (v <= UInt8Parser::max_value + 128) {
403         if (b != 2) resize_(2);
404         return;
405     }
406     if (v <= UInt16Parser::max_value + 128) {
407         if (b != 3) resize_(3);
408         return;
409     }
410     if (v <= UInt24Parser::max_value + 128 ) {
411         if (b != 4) resize_(4);
412         return;
413     }
414     if (b != 5) resize_(5);
415 }
416
417 prefix_ void senf::MIHLengthParser::capacity(MIHLengthParser::value_type v)
418 {
419     if (v <= 128)
420         return;
421     size_type b = bytes();
422     if (v <= UInt8Parser::max_value + 128) {
423         if (b < 2) resize_(2);
424         return;
425     }
426     if (v <= UInt16Parser::max_value + 128) {
427         if (b < 3) resize_(3);
428         return;
429     }
430     if (v <= UInt24Parser::max_value + 128) {
431         if (b < 4) resize_(4);
432         return;
433     }
434     if (b < 5) resize_(5);
435 }
436
437 prefix_ void senf::MIHLengthParser::resize_(size_type size)
438 {
439     value_type v = value();
440     resize(bytes(), size);
441     if (size > 1) {
442         extended_length_flag() = true;
443         fixed_length_field() = size - 1;
444     } else {
445         extended_length_flag() = false;
446     }
447     value(v);
448 }
449
450
451 //-/////////////////////////////////////////////////////////////////////////////////////////////////
452 #undef prefix_
453
454 \f
455 // Local Variables:
456 // mode: c++
457 // fill-column: 100
458 // c-file-style: "senf"
459 // indent-tabs-mode: nil
460 // ispell-local-dictionary: "american"
461 // compile-command: "scons -u test"
462 // comment-column: 40
463 // End: