X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=include%2Fanna%2Fdiameter%2Fcodec%2FEngineImpl.hpp;h=22fb82f4c8b39b2440a79b576e0bd205706b90f7;hb=5a6cba5fde2b2f538a7515f8293cc0a8d9589dfa;hp=e49f61dede6ac41fa590230f473c3016d85a6042;hpb=4e12ac57e93c052f716a6305ad8fc099c45899d1;p=anna.git diff --git a/include/anna/diameter/codec/EngineImpl.hpp b/include/anna/diameter/codec/EngineImpl.hpp index e49f61d..22fb82f 100644 --- a/include/anna/diameter/codec/EngineImpl.hpp +++ b/include/anna/diameter/codec/EngineImpl.hpp @@ -1,37 +1,9 @@ -// ANNA - Anna is Not 'N' Anymore -// -// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo -// -// https://bitbucket.org/testillano/anna -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Authors: eduardo.ramos.testillano@gmail.com -// cisco.tierra@gmail.com +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // #ifndef anna_diameter_codec_EngineImpl_hpp @@ -64,8 +36,6 @@ class Dictionary; namespace codec { -extern const char *MessageDTD; - class Message; class Avp; @@ -78,23 +48,15 @@ class Avp; * A child implementation could manage complex Avp classes with new data-part formats. Grouped ones could * allocate new complex Avps through such engine which knows how to allocate this special Avp's (also for * complex Message classes with application-specific setters and getters as credit-control related avps, - * or some another context items). For example helpers for TME scope stands for a new engine component - * called tme::Engine, allocating tme::Avp and tme::Message classes which support three new Avp formats: + * or some another context items). For example tme::Avp and tme::Message classes support three new Avp formats: * ISDNNumber, ISDNAddress and Unsigned16. Anyway, main Message/Avp and Engine classes stand for all contexts * included in anna::diameter, that is to say, whole contexts (at the time only TME) will be included in future * when needed apart from the independent namespace version. Thank to this, single threaded applications could * use whole engine in a easy way. * - * Usually an engine component is associated to a single diameter stack, although single threaded processes could - * use a common engine alternating different stack dictionaries by mean #setDictionary, depending on which kind of - * messages are being analyzed. Although the application must ensure that a single dictionary is activated during - * the same context operations an Avp could be considered as Unknown if was created with another, and we could - * have validation problems (i.e. if mandatory Avp bit is enabled). In general, managing Unknown data-part format - * don't have to be a problem because it is interpreted as OctetString format. Depending on what setters/getters - * we use, it could reach a RuntimeException at our application. - * - * At multithread processes we must use one heir engine per stack and never switching stacks within same component. - * We will use each engine for each context. + * An engine component is associated to a single diameter stack. It is application responsability to use message + * container initialized with the correct codec engine depending on the context. There are helpers to do this at + * anna::diameter::codec::functions::getApplicationId (from xml document or hexadecimal buffer). * * It is recommended to use Message class to create Avps (adding them through pair identification * prototype), but we could create Avps separately (other program section, i.e) and join them after: @@ -103,7 +65,7 @@ class Avp; * 1. Recommended way: * * // Message creation: - * Message * msg = new Message(helpers::base::COMMANDID__Re_Auth_Answer); + * Message * msg = new Message(helpers::base::COMMANDID__Re_Auth_Answer, codecEngine); * // Adding + creation: * Avp * avp_sid = msg->addAvp(helpers::base::AVPID__Session_Id); * Avp * avp_oh = msg->addAvp(helpers::base::AVPID__Origin_Host); @@ -116,12 +78,12 @@ class Avp; * 2. External Avp creation: * * // Message creation: - * Message * msg = new Message(helpers::base::COMMANDID__Re_Auth_Answer); + * Message * msg = new Message(helpers::base::COMMANDID__Re_Auth_Answer, codecEngine); * // Creation: - * Avp * avp_sid = new Avp(helpers::base::AVPID__Session_Id); - * Avp * avp_oh = new Avp(helpers::base::AVPID__Origin_Host); - * Avp * avp_or = new Avp(helpers::base::AVPID__Origin_Realm); - * Avp * avp_rc = new Avp(helpers::base::AVPID__Result_Code); + * Avp * avp_sid = new Avp(helpers::base::AVPID__Session_Id, codecEngine); + * Avp * avp_oh = new Avp(helpers::base::AVPID__Origin_Host, codecEngine); + * Avp * avp_or = new Avp(helpers::base::AVPID__Origin_Realm, codecEngine); + * Avp * avp_rc = new Avp(helpers::base::AVPID__Result_Code, codecEngine); * // Adding: * msg->addAvp(avp_sid); * msg->addAvp(avp_oh); @@ -142,25 +104,24 @@ class Avp; * * class MyEngine : public EngineImpl { * public: - * Engine (getClassName()) {;} - * static const char* getClassName() throw() { return "::MyEngine"; } + * MyEngine (const char *className = "MyEngine") : Engine(className) {;} * * private: * anna::Recycler a_avps; * anna::Recycler a_messages; * - * anna::diameter::codec::Avp* allocateAvp () throw () { return a_avps.create (); } + * anna::diameter::codec::Avp* allocateAvp () { return a_avps.create (); } * - * void releaseAvp (anna::diameter::codec::Avp* avp) throw () { + * void releaseAvp (anna::diameter::codec::Avp* avp) { * if (avp == NULL) return; * MyAvp* aux = static_cast (avp); * aux->clear(); // free internal data-part storage specially for grouped avps which will release its childrens * a_avps.release (aux); * } * - * anna::diameter::codec::Message* allocateMessage () throw () { return a_messages.create (); } + * anna::diameter::codec::Message* allocateMessage () { return a_messages.create (); } * - * void releaseMessage (anna::diameter::codec::Message* message) throw () { + * void releaseMessage (anna::diameter::codec::Message* message) { * if (message == NULL) return; * MyMessage* aux = static_cast (message); * aux->clear(); // free internal data-part storage specially for childrens releasing @@ -183,7 +144,7 @@ public: * Defines behaviour mode regarding when to validate a message: before encoding, after decoding (by default), always or never * Anyway validation procedure may be called at any moment (#valid) */ - struct ValidationMode { enum _v { BeforeCoding, AfterDecoding /* default */, Always, Never /* optimization */ }; }; + struct ValidationMode { enum _v { BeforeEncoding, AfterDecoding /* default */, Always, Never /* optimization */ }; }; /** * Defines behaviour mode regarding when to fix a message: before encoding (by default), after decoding, always or never. @@ -194,19 +155,19 @@ public: * hide any validation problem regarding Avps position at any level. * Anyway fix procedure may be called at any moment (#fix) */ - struct FixMode { enum _v { BeforeCoding /* default */, AfterDecoding, Always, Never /* optimization */ }; }; + struct FixMode { enum _v { BeforeEncoding /* default */, AfterDecoding, Always, Never /* optimization */ }; }; // Creators - Avp* createAvp(const AvpId *id) throw(anna::RuntimeException); - Message* createMessage(const CommandId *id) throw(anna::RuntimeException); + Avp* createAvp(const AvpId *id) noexcept(false); + Message* createMessage(const CommandId *id) noexcept(false); private: - anna::xml::DTDMemory a_dtd; ValidationDepth::_v a_validationDepth; ValidationMode::_v a_validationMode; + bool a_singleFailedAVP; bool a_ignoreFlags; FixMode::_v a_fixMode; @@ -214,16 +175,22 @@ private: const stack::Dictionary * a_dictionary; // helpers - static const char* asText(const ValidationDepth::_v) throw(); - static const char* asText(const ValidationMode::_v) throw(); - static const char* asText(const FixMode::_v) throw(); + static const char* asText(const ValidationDepth::_v) ; + static const char* asText(const ValidationMode::_v) ; + static const char* asText(const FixMode::_v) ; public: /** Constructor @param className Logical name for the class. + @param dictionary Diameter dictionary. At single threaded processes, the same codec engine could be used with + different diameter dictionaries (multi-stack applications). In that case the process must switch the stack for + the whole decoding or enconding operation over a Message depending on the context (normally the message header + Application-Id is used as stack identifier). But the smart way implies inherit from this engine creating a + component for each diameter stack managed in the application. Inheritance is mandatory in multi-threaded processes: + one engine, a unique stack. */ - EngineImpl(const char* className); + EngineImpl(const char* className, const stack::Dictionary * dictionary); /** * Destructor @@ -231,41 +198,19 @@ public: virtual ~EngineImpl() {;} - /** - Sets diameter dictionary loaded at stack engine. It's recommended to configure a valid dictionary - (if not, or NULL provided at #setDictionary, all avps will be managed as 'Unknown' format and all - items will need to be manually updated, i.e. message and avp flags). - - @param dictionary Diameter dictionary. At single threaded processes, the same codec engine could be used with - different diameter dictionaries (multi-stack applications). In that case the process must switch the stack for - the whole decoding or enconding operation over a Message depending on the context. But the smart way implies - inherit from this engine creating a component for each diameter stack managed in the application. Inheritance - is mandatory in multi-threaded processes: one engine, a unique stack. - */ - void setDictionary(const stack::Dictionary * dictionary) throw() { a_dictionary = dictionary; } - - // get - /** - * Sets diameter dictionary loaded at stack engine with the provided identifier. - * - * @param stackId Stack identifier. When missing, default stack (stack::Engine::getDefaultStack()) will be used - * @return Returns configured dictionary (NULL if stack id was not found) - */ - const stack::Dictionary *setDictionary(int stackId = -1) throw(); - /** Gets currently configured dictionary. NULL if not configured (manual encode/decode operations). @return Returns currently configured engine dictionary */ - const stack::Dictionary *getDictionary() const throw() { return a_dictionary; } + const stack::Dictionary *getDictionary() const { return a_dictionary; } /** * Sets behaviour on validation procedure. * \param validationDepth Behaviour on validation procedure: complete analysis or stop at first validation error over the message. */ - void setValidationDepth(const ValidationDepth::_v validationDepth) throw() { a_validationDepth = validationDepth; } + void setValidationDepth(const ValidationDepth::_v validationDepth) { a_validationDepth = validationDepth; } /** * Returns behaviour on on validation procedure. @@ -275,7 +220,7 @@ public: * * \return Behaviour on validation procedure: complete analysis or stop at first validation error over the message (by default). */ - ValidationDepth::_v getValidationDepth() const throw() { return a_validationDepth; } + ValidationDepth::_v getValidationDepth() const { return a_validationDepth; } /** * Sets behaviour on validation procedure regarding stack flags. Actually, only AVP flags M & P are affected. The vendor bit is @@ -284,7 +229,7 @@ public: * \param ignoreFlags Validation will ignore flags. */ - void ignoreFlagsOnValidation(bool ignoreFlags) throw() { a_ignoreFlags = ignoreFlags; } + void ignoreFlagsOnValidation(bool ignoreFlags) { a_ignoreFlags = ignoreFlags; } /** * Gets behaviour on validation procedure regarding stack flags. Actually, only AVP flags M & P are affected. The vendor bit is @@ -292,13 +237,13 @@ public: * By default (at engine start), flags are verified. * \return Validation ignore flags indicator. */ - bool ignoreFlagsOnValidation() const throw() { return a_ignoreFlags; } + bool ignoreFlagsOnValidation() const { return a_ignoreFlags; } /** * Sets validation mode. * \param validationMode Validation mode: before encoding, after decoding, always or never. */ - void setValidationMode(const ValidationMode::_v validationMode) throw() { a_validationMode = validationMode; } + void setValidationMode(const ValidationMode::_v validationMode) { a_validationMode = validationMode; } /** * Returns validation mode. @@ -306,7 +251,7 @@ public: * during development phase. * \return Validation mode: before encoding, after decoding (by default), always or never. */ - ValidationMode::_v getValidationMode() const throw() { return a_validationMode; } + ValidationMode::_v getValidationMode() const { return a_validationMode; } @@ -314,20 +259,28 @@ public: * Sets fix mode. * \param fixMode Fix mode: before encoding, after decoding, always or never. */ - void setFixMode(const FixMode::_v fixMode) throw() { a_fixMode = fixMode; } + void setFixMode(const FixMode::_v fixMode) { a_fixMode = fixMode; } /** * Returns fix mode. * \return Fix mode: before encoding (by default), after decoding, always or never. */ - FixMode::_v getFixMode() const throw() { return a_fixMode; } - + FixMode::_v getFixMode() const { return a_fixMode; } + /** + * Sets single FailedAVP. True by default. If false, and more than one wrong avp are found during message + * decoding and or validation, a new Failed-AVP will be added to the dynamic answer provided. The standard + * talks about only one but it is open to do this. + * + * \param single Single Failed-AVP boolean. + */ + void setSingleFailedAVP(bool single = true) { a_singleFailedAVP = single; } /** - DTD document for xml message parsing - */ - const anna::xml::DTDMemory & getDTD() const throw() { return a_dtd; } + * Returns single Failed-AVP boolean. + * \return Failed-AVP could be one (true) or more (false) in answer message. + */ + bool getSingleFailedAVP() const { return a_singleFailedAVP; } /** * Creates a new diameter avp assigning its identifier, using engine resources to allocate memory (recommended @@ -339,7 +292,7 @@ public: * * @return Created avp ready to be used */ - Avp* createAvp(AvpId id) throw(anna::RuntimeException) { return createAvp(&id); } + Avp* createAvp(AvpId id) noexcept(false) { return createAvp(&id); } /** * Creates a new diameter avp, using engine resources to allocate memory (recommended recycler allocation at @@ -347,7 +300,7 @@ public: * * @return Created avp ready to be used */ - Avp* createAvp() throw(anna::RuntimeException) { return createAvp(NULL); } + Avp* createAvp() noexcept(false) { return createAvp(NULL); } /** * Creates a new diameter Message assigning its identifier, using engine resources to allocate memory (recommended @@ -359,7 +312,7 @@ public: * * @return Created message ready to be used */ - Message* createMessage(CommandId id) throw(anna::RuntimeException) { return createMessage(&id); } + Message* createMessage(CommandId id) noexcept(false) { return createMessage(&id); } /** * Creates a new diameter message, using engine resources to allocate memory (recommended recycler allocation @@ -367,28 +320,29 @@ public: * * @return Created message ready to be used */ - Message* createMessage() throw(anna::RuntimeException) { return createMessage(NULL); } + Message* createMessage() noexcept(false) { return createMessage(NULL); } /** - Loads an xml file representing a diameter message base in a DTD document (#getDTD) + Loads an xml file/string representing a diameter message base in a DTD document (#getDTD) - @param xmlPathFile Complete path file to the xml document which represents the diameter message + @param xmlPathFile_or_string Complete path file or string representation for the xml document which represents the diameter message + @param pathfile_or_string boolean about the interpretation of the previous argument */ - Message *createMessage(const std::string & xmlPathFile) throw(anna::RuntimeException); + Message *createMessage(const std::string & xmlPathFile_or_string, bool pathfile_or_string = true) noexcept(false); /** Invoked to free Avps. \see anna::Recycler */ - virtual void releaseAvp(Avp*) throw() = 0; + virtual void releaseAvp(Avp*) = 0; /** Invoked to free Messages. \see anna::Recycler */ - virtual void releaseMessage(Message*) throw() = 0; + virtual void releaseMessage(Message*) = 0; /** @@ -396,14 +350,14 @@ public: * * @return String with class content */ - virtual std::string asString(void) const throw(); + virtual std::string asString(void) const ; /** Class XML representation. \param parent XML node over which we will put instance information. \return XML documentcon with class content. */ - virtual anna::xml::Node* asXML(anna::xml::Node* parent) const throw(); + virtual anna::xml::Node* asXML(anna::xml::Node* parent) const ; /** @@ -413,7 +367,7 @@ public: @return Avp identifier as pair (code,vendor-id) */ - AvpId avpIdForName(const char * name) throw(anna::RuntimeException); + AvpId avpIdForName(const char * name) noexcept(false); /** @@ -423,7 +377,7 @@ public: @return Command identifier as pair (code,request-indicator) */ - CommandId commandIdForName(const char * name) throw(anna::RuntimeException); + CommandId commandIdForName(const char * name) noexcept(false); protected: @@ -435,7 +389,7 @@ protected: \see anna::Recycler */ - virtual Avp* allocateAvp() throw() = 0; + virtual Avp* allocateAvp() = 0; /** @@ -445,7 +399,7 @@ protected: \see anna::Recycler */ - virtual Message* allocateMessage() throw() = 0; + virtual Message* allocateMessage() = 0; /** @@ -457,7 +411,7 @@ protected: @see setValidationDepth @see getValidationDepth */ - void validationAnomaly(const std::string & description) const throw(anna::RuntimeException); + void validationAnomaly(const std::string & description) const noexcept(false); }; }