00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00044 #ifndef _PROTLIB__IE_H_
00045 #define _PROTLIB__IE_H_
00046
00047 #include <boost/unordered_map.hpp>
00048 #include <deque>
00049 #include <string>
00050 #include <iostream>
00051 #include <map>
00052
00053 #include "protlib_types.h"
00054 #include "network_message.h"
00055
00056 using boost::unordered_map;
00057
00058 namespace protlib {
00059
00060
00061
00066
00067 #define catch_bad_alloc(x) try { x; } catch(bad_alloc) { throw_nomem_error(); }
00068
00069
00070 class IEManager;
00071 class IEErrorList;
00072 class IEError;
00073
00076 class IE {
00077 public:
00078 virtual ~IE() { }
00079
00080 friend class IEManager;
00082
00089 enum coding_t {
00090 nslp_v1 = 1,
00091 protocol_v1 = 1,
00092 protocol_v2 = 2,
00093 nslp_v2 = 3,
00094 nslp_v2_yoda = 4
00095 };
00096 protected:
00098 IE(uint16 category);
00100 IE(const IE& n);
00101 public:
00103 virtual IE* new_instance() const = 0;
00105 virtual IE* copy() const = 0;
00107 virtual IE* deserialize(NetMsg& msg, coding_t coding, IEErrorList& errorlist, uint32& bread, bool skip = true) = 0;
00109 virtual void serialize(NetMsg& msg, coding_t coding, uint32& wbytes) const = 0;
00110 protected:
00112 bool check_deser_args(coding_t cod, IEErrorList& errorlist, uint32 &bread) const;
00114 void check_ser_args(coding_t cod, uint32 &wbytes) const;
00115 public:
00117 virtual bool check() const = 0;
00119 virtual bool supports_coding(coding_t c) const = 0;
00121 virtual size_t get_serialized_size(coding_t coding) const = 0;
00123 uint16 get_category() const;
00125 virtual bool operator==(const IE& ie) const = 0;
00127 inline bool operator!=(const IE& ie) const { return (!(*this==ie)); }
00129
00130 virtual const char* get_ie_name() const = 0;
00132 virtual ostream& print(ostream& os, uint32 level, const uint32 indent, const char* name = NULL) const;
00134 string to_string(const char* name = 0) const;
00136
00137 virtual istream& input(istream& is, bool istty, uint32 level, const uint32 indent, const char* name = NULL);
00139 virtual void clear_pointers();
00140 protected:
00142 virtual void register_ie(IEManager *iem) const = 0;
00144 const uint16 category;
00146 void throw_nomem_error() const;
00147 };
00148
00149
00150
00160 class IEError : public ProtLibException {
00161 public:
00163 enum error_t {
00164 ERROR_REGISTER,
00165 ERROR_CODING,
00166 ERROR_CATEGORY,
00167 ERROR_NO_IEMANAGER,
00168 ERROR_MSG_TOO_SHORT,
00169 ERROR_INVALID_STATE,
00170 ERROR_WRONG_TYPE,
00171 ERROR_WRONG_SUBTYPE,
00172 ERROR_WRONG_LENGTH,
00173 ERROR_NO_MEM,
00174 ERROR_TOO_BIG_FOR_IMPL,
00175 ERROR_UNKNOWN_ERRORCODE,
00176 ERROR_WRONG_VERSION,
00177 ERROR_UNEXPECTED_OBJECT,
00178 ERROR_PDU_SYNTAX,
00179 ERROR_OBJ_SET_FAILED,
00180 ERROR_PROT_SPECIFIC
00181 };
00182
00183 const error_t err;
00184
00185 IEError(error_t e);
00186 virtual ~IEError() throw ();
00187
00188 virtual const char *getstr() const;
00189
00190 protected:
00191 IEError(std::string msg) throw ();
00192
00193 private:
00194 static const char* err_str[];
00195 };
00196
00197
00204 class PDUSyntaxError : public IEError {
00205 public:
00206 PDUSyntaxError(const char* msg);
00207 PDUSyntaxError(IE::coding_t coding, uint16 category, uint16 type,
00208 uint16 subtype, uint32 pos, const char *msg = "");
00209 virtual ~PDUSyntaxError() throw () { }
00210
00211 const IE::coding_t coding;
00212 const uint16 category;
00213 const uint16 type;
00214 const uint16 subtype;
00215 const uint32 errorpos;
00216 const string message;
00217 };
00218
00219
00227 class IEMsgTooShort : public IEError {
00228 public:
00229 IEMsgTooShort(IE::coding_t coding, uint16 category, uint32 pos);
00230 virtual ~IEMsgTooShort() throw () { }
00231
00232 const IE::coding_t coding;
00233 const uint16 category;
00234 const uint32 errorpos;
00235 };
00236
00237
00244 class IEWrongVersion : public IEError {
00245 public:
00246 IEWrongVersion(IE::coding_t coding, uint16 category, uint32 pos);
00247 virtual ~IEWrongVersion() throw () { }
00248
00249 const IE::coding_t coding;
00250 const uint16 category;
00251 const uint32 errorpos;
00252 };
00253
00254
00261 class IEWrongType : public IEError {
00262 public:
00263
00264 IEWrongType(IE::coding_t coding, uint16 category, uint32 pos);
00265 IEWrongType(IE::coding_t coding, uint16 category, uint16 type,
00266 uint32 pos);
00267 virtual ~IEWrongType() throw () { }
00268
00269 const IE::coding_t coding;
00270 const uint16 category;
00271 const uint16 type;
00272 const uint32 errorpos;
00273 };
00274
00275
00282 class IEWrongSubtype : public IEError {
00283 public:
00284
00285 IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
00286 uint32 pos);
00287 IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
00288 uint16 subtype, uint32 pos);
00289 virtual ~IEWrongSubtype() throw () { }
00290
00291 const IE::coding_t coding;
00292 const uint16 category;
00293 const uint16 type;
00294 const uint16 subtype;
00295 const uint32 errorpos;
00296 };
00297
00298
00306 class IEWrongLength : public IEError {
00307 public:
00308 IEWrongLength(IE::coding_t coding, uint16 category, uint16 type,
00309 uint16 subtype, uint32 pos);
00310 virtual ~IEWrongLength() throw () { }
00311
00312 const IE::coding_t coding;
00313 const uint16 category;
00314 const uint16 type;
00315 const uint16 subtype;
00316 const uint32 errorpos;
00317 };
00318
00319
00326 class IETooBigForImpl : public IEError {
00327 public:
00328 IETooBigForImpl(IE::coding_t coding, uint16 category, uint32 pos);
00329 virtual ~IETooBigForImpl() throw () { }
00330
00331 const IE::coding_t coding;
00332 const uint16 category;
00333 const uint32 errorpos;
00334 };
00335
00336
00343 class IEProtocolSpecific : public IEError {
00344 public:
00345 IEProtocolSpecific(IE::coding_t coding, uint16 category, uint32 pos);
00346 virtual ~IEProtocolSpecific() throw () { }
00347
00348 const IE::coding_t coding;
00349 const uint16 category;
00350 const uint32 errorpos;
00351 };
00352
00353
00355
00356 class IEErrorList {
00357 public:
00359 void put(IEError* iee);
00361 IEError* get();
00363 bool is_empty() const;
00365 void clear();
00367 ~IEErrorList();
00368 private:
00370 typedef deque<IEError*> queue_t;
00372 typedef queue_t::iterator queueit_t;
00374 queue_t queue;
00375 };
00376
00377
00383 class IE_Key {
00384 public:
00385 inline IE_Key(uint16 category, uint16 type, uint16 subtype)
00386 : category(category), type(type), subtype(subtype) { }
00387
00388 inline bool operator==(const IE_Key &other) const {
00389 return category == other.category && type == other.type
00390 && subtype == other.subtype;
00391 }
00392
00393 inline uint16 get_category() const { return category; }
00394 inline uint16 get_type() const { return type; }
00395 inline uint16 get_subtype() const { return subtype; }
00396
00397 private:
00398 uint16 category;
00399 uint16 type;
00400 uint16 subtype;
00401 };
00402
00403 struct hash_IE_Key {
00404 inline size_t operator()(const protlib::IE_Key &k) const {
00405 return (k.get_category() << 16)
00406 | ( k.get_type() ^ k.get_subtype() );
00407 }
00408 };
00409
00410
00441 class IEManager {
00442
00443 public:
00444 virtual ~IEManager();
00445
00446 virtual void register_ie(const IE *ie);
00447 virtual void register_ie(uint16 category, uint16 type, uint16 subtype,
00448 const IE *ie);
00449
00450 virtual IE *new_instance(uint16 category, uint16 type, uint16 subtype);
00451
00452 virtual void serialize(IE &ie, NetMsg &msg, IE::coding_t coding,
00453 uint32 &bytes_written) const;
00454
00455 virtual IE *deserialize(NetMsg &msg, uint16 category,
00456 IE::coding_t coding, IEErrorList& errorlist,
00457 uint32 &bytes_read, bool skip = true) = 0;
00458
00459 protected:
00460 IEManager();
00461
00462 virtual IE *lookup_ie(uint16 category, uint16 type, uint16 subtype);
00463
00464 virtual void throw_nomem_error() const;
00465
00466 private:
00467 typedef unordered_map<IE_Key, IE *, hash_IE_Key> category_map_t;
00468
00469 category_map_t registry;
00470 };
00471
00472
00479 inline
00480 void IEManager::serialize(IE& ie, NetMsg& msg, IE::coding_t coding, uint32& wbytes) const {
00481 ie.serialize(msg,coding,wbytes);
00482 }
00483
00484
00486 ostream& operator<<(ostream& os, const IE& ie);
00487
00489 istream& operator>>(istream& is, IE& ie);
00490
00492
00493 inline uint32 round_up4(uint32 i) {
00494 if (i%4) i = i-(i%4)+4;
00495 return i;
00496 }
00497
00499
00500 }
00501
00502 #endif // _PROTLIB__IE_H_