X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=source%2Fdiameter%2Fcodec%2FMessage.cpp;h=a049e1b7064504c23459a9a1f6a9697563c4f162;hb=5a6cba5fde2b2f538a7515f8293cc0a8d9589dfa;hp=5f21bb2cf6376a7d603d517a4d979e4373d271ee;hpb=93366a0bda79e6fd6e7dad6316bfcf8cc82f5731;p=anna.git diff --git a/source/diameter/codec/Message.cpp b/source/diameter/codec/Message.cpp index 5f21bb2..a049e1b 100644 --- a/source/diameter/codec/Message.cpp +++ b/source/diameter/codec/Message.cpp @@ -16,6 +16,7 @@ #include // REQUIRED_WORDS #include #include +#include #include #include #include @@ -56,7 +57,7 @@ const U8 Message::TBitMask(0x10); //------------------------------------------------------------------------------ //----------------------------------------------------------- Message::Message() //------------------------------------------------------------------------------ -Message::Message() : a_forCode(true) { +Message::Message(Engine *engine) : a_engine(engine), a_forCode(true) { initialize(); } @@ -64,7 +65,7 @@ Message::Message() : a_forCode(true) { //------------------------------------------------------------------------------ //----------------------------------------------------------- Message::Message() //------------------------------------------------------------------------------ -Message::Message(CommandId id) : a_forCode(true) { +Message::Message(CommandId id, Engine *engine) : a_engine(engine), a_forCode(true) { initialize(); setId(id); } @@ -78,19 +79,41 @@ Message::~Message() { } +//------------------------------------------------------------------------------ +//--------------------------------------------------------- Message::setEngine() +//------------------------------------------------------------------------------ +void Message::setEngine(Engine *engine) { + + if (!engine) { + LOGWARNING(anna::Logger::warning("Ignored: you must assign a valid codec engine. If you want to set NULL engine, clear the message", ANNA_FILE_LOCATION)); + return; + } + + if (a_engine && (engine != a_engine)) { + LOGWARNING(anna::Logger::warning("Ignored: it is not a good practice to change the codec engine once assigned. Clear the message first to set the engine again.", ANNA_FILE_LOCATION)); + return; + } + + a_engine = engine; +} + + //------------------------------------------------------------------------------ //--------------------------------------------------------- Message::getEngine() //------------------------------------------------------------------------------ -Engine * Message::getEngine() const throw(anna::RuntimeException) { - return a_engine ? a_engine : (a_engine = anna::functions::component (ANNA_FILE_LOCATION)); +Engine * Message::getEngine() const noexcept(false) { + if(!a_engine) + throw anna::RuntimeException("Invalid codec engine reference (NULL). Use setEngine() to set the corresponding codec engine", ANNA_FILE_LOCATION); + + return a_engine; + } //------------------------------------------------------------------------------ //-------------------------------------------------------- Message::initialize() //------------------------------------------------------------------------------ -void Message::initialize() throw() { - a_engine = NULL; +void Message::initialize() { a_version = 1; a_id = CommandId(0, false); a_flags = 0x00; @@ -106,7 +129,7 @@ void Message::initialize() throw() { //------------------------------------------------------------------------------ //------------------------------------------------------------- Message::clear() //------------------------------------------------------------------------------ -void Message::clear() throw(anna::RuntimeException) { +void Message::clear(bool resetEngine) noexcept(false) { for(avp_iterator it = avp_begin(); it != avp_end(); it++) { /*avp(it)->clear(); */getEngine()->releaseAvp(Avp::avp(it)); } a_avps.clear(); @@ -115,18 +138,21 @@ void Message::clear() throw(anna::RuntimeException) { a_finds.clear(); // Initialize: initialize(); + if (resetEngine) a_engine = NULL; } //------------------------------------------------------------------------------ //----------------------------------------------------------- Message::flagsOK() //------------------------------------------------------------------------------ -bool Message::flagsOK(int &rc) const throw() { +bool Message::flagsOK(int &rc) const { // Dictionary stack command: const stack::Command *stackCommand = getStackCommand(); if(!stackCommand) { - anna::Logger::error("Impossible to decide if flags are correct because stack command is not identified. Assume flags ok", ANNA_FILE_LOCATION); + std::string msg = "Impossible to decide if flags are correct because stack command is not identified. Assume flags ok for Message "; + msg += anna::diameter::functions::commandIdAsPairString(a_id); + anna::Logger::error(msg, ANNA_FILE_LOCATION); //rc = helpers::base::AVPVALUES__Result_Code::?????; return true; }; @@ -141,12 +167,16 @@ bool Message::flagsOK(int &rc) const throw() { if(stackCommand->isRequest() != isRequest()) ok = false; // en teoria es imposible salir por aqui: blindado en la dtd if(isRequest() && errorBit()) { - anna::Logger::error("E(rror) bit is not allowed at diameter requests", ANNA_FILE_LOCATION); + std::string msg = "E(rror) bit is not allowed at diameter requests as "; + msg += stackCommand->getName(); + anna::Logger::error(msg, ANNA_FILE_LOCATION); ok = false; } if(isAnswer() && potentiallyReTransmittedMessageBit()) { - anna::Logger::error("T(Potentially re-transmitted message) bit is not allowed at diameter answers", ANNA_FILE_LOCATION); + std::string msg = "T(Potentially re-transmitted message) bit is not allowed at diameter answers as "; + msg += stackCommand->getName(); + anna::Logger::error(msg, ANNA_FILE_LOCATION); ok = false; } @@ -161,7 +191,9 @@ bool Message::flagsOK(int &rc) const throw() { // is set to one (1) or the bits in the Diameter header are set // incorrectly. if((a_flags & 0x0f) != 0x00) { - anna::Logger::error("Any (or more than one) of the reserved message flags bit has been activated. Reserved bits must be null", ANNA_FILE_LOCATION); + std::string msg = "Any (or more than one) of the reserved message flags bit has been activated. Reserved bits must be null. Message is "; + msg += stackCommand->getName(); + anna::Logger::error(msg, ANNA_FILE_LOCATION); rc = helpers::base::AVPVALUES__Result_Code::DIAMETER_INVALID_BIT_IN_HEADER; return false; } @@ -173,9 +205,7 @@ bool Message::flagsOK(int &rc) const throw() { //------------------------------------------------------------------------------ //------------------------------------------------------------- Message::setId() //------------------------------------------------------------------------------ -void Message::setId(CommandId id, bool _clear) throw(anna::RuntimeException) { - // Clear class content: - if(_clear) clear(); +void Message::setId(CommandId id) noexcept(false) { // Id assignment: a_id = id; @@ -194,7 +224,7 @@ void Message::setId(CommandId id, bool _clear) throw(anna::RuntimeException) { //------------------------------------------------------------------------------ //------------------------------------------------------------- Message::setId() //------------------------------------------------------------------------------ -void Message::setId(const char *name) throw(anna::RuntimeException) { +void Message::setId(const char *name) noexcept(false) { setId(getEngine()->commandIdForName(name)); } @@ -202,29 +232,47 @@ void Message::setId(const char *name) throw(anna::RuntimeException) { //------------------------------------------------------------------------------ //-------------------------------------------------- Message::setApplicationId() //------------------------------------------------------------------------------ -void Message::setApplicationId(U32 aid) throw() { +void Message::setApplicationId(U32 aid) noexcept(false) { a_applicationId = aid; - // Default behaviour: - if (!getEngine()->hasSelectStackWithApplicationId()) return; - - // Adapts for Application-ID stack identifier: - getEngine()->setDictionary(aid); + // Automatic engine configuration: + if (a_engine) return; + + // Codec engine manager (a multithreaded application, normally does not achieve this point, because + // messages are prepared for each interface with the corresponding codec engine) + anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate(); + if (em.size() == 0) return; + if (em.selectFromApplicationId()) { + Engine *monostackEngine = em.getMonoStackCodecEngine(); + if (monostackEngine) { a_engine = monostackEngine; return; } + a_engine = em.getCodecEngine(aid); + } } //------------------------------------------------------------------------------ //------------------------------------------------------------ Message::addAvp() //------------------------------------------------------------------------------ -Avp * Message::addAvp(const char *name) throw(anna::RuntimeException) { +Avp * Message::addAvp(const char *name) noexcept(false) { return addAvp(getEngine()->avpIdForName(name)); } +//------------------------------------------------------------------------------ +//------------------------------------------------------------ Message::addAvp() +//------------------------------------------------------------------------------ +Avp * Message::addAvp(Avp * avp) { + if(!avp) return NULL; + if (avp->getEngine() != getEngine()) return NULL; + addChild(avp); + return avp; +} + + //------------------------------------------------------------------------------ //--------------------------------------------------------- Message::removeAvp() //------------------------------------------------------------------------------ -bool Message::removeAvp(const char *name, int ocurrence) throw(anna::RuntimeException) { +bool Message::removeAvp(const char *name, int ocurrence) noexcept(false) { return removeAvp(getEngine()->avpIdForName(name), ocurrence); } @@ -232,7 +280,7 @@ bool Message::removeAvp(const char *name, int ocurrence) throw(anna::RuntimeExce //------------------------------------------------------------------------------ //----------------------------------------------------------- Message::_getAvp() //------------------------------------------------------------------------------ -const Avp * Message::_getAvp(const char *name, int ocurrence, anna::Exception::Mode::_v emode) const throw(anna::RuntimeException) { +const Avp * Message::_getAvp(const char *name, int ocurrence, anna::Exception::Mode::_v emode) const noexcept(false) { return getAvp(getEngine()->avpIdForName(name), ocurrence, emode); } @@ -240,7 +288,7 @@ const Avp * Message::_getAvp(const char *name, int ocurrence, anna::Exception::M //------------------------------------------------------------------------------ //---------------------------------------------------------- Message::countAvp() //------------------------------------------------------------------------------ -int Message::countAvp(const char *name) const throw(anna::RuntimeException) { +int Message::countAvp(const char *name) const noexcept(false) { return countAvp(getEngine()->avpIdForName(name)); } @@ -248,7 +296,7 @@ int Message::countAvp(const char *name) const throw(anna::RuntimeException) { //------------------------------------------------------------------------------ //--------------------------------------------------------- Message::getLength() //------------------------------------------------------------------------------ -U24 Message::getLength() const throw() { +U24 Message::getLength() const { U24 result; // Header length: result = HeaderLength; @@ -262,15 +310,15 @@ U24 Message::getLength() const throw() { //------------------------------------------------------------------------------ //------------------------------------------------------------ Message::decode() //------------------------------------------------------------------------------ -void Message::decode(const anna::DataBlock &db, Message *ptrAnswer) throw(anna::RuntimeException) { +void Message::decode(const anna::DataBlock &db, Message *ptrAnswer) noexcept(false) { // Trace LOGDEBUG( - anna::xml::Node root("Message::decode"); - std::string trace = "DataBlock to decode:\n"; - trace += db.asString(); - anna::Logger::debug(trace, ANNA_FILE_LOCATION); + anna::xml::Node root("Message::decode"); + std::string trace = "DataBlock to decode:\n"; + trace += db.asString(); + anna::Logger::debug(trace, ANNA_FILE_LOCATION); ); - clear(); + clear(false /* respect engine */); // EXCEPTION MANAGEMENT IN THIS METHOD // =================================== // DECODE PHASE @@ -363,14 +411,14 @@ void Message::decode(const anna::DataBlock &db, Message *ptrAnswer) throw(anna:: while(avpPos < dataBytes) { try { - avp = getEngine()->allocateAvp(); + avp = getEngine()->createAvp(NULL); db_aux.assign(startData + avpPos, dataBytes - avpPos /* is valid to pass total length (indeed i don't know the real avp length) because it will be limited and this has deep copy disabled (no memory is reserved) */); avp -> decode(db_aux, parent, answer); } catch(anna::RuntimeException &ex) { getEngine()->releaseAvp(avp); LOGWARNING( - anna::Logger::warning(ex.getText(), ANNA_FILE_LOCATION); - anna::Logger::warning("Although a decoding error was found, validation could be checked because message could be enough for the application", ANNA_FILE_LOCATION); + anna::Logger::warning(ex.getText(), ANNA_FILE_LOCATION); + anna::Logger::warning("Although a decoding error was found, validation could be checked because message could be enough for the application", ANNA_FILE_LOCATION); ); break; } @@ -386,9 +434,9 @@ void Message::decode(const anna::DataBlock &db, Message *ptrAnswer) throw(anna:: // Trace LOGDEBUG( - std::string trace = "Message decoded:\n"; - trace += asXMLString(); - anna::Logger::debug(trace, ANNA_FILE_LOCATION); + std::string trace = "Message decoded:\n"; + trace += asXMLString(); + anna::Logger::debug(trace, ANNA_FILE_LOCATION); ); // Post-Validation Engine::ValidationMode::_v vmode = getEngine()->getValidationMode(); @@ -402,7 +450,7 @@ void Message::decode(const anna::DataBlock &db, Message *ptrAnswer) throw(anna:: //------------------------------------------------------------------------------ //--------------------------------------------------- Message::getStackCommand() //------------------------------------------------------------------------------ -const anna::diameter::stack::Command *Message::getStackCommand(CommandId id) const throw(anna::RuntimeException) { +const anna::diameter::stack::Command *Message::getStackCommand(CommandId id) const noexcept(false) { const stack::Dictionary * dictionary = getEngine()->getDictionary(); return (dictionary ? (dictionary->getCommand(id)) : NULL); } @@ -411,7 +459,7 @@ const anna::diameter::stack::Command *Message::getStackCommand(CommandId id) con //------------------------------------------------------------------------------ //----------------------------------------------------- Message::setResultCode() //------------------------------------------------------------------------------ -void Message::setResultCode(int rc) throw(anna::RuntimeException) { +void Message::setResultCode(int rc) noexcept(false) { if(isRequest()) return; // Add Result-Code if not yet added. Even if validation depth is set to 'Complete', @@ -431,7 +479,7 @@ void Message::setResultCode(int rc) throw(anna::RuntimeException) { //------------------------------------------------------------------------------ //----------------------------------------------------- Message::getResultCode() //------------------------------------------------------------------------------ -int Message::getResultCode() const throw() { +int Message::getResultCode() const { if(isAnswer()) { const Avp *resultCodeAvp = getAvp(helpers::base::AVPID__Result_Code, 1, anna::Exception::Mode::Ignore); @@ -446,33 +494,35 @@ int Message::getResultCode() const throw() { //------------------------------------------------------------------------------ //------------------------------------------------------ Message::setFailedAvp() //------------------------------------------------------------------------------ -void Message::setFailedAvp(const parent_t &parent, AvpId wrong, const char *wrongName) throw(anna::RuntimeException) { +void Message::setFailedAvp(const parent_t &parent, AvpId wrong, const char *wrongName) noexcept(false) { if(isRequest()) return; -// RFC 6733: -// -// 7.5. Failed-AVP AVP -// -// The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides -// debugging information in cases where a request is rejected or not -// fully processed due to erroneous information in a specific AVP. The -// value of the Result-Code AVP will provide information on the reason -// for the Failed-AVP AVP. A Diameter answer message SHOULD contain an -// instance of the Failed-AVP AVP that corresponds to the error -// indicated by the Result-Code AVP. For practical purposes, this -// Failed-AVP would typically refer to the first AVP processing error -// that a Diameter node encounters. + // RFC 6733: + // + // 7.5. Failed-AVP AVP + // + // The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides + // debugging information in cases where a request is rejected or not + // fully processed due to erroneous information in a specific AVP. The + // value of the Result-Code AVP will provide information on the reason + // for the Failed-AVP AVP. A Diameter answer message SHOULD contain an + // instance of the Failed-AVP AVP that corresponds to the error + // indicated by the Result-Code AVP. For practical purposes, this + // Failed-AVP would typically refer to the first AVP processing error + // that a Diameter node encounters. // Although the Failed-AVP definition has cardinality 1* and Failed-AVP itself is defined in // most of the command codes as *[Failed-AVP], i think this is not a deliberate ambiguity. // Probably the RFC wants to give freedom to the application layer, but it is recommended to // have only one child (wrong avp) inside a unique message Failed-AVP to ease the Result-Code - // correspondence. Anyway, this behaviour could be easily opened commenting condition block (*). + // correspondence. Anyway, this behaviour could be easily opened by mean 'setSingleFailedAVP(false)' Avp *theFailedAvp = getAvp(helpers::base::AVPID__Failed_AVP, 1, anna::Exception::Mode::Ignore); if (theFailedAvp) { - LOGDEBUG(anna::Logger::debug("Failed-AVP has already been added. RFC 6733 Section 7.5 recommends to store only the first error found", ANNA_FILE_LOCATION)); - return; + if (getEngine()->getSingleFailedAVP()) { + LOGDEBUG(anna::Logger::debug("Failed-AVP has already been added. RFC 6733 Section 7.5 recommends to store only the first error found", ANNA_FILE_LOCATION)); + return; + } } // Section 7.5 RFC 6733: A Diameter message SHOULD contain one Failed-AVP AVP @@ -480,17 +530,17 @@ void Message::setFailedAvp(const parent_t &parent, AvpId wrong, const char *wron Avp *leaf = theFailedAvp; LOGDEBUG( - std::string msg = "Adding to Failed-AVP, the wrong avp "; - msg += wrongName ? wrongName : (anna::diameter::functions::avpIdAsPairString(wrong)); - msg += " found inside "; - msg += parent.asString(); + std::string msg = "Adding to Failed-AVP, the wrong avp "; + msg += wrongName ? wrongName : (anna::diameter::functions::avpIdAsPairString(wrong)); + msg += " found inside "; + msg += parent.asString(); - anna::Logger::debug(msg, ANNA_FILE_LOCATION); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); std::vector::const_iterator it; for(it = parent.AvpsId.begin(); it != parent.AvpsId.end(); it++) - leaf = leaf->addAvp(*it); + leaf = leaf->addAvp(*it); leaf->addAvp(wrong); } @@ -499,7 +549,7 @@ void Message::setFailedAvp(const parent_t &parent, AvpId wrong, const char *wron //------------------------------------------------------------------------------ //----------------------------------------------- Message::setStandardToAnswer() //------------------------------------------------------------------------------ -void Message::setStandardToAnswer(const Message &request, const std::string &originHost, const std::string &originRealm, int resultCode) throw() { +void Message::setStandardToAnswer(const Message &request, const std::string &originHost, const std::string &originRealm, int resultCode) noexcept(false) { if(!request.getId().second) return; // Message header: @@ -507,8 +557,10 @@ void Message::setStandardToAnswer(const Message &request, const std::string &ori // Session-Id if exists: const Avp *reqSessionId = request.getAvp(helpers::base::AVPID__Session_Id, 1, anna::Exception::Mode::Ignore); + LOGDEBUG(anna::Logger::debug("Check answer message AVPs Session-Id, Origin-Host and Origin-Realm => replace them if missing, with request session-id & node configuration:", ANNA_FILE_LOCATION)); + if(reqSessionId) - if(!getAvp(helpers::base::AVPID__Session_Id, 1, anna::Exception::Mode::Ignore)) + if(!getAvp(helpers::base::AVPID__Session_Id, 1, anna::Exception::Mode::Ignore)) addAvp(helpers::base::AVPID__Session_Id)->getUTF8String()->setValue(reqSessionId->getUTF8String()->getValue()); // Origin-Host & Realm @@ -528,9 +580,9 @@ void Message::setStandardToAnswer(const Message &request, const std::string &ori // Fix: fix(); LOGDEBUG( - std::string msg = "Completed answer:\n"; - msg += asXMLString(); - anna::Logger::debug(msg, ANNA_FILE_LOCATION); + std::string msg = "Completed answer:\n"; + msg += asXMLString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); } @@ -538,7 +590,7 @@ void Message::setStandardToAnswer(const Message &request, const std::string &ori //------------------------------------------------------------------------------ //--------------------------------------------------------------- Message::fix() //------------------------------------------------------------------------------ -void Message::fix() throw() { +void Message::fix() { // Dictionary stack command: const stack::Command *stackCommand = getStackCommand(); @@ -567,7 +619,7 @@ void Message::fix() throw() { //------------------------------------------------------------------------------ //------------------------------------------------------------- Message::valid() //------------------------------------------------------------------------------ -bool Message::valid(Message *ptrAnswer) const throw(anna::RuntimeException) { +bool Message::valid(Message *ptrAnswer) const noexcept(false) { // OAM OamModule &oamModule = OamModule::instantiate(); // Dictionary stack command: @@ -627,7 +679,7 @@ bool Message::valid(Message *ptrAnswer) const throw(anna::RuntimeException) { //------------------------------------------------------------------------------ //-------------------------------------------------------------- Message::code() //------------------------------------------------------------------------------ -const anna::DataBlock & Message::code() throw(anna::RuntimeException) { +const anna::DataBlock & Message::code() noexcept(false) { // Pre-Validation Engine::ValidationMode::_v vmode = getEngine()->getValidationMode(); @@ -643,9 +695,9 @@ const anna::DataBlock & Message::code() throw(anna::RuntimeException) { // Trace LOGDEBUG( - std::string trace = "Message to code:\n"; - trace += asXMLString(); - anna::Logger::debug(trace, ANNA_FILE_LOCATION); + std::string trace = "Message to code:\n"; + trace += asXMLString(); + anna::Logger::debug(trace, ANNA_FILE_LOCATION); ); // Memory allocation U24 length = getLength(); @@ -699,35 +751,40 @@ const anna::DataBlock & Message::code() throw(anna::RuntimeException) { // Trace LOGDEBUG( - std::string trace = "DataBlock encoded:\n"; - trace += a_forCode.asString(); -// trace += "\nAs continuous hexadecimal string:\n"; -// trace += anna::functions::asHexString(a_forCode); - anna::Logger::debug(trace, ANNA_FILE_LOCATION); + std::string trace = "DataBlock encoded:\n"; + trace += a_forCode.asString(); + // trace += "\nAs continuous hexadecimal string:\n"; + // trace += anna::functions::asHexString(a_forCode); + anna::Logger::debug(trace, ANNA_FILE_LOCATION); ); return a_forCode; } - //------------------------------------------------------------------------------ -//----------------------------------------------------- Message::fromXMLString() +//------------------------------------------------------- Message::loadXMLFile() //------------------------------------------------------------------------------ -void Message::fromXMLString(const std::string &xmlString) throw(anna::RuntimeException) { - LOGDEBUG(anna::Logger::debug("Reading diameter message from xml string representation", ANNA_FILE_LOCATION)); - anna::xml::DocumentMemory xmlDocument; // has private copy constructor defined but not implemented to avoid inhenrit/copy (is very heavy) - const anna::xml::Node *rootNode; - xmlDocument.initialize(xmlString.c_str()); - rootNode = xmlDocument.parse(getEngine()->getDTD()); // Parsing: fail here if xml violates dtd - LOGDEBUG(anna::Logger::debug("Read OK from XML string representation", ANNA_FILE_LOCATION)); - fromXML(rootNode); +void Message::loadXMLFile(const std::string &xmlPathFile) noexcept(false) { + + anna::xml::DocumentFile xmlDocument; + anna::diameter::codec::functions::messageXmlDocumentFromXmlFile(xmlDocument, xmlPathFile); + fromXML(xmlDocument.getRootNode()); } +//------------------------------------------------------------------------------ +//----------------------------------------------------- Message::loadXMLString() +//------------------------------------------------------------------------------ +void Message::loadXMLString(const std::string &xmlString) noexcept(false) { + + anna::xml::DocumentMemory xmlDocument; + anna::diameter::codec::functions::messageXmlDocumentFromXmlString(xmlDocument, xmlString); + fromXML(xmlDocument.getRootNode()); +} //------------------------------------------------------------------------------ //----------------------------------------------------------- Message::fromXML() //------------------------------------------------------------------------------ -void Message::fromXML(const anna::xml::Node* messageNode) throw(anna::RuntimeException) { - // +void Message::fromXML(const anna::xml::Node* messageNode) noexcept(false) { + // const anna::xml::Attribute *version, *name, *code, *flags, *pbit, *ebit, *tbit, *appid, *hbh, *ete; version = messageNode->getAttribute("version", false /* no exception */); name = messageNode->getAttribute("name", false /* no exception */); @@ -738,12 +795,12 @@ void Message::fromXML(const anna::xml::Node* messageNode) throw(anna::RuntimeExc tbit = messageNode->getAttribute("t-bit", false /* no exception */); appid = messageNode->getAttribute("application-id"); // required hbh = messageNode->getAttribute("hop-by-hop-id", false /* no exception */); - ete = messageNode->getAttribute("end-by-end-id", false /* no exception */); + ete = messageNode->getAttribute("end-to-end-id", false /* no exception */); int i_aux; unsigned int u_aux; // Clear the message - clear(); + clear(false /* respect engine */); if(version) { i_aux = version->getIntegerValue(); @@ -790,7 +847,8 @@ void Message::fromXML(const anna::xml::Node* messageNode) throw(anna::RuntimeExc throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); } - setId(stackCommand->getId(), false /* don't clear */); + setId(stackCommand->getId()); + // 'P', 'E' and 'T' flags: bool activateP = pbit ? (pbit->getValue() == "yes") : false; bool activateE = ebit ? (ebit->getValue() == "yes") : false; @@ -856,7 +914,7 @@ void Message::fromXML(const anna::xml::Node* messageNode) throw(anna::RuntimeExc msg += "': negative values are not allowed"; throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); } - */ + */ } else u_aux = 0; setHopByHop(u_aux); @@ -871,7 +929,7 @@ void Message::fromXML(const anna::xml::Node* messageNode) throw(anna::RuntimeExc msg += "': negative values are not allowed"; throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); } - */ + */ } else u_aux = 0; setEndToEnd(u_aux); @@ -888,7 +946,7 @@ void Message::fromXML(const anna::xml::Node* messageNode) throw(anna::RuntimeExc } try { - avp = getEngine()->allocateAvp(); + avp = getEngine()->createAvp(NULL); avp -> fromXML(*it); } catch(anna::RuntimeException &ex) { getEngine()->releaseAvp(avp); @@ -900,36 +958,11 @@ void Message::fromXML(const anna::xml::Node* messageNode) throw(anna::RuntimeExc } -//------------------------------------------------------------------------------ -//----------------------------------------------------------- Message::loadXML() -//------------------------------------------------------------------------------ -void Message::loadXML(const std::string & xmlPathFile) throw(anna::RuntimeException) { - LOGDEBUG( - std::string trace = "Loading diameter message from file '"; - trace += xmlPathFile; - trace += "'"; - anna::Logger::debug(trace, ANNA_FILE_LOCATION); - ); - anna::xml::DocumentFile xmlDocument; // has private copy constructor defined but not implemented to avoid inhenrit/copy (is very heavy) - const anna::xml::Node *rootNode; - xmlDocument.initialize(xmlPathFile.c_str()); // fail here is i/o error - rootNode = xmlDocument.parse(getEngine()->getDTD()); // Parsing: fail here if xml violates dtd - LOGDEBUG( - std::string trace = "Loaded XML file ("; - trace += xmlPathFile; - trace += "):\n"; - trace += anna::xml::Compiler().apply(rootNode); - anna::Logger::debug(trace, ANNA_FILE_LOCATION); - ); - fromXML(rootNode); -} - - //------------------------------------------------------------------------------ //------------------------------------------------------------- Message::asXML() //------------------------------------------------------------------------------ -anna::xml::Node* Message::asXML(anna::xml::Node* parent) const throw() { - // +anna::xml::Node* Message::asXML(anna::xml::Node* parent) const { + // anna::xml::Node* result = parent->createChild("message"); // Dictionary stack command: const stack::Command *stackCommand = getStackCommand(); @@ -951,7 +984,7 @@ anna::xml::Node* Message::asXML(anna::xml::Node* parent) const throw() { result->createAttribute("application-id", anna::functions::asString(a_applicationId)); result->createAttribute("hop-by-hop-id", anna::functions::asString(a_hopByHop)); - result->createAttribute("end-by-end-id", anna::functions::asString(a_endToEnd)); + result->createAttribute("end-to-end-id", anna::functions::asString(a_endToEnd)); // Avps: for(const_avp_iterator it = avp_begin(); it != avp_end(); it++) { @@ -965,16 +998,24 @@ anna::xml::Node* Message::asXML(anna::xml::Node* parent) const throw() { //------------------------------------------------------------------------------ //------------------------------------------------------- Message::asXMLString() //------------------------------------------------------------------------------ -std::string Message::asXMLString() const throw() { +std::string Message::asXMLString(bool normalize) const { anna::xml::Node root("root"); - return anna::xml::Compiler().apply(asXML(&root)); + + anna::xml::Compiler::Mode::_v mode = normalize ? anna::xml::Compiler::Mode::Sort : anna::xml::Compiler::Mode::Visual; + std::string result = anna::xml::Compiler().apply(asXML(&root), mode); + + if (normalize) + result.erase(std::remove(result.begin(), result.end(), '\n'), result.end()); + + return result; } //------------------------------------------------------------------------------ //------------------------------------------------------------ Message::isLike() //------------------------------------------------------------------------------ -bool Message::isLike(const std::string &pattern) const throw() { +bool Message::isLike(const std::string &pattern) const { anna::RegularExpression re(pattern); - return re.isLike(asXMLString()); + return re.isLike(asXMLString(true /* normalize by mean sorting attribute names and removing new lines */)); } +