X-Git-Url: https://git.teslayout.com/public/public/public/?p=anna.git;a=blobdiff_plain;f=include%2Fanna%2Fdiameter%2Fcodec%2FAvp.hpp;h=2454d4d48c1b3bed4f7236dab9a2ee61c5078cc3;hp=cd6c1008c97f676f403632575cd8c89cd2b4f183;hb=415985b3f67878c2e3cee785a0b1cb36f4eff901;hpb=4e12ac57e93c052f716a6305ad8fc099c45899d1 diff --git a/include/anna/diameter/codec/Avp.hpp b/include/anna/diameter/codec/Avp.hpp index cd6c100..2454d4d 100644 --- a/include/anna/diameter/codec/Avp.hpp +++ b/include/anna/diameter/codec/Avp.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_Avp_hpp @@ -42,8 +14,8 @@ #include #include #include +#include #include -#include #include @@ -70,17 +42,6 @@ namespace anna { namespace diameter { -namespace helpers { -namespace tme { -namespace codectypes { -class Unsigned16; -class ISDNNumber; -class ISDNAddress; -} -} -} - - namespace stack { class Dictionary; class Format; @@ -124,7 +85,6 @@ typedef std::map::iterator find_iterator; using namespace basetypes; -using namespace helpers::tme::codectypes; /** * Diameter avp generic container @@ -201,14 +161,6 @@ class Avp { QoSFilterRule *a_QoSFilterRule; Unknown *a_Unknown; - // Derived formats //////////////////////////////////////////// - /* TME */ - ISDNNumber *a_ISDNNumber; - ISDNAddress *a_ISDNAddress; - Unsigned16 *a_Unsigned16; - - - // Grouped helpers find_container a_finds; // fast access for grouped and message first-level avps @@ -226,7 +178,7 @@ class Avp { static Avp * addAvp(avp_container &avps, int &insertionPositionForChilds, AvpId id, Engine *engine) throw(); static bool removeAvp(avp_container &avps, find_container &finds, AvpId id, int ocurrence, Engine *engine) throw(); static void fix(avp_container &avps, find_container &finds, int &insertionPositionForChilds, anna::diameter::stack::const_avprule_iterator ruleBegin, anna::diameter::stack::const_avprule_iterator ruleEnd) throw(); - static bool validLevel(const avp_container &avps, anna::diameter::stack::const_avprule_iterator ruleBegin, anna::diameter::stack::const_avprule_iterator ruleEnd, Engine * engine, const std::string & parentDescription, Message *answer) throw(anna::RuntimeException); // validates mandatory/fixed and cardinality + static bool validLevel(const avp_container &avps, anna::diameter::stack::const_avprule_iterator ruleBegin, anna::diameter::stack::const_avprule_iterator ruleEnd, Engine * engine, const anna::diameter::codec::parent_t & parent, Message *answer) throw(anna::RuntimeException); // validates mandatory/fixed and cardinality static const Avp* getAvp(const avp_container &avps, find_container &finds, AvpId id, int ocurrence, Engine *engine, anna::Exception::Mode::_v emode) throw(anna::RuntimeException); static int countAvp(const avp_container &avps, AvpId id) throw(); static const Avp* firstAvp(const avp_container &avps, AvpId id) throw(); @@ -250,7 +202,6 @@ class Avp { static const Avp* avp(const_avp_iterator ii) throw() { return ii->second; } // Internal - void assertFormat(const std::string &name) const throw(anna::RuntimeException); bool flagsOK() const throw(); // flags coherence regarding dictionary. Only must be called when AVP is identified at the dictionary. int addChild(Avp *avp) throw(anna::RuntimeException) { assertFormat("Grouped"); return addChild(a_avps, a_insertionPositionForChilds, avp); } bool hasChildren() throw() { return a_avps.size() != 0; } @@ -269,12 +220,12 @@ class Avp { /** Validates an Avp regarding dictionary rules like enumerated range, flags coherence, mandatory and fixed types, cardinality qualifiers, etc. - @param parentDescription Parent description. Internally used for alarms and tracing + @param parent Parent description. Internally used for alarms, tracing and Failed-AVP construction @param answer Answer could be modified with any validation problem during requests validation @return Boolean indicating validation result */ - bool valid(const std::string & parentDescription, Message *answer) const throw(anna::RuntimeException); + bool valid(const anna::diameter::codec::parent_t & parent, Message *answer) const throw(anna::RuntimeException); /** Decodes buffer provided over class content. If an error ocurred, decoding will stop launching exception (fatal error) or a warning trace (perhaps the achieved @@ -282,9 +233,10 @@ class Avp { depending on validation depth (codec::Engine::ValidationDepth). @param db Buffer data block processed + @param parent Parent description. Internally used for alarms, tracing and Failed-AVP construction @param answer Answer built for request decoding/validation */ - void decode(const anna::DataBlock &db, Message *answer) throw(anna::RuntimeException); + void decode(const anna::DataBlock &db, const anna::diameter::codec::parent_t & parent, Message *answer) throw(anna::RuntimeException); ///////////////////////////////////////////// @@ -293,80 +245,80 @@ class Avp { /** * Initializes Avp class information. - * Default implementation supports all anna::diameter formats (including i.e. tme.db ones). + * Default implementation supports all anna::diameter formats (including derived ones). * Diameter basic formats are managed at #initialize, which will invoke this method at the end. */ - virtual void initializeByFormat() throw(); + virtual void initializeByFormat() throw() {}; /** * Gets avp data-part length. - * Default implementation supports all anna::diameter formats (including i.e. tme.db ones). + * Default implementation supports all anna::diameter formats (including derived ones). * Diameter basic formats are managed at #initialize, which will invoke this method at the end. * * @param stackFormat Stack avp format in which data extraction is based. * * @return Avp data-part size. */ - virtual U24 getLengthByFormat(const anna::diameter::stack::Format *stackFormat) const throw(); + virtual U24 getLengthByFormat(const anna::diameter::stack::Format *stackFormat) const throw() { return 0; }; /** Gets data or hexadecimal data depending on avp format, for xml creating - Default implementation supports all anna::diameter formats (including i.e. tme.db ones). + Default implementation supports all anna::diameter formats (including derived ones). Diameter basic formats are managed at #initialize, which will invoke this method at the end. \param isHex Hexadecimal/Natural data when apply. \param stackFormat Stack avp format in which data extraction is based. \return xml data representation */ - virtual std::string getXMLdataByFormat(bool & isHex, const anna::diameter::stack::Format *stackFormat) const throw(); + virtual std::string getXMLdataByFormat(bool & isHex, const anna::diameter::stack::Format *stackFormat) const throw() { return ""; }; /** Interpret xml data in order to dump over the class content. - Default implementation supports all anna::diameter formats (including i.e. tme.db ones). + Default implementation supports all anna::diameter formats (including derived ones). Diameter basic formats are managed at #initialize, which will invoke this method at the end. \param data Avp data attribute \param hexData Avp hex-data attribute \param stackFormat Stack avp format in which data extraction is based. */ - virtual void fromXMLByFormat(const anna::xml::Attribute* data, const anna::xml::Attribute* hexData, const anna::diameter::stack::Format *stackFormat) throw(anna::RuntimeException); + virtual void fromXMLByFormat(const anna::xml::Attribute* data, const anna::xml::Attribute* hexData, const anna::diameter::stack::Format *stackFormat) throw(anna::RuntimeException) {}; /** Encodes buffer with the class content. - Default implementation supports all anna::diameter formats (including i.e. tme.db ones). + Default implementation supports all anna::diameter formats (including derived ones). Diameter basic formats are managed at #initialize, which will invoke this method at the end. @param dataPart Data-part begin pointer @param stackFormat Stack avp format in which data extraction is based. */ - virtual void codeByFormat(char* dataPart, const anna::diameter::stack::Format *stackFormat) const throw(anna::RuntimeException); + virtual void codeByFormat(char* dataPart, const anna::diameter::stack::Format *stackFormat) const throw(anna::RuntimeException) {}; /** Decodes Avp data part. - Default implementation supports all anna::diameter formats (including i.e. tme.db ones). + Default implementation supports all anna::diameter formats (including derived ones). Diameter basic formats are managed at #initialize, which will invoke this method at the end. @param buffer Avp data part start pointer @param size Avp data part size @param stackFormat Stack avp format in which data extraction is based. */ - virtual void decodeDataPartByFormat(const char * buffer, int size, const anna::diameter::stack::Format *stackFormat) throw(anna::RuntimeException); + virtual void decodeDataPartByFormat(const char * buffer, int size, const anna::diameter::stack::Format *stackFormat) throw(anna::RuntimeException) {}; /** Reserves memory for data part depending on avp format for the identifier provided. - Default implementation supports all anna::diameter formats (including i.e. tme.db ones). + Default implementation supports all anna::diameter formats (including derived ones). Diameter basic formats are managed at #initialize, which will invoke this method at the end. @param stackFormat Stack avp format in which data extraction is based. */ - virtual void allocationByFormat(const anna::diameter::stack::Format *stackFormat) throw(); + virtual void allocationByFormat(const anna::diameter::stack::Format *stackFormat) throw() {}; /** * Clears Avp data-part format containers. */ - virtual void clearByFormat() throw(); + virtual void clearByFormat() throw() {}; @@ -383,6 +335,10 @@ protected: */ void initialize() throw(); + /** + * Assert format regarding dictionary + */ + void assertFormat(const std::string &name) const throw(anna::RuntimeException); /** * Gets avp total length based on internal data part and header configuration. @@ -401,45 +357,51 @@ protected: */ std::string getXMLdata(bool & isHex, const anna::diameter::stack::Format *stackFormat) const throw(); - /** - Interpret xml data in order to dump over the class content. - - \param avpNode Avp root node - */ - void fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException); - - - /** - Encodes buffer with the class content. - - * @param buffer Raw data to be encoded - * @param size Size of raw data to be encoded - */ - void code(char* buffer, int &size) const throw(anna::RuntimeException); - /** Decodes Avp data part. @param buffer Avp data part start pointer @param size Avp data part size + @param parent Parent description. Internally used for alarms, tracing and Failed-AVP construction @param answer Answer built for request decoding/validation */ - void decodeDataPart(const char * buffer, int size, Message *answer) throw(anna::RuntimeException); + void decodeDataPart(const char * buffer, int size, const anna::diameter::codec::parent_t & parent, Message *answer) throw(anna::RuntimeException); public: /** * Default constructor + * @param engine Codec engine used */ - Avp(); + Avp(Engine *engine = NULL); /** * Identified constructor * @param id Avp identifier as pair (code,vendor-id). + * @param engine Codec engine used */ - Avp(AvpId id); + Avp(AvpId id, Engine *engine = NULL); + + + /** + * Sets the codec engine + * + * Once assigned (here or at constructor), this method SHALL NOT be used anymore. + * Also, the associated dictionary SHOULD NOT BE CHANGED through the engine, + * unless you know what are you doing. If you want to reconfigure the engine, + * first #clear the avp and then you could reuse the same object with + * different configurations (execution contexts). + * + * Setting a new different engine with different stack, even same engine where the + * stack has been dynamically changed, could cause a bad behaviour depending on the + * changes: in general, if the dictionary grows, nothing bad will happen, but if + * you remove or modified some elements which were processed with a certain format, + * will be interpreted as 'unknown' with the new dictionary, and then some problems + * may occur. If you add elements (vendors, avps, messages) is not a problem. + */ + void setEngine(Engine *engine) throw(); // Length references @@ -463,7 +425,7 @@ public: /** * Destructor */ - ~Avp(); + virtual ~Avp(); // setters @@ -515,7 +477,7 @@ public: /** Adds an avp child providing its identifier and reserve internal memory it. - An exception is launched is the Avp is not a grouped avp. + An exception is launched is the Avp over which we add the new avp, is not a grouped avp. @param id Avp identifier as pair (code,vendor-id). @@ -529,16 +491,19 @@ public: */ Avp * addAvp(const char *name) throw(anna::RuntimeException); - /** Adds an avp child providing a persistent pointer (must be maintained by application). - An exception is launched is the Avp is not a grouped avp. + An exception is launched is the Avp over which we add the new avp, is not a grouped avp. + It is not allowed to add an avp with no codec engine configured, neither if the engine + is not the same. @param avp Avp external pointer. If NULL provided, nothing is done and NULL returned. + Also NULL returned for bad engine configuration. @return Pointer to the added avp (again). */ - Avp * addAvp(Avp * avp) throw(anna::RuntimeException) { if(!avp) return NULL; addChild(avp); return avp; } + Avp * addAvp(Avp * avp) throw(anna::RuntimeException); + // Data part access /** Access content for OctetString Avp in order to set data part */ @@ -574,15 +539,6 @@ public: /** Access content for Unknown Avp in order to set data part */ Unknown * getUnknown() throw(anna::RuntimeException) { assertFormat("Unknown"); return a_Unknown; } - // Derived formats //////////////////////////////////////////// - /* TME */ - /** Access content for ISDNNumber Avp in order to set data part */ - ISDNNumber * getISDNNumber() throw(anna::RuntimeException) { assertFormat("ISDNNumber"); return a_ISDNNumber; } - /** Access content for ISDNAddress Avp in order to set data part */ - ISDNAddress * getISDNAddress() throw(anna::RuntimeException) { assertFormat("ISDNAddress"); return a_ISDNAddress; } - /** Access content for Unsigned16 Avp in order to set data part */ - Unsigned16 * getUnsigned16() throw(anna::RuntimeException) { assertFormat("Unsigned16"); return a_Unsigned16; } - /** Removes an Avp within grouped type (first level) and free resources. @@ -714,14 +670,35 @@ public: const Unknown * getUnknown() const throw(anna::RuntimeException) { assertFormat("Unknown"); return a_Unknown; } - // Derived formats //////////////////////////////////////////// - /* TME */ - /** Access content for ISDNNumber Avp */ - const ISDNNumber * getISDNNumber() const throw(anna::RuntimeException) { assertFormat("ISDNNumber"); return a_ISDNNumber; } - /** Access content for ISDNAddress Avp */ - const ISDNAddress * getISDNAddress() const throw(anna::RuntimeException) { assertFormat("ISDNAddress"); return a_ISDNAddress; } - /** Access content for Unsigned16 Avp */ - const Unsigned16 * getUnsigned16() const throw(anna::RuntimeException) { assertFormat("Unsigned16"); return a_Unsigned16; } + /** + Decodes buffer provided over class content. If an error ocurred, decoding will stop launching exception (fatal error) or a warning trace (perhaps the achieved + avp is valid against all odds then validation will go on). In case that validation is enabled (codec::Engine::ValidationMode) an exception will be launched + depending on validation depth (codec::Engine::ValidationDepth). + + Useful as serialization procedure with #code + + @param db Buffer data block processed + */ + void decode(const anna::DataBlock &db) throw(anna::RuntimeException); + + + /** + Interpret xml data in order to dump over the class content. + + \param avpNode Avp root node + */ + void fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException); + + + /** + Encodes buffer with the class content. This method is internally used to encode diameter messages, but is declared as public, to allow + its use as serialization procedure. Then, it's assumed that this Avp is valid (validation shall be applied as part of a whole diameter + message but nothing will be verified now). + + * @param buffer Raw data to be encoded (shall be externally allocated) + * @param size Size of raw data to be encoded + */ + void code(char* buffer, int &size) const throw(anna::RuntimeException); // Helpers @@ -735,9 +712,32 @@ public: /** Class xml string representation + @param normalize Optional normalization which sorts attribute names and removes + newlines in the xml representation in order to ease regexp matching. + \return XML string representation with relevant information for this instance. */ - std::string asXMLString() const throw(); + std::string asXMLString(bool normalize = false) const throw(); + + /** + Comparison operator by mean serialization + + @param a1 Instance 1 for Avp class + @param a2 Instance 2 for Avp class + + @return Comparison result + */ + friend bool operator == (const Avp & a1, const Avp & a2) throw() { return (a1.asXMLString() == a2.asXMLString()); } + + /** + Match a regular expression (string pattern) regarding xml string serialization for this avp. + This works same as #Message::isLike + + @param pattern Pattern to match + + \return Returns the match result + */ + bool isLike(const std::string &pattern) const throw(); /** Counts the number of ocurrences of Avps (first level) with the identifier provided @@ -764,12 +764,10 @@ public: Diameter Relay and redirect agents MUST NOT reject messages with unrecognized AVPs. Default implementation launch alarm and counter indicating the anomaly but don't launch exception (traces at warning level). - Realy and Redirect agents could reimplement this method to avoid oam management (another way is avoid alarm/counter registration on + Relay and Redirect agents could reimplement this method to avoid oam management (another way is avoid alarm/counter registration on these applications). Result-Code DIAMETER_AVP_UNSUPPORTED will be stored for possible answer message. - - @param answer Answer built for request decoding/validation */ - virtual void unknownAvpWithMandatoryBit(Message *answer) const throw(anna::RuntimeException); + virtual void unknownAvpWithMandatoryBit() const throw(anna::RuntimeException); friend class Message;