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
00038 #include "ie.h"
00039 #include "logfile.h"
00040
00041 #include <unistd.h>
00042 #include <stdio.h>
00043 #include <string.h>
00044 #include <sstream>
00045 #include <iomanip>
00046
00047 namespace protlib {
00048 using namespace log;
00049
00050
00051
00056
00057
00059 IE::IE(uint16 category) : category(category) {}
00060
00061 IE::IE(const IE& n) : category(n.category) {}
00062
00064 uint16 IE::get_category() const {
00065 return category;
00066 }
00067
00071 bool IE::check_deser_args(coding_t cod, IEErrorList& errorlist, uint32 &bread) const {
00072 bread = 0;
00073
00074 if (!supports_coding(cod)) {
00075 Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_deser_args(): IE " << get_ie_name() << " does not support coding " << cod );
00076 catch_bad_alloc(errorlist.put(new IEError(IEError::ERROR_CODING)));
00077 return false;
00078 }
00079 return true;
00080 }
00081
00085 void IE::check_ser_args(coding_t cod, uint32 &wbytes) const {
00086 wbytes = 0;
00087
00088 if (!check()) {
00089 IEError err(IEError::ERROR_INVALID_STATE);
00090 Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_ser_args() for IE " << get_ie_name() << ", error: " << err.getstr());
00091 throw err;
00092 }
00093
00094 if (!supports_coding(cod)) {
00095 IEError err(IEError::ERROR_CODING);
00096 Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_ser_args() for IE " << get_ie_name() << ", error: " << err.getstr() << ", coding: " << cod);
00097 throw err;
00098 }
00099 return;
00100 }
00101
00102
00108 ostream& IE::print(ostream& os, uint32 level, const uint32 indent, const char* name) const {
00109 os<<setw(level*indent)<<"";
00110 if (name && (*name!=0)) os<<name<<" ";
00111 os<<"<"<<get_ie_name()<<">";
00112 return os;
00113 }
00114
00115 istream& IE::input(istream& is, bool istty, uint32 level, const uint32 indent, const char* name) {
00116 Log(ERROR_LOG,LOG_NORMAL, "IE", "IE " << get_ie_name() << "::input not yet implemented");
00117 if (istty) {
00118 cout<<setw(level*indent)<<"";
00119 if (name && (*name!=0)) cout<<name<<" ";
00120 cout<<"<"<<get_ie_name()<<">: Input not yet implemented."<<endl;
00121 }
00122 return is;
00123 }
00124
00126 string IE::to_string(const char* name) const {
00127 ostringstream os;
00128 print(os,0,3,name);
00129 return os.str();
00130 }
00131
00133 void IE::throw_nomem_error() const {
00134 try {
00135 Log(ERROR_LOG,LOG_CRIT, "IE", "Not enough memory for IE " << get_ie_name());
00136 } catch(...) {}
00137 throw IEError(IEError::ERROR_NO_MEM);
00138 }
00139
00143 void IE::clear_pointers() {}
00144
00145
00146
00147
00149 const char* IEError::err_str[] = {
00150 "Error while registering IE. Either pointer to IE is NULL or registered IE already.",
00151 "IE coding scheme is not supported by this function.",
00152 "IE category is not supported by this function or in the applied coding scheme.",
00153 "IE Manager instance does not exist (possible mem alloc problem?)",
00154 "NetMsg too short for (de)serialization.",
00155 "IE is in invalid state.",
00156 "Wrong/unexpected IE type.",
00157 "Wrong/unexpected IE subtype.",
00158 "Wrong IE length.",
00159 "Not enough memory to allocate IE.",
00160 "Too big for this protocol implementation.",
00161 "Unknown error code for this error class.",
00162 "Wrong or unknown protocol version.",
00163 "Unexpected object",
00164 "PDU syntax error",
00165 "PDU Object set failed (wrong index)",
00166 "Protocol Specific Error"
00167 };
00168
00169
00179 IEError::IEError(error_t error) : ProtLibException(err_str[error]), err(error) {
00180
00181 }
00182
00183
00184 IEError::IEError(std::string msg) throw ()
00185 : ProtLibException(msg), err(ERROR_UNKNOWN_ERRORCODE) {
00186
00187
00188 }
00189
00190
00196 IEError::~IEError() throw () {
00197
00198 }
00199
00200
00208 const char* IEError::getstr() const {
00209 return err_str[err];
00210 }
00211
00212
00213
00214
00222 PDUSyntaxError::PDUSyntaxError(const char* msg)
00223 : IEError(IEError::ERROR_PDU_SYNTAX),
00224 coding(coding), category(0), type(0), subtype(0),
00225 errorpos(0), message(msg) {
00226
00227 ostringstream ost;
00228 ost << "[coding " << coding << ", cat " << category << ", type " << type
00229 << ", subtype " << subtype << "] " << message;
00230
00231 error_msg = ost.str();
00232 }
00233
00234
00245 PDUSyntaxError::PDUSyntaxError(IE::coding_t coding, uint16 category,
00246 uint16 type, uint16 subtype, uint32 pos, const char *msg)
00247 : IEError(IEError::ERROR_PDU_SYNTAX),
00248 coding(coding), category(category), type(type),
00249 subtype(subtype), errorpos(pos), message(msg) {
00250
00251 ostringstream ost;
00252 ost << "[coding " << coding << ", cat " << category << ", type " << type
00253 << ", subtype " << subtype << "] " << message;
00254
00255 error_msg = ost.str();
00256 }
00257
00258
00259
00260
00268 IEMsgTooShort::IEMsgTooShort(IE::coding_t coding, uint16 category, uint32 pos)
00269 : IEError(ERROR_MSG_TOO_SHORT),
00270 coding(coding), category(category), errorpos(pos) {
00271
00272 ostringstream ost;
00273 ost << "[coding " << coding << ", cat " << category
00274 << ", pos" << errorpos << IEError::getstr();
00275
00276 error_msg = ost.str();
00277 }
00278
00279
00280
00281
00289 IEWrongVersion::IEWrongVersion(IE::coding_t coding, uint16 category, uint32 pos)
00290 : IEError(ERROR_WRONG_VERSION),
00291 coding(coding), category(category), errorpos(pos) {
00292
00293 ostringstream ost;
00294 ost << "[coding " << coding << ", cat " << category
00295 << ", pos" << errorpos << IEError::getstr();
00296
00297 error_msg = ost.str();
00298 }
00299
00300
00301
00302
00312 IEWrongType::IEWrongType(IE::coding_t coding, uint16 category, uint32 pos)
00313 : IEError(ERROR_WRONG_TYPE), coding(coding),
00314 category(category), type(0), errorpos(pos) {
00315
00316 ostringstream ost;
00317 ost << "[coding " << coding << ", cat " << category << ", type " << type
00318 << ", pos" << errorpos << IEError::getstr();
00319
00320 error_msg = ost.str();
00321 }
00322
00323
00332 IEWrongType::IEWrongType(IE::coding_t coding, uint16 category, uint16 type,
00333 uint32 pos)
00334 : IEError(ERROR_WRONG_TYPE), coding(coding),
00335 category(category), type(type), errorpos(pos) {
00336
00337 ostringstream ost;
00338 ost << "[coding " << coding << ", cat " << category << ", type " << type
00339 << ", pos" << errorpos << IEError::getstr();
00340
00341 error_msg = ost.str();
00342 }
00343
00344
00345
00346
00357 IEWrongSubtype::IEWrongSubtype(IE::coding_t coding, uint16 category,
00358 uint16 type, uint32 pos)
00359 : IEError(ERROR_WRONG_SUBTYPE), coding(coding),
00360 category(category), type(type), subtype(0), errorpos(pos) {
00361
00362 ostringstream ost;
00363 ost << "[coding " << coding << ", cat " << category << ", type " << type
00364 << ", subtype " << subtype << ", pos" << errorpos
00365 << IEError::getstr();
00366
00367 error_msg = ost.str();
00368 }
00369
00370
00380 IEWrongSubtype::IEWrongSubtype(IE::coding_t coding, uint16 category,
00381 uint16 type, uint16 subtype, uint32 pos)
00382 : IEError(ERROR_WRONG_SUBTYPE),
00383 coding(coding), category(category), type(type),
00384 subtype(subtype), errorpos(pos) {
00385
00386 ostringstream ost;
00387 ost << "[coding " << coding << ", cat " << category << ", type " << type
00388 << ", subtype " << subtype << ", pos" << errorpos
00389 << IEError::getstr();
00390
00391 error_msg = ost.str();
00392 }
00393
00394
00395
00396
00409 IEWrongLength::IEWrongLength(IE::coding_t coding, uint16 category, uint16 type,
00410 uint16 subtype, uint32 pos)
00411 : IEError(ERROR_WRONG_LENGTH),
00412 coding(coding), category(category), type(type),
00413 subtype(subtype), errorpos(pos) {
00414
00415 ostringstream ost;
00416 ost << "[coding " << coding << ", cat " << category << ", type " << type
00417 << ", subtype " << subtype << ", pos" << errorpos
00418 << IEError::getstr();
00419
00420 error_msg = ost.str();
00421 }
00422
00423
00424
00425
00433 IETooBigForImpl::IETooBigForImpl(IE::coding_t coding, uint16 category,
00434 uint32 pos)
00435 : IEError(ERROR_TOO_BIG_FOR_IMPL),
00436 coding(coding), category(category), errorpos(pos) {
00437
00438 ostringstream ost;
00439 ost << "[coding " << coding << ", cat " << category
00440 << ", pos" << errorpos << IEError::getstr();
00441
00442 error_msg = ost.str();
00443 }
00444
00445
00446
00447
00455 IEProtocolSpecific::IEProtocolSpecific(IE::coding_t coding, uint16 category,
00456 uint32 pos)
00457 : IEError(ERROR_PROT_SPECIFIC),
00458 coding(coding), category(category), errorpos(pos) {
00459
00460 ostringstream ost;
00461 ost << "[coding " << coding << ", cat " << category
00462 << ", pos" << errorpos << IEError::getstr();
00463
00464 error_msg = ost.str();
00465 }
00466
00467
00468
00469
00471 void IEErrorList::put(IEError* iee) {
00472 if (iee) queue.push_front(iee);
00473 }
00474
00478 IEError* IEErrorList::get() {
00479 register IEError* iee;
00480 if (queue.empty()) return NULL;
00481 else {
00482 iee = queue.back();
00483 queue.pop_back();
00484 return iee;
00485 }
00486 }
00487
00489 bool IEErrorList::is_empty() const {
00490 return queue.empty();
00491 }
00492
00494 void IEErrorList::clear() {
00495 queueit_t qit;
00496
00497 for (qit=queue.begin();qit!=queue.end();++qit)
00498 if (*qit) delete *qit;
00499
00500 queue.clear();
00501 }
00502
00504 IEErrorList::~IEErrorList() {
00505 if (!queue.empty()) {
00506 Log(DEBUG_LOG,LOG_CRIT, "IE", "Destroying non-empty IEErrorList, deleting IEError objects.");
00507 clear();
00508 }
00509 }
00510
00511
00512
00513
00514
00518 IEManager::IEManager() {
00519
00520 }
00521
00522
00528 IEManager::~IEManager() {
00529
00530 typedef category_map_t::const_iterator c_iter;
00531
00532
00533
00534
00535 int num_deleted = 0;
00536
00537 for (c_iter i = registry.begin(); i != registry.end(); i++) {
00538 IE *ie = i->second;
00539
00540 if ( ie != NULL ) {
00541 delete ie;
00542 num_deleted++;
00543 }
00544 }
00545
00546 DLog("IEManager", "Deleted " << num_deleted << " IEs");
00547 }
00548
00549
00561 void IEManager::register_ie(const IE* ie) {
00562 if ( ie == NULL )
00563 throw IEError(IEError::ERROR_REGISTER);
00564
00565 return ie->register_ie(this);
00566 }
00567
00568
00587 void IEManager::register_ie(uint16 category, uint16 type, uint16 subtype,
00588 const IE* ie) {
00589
00590
00591 ostringstream triple;
00592 triple << "(" << category << ", " << type << ", " << subtype << ")";
00593
00594 if ( ie == NULL )
00595 throw IEError(IEError::ERROR_REGISTER);
00596
00597 IE_Key key(category, type, subtype);
00598
00599
00600 if ( registry[key] != NULL ) {
00601 ERRLog("IEManager",
00602 "An IE is already " << "registered for " << triple);
00603 return;
00604 }
00605
00606
00607 try {
00608 registry[key] = const_cast<IE *>(ie);
00609 }
00610 catch ( ... ) {
00611 ERRLog("IEManager", "Cannot register IE for " << triple);
00612
00613 throw IEError(IEError::ERROR_REGISTER);
00614 }
00615
00616
00617 DLog("IEManager",
00618 "Registered IE " << ie->get_ie_name() << " for " << triple);
00619 }
00620
00621
00636 IE *IEManager::new_instance(uint16 category, uint16 type, uint16 subtype) {
00637 IE *ie = lookup_ie(category, type, subtype);
00638
00639 if ( ie )
00640 return ie->copy();
00641 else
00642 return NULL;
00643 }
00644
00645
00661 IE *IEManager::lookup_ie(uint16 category, uint16 type, uint16 subtype) {
00662 return registry[IE_Key(category, type, subtype)];
00663 }
00664
00665
00669 void IEManager::throw_nomem_error() const {
00670 try {
00671 ERRLog("IEManager", "Out of memory.");
00672 }
00673 catch ( ... ) {
00674
00675 }
00676
00677 throw IEError(IEError::ERROR_NO_MEM);
00678 }
00679
00680
00681
00682
00684 ostream& operator<<(ostream& os, const IE& ie) {
00685 ie.print(os,0,3);
00686 return os;
00687 }
00688
00689 istream& operator>>(istream& is, IE& ie) {
00690 ie.input(is,isatty(0),0,3);
00691 return is;
00692 }
00693
00695
00696 }