X-Git-Url: https://git.teslayout.com/public/public/public/?p=anna.git;a=blobdiff_plain;f=source%2Fdiameter%2Fcodec%2FAvp.cpp;h=be51349b25189c37c348179f1949aab199a77e7b;hp=26df7412d200037be9fb3b110b09b46f1ed69cc8;hb=7b7396649970852a360255f1db2f044d13913e39;hpb=93366a0bda79e6fd6e7dad6316bfcf8cc82f5731 diff --git a/source/diameter/codec/Avp.cpp b/source/diameter/codec/Avp.cpp index 26df741..be51349 100644 --- a/source/diameter/codec/Avp.cpp +++ b/source/diameter/codec/Avp.cpp @@ -55,20 +55,18 @@ const U8 Avp::PBitMask(0x20); //------------------------------------------------------------------------------ //------------------------------------------------------------------- Avp::Avp() //------------------------------------------------------------------------------ -Avp::Avp() { +Avp::Avp(Engine *engine) : a_engine(engine) { initialize(); } - //------------------------------------------------------------------------------ //------------------------------------------------------------------- Avp::Avp() //------------------------------------------------------------------------------ -Avp::Avp(AvpId id) { +Avp::Avp(AvpId id, Engine *engine) : a_engine(engine) { initialize(); setId(id); } - //------------------------------------------------------------------------------ //------------------------------------------------------------------ Avp::~Avp() //------------------------------------------------------------------------------ @@ -76,12 +74,26 @@ Avp::~Avp() { clear(); } +//------------------------------------------------------------------------------ +//------------------------------------------------------------- Avp::setEngine() +//------------------------------------------------------------------------------ +void Avp::setEngine(Engine *engine) throw() { + 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 avp first to set the engine again.", ANNA_FILE_LOCATION)); + return; + } + + a_engine = engine; +} //------------------------------------------------------------------------------ //------------------------------------------------------------- Avp::getEngine() //------------------------------------------------------------------------------ Engine * Avp::getEngine() const throw(anna::RuntimeException) { - return a_engine ? a_engine : (a_engine = anna::functions::component (ANNA_FILE_LOCATION)); + 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; } @@ -89,7 +101,6 @@ Engine * Avp::getEngine() const throw(anna::RuntimeException) { //------------------------------------------------------------ Avp::initialize() //------------------------------------------------------------------------------ void Avp::initialize() throw() { - a_engine = NULL; a_id = helpers::AVPID__AVP; // (0,0) a_flags = 0x00; a_insertionPositionForChilds = 0; @@ -178,13 +189,24 @@ avp_iterator Avp::avp_find(avp_container &avps, AvpId id, unsigned int position) //---------------------------------------------------------------- Avp::addAvp() //------------------------------------------------------------------------------ Avp * Avp::addAvp(avp_container &avps, int &insertionPositionForChilds, AvpId id, Engine *engine) throw() { - Avp * result = engine->allocateAvp(); + Avp * result = engine->createAvp(NULL); result->setId(id); addChild(avps, insertionPositionForChilds, result); return result; } +//------------------------------------------------------------------------------ +//---------------------------------------------------------------- Avp::addAvp() +//------------------------------------------------------------------------------ +Avp * Avp::addAvp(Avp * avp) throw(anna::RuntimeException) { + if(!avp) return NULL; + if (avp->getEngine() != getEngine()) return NULL; + addChild(avp); + return avp; +} + + //------------------------------------------------------------------------------ //------------------------------------------------------------- Avp::removeAvp() //------------------------------------------------------------------------------ @@ -406,7 +428,9 @@ bool Avp::flagsOK() const throw() { const stack::Avp *stackAvp = getStackAvp(); if(!stackAvp) { - anna::Logger::error("Impossible to decide if flags are correct because stack avp is not identified. Assume flags ok", ANNA_FILE_LOCATION); + std::string msg = "Impossible to decide if flags are correct because stack avp is not identified. Assume flags ok for Avp "; + msg += anna::diameter::functions::avpIdAsPairString(a_id); + anna::Logger::error(msg, ANNA_FILE_LOCATION); return true; }; @@ -431,7 +455,9 @@ bool Avp::flagsOK() const throw() { // V-bit if((Vnone && Mnone && Pnone && vendorBit()) || (Vmust && !vendorBit()) || (Vmustnot && vendorBit())) { - anna::Logger::error("Vendor Bit (V) incoherence found", ANNA_FILE_LOCATION); + std::string msg = "Vendor Bit (V) incoherence found for Avp "; + msg += stackAvp->getName(); + anna::Logger::error(msg, ANNA_FILE_LOCATION); return false; } @@ -440,19 +466,25 @@ bool Avp::flagsOK() const throw() { // M-bit if((Mmust && !mandatoryBit()) || (Mmustnot && mandatoryBit())) { - anna::Logger::error("Mandatory Bit (M) incoherence found", ANNA_FILE_LOCATION); + std::string msg = "Mandatory Bit (M) incoherence found for Avp "; + msg += stackAvp->getName(); + anna::Logger::error(msg, ANNA_FILE_LOCATION); return false; } // P-bit if((Pmust && !encryptionBit()) || (Pmustnot && encryptionBit())) { - anna::Logger::error("Encryption Bit (P) incoherence found", ANNA_FILE_LOCATION); + std::string msg = "Encryption Bit (P) incoherence found for Avp "; + msg += stackAvp->getName(); + anna::Logger::error(msg, ANNA_FILE_LOCATION); return false; } // Reserved bits if((a_flags & 0x1f) != 0x00) { - anna::Logger::error("Any (or more than one) of the reserved avp flags bit has been activated. Reserved bits must be null", ANNA_FILE_LOCATION); + std::string msg = "Any (or more than one) of the reserved avp flags bit has been activated. Reserved bits must be null. Avp is "; + msg += stackAvp->getName(); + anna::Logger::error(msg, ANNA_FILE_LOCATION); return false; } @@ -665,7 +697,7 @@ void Avp::decodeDataPart(const char * buffer, int size, const parent_t & parent, while(avpPos < size) { try { - avp = getEngine()->allocateAvp(); + avp = getEngine()->createAvp(NULL); db.assign(buffer + avpPos, size - avpPos /* is valid to pass total size (indeed i don't know the real avp size) because it will be limited and this has deep copy disabled (no memory is reserved) */); avp -> decode(db, me, answer); } catch(anna::RuntimeException &ex) { @@ -1225,7 +1257,17 @@ std::string Avp::getXMLdata(bool & isHex, const stack::Format *stackFormat) cons if(!stackFormat) { isHex = true; - return a_Unknown->asHexString(); // el asHexString del OctetString no puede lanzar una excepcion en realidad + // Tricky situation: if you change the dictionary dynamically, and a previous formatted avp + // becomes unknown (the change consists in remove Avps basically), then this would get a core + // dump: a_Unknown = NULL. We are not going to protect that situation because it represents a + // implementation fault, and there are many points which could have similar bad behaviour + // (those where we access directly the a_Unknown pointer). + // The best way to afford this is ... TODO: + // Freeze dictionary after use from any resource (avp, message), setting a flag which deny + // any modification in such dictionary. The best way to do this is on engine configuration + // for Avp o Message, where we could invoke something like getEngine()->getDictionary()->freeze() + + return a_Unknown->asHexString(); // asHexString for OctetString cannot launch exception } // Special case for Address: could launch exception if not printable @@ -1332,20 +1374,28 @@ void Avp::fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException) // Check attributes exclusiveness if(name) { // compact mode - bool allowFlagsField = ( stackAvp->getVbit() == anna::diameter::stack::Avp::FlagRule::may || stackAvp->getVbit() == anna::diameter::stack::Avp::FlagRule::shouldnot + + if(code || vendorCode) { + std::string msg = "Error processing avp getValue(); + msg += "'>: avp attributes <'code' + 'vendorCode'> are not allowed if <'name'> is provided"; + throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); + } + + // flags uncertainty: + bool flagsUncertainty = ( stackAvp->getVbit() == anna::diameter::stack::Avp::FlagRule::may || stackAvp->getVbit() == anna::diameter::stack::Avp::FlagRule::shouldnot || stackAvp->getMbit() == anna::diameter::stack::Avp::FlagRule::may || stackAvp->getMbit() == anna::diameter::stack::Avp::FlagRule::shouldnot /* umm, perhaps we could omit for bit P, whic is deprecated ... */ /* || stackAvp->getPbit() == anna::diameter::stack::Avp::FlagRule::may || stackAvp->getPbit() == anna::diameter::stack::Avp::FlagRule::shouldnot*/ ); - if(code || (flags && !allowFlagsField) || vendorCode) { - std::string msg = "Error processing avp getValue(); - if (flags) msg += "'>: avp attributes <'code' + 'flags' + 'vendorCode'> are not allowed if <'name'> is provided (also flags is not permitted: no may, no shouldnot)"; - else msg += "'>: avp attributes <'code' + 'vendorCode'> are not allowed if <'name'> is provided"; - throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); + if(flags && !flagsUncertainty) { + std::string msg = "Be careful processing avp getValue(); + msg += "'> together with avp 'flags' attribute, because may/shouldnot uncertainty was not specified"; + LOGINFORMATION(Logger::information(msg, ANNA_FILE_LOCATION)); } setId(stackAvp->getId()); - if (flags && allowFlagsField) { + //if (flags && flagsUncertainty) { + if (flags) { // Flags check int i_aux = flags->getIntegerValue(); @@ -1503,7 +1553,7 @@ void Avp::fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException) } try { - avp = getEngine()->allocateAvp(); + avp = getEngine()->createAvp(NULL); avp -> fromXML(*it); } catch(anna::RuntimeException &ex) { getEngine()->releaseAvp(avp);