X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=source%2Fdiameter%2Fcodec%2Ffunctions.cpp;h=fe0ee03fd895ef36a155de968c6c5d6bc33e359e;hb=57040efdece4ea1f4487608de3d1afbb9d1378c8;hp=3e8ce1fa5ca5c4722de671f823ace0a09ddf1599;hpb=93366a0bda79e6fd6e7dad6316bfcf8cc82f5731;p=anna.git diff --git a/source/diameter/codec/functions.cpp b/source/diameter/codec/functions.cpp index 3e8ce1f..fe0ee03 100644 --- a/source/diameter/codec/functions.cpp +++ b/source/diameter/codec/functions.cpp @@ -22,41 +22,47 @@ #include -using namespace anna::diameter::codec; - +namespace anna { +namespace diameter { +namespace codec { +// Preloaded MemoryDTD for function helpers: +anna::xml::DTDMemory MessageDTDMemory(MessageDTD); +} +} +} // Parent struct helper ///////////////////////////////////////////////////////////////////////////// -void parent::setMessage(const anna::diameter::CommandId & mid, const char *mname) throw() { +void anna::diameter::codec::parent::setMessage(const anna::diameter::CommandId & mid, const char *mname) throw() { MessageId = mid; if (mname) { MessageName = mname; } else { - MessageName = "Message"; + MessageName = "Message"; MessageName += anna::diameter::functions::commandIdAsPairString(mid); } } -void parent::addAvp(const anna::diameter::AvpId & aid, const char *aname) throw() { +void anna::diameter::codec::parent::addAvp(const anna::diameter::AvpId & aid, const char *aname) throw() { AvpsId.push_back(aid); std::string name; if (aname) { - name = aname; + name = aname; } else { name = "Avp"; - name += anna::diameter::functions::avpIdAsPairString(aid); + name += anna::diameter::functions::avpIdAsPairString(aid); } AvpsName.push_back(name); } -std::string parent::asString() const throw() { // "->->...->" +std::string anna::diameter::codec::parent::asString() const throw() { // "->->...->" std::string result = MessageName; for (std::vector::const_iterator it = AvpsName.begin(); it != AvpsName.end(); it++) { - result += "->"; - result += (*it); + result += "->"; + result += (*it); } return result; @@ -64,70 +70,88 @@ std::string parent::asString() const throw() { // "->->.. ///////////////////////////////////////////////////////////////////////////////////////////////////// - - // getters -anna::diameter::CommandId functions::getCommandId(const anna::DataBlock & db) throw(anna::RuntimeException) { +anna::diameter::CommandId anna::diameter::codec::functions::getCommandId(const anna::DataBlock & db) throw(anna::RuntimeException) { if(db.getSize() < Message::HeaderLength) throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); const char * data = db.getData(); U8 flags = data[4]; U24 code = DECODE3BYTES_INDX_VALUETYPE(data, 5, U24); -// U24 code = (((U24)data[5] << 16) & 0xFF0000) + -// (((U24)data[6] << 8) & 0x00FF00) + -// (((U24)data[7]) & 0x0000FF); + // U24 code = (((U24)data[5] << 16) & 0xFF0000) + + // (((U24)data[6] << 8) & 0x00FF00) + + // (((U24)data[7]) & 0x0000FF); return (anna::diameter::CommandId(code, (flags & Message::RBitMask) != 0x00)); } - -bool functions::isRequest(const anna::DataBlock & db) throw(anna::RuntimeException) { +bool anna::diameter::codec::functions::requestBit(const anna::DataBlock & db) throw(anna::RuntimeException) { if(db.getSize() < Message::HeaderLength) throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); return (((db.getData())[4] & Message::RBitMask) != 0x00); } -anna::diameter::ApplicationId functions::getApplicationId(const anna::DataBlock & db) throw(anna::RuntimeException) { +bool anna::diameter::codec::functions::proxiableBit(const anna::DataBlock & db) throw(anna::RuntimeException) { + if(db.getSize() < Message::HeaderLength) + throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); + + return (((db.getData())[4] & Message::PBitMask) != 0x00); +} + +bool anna::diameter::codec::functions::errorBit(const anna::DataBlock & db) throw(anna::RuntimeException) { + if(db.getSize() < Message::HeaderLength) + throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); + + return (((db.getData())[4] & Message::EBitMask) != 0x00); +} + +bool anna::diameter::codec::functions::potentiallyReTransmittedMessageBit(const anna::DataBlock & db) throw(anna::RuntimeException) { + if(db.getSize() < Message::HeaderLength) + throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); + + return (((db.getData())[4] & Message::TBitMask) != 0x00); +} + +anna::diameter::ApplicationId anna::diameter::codec::functions::getApplicationId(const anna::DataBlock & db) throw(anna::RuntimeException) { if(db.getSize() < Message::HeaderLength) throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); const char * appidPtr = db.getData() + 8; anna::diameter::ApplicationId result = DECODE4BYTES_INDX_VALUETYPE(appidPtr, 0, U32); -// anna::diameter::ApplicationId result = (((U32)appidPtr[0] << 24) & 0xFF000000) + -// (((U32)appidPtr[1] << 16) & 0x00FF0000) + -// (((U32)appidPtr[2] << 8) & 0x0000FF00) + -// (((U32)appidPtr[3]) & 0x000000FF); + // anna::diameter::ApplicationId result = (((U32)appidPtr[0] << 24) & 0xFF000000) + + // (((U32)appidPtr[1] << 16) & 0x00FF0000) + + // (((U32)appidPtr[2] << 8) & 0x0000FF00) + + // (((U32)appidPtr[3]) & 0x000000FF); return result; } -anna::diameter::HopByHop functions::getHopByHop(const anna::DataBlock & db) throw(anna::RuntimeException) { +anna::diameter::HopByHop anna::diameter::codec::functions::getHopByHop(const anna::DataBlock & db) throw(anna::RuntimeException) { if(db.getSize() < Message::HeaderLength) throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); const char * hbhPtr = db.getData() + 12; anna::diameter::HopByHop result = DECODE4BYTES_INDX_VALUETYPE(hbhPtr, 0, U32); -// anna::diameter::HopByHop result = (((U32)hbhPtr[0] << 24) & 0xFF000000) + -// (((U32)hbhPtr[1] << 16) & 0x00FF0000) + -// (((U32)hbhPtr[2] << 8) & 0x0000FF00) + -// (((U32)hbhPtr[3]) & 0x000000FF); + // anna::diameter::HopByHop result = (((U32)hbhPtr[0] << 24) & 0xFF000000) + + // (((U32)hbhPtr[1] << 16) & 0x00FF0000) + + // (((U32)hbhPtr[2] << 8) & 0x0000FF00) + + // (((U32)hbhPtr[3]) & 0x000000FF); return result; } -anna::diameter::EndToEnd functions::getEndToEnd(const anna::DataBlock & db) throw(anna::RuntimeException) { +anna::diameter::EndToEnd anna::diameter::codec::functions::getEndToEnd(const anna::DataBlock & db) throw(anna::RuntimeException) { if(db.getSize() < Message::HeaderLength) throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); const char * etePtr = db.getData() + 16; anna::diameter::EndToEnd result = DECODE4BYTES_INDX_VALUETYPE(etePtr, 0, U32); -// anna::diameter::EndToEnd result = (((U32)etePtr[0] << 24) & 0xFF000000) + -// (((U32)etePtr[1] << 16) & 0x00FF0000) + -// (((U32)etePtr[2] << 8) & 0x0000FF00) + -// (((U32)etePtr[3]) & 0x000000FF); + // anna::diameter::EndToEnd result = (((U32)etePtr[0] << 24) & 0xFF000000) + + // (((U32)etePtr[1] << 16) & 0x00FF0000) + + // (((U32)etePtr[2] << 8) & 0x0000FF00) + + // (((U32)etePtr[3]) & 0x000000FF); return result; } -void functions::decodeCommandHeader(const char *start, char & version, U24 & length, char & flags, diameter::CommandId & id, int & appId, int & hbh, int & ete) throw(anna::RuntimeException) { +void anna::diameter::codec::functions::decodeCommandHeader(const char *start, char & version, U24 & length, char & flags, diameter::CommandId & id, int & appId, int & hbh, int & ete) throw(anna::RuntimeException) { if(start == NULL) throw anna::RuntimeException("NULL provided start pointer", ANNA_FILE_LOCATION); @@ -161,7 +185,7 @@ void functions::decodeCommandHeader(const char *start, char & version, U24 & len ete = DECODE4BYTES_INDX_VALUETYPE(start, 16, U32); } -void functions::decodeAVP(const char *start, diameter::AvpId & id, char & flags, int & length, std::string & data) throw(anna::RuntimeException) { +void anna::diameter::codec::functions::decodeAVP(const char *start, diameter::AvpId & id, char & flags, int & length, std::string & data) throw(anna::RuntimeException) { if(start == NULL) throw anna::RuntimeException("NULL provided start pointer", ANNA_FILE_LOCATION); @@ -188,37 +212,42 @@ void functions::decodeAVP(const char *start, diameter::AvpId & id, char & flags, const char *dataPointer = (vendorSpecific ? (start + 12) : (start + 8)); // pointer to data part data.assign(dataPointer, dataLength); LOGLOCAL3( - std::string msg = anna::functions::asString("decodedAVP id (%d,%d), length %d, data length %d, data part 0x%s", - id.first, id.second, length, dataLength, anna::functions::asHexString(anna::DataBlock(dataPointer, dataLength)).c_str()); - anna::Logger::write(anna::Logger::Local3, msg, ANNA_FILE_LOCATION); + std::string msg = anna::functions::asString("decodedAVP id (%d,%d), length %d, data length %d, data part 0x%s", + id.first, id.second, length, dataLength, anna::functions::asHexString(anna::DataBlock(dataPointer, dataLength)).c_str()); + anna::Logger::write(anna::Logger::Local3, msg, ANNA_FILE_LOCATION); ); } -const char * functions::nextAVP(const anna::DataBlock & avpsDB, const char *start) throw(anna::RuntimeException) { +const char * anna::diameter::codec::functions::nextAVP(const char *avpsDB, int avpsLen, const char *start) throw(anna::RuntimeException) { if(start == NULL) throw anna::RuntimeException("NULL provided start pointer", ANNA_FILE_LOCATION); + if(avpsDB == NULL) + throw anna::RuntimeException("NULL provided avpsDB pointer", ANNA_FILE_LOCATION); const char *result; -// LOGDEBUG( -// std::string msg("DataBlock provided to 'nextAVP'"); -// msg += avpsDB.asString(); -// anna::Logger::debug(msg, ANNA_FILE_LOCATION); -// ); + // LOGDEBUG( + // std::string msg("DataBlock provided to 'nextAVP'"); + // msg += avpsDB.asString(); + // anna::Logger::debug(msg, ANNA_FILE_LOCATION); + // ); //int avpLength = (start[5] << 16) + (start[6] << 8) + start[7]; // AVP Length int avpLength = DECODE3BYTES_INDX_VALUETYPE(start, 5, int); result = start + 4 * REQUIRED_WORDS(avpLength); - const char * first = avpsDB.getData(); - int offset = (result - first); + int offset = (result - avpsDB); - if(offset > (avpsDB.getSize() - 1)) - //throw anna::RuntimeException("Start pointer out of boundaries for DataBlock", ANNA_FILE_LOCATION); + if(offset > (avpsLen - 1)) + //throw anna::RuntimeException("Start pointer out of boundaries for block(avpsDB, avpsLen)", ANNA_FILE_LOCATION); return NULL; // (*) return result; } -const char * functions::findAVP(const anna::DataBlock & avpsDB, const diameter::AvpId & id, int n) throw(anna::RuntimeException) { - const char * result = avpsDB.getData(); // first avp +//const char * functions::nextAVP(const anna::DataBlock & avpsDB, const char *start) throw(anna::RuntimeException) { +// return nextAVP(avpsDB.getData(), avpsDB.getSize(), start); +//} + +const char * anna::diameter::codec::functions::findAVP(const char *avpsDB, int avpsLen, const diameter::AvpId & id, int n) throw(anna::RuntimeException) { + const char *result = avpsDB; // first avp int positives = 0; // Decoded avp information: diameter::AvpId _id; @@ -230,14 +259,14 @@ const char * functions::findAVP(const anna::DataBlock & avpsDB, const diameter:: if(_id == id) positives++; while((_id != id) || (positives != n)) { // next search if not found or not ocurrence number reached - result = nextAVP(avpsDB, result); + result = nextAVP(avpsDB, avpsLen, result); if(result == NULL) { // (*) LOGDEBUG( - std::string msg = "AVP "; - msg += anna::diameter::functions::avpIdAsPairString(id); - msg += " not found at DataBlock"; - anna::Logger::debug(msg, ANNA_FILE_LOCATION); + std::string msg = "AVP "; + msg += anna::diameter::functions::avpIdAsPairString(id); + msg += " not found at DataBlock"; + anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); return NULL; } @@ -250,14 +279,17 @@ const char * functions::findAVP(const anna::DataBlock & avpsDB, const diameter:: return result; } +//const char * functions::findAVP(const anna::DataBlock & avpsDB, const diameter::AvpId & id, int n) throw(anna::RuntimeException) { +// return findAVP(avpsDB.getData(), avpsDB.getSize(), id, n); +//} // modifiers -void functions::setHopByHop(anna::DataBlock & db, diameter::HopByHop hbh) throw(anna::RuntimeException) { +void anna::diameter::codec::functions::setHopByHop(anna::DataBlock & db, diameter::HopByHop hbh) throw(anna::RuntimeException) { if(db.getSize() < Message::HeaderLength) { throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); } - static char source[4]; + char source[4]; source[0] = (char)(hbh >> 24); source[1] = (char)(hbh >> 16); source[2] = (char)(hbh >> 8); @@ -266,12 +298,12 @@ void functions::setHopByHop(anna::DataBlock & db, diameter::HopByHop hbh) throw( } -void functions::setEndToEnd(anna::DataBlock & db, diameter::EndToEnd ete) throw(anna::RuntimeException) { +void anna::diameter::codec::functions::setEndToEnd(anna::DataBlock & db, diameter::EndToEnd ete) throw(anna::RuntimeException) { if(db.getSize() < Message::HeaderLength) { throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); } - static char source[4]; + char source[4]; source[0] = (char)(ete >> 24); source[1] = (char)(ete >> 16); source[2] = (char)(ete >> 8); @@ -279,4 +311,40 @@ void functions::setEndToEnd(anna::DataBlock & db, diameter::EndToEnd ete) throw( memcpy((char *)(db.getData() + 16), source, 4); } +void anna::diameter::codec::functions::setPotentiallyReTransmittedMessageBit(const anna::DataBlock & db, bool activate) throw(anna::RuntimeException) { + if(db.getSize() < Message::HeaderLength) { + throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION); + } + + char flags[1]; + flags[0] = *(db.getData() + 4); + if(activate) flags[0] |= Message::TBitMask; else flags[0] &= (~Message::TBitMask); + memcpy((char *)(db.getData() + 4), flags, 1); +} + +// XML parsers for diameter messages /////////////////////////////////////////////////////////////////////////// +void anna::diameter::codec::functions::messageXmlDocumentFromXmlFile(anna::xml::DocumentFile &xmlDocument, const std::string & xmlPathFile) throw(anna::RuntimeException) { + LOGDEBUG(anna::Logger::debug(anna::functions::asString("Parsing diameter message from xml file '%s' into xml document", xmlPathFile.c_str()), ANNA_FILE_LOCATION)); + xmlDocument.initialize(xmlPathFile.c_str()); // fail here is i/o error + const anna::xml::Node *rootNode = xmlDocument.parse(MessageDTDMemory); // Parsing: fail here if xml violates dtd + LOGDEBUG( + std::string trace = "Parsing OK from XML file '"; + trace += xmlPathFile; + trace += "':\n"; + trace += anna::xml::Compiler().apply(rootNode); + anna::Logger::debug(trace, ANNA_FILE_LOCATION); + ); +} +void anna::diameter::codec::functions::messageXmlDocumentFromXmlString(anna::xml::DocumentMemory &xmlDocument, const std::string &xmlString) throw(anna::RuntimeException) { + LOGDEBUG(anna::Logger::debug("Parsing diameter message from xml string representation into xml document", ANNA_FILE_LOCATION)); + xmlDocument.initialize(xmlString.c_str()); + const anna::xml::Node *rootNode = xmlDocument.parse(MessageDTDMemory); // Parsing: fail here if xml violates dtd + LOGDEBUG( + std::string trace = "Parsing OK from XML string representation '"; + trace += xmlString; + trace += "':\n"; + trace += anna::xml::Compiler().apply(rootNode); + anna::Logger::debug(trace, ANNA_FILE_LOCATION); + ); +}