/// ----------------------------------------*- mode: C++; -*-- /// @file ie.cpp /// information elements for the protocol, IE manager singleton /// ---------------------------------------------------------- /// $Id: ie.cpp 2549 2007-04-02 22:17:37Z bless $ /// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/ie.cpp $ // =========================================================== // // Copyright (C) 2005-2007, all rights reserved by // - Institute of Telematics, Universitaet Karlsruhe (TH) // // More information and contact: // https://projekte.tm.uka.de/trac/NSIS // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // =========================================================== /** @ingroup ie * This file defines the base class of all information elements, the * information elements for the GIST protocol and an IE manager singleton * object. * Although the IEs are closely related to the structure of GIST messages, * they may be used in other contexts as well because of the coding shemes. */ #include "ie.h" #include "logfile.h" #include #include #include #include #include namespace protlib { using namespace log; /** @addtogroup ie Information Elements * @{ */ /***** class IE *****/ /** Constructor. Sets category of IE. */ IE::IE(uint16 category) : category(category) {} IE::IE(const IE& n) : category(n.category) {} /** Get the category of the IE. */ uint16 IE::get_category() const { return category; } // end get_category /** Check arguments of IE deserialization member functions. * Additionally, bread is set to 0. */ bool IE::check_deser_args(coding_t cod, IEErrorList& errorlist, uint32 &bread) const { bread = 0; // check coding if (!supports_coding(cod)) { Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_deser_args(): IE " << get_ie_name() << " does not support coding " << cod ); catch_bad_alloc(errorlist.put(new IEError(IEError::ERROR_CODING))); return false; } // end if cod return true; } // end check_deser_args() /** Check arguments of IE serialization member functions. * Additionally, wbytes is set to 0. */ void IE::check_ser_args(coding_t cod, uint32 &wbytes) const { wbytes = 0; // check IE state if (!check()) { IEError err(IEError::ERROR_INVALID_STATE); Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_ser_args() for IE " << get_ie_name() << ", error: " << err.getstr()); throw err; } // end if !check() // check coding if (!supports_coding(cod)) { IEError err(IEError::ERROR_CODING); Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_ser_args() for IE " << get_ie_name() << ", error: " << err.getstr() << ", coding: " << cod); throw err; } // end if cod return; } // end check_ser_args() /** Print the content of the IE, default behaviour is to print its name. * Level and indent control how much space is inserted after a newline. * If name points to a string, this string is printed before the * get_ie_name(). */ ostream& IE::print(ostream& os, uint32 level, const uint32 indent, const char* name) const { os<"; return os; } // end print istream& IE::input(istream& is, bool istty, uint32 level, const uint32 indent, const char* name) { Log(ERROR_LOG,LOG_NORMAL, "IE", "IE " << get_ie_name() << "::input not yet implemented"); if (istty) { cout<: Input not yet implemented."<second; if ( ie != NULL ) { delete ie; num_deleted++; } } DLog("IEManager", "Deleted " << num_deleted << " IEs"); } /** * Register an Information Element. * * Make the IE object passed as the argument register itself with this * IEManager. See IE's register_ie() method for the rules. * * This method exists for convenience only, please see the other register_ie() * method for details. * * @param ie pointer to IE (NULL is not allowed) */ void IEManager::register_ie(const IE* ie) { if ( ie == NULL ) throw IEError(IEError::ERROR_REGISTER); return ie->register_ie(this); } /** * Register an Information Element. * * Register an IE for the given category, type and subtype. It is not allowed * to register more than one IE for a (category, type, subtype) triple. * * It is @em very important that each IE instance is registered only once. * If a class can handle multiple (category, type, subtype) triples, one * instance per triple has to be registered. * * There is no way to unregister an IE. All registered IEs will be deleted * by IEManager's destructor. * * @param category category of the IE * @param type IE type * @param subtype IE subtype * @param ie the IE to register (NULL is not allowed) */ void IEManager::register_ie(uint16 category, uint16 type, uint16 subtype, const IE* ie) { // for logging ostringstream triple; triple << "(" << category << ", " << type << ", " << subtype << ")"; if ( ie == NULL ) throw IEError(IEError::ERROR_REGISTER); IE_Key key(category, type, subtype); // don't allow overwriting if ( registry[key] != NULL ) { ERRLog("IEManager", "An IE is already " << "registered for " << triple); return; } try { registry[key] = const_cast(ie); } catch ( ... ) { ERRLog("IEManager", "Cannot register IE for " << triple); throw IEError(IEError::ERROR_REGISTER); } // We made it so far, this means success. DLog("IEManager", "Registered IE " << ie->get_ie_name() << " for " << triple); } /** * Create a new instance. * * Creates a new instance using the appropriate registered IE. The definition * of @em appropriate depends on lookup_ie(). * * Note that some old IEManager child classes called this method lookup(). * This old lookup() method should not be confused with lookup_ie(). * * @param category category of the IE * @param type IE type * @param subtype IE subtype * @return a new instance, or NULL if no matching IE is found */ IE *IEManager::new_instance(uint16 category, uint16 type, uint16 subtype) { IE *ie = lookup_ie(category, type, subtype); if ( ie ) return ie->copy(); else return NULL; } /** * Return a registered IE. * * Returns a registered IE instance. It does @em not create a new instance, * it is really an instance you registered earlier. Use new_instance() if * you need new instances! * * This method is an extension point that can be used, for example, to return * "default" IEs if no matching IE is found in the registry. * * @param category category of the IE * @param type IE type * @param subtype IE subtype * @return a registered instance, or NULL if no matching IE is found */ IE *IEManager::lookup_ie(uint16 category, uint16 type, uint16 subtype) { return registry[IE_Key(category, type, subtype)]; } /** * Throw an exception and log it. */ void IEManager::throw_nomem_error() const { try { ERRLog("IEManager", "Out of memory."); } catch ( ... ) { // There's no way to handle this! } throw IEError(IEError::ERROR_NO_MEM); } /***** operator<< and >> *****/ /** Print the given IE to the ostream using level=0 and indent=3. */ ostream& operator<<(ostream& os, const IE& ie) { ie.print(os,0,3); return os; } // end operator<< istream& operator>>(istream& is, IE& ie) { ie.input(is,isatty(0),0,3); return is; } // end operator>> //@} } // end namespace protlib