An Overlay-based
Virtual Network Substrate
SpoVNet

source: source/ariba/utility/transport/tcpip/protlib/ie.h @ 6922

Last change on this file since 6922 was 6922, checked in by mies, 10 years ago

replaced deprecated hash_map, hash_set classes with boost
added unsigned serialization
fixed more warnings
included -Wall to Makefile.am

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