source: source/ariba/communication/modules/transport/protlib/ie.h@ 5638

Last change on this file since 5638 was 5638, checked in by Christoph Mayer, 15 years ago

adress detection aufgeräumt, network info für bleutooth, data stream (hopeful crash fix), logging auf maemo nur warn, ...

File size: 13.8 KB
Line 
1/// ----------------------------------------*- mode: C++; -*--
2/// @file ie.h
3/// Basic information elements (PDUs and PDU objects)
4/// ----------------------------------------------------------
5/// $Id: ie.h 2549 2007-04-02 22:17:37Z bless $
6/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/ie.h $
7// ===========================================================
8//
9// Copyright (C) 2005-2007, all rights reserved by
10// - Institute of Telematics, Universitaet Karlsruhe (TH)
11//
12// More information and contact:
13// https://projekte.tm.uka.de/trac/NSIS
14//
15// This program is free software; you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation; version 2 of the License
18//
19// This program is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License along
25// with this program; if not, write to the Free Software Foundation, Inc.,
26// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27//
28// ===========================================================
29
30/** @ingroup ie
31 * @todo Use objectpool by deriving classes from class poolobject and
32 * linking executables against objectpool.o or including objectpool.o into
33 * libie.a.
34 *
35 * This header file defines the base class of all information elements, the
36 * information elements for the protocol and an IE manager object.
37 *
38 * For performance only pointers are exchanged. The copy member function is
39 * the way to duplicate an IE. It does much the same as a copy constructor
40 * but returns not the IE but a pointer to it. If the IE contains pointers,
41 * their target objects are copied too.
42 */
43
44#ifndef _PROTLIB__IE_H_
45#define _PROTLIB__IE_H_
46
47#include <ext/hash_map>
48#include <deque>
49#include <string>
50#include <iostream>
51#include <map>
52
53#include "protlib_types.h"
54#include "network_message.h"
55
56namespace protlib {
57
58
59
60/** @addtogroup ie Information Elements
61 * @{
62 */
63
64/// Catch bad_alloc and call throw_nomem_error
65#define catch_bad_alloc(x) try { x; } catch(bad_alloc) { throw_nomem_error(); }
66
67// forward declarations
68class IEManager;
69class IEErrorList;
70class IEError;
71
72/** Abstract Information Element (IE) interface
73 */
74class IE {
75public:
76 virtual ~IE() { }
77
78 friend class IEManager;
79 /// IE coding sheme
80 /** All coding shemes have to be listed here. Each IE should support at
81 * least one listed coding sheme. This is used when serializing or
82 * deserializing from a NetMsg object to (de)code the IE in the right way.
83 * Note that coding schemes and protocol version are not the same.
84 * There could also be a coding sheme to (de)code IEs e.g. for router
85 * configuration.
86 */
87 enum coding_t {
88 nslp_v1 = 1,
89 protocol_v1 = 1,
90 protocol_v2 = 2,
91 nslp_v2 = 3,
92 nslp_v2_yoda = 4
93 }; // end coding_t
94protected:
95 /// contructor
96 IE(uint16 category);
97 /// copy constructor
98 IE(const IE& n);
99public:
100 /// get a new instance of the IE
101 virtual IE* new_instance() const = 0;
102 /// copy an IE
103 virtual IE* copy() const = 0;
104 /// deserialization
105 virtual IE* deserialize(NetMsg& msg, coding_t coding, IEErrorList& errorlist, uint32& bread, bool skip = true) = 0;
106 /// serialize
107 virtual void serialize(NetMsg& msg, coding_t coding, uint32& wbytes) const = 0;
108protected:
109 /// check arguments for deserialization
110 bool check_deser_args(coding_t cod, IEErrorList& errorlist, uint32 &bread) const;
111 /// check arguments for serialization
112 void check_ser_args(coding_t cod, uint32 &wbytes) const;
113public:
114 /// IE consistency check
115 virtual bool check() const = 0;
116 /// check if IE supports coding sheme
117 virtual bool supports_coding(coding_t c) const = 0;
118 /// IE serialized size
119 virtual size_t get_serialized_size(coding_t coding) const = 0;
120 /// get category
121 uint16 get_category() const;
122 /// equality
123 virtual bool operator==(const IE& ie) const = 0;
124 /// not equal
125 inline bool operator!=(const IE& ie) const { return (!(*this==ie)); }
126 /// get IE name
127 /** This is mainly for error reporting. */
128 virtual const char* get_ie_name() const = 0;
129 /// print to a ostream
130 virtual ostream& print(ostream& os, uint32 level, const uint32 indent, const char* name = NULL) const;
131 /// get a string representing the IE content
132 string to_string(const char* name = 0) const;
133 /// input from an istream
134 /** Attention: No checking, no warnings. This is ONLY for testing. */
135 virtual istream& input(istream& is, bool istty, uint32 level, const uint32 indent, const char* name = NULL);
136 /// clear all pointer fields
137 virtual void clear_pointers();
138protected:
139 /// register this IE
140 virtual void register_ie(IEManager *iem) const = 0;
141 /// IE category
142 const uint16 category;
143 /// throw a NO_MEM exception
144 void throw_nomem_error() const;
145}; // end class IE
146
147
148
149/**
150 * IE Error base class.
151 *
152 * This is the base for all exceptions thrown during serialize() and
153 * deserialize().
154 *
155 * @warning New code should use the exceptions derived from this class.
156 * This class should be abstract but isn't for compatibility reasons.
157 */
158class IEError : public ProtLibException {
159 public:
160 /// IE error code - common parsing errors
161 enum error_t {
162 ERROR_REGISTER,
163 ERROR_CODING,
164 ERROR_CATEGORY,
165 ERROR_NO_IEMANAGER,
166 ERROR_MSG_TOO_SHORT,
167 ERROR_INVALID_STATE,
168 ERROR_WRONG_TYPE,
169 ERROR_WRONG_SUBTYPE,
170 ERROR_WRONG_LENGTH,
171 ERROR_NO_MEM,
172 ERROR_TOO_BIG_FOR_IMPL,
173 ERROR_UNKNOWN_ERRORCODE,
174 ERROR_WRONG_VERSION,
175 ERROR_UNEXPECTED_OBJECT,
176 ERROR_PDU_SYNTAX,
177 ERROR_OBJ_SET_FAILED,
178 ERROR_PROT_SPECIFIC
179 }; // end error_t
180
181 const error_t err;
182
183 IEError(error_t e);
184 virtual ~IEError() throw ();
185
186 virtual const char *getstr() const;
187
188 protected:
189 IEError(std::string msg) throw ();
190
191 private:
192 static const char* err_str[];
193};
194
195
196/**
197 * Syntax error during deserialization.
198 *
199 * This exception is thrown if a syntax error is detected during
200 * deserialization.
201 */
202class PDUSyntaxError : public IEError {
203 public:
204 PDUSyntaxError(const char* msg); // deprecated!
205 PDUSyntaxError(IE::coding_t coding, uint16 category, uint16 type,
206 uint16 subtype, uint32 pos, const char *msg = "");
207 virtual ~PDUSyntaxError() throw () { }
208
209 const IE::coding_t coding;
210 const uint16 category;
211 const uint16 type;
212 const uint16 subtype;
213 const uint32 errorpos;
214 const string message;
215};
216
217
218/**
219 * NetMsg is too short to serialize/deserialize.
220 *
221 * This exception is typically thrown if a NetMsg ended unexpectedly
222 * which indicates a truncated message. It may also be thrown if a
223 * NetMsg is too short to hold a serialized IE object.
224 */
225class IEMsgTooShort : public IEError {
226 public:
227 IEMsgTooShort(IE::coding_t coding, uint16 category, uint32 pos);
228 virtual ~IEMsgTooShort() throw () { }
229
230 const IE::coding_t coding;
231 const uint16 category;
232 const uint32 errorpos;
233};
234
235
236/**
237 * Wrong protocol version.
238 *
239 * This exception is thrown in case of a version conflict, like a
240 * deserialize() method not being able to handle a coding.
241 */
242class IEWrongVersion : public IEError {
243 public:
244 IEWrongVersion(IE::coding_t coding, uint16 category, uint32 pos);
245 virtual ~IEWrongVersion() throw () { }
246
247 const IE::coding_t coding;
248 const uint16 category;
249 const uint32 errorpos;
250};
251
252
253/**
254 * Invalid IE type.
255 *
256 * Typically thrown if deserialize() fails because there is no matching IE
257 * registered with the IEManager.
258 */
259class IEWrongType : public IEError {
260 public:
261 // The first constructor is deprecated!
262 IEWrongType(IE::coding_t coding, uint16 category, uint32 pos);
263 IEWrongType(IE::coding_t coding, uint16 category, uint16 type,
264 uint32 pos);
265 virtual ~IEWrongType() throw () { }
266
267 const IE::coding_t coding;
268 const uint16 category;
269 const uint16 type;
270 const uint32 errorpos;
271};
272
273
274/**
275 * Invalid IE subtype.
276 *
277 * Typically thrown if deserialize() fails because there is no matching IE
278 * registered with the IEManager.
279 */
280class IEWrongSubtype : public IEError {
281 public:
282 // The first constructor is deprecated!
283 IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
284 uint32 pos);
285 IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
286 uint16 subtype, uint32 pos);
287 virtual ~IEWrongSubtype() throw () { }
288
289 const IE::coding_t coding;
290 const uint16 category;
291 const uint16 type;
292 const uint16 subtype;
293 const uint32 errorpos;
294};
295
296
297/**
298 * An invalid length field was read.
299 *
300 * This exception is thrown if a length field inside a NetMsg has a wrong
301 * length (either too long or too short, but makes no sense). Note that
302 * this overlaps with IEMsgTooShort in some cases.
303 */
304class IEWrongLength : public IEError {
305 public:
306 IEWrongLength(IE::coding_t coding, uint16 category, uint16 type,
307 uint16 subtype, uint32 pos);
308 virtual ~IEWrongLength() throw () { }
309
310 const IE::coding_t coding;
311 const uint16 category;
312 const uint16 type;
313 const uint16 subtype;
314 const uint32 errorpos;
315};
316
317
318/**
319 * Some entity is too big for this implementation.
320 *
321 * This exception is thrown if an operation can't be performed because
322 * of some implementation limit.
323 */
324class IETooBigForImpl : public IEError {
325 public:
326 IETooBigForImpl(IE::coding_t coding, uint16 category, uint32 pos);
327 virtual ~IETooBigForImpl() throw () { }
328
329 const IE::coding_t coding;
330 const uint16 category;
331 const uint32 errorpos;
332};
333
334
335/**
336 * Protocol Specific Error
337 *
338 * This exception is thrown if a protocol specific error
339 * occurred.
340 */
341class IEProtocolSpecific : public IEError {
342 public:
343 IEProtocolSpecific(IE::coding_t coding, uint16 category, uint32 pos);
344 virtual ~IEProtocolSpecific() throw () { }
345
346 const IE::coding_t coding;
347 const uint16 category;
348 const uint32 errorpos;
349};
350
351
352/// IE error list
353/** This represents a list of IE errors. */
354class IEErrorList {
355public:
356 /// put an IEError on the list
357 void put(IEError* iee);
358 /// get and remove next IEError
359 IEError* get();
360 /// is list empty
361 bool is_empty() const;
362 /// clear list
363 void clear();
364 /// destructor
365 ~IEErrorList();
366private:
367 /// internal queue type
368 typedef deque<IEError*> queue_t;
369 /// queue iterator type
370 typedef queue_t::iterator queueit_t;
371 /// IEError storage
372 queue_t queue;
373}; // end IEErrorList
374
375
376/**
377 * Represents a (category, type, subtype) tuple.
378 *
379 * Used internally by IEManager.
380 */
381class IE_Key {
382 public:
383 inline IE_Key(uint16 category, uint16 type, uint16 subtype)
384 : category(category), type(type), subtype(subtype) { }
385
386 inline bool operator==(const IE_Key &other) const {
387 return category == other.category && type == other.type
388 && subtype == other.subtype;
389 }
390
391 inline uint16 get_category() const { return category; }
392 inline uint16 get_type() const { return type; }
393 inline uint16 get_subtype() const { return subtype; }
394
395 private:
396 uint16 category;
397 uint16 type;
398 uint16 subtype;
399};
400
401struct hash_IE_Key {
402 inline size_t operator()(const protlib::IE_Key &k) const {
403 return (k.get_category() << 16)
404 | ( k.get_type() ^ k.get_subtype() );
405 }
406};
407
408
409/**
410 * A registry and factory for IEs.
411 *
412 * Each IE has to register at the IE Manager. The IEManager then provides
413 * methods to deserialize IEs from or serialize IEs to a NetMsg object.
414 * IEManager is abstract and thus can't be instantiated.
415 *
416 * In contrast to earlier implementations, IEManager itself is no longer a
417 * singleton. Inheriting from singletons is a tricky business in C++ (and
418 * much easier in Java) because static methods can't be virtual. Because
419 * of this, multiple badly implemented child classes were unable to coexist
420 * in a single program.
421 *
422 * The following has to be done in each protocol to use IEManager and
423 * create a protocol-specific singleton (called PROT_IEManager):
424 *
425 * - Inherit from IEManager.
426 * - Make the constructor private.
427 * - Provide a "private: static PROT_IEManager *inst" attribute.
428 * - Provide a "public: static PROT_IEManager *instance()" method.
429 * - Provide a "public: static void clear()" method.
430 * - Define your own category_t with categories appropriate for your protocol.
431 *
432 * An example implementation can be found in the QSPEC code. Please note that
433 * old code (r286 and earlier) won't compile because of interface changes.
434 * The ability to register "default" IEs that are returned if no more specific
435 * IE is found has been removed because it depended on coding_t. If derived
436 * IEManagers need this functionality, they have to override lookup_ie().
437 *
438 */
439class IEManager {
440
441 public:
442 virtual ~IEManager();
443
444 virtual void register_ie(const IE *ie);
445 virtual void register_ie(uint16 category, uint16 type, uint16 subtype,
446 const IE *ie);
447
448 virtual IE *new_instance(uint16 category, uint16 type, uint16 subtype);
449
450 virtual void serialize(IE &ie, NetMsg &msg, IE::coding_t coding,
451 uint32 &bytes_written) const;
452
453 virtual IE *deserialize(NetMsg &msg, uint16 category,
454 IE::coding_t coding, IEErrorList& errorlist,
455 uint32 &bytes_read, bool skip = true) = 0;
456
457 protected:
458 IEManager();
459
460 virtual IE *lookup_ie(uint16 category, uint16 type, uint16 subtype);
461
462 virtual void throw_nomem_error() const;
463
464 private:
465 typedef hash_map<IE_Key, IE *, hash_IE_Key> category_map_t;
466
467 category_map_t registry;
468};
469
470
471/** This mainly calls the serialize member function of the given IE.
472 * @param ie pointer to an IE
473 * @param msg NetMsg object that will hold the serialized IE.
474 * @param coding IE coding sheme
475 * @param wbytes number of output bytes
476 */
477inline
478void IEManager::serialize(IE& ie, NetMsg& msg, IE::coding_t coding, uint32& wbytes) const {
479 ie.serialize(msg,coding,wbytes);
480} // end serialize
481
482
483/// print an IE to an ostream
484ostream& operator<<(ostream& os, const IE& ie);
485
486/// input operator
487istream& operator>>(istream& is, IE& ie);
488
489/// round uint32 up
490/** Adds up the given uint32 to fit a 32-bit or 4-byte border. */
491inline uint32 round_up4(uint32 i) {
492 if (i%4) i = i-(i%4)+4;
493 return i;
494} // end round_up4
495
496//@}
497
498} // end namespace protlib
499
500#endif // _PROTLIB__IE_H_
Note: See TracBrowser for help on using the repository browser.