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 <ext/hash_map>
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 namespace protlib {
00057
00058
00059
00064
00065 #define catch_bad_alloc(x) try { x; } catch(bad_alloc) { throw_nomem_error(); }
00066
00067
00068 class IEManager;
00069 class IEErrorList;
00070 class IEError;
00071
00074 class IE {
00075 public:
00076 virtual ~IE() { }
00077
00078 friend class IEManager;
00080
00087 enum coding_t {
00088 nslp_v1 = 1,
00089 protocol_v1 = 1,
00090 protocol_v2 = 2,
00091 nslp_v2 = 3,
00092 nslp_v2_yoda = 4
00093 };
00094 protected:
00096 IE(uint16 category);
00098 IE(const IE& n);
00099 public:
00101 virtual IE* new_instance() const = 0;
00103 virtual IE* copy() const = 0;
00105 virtual IE* deserialize(NetMsg& msg, coding_t coding, IEErrorList& errorlist, uint32& bread, bool skip = true) = 0;
00107 virtual void serialize(NetMsg& msg, coding_t coding, uint32& wbytes) const = 0;
00108 protected:
00110 bool check_deser_args(coding_t cod, IEErrorList& errorlist, uint32 &bread) const;
00112 void check_ser_args(coding_t cod, uint32 &wbytes) const;
00113 public:
00115 virtual bool check() const = 0;
00117 virtual bool supports_coding(coding_t c) const = 0;
00119 virtual size_t get_serialized_size(coding_t coding) const = 0;
00121 uint16 get_category() const;
00123 virtual bool operator==(const IE& ie) const = 0;
00125 inline bool operator!=(const IE& ie) const { return (!(*this==ie)); }
00127
00128 virtual const char* get_ie_name() const = 0;
00130 virtual ostream& print(ostream& os, uint32 level, const uint32 indent, const char* name = NULL) const;
00132 string to_string(const char* name = 0) const;
00134
00135 virtual istream& input(istream& is, bool istty, uint32 level, const uint32 indent, const char* name = NULL);
00137 virtual void clear_pointers();
00138 protected:
00140 virtual void register_ie(IEManager *iem) const = 0;
00142 const uint16 category;
00144 void throw_nomem_error() const;
00145 };
00146
00147
00148
00158 class IEError : public ProtLibException {
00159 public:
00161 enum error_t {
00162 ERROR_REGISTER,
00163 ERROR_CODING,
00164 ERROR_CATEGORY,
00165 ERROR_NO_IEMANAGER,
00166 ERROR_MSG_TOO_SHORT,
00167 ERROR_INVALID_STATE,
00168 ERROR_WRONG_TYPE,
00169 ERROR_WRONG_SUBTYPE,
00170 ERROR_WRONG_LENGTH,
00171 ERROR_NO_MEM,
00172 ERROR_TOO_BIG_FOR_IMPL,
00173 ERROR_UNKNOWN_ERRORCODE,
00174 ERROR_WRONG_VERSION,
00175 ERROR_UNEXPECTED_OBJECT,
00176 ERROR_PDU_SYNTAX,
00177 ERROR_OBJ_SET_FAILED,
00178 ERROR_PROT_SPECIFIC
00179 };
00180
00181 const error_t err;
00182
00183 IEError(error_t e);
00184 virtual ~IEError() throw ();
00185
00186 virtual const char *getstr() const;
00187
00188 protected:
00189 IEError(std::string msg) throw ();
00190
00191 private:
00192 static const char* err_str[];
00193 };
00194
00195
00202 class PDUSyntaxError : public IEError {
00203 public:
00204 PDUSyntaxError(const char* msg);
00205 PDUSyntaxError(IE::coding_t coding, uint16 category, uint16 type,
00206 uint16 subtype, uint32 pos, const char *msg = "");
00207 virtual ~PDUSyntaxError() throw () { }
00208
00209 const IE::coding_t coding;
00210 const uint16 category;
00211 const uint16 type;
00212 const uint16 subtype;
00213 const uint32 errorpos;
00214 const string message;
00215 };
00216
00217
00225 class IEMsgTooShort : public IEError {
00226 public:
00227 IEMsgTooShort(IE::coding_t coding, uint16 category, uint32 pos);
00228 virtual ~IEMsgTooShort() throw () { }
00229
00230 const IE::coding_t coding;
00231 const uint16 category;
00232 const uint32 errorpos;
00233 };
00234
00235
00242 class IEWrongVersion : public IEError {
00243 public:
00244 IEWrongVersion(IE::coding_t coding, uint16 category, uint32 pos);
00245 virtual ~IEWrongVersion() throw () { }
00246
00247 const IE::coding_t coding;
00248 const uint16 category;
00249 const uint32 errorpos;
00250 };
00251
00252
00259 class IEWrongType : public IEError {
00260 public:
00261
00262 IEWrongType(IE::coding_t coding, uint16 category, uint32 pos);
00263 IEWrongType(IE::coding_t coding, uint16 category, uint16 type,
00264 uint32 pos);
00265 virtual ~IEWrongType() throw () { }
00266
00267 const IE::coding_t coding;
00268 const uint16 category;
00269 const uint16 type;
00270 const uint32 errorpos;
00271 };
00272
00273
00280 class IEWrongSubtype : public IEError {
00281 public:
00282
00283 IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
00284 uint32 pos);
00285 IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
00286 uint16 subtype, uint32 pos);
00287 virtual ~IEWrongSubtype() throw () { }
00288
00289 const IE::coding_t coding;
00290 const uint16 category;
00291 const uint16 type;
00292 const uint16 subtype;
00293 const uint32 errorpos;
00294 };
00295
00296
00304 class IEWrongLength : public IEError {
00305 public:
00306 IEWrongLength(IE::coding_t coding, uint16 category, uint16 type,
00307 uint16 subtype, uint32 pos);
00308 virtual ~IEWrongLength() throw () { }
00309
00310 const IE::coding_t coding;
00311 const uint16 category;
00312 const uint16 type;
00313 const uint16 subtype;
00314 const uint32 errorpos;
00315 };
00316
00317
00324 class IETooBigForImpl : public IEError {
00325 public:
00326 IETooBigForImpl(IE::coding_t coding, uint16 category, uint32 pos);
00327 virtual ~IETooBigForImpl() throw () { }
00328
00329 const IE::coding_t coding;
00330 const uint16 category;
00331 const uint32 errorpos;
00332 };
00333
00334
00341 class IEProtocolSpecific : public IEError {
00342 public:
00343 IEProtocolSpecific(IE::coding_t coding, uint16 category, uint32 pos);
00344 virtual ~IEProtocolSpecific() throw () { }
00345
00346 const IE::coding_t coding;
00347 const uint16 category;
00348 const uint32 errorpos;
00349 };
00350
00351
00353
00354 class IEErrorList {
00355 public:
00357 void put(IEError* iee);
00359 IEError* get();
00361 bool is_empty() const;
00363 void clear();
00365 ~IEErrorList();
00366 private:
00368 typedef deque<IEError*> queue_t;
00370 typedef queue_t::iterator queueit_t;
00372 queue_t queue;
00373 };
00374
00375
00381 class IE_Key {
00382 public:
00383 inline IE_Key(uint16 category, uint16 type, uint16 subtype)
00384 : category(category), type(type), subtype(subtype) { }
00385
00386 inline bool operator==(const IE_Key &other) const {
00387 return category == other.category && type == other.type
00388 && subtype == other.subtype;
00389 }
00390
00391 inline uint16 get_category() const { return category; }
00392 inline uint16 get_type() const { return type; }
00393 inline uint16 get_subtype() const { return subtype; }
00394
00395 private:
00396 uint16 category;
00397 uint16 type;
00398 uint16 subtype;
00399 };
00400
00401 struct hash_IE_Key {
00402 inline size_t operator()(const protlib::IE_Key &k) const {
00403 return (k.get_category() << 16)
00404 | ( k.get_type() ^ k.get_subtype() );
00405 }
00406 };
00407
00408
00439 class IEManager {
00440
00441 public:
00442 virtual ~IEManager();
00443
00444 virtual void register_ie(const IE *ie);
00445 virtual void register_ie(uint16 category, uint16 type, uint16 subtype,
00446 const IE *ie);
00447
00448 virtual IE *new_instance(uint16 category, uint16 type, uint16 subtype);
00449
00450 virtual void serialize(IE &ie, NetMsg &msg, IE::coding_t coding,
00451 uint32 &bytes_written) const;
00452
00453 virtual IE *deserialize(NetMsg &msg, uint16 category,
00454 IE::coding_t coding, IEErrorList& errorlist,
00455 uint32 &bytes_read, bool skip = true) = 0;
00456
00457 protected:
00458 IEManager();
00459
00460 virtual IE *lookup_ie(uint16 category, uint16 type, uint16 subtype);
00461
00462 virtual void throw_nomem_error() const;
00463
00464 private:
00465 typedef hash_map<IE_Key, IE *, hash_IE_Key> category_map_t;
00466
00467 category_map_t registry;
00468 };
00469
00470
00477 inline
00478 void IEManager::serialize(IE& ie, NetMsg& msg, IE::coding_t coding, uint32& wbytes) const {
00479 ie.serialize(msg,coding,wbytes);
00480 }
00481
00482
00484 ostream& operator<<(ostream& os, const IE& ie);
00485
00487 istream& operator>>(istream& is, IE& ie);
00488
00490
00491 inline uint32 round_up4(uint32 i) {
00492 if (i%4) i = i-(i%4)+4;
00493 return i;
00494 }
00495
00497
00498 }
00499
00500 #endif // _PROTLIB__IE_H_