X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;ds=sidebyside;f=include%2Fanna%2Fdiameter%2Fcodec%2FEngineImpl.hpp;h=a73b42a81cefadfb0597a1b4eeae9be491eededd;hb=c56124ff93e8bceec159748dfe5ba8d56c62e3de;hp=e28272426f13c85ad290e6247ec7682d195668a4;hpb=93366a0bda79e6fd6e7dad6316bfcf8cc82f5731;p=anna.git diff --git a/include/anna/diameter/codec/EngineImpl.hpp b/include/anna/diameter/codec/EngineImpl.hpp index e282724..a73b42a 100644 --- a/include/anna/diameter/codec/EngineImpl.hpp +++ b/include/anna/diameter/codec/EngineImpl.hpp @@ -36,8 +36,6 @@ class Dictionary; namespace codec { -extern const char *MessageDTD; - class Message; class Avp; @@ -50,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: @@ -75,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); @@ -88,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); @@ -114,8 +104,7 @@ 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; @@ -176,13 +165,11 @@ public: private: - anna::xml::DTDMemory a_dtd; ValidationDepth::_v a_validationDepth; ValidationMode::_v a_validationMode; + bool a_singleFailedAVP; bool a_ignoreFlags; FixMode::_v a_fixMode; - bool a_selectStackWithApplicationId; // default behaviour: let the user switch the stack (false for this boolean) - // Auxiliary const stack::Dictionary * a_dictionary; @@ -196,8 +183,14 @@ 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 @@ -205,54 +198,6 @@ public: virtual ~EngineImpl() {;} - // setters - /** - 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 (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. - */ - void setDictionary(const stack::Dictionary * dictionary) throw() { a_dictionary = dictionary; } - - /** - * Sets diameter dictionary loaded at stack engine with the provided identifier. - * - * @param stackId Stack identifier. When missing, NULL will be returned - * @return Returns configured dictionary (NULL if stack id was not found) - */ - const stack::Dictionary *setDictionary(unsigned int stackId) throw(); - - - /** - * By default, the user will select the appropiate stack id depending on the context (see #setDictionary), but - * some applications could consider interesting automatic stack selection based on managed messages (incoming - * decoded ones, or built messages to be encoded). By default, on engine construction, no changes are done. - * Multithreaded processes should have a unique codec engine for each managed stack (then you don't have to - * worry about), but mono processes with multistack implementation over the same-unique engine, should activate - * this to have the commonly recommended way to choose the stack: using the Application-Id value. - * - * @warning do not activate in case of multithreaded applications. - * @param enable Activates/deactivates the stack selection from the Application-Id value within the message header. - */ - void selectStackWithApplicationId (bool enable) throw() { a_selectStackWithApplicationId = enable; } - - // getters - - /** - Gets the currently configured behaviour regarding stack selection for multistack codec engines in mono thread - applications. - - @return True if selection is done with the Application-Id. False if no selection is performed (user responsibility). - */ - bool hasSelectStackWithApplicationId (void) throw() { return a_selectStackWithApplicationId; } - - /** Gets currently configured dictionary. NULL if not configured (manual encode/decode operations). @@ -322,12 +267,20 @@ public: */ FixMode::_v getFixMode() const throw() { 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) throw() { 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 throw() { return a_singleFailedAVP; } /** * Creates a new diameter avp assigning its identifier, using engine resources to allocate memory (recommended @@ -371,11 +324,12 @@ public: /** - 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) throw(anna::RuntimeException); /**