From: Eduardo Ramos Testillano Date: Sun, 7 Jun 2015 22:06:29 +0000 (+0200) Subject: Multistack launcher X-Git-Tag: REFACTORING_TESTING_LIBRARY~123 X-Git-Url: https://git.teslayout.com/public/public/public/?a=commitdiff_plain;h=431d322261ecfd6ef354abb392edbf8987e2407a;p=anna.git Multistack launcher --- diff --git a/example/diameter/launcher/Launcher.cpp b/example/diameter/launcher/Launcher.cpp index 59f5202..f5fac98 100644 --- a/example/diameter/launcher/Launcher.cpp +++ b/example/diameter/launcher/Launcher.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -24,6 +23,41 @@ #define SIGUSR2_TASKS_OUTPUT_FILENAME "./sigusr2.tasks.output" #define DIAMETER_CODEC_ENGINE_NAME_PREFIX "MyCodecEngine" +const char *ServicesDTD = "\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +"; + + Launcher::Launcher() : anna::comm::Application("launcher", "DiameterLauncher", "1.1"), a_communicator(NULL) { a_myDiameterEngine = new MyDiameterEngine(); a_myDiameterEngine->setRealm("ADL.ericsson.com"); @@ -40,6 +74,8 @@ Launcher::Launcher() : anna::comm::Application("launcher", "DiameterLauncher", " a_diameterLocalServer = NULL; a_cerPathfile = "cer.xml"; a_dwrPathfile = "dwr.xml"; + a_workingStackId = 0; + // Burst a_burstCycle = 1; a_burstRepeat = false; @@ -341,36 +377,49 @@ throw(anna::RuntimeException) { // Stack: a_codecEngine = new anna::diameter::codec::Engine(DIAMETER_CODEC_ENGINE_NAME_PREFIX); anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate(); - anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* stack id; its value don't mind, is not used (ADL is monostack) */); - // Analyze comma-separated list: - anna::Tokenizer lst; - std::string dictionaryParameter = cl.getValue("dictionary"); - lst.apply(dictionaryParameter, ","); - - if(lst.size() >= 1) { // always true (at least one, because --dictionary is mandatory) - anna::Tokenizer::const_iterator tok_min(lst.begin()); - anna::Tokenizer::const_iterator tok_max(lst.end()); - anna::Tokenizer::const_iterator tok_iter; - std::string pathFile; - d->allowUpdates(); - - for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) { - pathFile = anna::Tokenizer::data(tok_iter); - d->load(pathFile); + std::string stacks = cl.getValue("stacks"); + bool multistack = false; + try { + anna::Tokenizer stacksTok; + stacksTok.apply(stacks, "#"); + anna::Tokenizer::const_iterator stacks_it, stack_it; + + for(stacks_it = stacksTok.begin(); stacks_it != stacksTok.end(); stacks_it++) { + std::string stack = anna::Tokenizer::data(stacks_it); + anna::Tokenizer stackTok; + stackTok.apply(stack, ","); + + if(stackTok.size() == 1) { + if(stacksTok.size() != 1) + throw anna::RuntimeException("Application Id value is mandatory when more than one stack is going to be configured", ANNA_FILE_LOCATION); + + anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* no matter */, stack); // the stack is the dictionary + codecEngine->setDictionary(d); + break; + } + + if(stackTok.size() != 2) + throw anna::RuntimeException("Each stack must be in the form ','", ANNA_FILE_LOCATION); + + multistack = true; + stack_it = stackTok.begin(); + unsigned int stackId = atoll(anna::Tokenizer::data(stack_it)); + stack_it++; + std::string file = anna::Tokenizer::data(stack_it); + anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(stackId, file); } - } - getCodecEngine()->setDictionary(d); // XXXX esto cambiara... - LOGDEBUG(anna::Logger::debug(getCodecEngine()->asString(), ANNA_FILE_LOCATION)); + // Auto stack selection based on Application-ID: + if (multistack) getCodecEngine()->selectStackWithApplicationId(true); - if(lst.size() > 1) { - std::string all_in_one = "./dictionary-all-in-one.xml"; - std::ofstream out(all_in_one.c_str(), std::ifstream::out); - std::string buffer = d->asXMLString(); - out.write(buffer.c_str(), buffer.size()); - out.close(); - std::cout << "Written accumulated '" << all_in_one << "' (provide it next time to be more comfortable)." << std::endl; + std::cout << "Stacks provided: " << std::endl; + std::cout << anna::functions::tab(stackEngine.asString(false /* light */)); + std::cout << std::endl; + } catch(anna::RuntimeException &ex) { + _exit(ex.asString()); } + //LOGDEBUG(anna::Logger::debug(codecEngine->asString(), ANNA_FILE_LOCATION)); + /////////////////////////////// // Diameter library COUNTERS // @@ -952,7 +1001,7 @@ std::string Launcher::help() const throw() { result += "\n vi /var/tmp/anna.context."; result += "\n"; result += "\nA complete xml report will show all the context information (counters, alarms, statistics,"; - result += "\n handlers, diameter dictionary, etc.), and a powerful log module could dump all the events"; + result += "\n handlers, diameter stacks, etc.), and a powerful log module could dump all the events"; result += "\n processed and flow information. Statistics could be analized at context dump and optionally"; result += "\n written to disk as sample files (useful for graphs and spreadsheet reports) with all the"; result += "\n measurements."; @@ -967,8 +1016,8 @@ std::string Launcher::help() const throw() { result += "\n posibilities, many of which could be modified on the air through the management interface"; result += "\n (we will talk later about this great feature). Some of the more common parameters are:"; result += "\n"; - result += "\nAs mandatory, the stack definition given through the xml dictionary:"; - result += "\n --dictionary "; + result += "\nAs mandatory, the stacks enabled given through the application-id and the xml dictionary:"; + result += "\n --stacks "; result += "\n"; result += "\nActing as a diameter server (accepting i.e. 10 connections), you would have:"; result += "\n --diameterServer localhost:3868 --diameterServerSessions 10 --entityServerSessions 0"; @@ -998,6 +1047,11 @@ std::string Launcher::help() const throw() { result += "\n"; result += "\nhelp This help. Startup information-level traces also dump this help."; result += "\n"; + result += "\n--------------------------------------------------------------------------------------- Stack selection"; + result += "\n"; + result += "\nstack| Select current working stack id (node selection). Many operations"; + result += " could use this value if proceed, in multistack configurations."; + result += "\n"; result += "\n------------------------------------------------------------------------------------ Parsing operations"; result += "\n"; result += "\ncode|| Encodes source file (pathfile) into target file (pathfile)."; @@ -1075,14 +1129,14 @@ std::string Launcher::help() const throw() { result += "\n to the peer which sent the request. If user wants to test a specific answer without changing it,"; result += "\n use sendxml/sendhex operations better than programming."; result += "\n"; - result += "\nBalance ('-balance' command line parameter) could be used to forward server socket receptions through"; + result += "\nBalance ('--balance' command line parameter) could be used to forward server socket receptions through"; result += "\n entity servers by mean a round-robin algorithm. Both diameter server socket and entity targets should"; result += "\n have been configured, that is to say: launcher acts as client and server. If no balance is used, an"; result += "\n standard delivery is performed: first primary entity server, secondary when fails, etc."; result += "\n"; result += "\n--------------------------------------------------------------------------- Processing types (log tags)"; result += "\n"; - result += "\nUsed as log file extensions (when '-splitLog' is provided on command line) and context preffixes on log"; + result += "\nUsed as log file extensions (when '--splitLog' is provided on command line) and context preffixes on log"; result += "\n details when unique log file is dumped:"; result += "\n"; result += "\n [sent2e/send2eError] Send to entity (success/error)"; @@ -1115,7 +1169,7 @@ std::string Launcher::help() const throw() { result += "\n burst|push| Sends specific non-aynchronous load."; result += "\n burst|pop| Skip send burst messages in order to reduce over-the-air requests."; result += "\n Popping all OTA requests implies burst stop because no more answer"; - result += "\n will arrive to the process. Burst output file (-burstLog command"; + result += "\n will arrive to the process. Burst output file (--burstLog command"; result += "\n line parameter) shows popped messages with crosses (x). Each cross"; result += "\n represents one received answer for which no new request is sent."; result += "\n burst|stop Stops the burst cycle. You can resume pushing 1 load amount."; @@ -1135,7 +1189,7 @@ std::string Launcher::help() const throw() { result += "\n------------------------------------------------------------------------- Operations via HTTP interface"; result += "\n"; result += "\nAll the operations described above can be used through the optional HTTP interface. You only have"; - result += "\n to define the http server at the command line with something like: '-httpServer localhost:9000'."; + result += "\n to define the http server at the command line with something like: '--httpServer localhost:9000'."; result += "\nTo send the task, we shall build the http request body with the operation string. Some examples"; result += "\n using curl client could be:"; result += "\n"; @@ -1685,3 +1739,4 @@ throw() { anna::statistics::Engine::instantiate().asXML(result); return result; } + diff --git a/example/diameter/launcher/Launcher.hpp b/example/diameter/launcher/Launcher.hpp index d7e4bba..f5f1eb9 100644 --- a/example/diameter/launcher/Launcher.hpp +++ b/example/diameter/launcher/Launcher.hpp @@ -50,14 +50,15 @@ class Launcher : public anna::comm::Application { anna::timex::Engine* a_timeEngine; MyCounterRecorder *a_counterRecorder; MyCounterRecorderClock *a_counterRecorderClock; - std::string a_cerPathfile; - std::string a_dwrPathfile; + std::string a_cerPathfile; // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + std::string a_dwrPathfile; // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + std::string a_workingNode; // this is the node name (usually equals to the Origin-Realm value // Burst feature int a_burstCycle; bool a_burstRepeat; bool a_burstActive; - std::map < int /* dummy, p.e. used for order number */, anna::diameter::comm::Message* > a_burstMessages; + std::map < int /* dummy, p.e. used for order number */, anna::diameter::comm::Message* > a_burstMessages; // XXXXXXXXXXXXXXXXXXXXX int a_burstLoadIndx; std::map::const_iterator a_burstDeliveryIt; int a_otaRequest; @@ -67,7 +68,7 @@ class Launcher : public anna::comm::Application { anna::Recycler a_commMessages; anna::comm::ServerSocket* a_httpServerSocket; // HTTP - MyLocalServer* a_diameterLocalServer; // DIAMETER + MyLocalServer* a_diameterLocalServer; // DIAMETER XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void checkTimeMeasure(const char * commandLineParameter, bool optional = true) throw(anna::RuntimeException); void initialize() throw(anna::RuntimeException); // HTTP void run() throw(anna::RuntimeException); @@ -75,22 +76,24 @@ class Launcher : public anna::comm::Application { public: Launcher(); - anna::diameter::codec::Engine *getCodecEngine() const throw() { return a_codecEngine; } // XXXXXXXXXXXXXXXXX El del nodo de trabajo + anna::diameter::codec::Engine *getCodecEngine() const throw() { return a_codecEngine; } + std::string getWorkingNode() const throw() { return a_workingNode; } + void setWorkingNode(const std::string &node) throw() { a_workingNode = node; } MyCommunicator *getCommunicator() throw() { return a_communicator; } MyDiameterEngine* getMyDiameterEngine() const throw() { return (a_myDiameterEngine); } - void baseProtocolSetupAsClient() throw(anna::RuntimeException); - MyDiameterEntity *getEntity() throw() { return a_entity; } - MyLocalServer* getDiameterLocalServer() throw() { return a_diameterLocalServer; } + void baseProtocolSetupAsClient(void) throw(anna::RuntimeException); + MyDiameterEntity *getEntity() throw() { return a_entity; } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + MyLocalServer* getDiameterLocalServer() throw() { return a_diameterLocalServer; } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void eventOperation(const std::string &, std::string &) throw(anna::RuntimeException); bool logEnabled() const throw() { return (((a_logFile == "") || (a_logFile == "null")) ? false : true); } - void writeLogFile(const anna::DataBlock & db, const std::string &logExtension, const std::string &detail, anna::diameter::codec::Engine *codecEngine) const throw(); - void writeLogFile(const anna::diameter::codec::Message & decodedMessage, const std::string &logExtension, const std::string &detail) const throw(); + void writeLogFile(const anna::DataBlock & db, const std::string &logExtension, const std::string &detail) const throw(); // XXXXXXXXXXXXXXXXXXXXX + void writeLogFile(const anna::diameter::codec::Message & decodedMessage, const std::string &logExtension, const std::string &detail) const throw(); // XXXXXXXXXXXXXXXXXX void writeBurstLogFile(const std::string &buffer) throw(); bool burstLogEnabled() const throw() { return (((a_burstLogFile == "") || (a_burstLogFile == "null")) ? false : true); } - void startDiameterServer(int) throw(anna::RuntimeException); + void startDiameterServer(int) throw(anna::RuntimeException); // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void forceCountersRecord() throw(anna::RuntimeException) { if (a_counterRecorderClock) a_counterRecorderClock->tick(); } - anna::xml::Node* asXML(anna::xml::Node* parent) const throw(); + anna::xml::Node* asXML(anna::xml::Node* parent) const throw(); // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void resetStatistics() throw() { a_myDiameterEngine->resetStatistics(); } void resetCounters() throw(); void signalUSR2() throw(anna::RuntimeException); diff --git a/example/diameter/launcher/MyDiameterEntity.cpp b/example/diameter/launcher/MyDiameterEntity.cpp index d16974b..6a27607 100644 --- a/example/diameter/launcher/MyDiameterEntity.cpp +++ b/example/diameter/launcher/MyDiameterEntity.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include // Process #include "MyDiameterEntity.hpp" @@ -45,6 +47,50 @@ void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::Cl } +int MyDiameterEntity::readSocketId(const anna::diameter::comm::Message* message, int maxClientSessions) const throw() { + CommandLine& cl(anna::CommandLine::instantiate()); + std::string sessionBasedModelsType = (cl.exists("sessionBasedModelsClientSocketSelection") ? cl.getValue("sessionBasedModelsClientSocketSelection") : "SessionIdLowPart"); + + if(sessionBasedModelsType == "RoundRobin") return -1; // IEC also would return -1 + + try { + // Service-Context-Id: + anna::diameter::helpers::dcca::ChargingContext::_v chargingContext; + std::string scid = anna::diameter::helpers::dcca::functions::getServiceContextId(message->getBody(), chargingContext); + + switch(chargingContext) { + case anna::diameter::helpers::dcca::ChargingContext::Data: + case anna::diameter::helpers::dcca::ChargingContext::Voice: + case anna::diameter::helpers::dcca::ChargingContext::Content: { + // Session-Id: ';;[;="">]' + std::string sid = anna::diameter::helpers::base::functions::getSessionId(message->getBody()); + std::string diameterIdentity, optional; + anna::U32 high, low; + anna::diameter::helpers::base::functions::decodeSessionId(sid, diameterIdentity, high, low /* context-teid */, optional); + + if(sessionBasedModelsType == "SessionIdLowPart") return (low % maxClientSessions); + + if(sessionBasedModelsType == "SessionIdHighPart") return (high % maxClientSessions); + + if(sessionBasedModelsType == "SessionIdOptionalPart") return (atoi(optional.c_str()) % maxClientSessions); + } + case anna::diameter::helpers::dcca::ChargingContext::SMS: + case anna::diameter::helpers::dcca::ChargingContext::MMS: + case anna::diameter::helpers::dcca::ChargingContext::Unknown: + default: + return -1; // IEC model and Unknown traffic types + } + } catch(anna::RuntimeException &ex) { + LOGDEBUG( + std::string msg = ex.getText(); + msg += " | Round-robin between sessions will be used to send"; + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + } + + return -1; +} + void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message) throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventRequest", ANNA_FILE_LOCATION)); diff --git a/example/diameter/launcher/Node.cpp b/example/diameter/launcher/Node.cpp new file mode 100644 index 0000000..2d87d8a --- /dev/null +++ b/example/diameter/launcher/Node.cpp @@ -0,0 +1,110 @@ +// 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 // + + +// Standard +#include + +// Project +//#include + +// Process +#include "Node.hpp" + + +void Node::clear () throw() { + for (reacting_answers_const_iterator it = a_deques.begin(); it != a_deques.end(); it++) { + anna::diameter::codec::Engine *engine = anna::functions::component (ANNA_FILE_LOCATION); + engine->releaseMessage(*(it->second->begin())); + delete(it->second); + } + a_deques.clear(); +} + +void Node::dump () throw() { + std::string outfilename, xmlString; + for(reacting_answers_const_iterator it = a_deques.begin(); it != a_deques.end(); it++) { + int sequence = 1; + for(codec_messages_deque_const_iterator itm = it->second->begin(); itm != it->second->end(); itm++) { + // programmed_answer.. + outfilename = "programmed_answer."; + outfilename += anna::functions::asString(it->first); + outfilename += "."; + outfilename += anna::functions::asString(sequence++); + outfilename += ".xml"; + std::ofstream outfile(outfilename.c_str(), std::ifstream::out); + xmlString = (*itm)->asXMLString(); + outfile.write(xmlString.c_str(), xmlString.size()); + outfile.close(); + } + } +} + +void Node::addMessage(int code, anna::diameter::codec::Message *message) throw() { + reacting_answers_const_iterator it = a_deques.find(code); + if (it != a_deques.end()) { + it->second->push_back(message); + } + else { + codec_messages_deque *deque = new codec_messages_deque; + a_deques[code] = deque; + deque->push_back(message); + } +} + +anna::diameter::codec::Message* Node::getMessage(int code) const throw() { //get the front message (begin()), returns NULL if deque is empty + anna::diameter::codec::Message *result = NULL; + reacting_answers_const_iterator it = a_deques.find(code); + if (it != a_deques.end()) { + if (!it->second->empty()) result = *(it->second->begin()); + } + return result; +} + +void Node::nextMessage(int code) throw() { //pops the deque and release the message (when deque is not empty: deque::empty) + reacting_answers_const_iterator it = a_deques.find(code); + if (it != a_deques.end()) { + if (!it->second->empty()) { + anna::diameter::codec::Engine *engine = anna::functions::component (ANNA_FILE_LOCATION); + if (a_rotate) { + addMessage(code, *(it->second->begin())); + } + else { + engine->releaseMessage(*(it->second->begin())); + } + it->second->pop_front(); + } + } +} + +std::string Node::asString(const char *queueName) const throw() { + std::string result = ""; + std::string aux = "FIFO QUEUE '"; + aux += queueName; + aux += "', Rotation "; + aux += a_rotate ? "enabled":"disabled"; + result += anna::functions::highlightJustify(aux); + if(a_deques.size() != 0) { + for(reacting_answers_const_iterator it = a_deques.begin(); it != a_deques.end(); it++) { + if (it->second->size() != 0) { + aux = "Answer code "; + aux += anna::functions::asString(it->first); + result += anna::functions::highlightJustify(aux, anna::functions::TextHighlightMode::OverAndUnderline, + anna::functions::TextJustifyMode::Left, '-'); + for(codec_messages_deque_const_iterator itm = it->second->begin(); itm != it->second->end(); itm++) { + result += (*itm)->asXMLString(); + result += "\n"; + } + result += "\n"; + } + } + } + else { + result = "No ocurrences found\n\n"; + } + return result; +} diff --git a/example/diameter/launcher/Node.hpp b/example/diameter/launcher/Node.hpp new file mode 100644 index 0000000..95b6af2 --- /dev/null +++ b/example/diameter/launcher/Node.hpp @@ -0,0 +1,48 @@ +// 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 example_diameter_launcher_Node_hpp +#define example_diameter_launcher_Node_hpp + +// Standard +#include + +// Process +#include "MyDiameterEntity.hpp" +#include "MyLocalServer.hpp" + + +class Node { + + std::string a_name; + unsigned int a_applicationId; + std::string a_cer; // path file + std::string a_dwr; // path file + MyDiameterEntity *a_entity; + MyLocalServer *a_diameterServer; + bool a_balance; // Balance over entity servers instead of doing standard behaviour (first primary, secondary if fails, etc.). Default: false. + bool a_ignoreErrors; // default: false + + +public: + Node() { a_rotate = false; } + ~Node() { clear(); } + + + bool rotate() const throw() { return a_rotate; } + void rotate(bool r) throw() { a_rotate = r; } + + void clear () throw(); + void dump () throw(); + void addMessage(int code, anna::diameter::codec::Message *message) throw(); + anna::diameter::codec::Message* getMessage(int code) const throw(); + void nextMessage(int code) throw(); + std::string asString(const char *queueName) const throw(); +}; + +#endif diff --git a/example/diameter/launcher/deployments/basic/hex_examples b/example/diameter/launcher/deployments/basic/hex_examples new file mode 120000 index 0000000..0a74a2d --- /dev/null +++ b/example/diameter/launcher/deployments/basic/hex_examples @@ -0,0 +1 @@ +../../resources/hex_examples/ \ No newline at end of file diff --git a/example/diameter/launcher/deployments/basic/hex_examples/aar-bad.hex b/example/diameter/launcher/deployments/basic/hex_examples/aar-bad.hex deleted file mode 100644 index 7588fa1..0000000 --- a/example/diameter/launcher/deployments/basic/hex_examples/aar-bad.hex +++ /dev/null @@ -1 +0,0 @@ -01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000021000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/deployments/basic/hex_examples/aar.hex b/example/diameter/launcher/deployments/basic/hex_examples/aar.hex deleted file mode 100644 index 9a2aeb9..0000000 --- a/example/diameter/launcher/deployments/basic/hex_examples/aar.hex +++ /dev/null @@ -1 +0,0 @@ -01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/deployments/basic/hex_examples/aar2-bad.hex b/example/diameter/launcher/deployments/basic/hex_examples/aar2-bad.hex deleted file mode 100644 index 4b5c1ed..0000000 --- a/example/diameter/launcher/deployments/basic/hex_examples/aar2-bad.hex +++ /dev/null @@ -1 +0,0 @@ -0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc000000a000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/deployments/basic/hex_examples/aar3-bad.hex b/example/diameter/launcher/deployments/basic/hex_examples/aar3-bad.hex deleted file mode 100644 index 62f45ba..0000000 --- a/example/diameter/launcher/deployments/basic/hex_examples/aar3-bad.hex +++ /dev/null @@ -1 +0,0 @@ -0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc0000010000028af00000010000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/deployments/basic/hex_examples/readme.txt b/example/diameter/launcher/deployments/basic/hex_examples/readme.txt deleted file mode 100644 index 6b66557..0000000 --- a/example/diameter/launcher/deployments/basic/hex_examples/readme.txt +++ /dev/null @@ -1,16 +0,0 @@ -Bad messages: - -aar-bad.hex: comes from ../xml_examples/aar.xml - Consists in a deliberated bad length encoded on grouped Subscription-Id length field (not multiple of 4). - -aar2-bad.hex: comes from ../xml_examples/aar2.xml - Consists in a deliberated bad length encoded on enumerated Flow-Status avp 2-level nested inside Media-Component-Description: - -> Media-Component-Description (grouped) - -> Media-Sub-Component (grouped) - -> Flow-Status (enumerated) - -aar3-bad.hex: comes from ../xml_examples/aar2.xml - Consists in a deliberated bad value (16) encoded on enumerated Flow-Status avp (range 0-15) 2-level nested inside Media-Component-Description: - -> Media-Component-Description (grouped) - -> Media-Sub-Component (grouped) - -> Flow-Status (enumerated) diff --git a/example/diameter/launcher/deployments/basic/hex_examples/tspCCA.hex b/example/diameter/launcher/deployments/basic/hex_examples/tspCCA.hex deleted file mode 100644 index 401687a..0000000 --- a/example/diameter/launcher/deployments/basic/hex_examples/tspCCA.hex +++ /dev/null @@ -1 +0,0 @@ -0100018c4000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b33000000010c4000000c000007d10000010840000019657063322e6570637265616c6d2e636f6d00000000000128400000146570637265616c6d2e636f6d000001026000000c01000016000001a06000000c000000010000019f6000000c00000000000003f8c000002c000028af00000410c0000010000028af004e200000000411c0000010000028af0007d00000000419c0000058000028af00000404c0000010000028af000000060000040ac000003c000028af00000416c0000010000028af000000030000041780000010000028af000000010000041880000010000028af000000000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003000003ffc0000010000028af00000002000001164000000c00000005 diff --git a/example/diameter/launcher/deployments/basic/hex_examples/tspCCR.hex b/example/diameter/launcher/deployments/basic/hex_examples/tspCCR.hex deleted file mode 100644 index 492384a..0000000 --- a/example/diameter/launcher/deployments/basic/hex_examples/tspCCR.hex +++ /dev/null @@ -1 +0,0 @@ -010002e8c000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b3300000001026000000c01000016000001084000003263302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e736500000000012840000018766570632e6572696373736f6e2e73650000011b600000146570637265616c6d2e636f6d000001a06000000c000000010000019f6000000c0000000000000017c000000e000028af80010000000001166000000c00000000000001bb60000028000001c26000000c00000000000001bc60000013343637303139343034313800000000086000000c0a46ee6200000403c0000010000028af0000000500000015e000000d000028af060000000000040880000010000028af000003ec000001ca6000002c000001cb2000000c00000000000001cc2000001833353734373330343030363632383030000003f8c000002c000028af0000041080000010000028af08f0d1800000041180000010000028af02faf0800000041980000058000028af00000404c0000010000028af000000090000040ac000003c000028af0000041680000010000028af000000020000041780000010000028af000000010000041880000010000028af0000000000000012e0000011000028af32343039390000000000041a80000012000028af00010a46ee3a000000000016c0000019000028af8242f099006742f0990186a4010000000000001e6000000d7665706731000000000003e8c0000010000028af0000000000000400c0000010000028af00000001000001f5c0000012000028af00010a46ee3a0000000003fec0000020000028af000001f7c0000013000028af34383030303438000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003 diff --git a/example/diameter/launcher/deployments/basic/operation.sh b/example/diameter/launcher/deployments/basic/operation.sh deleted file mode 100755 index 5f3afc0..0000000 --- a/example/diameter/launcher/deployments/basic/operation.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -############# -# FUNCTIONS # -############# -_exit () { - echo - echo -e $1 - echo - exit 1 -} - -############# -# EXECUTION # -############# -cd `dirname $0` -echo -# Get the PID: -[ ! -f .pid ] && _exit "Can't found '`pwd`/.pid'.\nTry to pgrep your process name and dump pid to that file." -PID=`cat .pid` - -# Send operation: -[ "$1" = "" ] && _exit "Use: $0 ; i.e.: $0 help" -echo $1 > sigusr2.tasks.input -kill -s SIGUSR2 $PID - -sleep 1 -echo -echo -echo "You could see results on '`pwd`/sigusr2.tasks.output' file." -echo -echo - diff --git a/example/diameter/launcher/deployments/basic/operation.sh b/example/diameter/launcher/deployments/basic/operation.sh new file mode 120000 index 0000000..c9b45ae --- /dev/null +++ b/example/diameter/launcher/deployments/basic/operation.sh @@ -0,0 +1 @@ +../../resources/scripts/operation_signal.sh \ No newline at end of file diff --git a/example/diameter/launcher/deployments/basic/xml_examples b/example/diameter/launcher/deployments/basic/xml_examples new file mode 120000 index 0000000..c18402a --- /dev/null +++ b/example/diameter/launcher/deployments/basic/xml_examples @@ -0,0 +1 @@ +../../resources/xml_examples \ No newline at end of file diff --git a/example/diameter/launcher/deployments/basic/xml_examples/aaa.xml b/example/diameter/launcher/deployments/basic/xml_examples/aaa.xml deleted file mode 100644 index 4892138..0000000 --- a/example/diameter/launcher/deployments/basic/xml_examples/aaa.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/example/diameter/launcher/deployments/basic/xml_examples/aar.xml b/example/diameter/launcher/deployments/basic/xml_examples/aar.xml deleted file mode 100644 index 1201655..0000000 --- a/example/diameter/launcher/deployments/basic/xml_examples/aar.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/diameter/launcher/deployments/basic/xml_examples/aar2.xml b/example/diameter/launcher/deployments/basic/xml_examples/aar2.xml deleted file mode 100644 index c163fb4..0000000 --- a/example/diameter/launcher/deployments/basic/xml_examples/aar2.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/diameter/launcher/deployments/basic/xml_examples/ccr.xml b/example/diameter/launcher/deployments/basic/xml_examples/ccr.xml deleted file mode 100644 index 46483a2..0000000 --- a/example/diameter/launcher/deployments/basic/xml_examples/ccr.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/diameter/launcher/deployments/ft-client/hex_examples b/example/diameter/launcher/deployments/ft-client/hex_examples index 9eee58b..74e9662 120000 --- a/example/diameter/launcher/deployments/ft-client/hex_examples +++ b/example/diameter/launcher/deployments/ft-client/hex_examples @@ -1 +1 @@ -../basic/hex_examples \ No newline at end of file +../../resources/hex_examples \ No newline at end of file diff --git a/example/diameter/launcher/deployments/ft-client/operation.sh b/example/diameter/launcher/deployments/ft-client/operation.sh index a61ab5e..c9b45ae 120000 --- a/example/diameter/launcher/deployments/ft-client/operation.sh +++ b/example/diameter/launcher/deployments/ft-client/operation.sh @@ -1 +1 @@ -../basic/operation.sh \ No newline at end of file +../../resources/scripts/operation_signal.sh \ No newline at end of file diff --git a/example/diameter/launcher/deployments/ft-client/xml_examples b/example/diameter/launcher/deployments/ft-client/xml_examples index 903e6fe..c18402a 120000 --- a/example/diameter/launcher/deployments/ft-client/xml_examples +++ b/example/diameter/launcher/deployments/ft-client/xml_examples @@ -1 +1 @@ -../basic/xml_examples \ No newline at end of file +../../resources/xml_examples \ No newline at end of file diff --git a/example/diameter/launcher/main.cpp b/example/diameter/launcher/main.cpp index b27f4ee..f0d780d 100644 --- a/example/diameter/launcher/main.cpp +++ b/example/diameter/launcher/main.cpp @@ -44,7 +44,7 @@ int main(int argc, const char** argv) { commandLine.add("entityServerSessions", anna::CommandLine::Argument::Optional, "Diameter entity server sessions (0: diameter entity disabled). Default value of 1"); commandLine.add("balance", anna::CommandLine::Argument::Optional, "Balance over entity servers instead of doing standard behaviour (first primary, secondary if fails, etc.)", false); commandLine.add("sessionBasedModelsClientSocketSelection", anna::CommandLine::Argument::Optional, "By default, round-robin will be applied for IEC model (SMS/MMS), and Session-Id Low Part will be analyzed for ECUR/SCUR model (data, voice and content). You could change ECUR/SCUR analysis behaviour providing 'SessionIdHighPart', 'SessionIdOptionalPart' (atoi applied; usually subscriber id data, i.e. MSISDN or IMSI) and 'RoundRobin'."); - commandLine.add("dictionary", anna::CommandLine::Argument::Mandatory, "Diameter dictionary pathfiles (could be one or more ocurrences in a comma separated list, in order to accumulate loads). For example: avps_etsi.xml,avps_ietf.xml,avps_tgpp.xml,commands_qosControl.xml"); + commandLine.add("stacks", anna::CommandLine::Argument::Mandatory, ": this is a list of #-separated stacks defined by a comma-separated pair . If only one stack is provided, application-id could be omitted and then, all the messages will be decoded with the dictionary regardless the value of the application-id (the stack will be registered with id=0)."); commandLine.add("ignoreFlags", anna::CommandLine::Argument::Optional, "Ignore flags on validation (at the moment only bits M & P from AVPs, because V bit is too important; no operation flags could be checked). Also force compact xml presentation ignoring flags during dictionary elements identification", false); commandLine.add("ignoreErrors", anna::CommandLine::Argument::Optional, "Local server skips requests errors analysis which would prepare automatic answers for them when a problem is found. If no answer is programmed and entity is configured, a failed request would be forwarded (delegates at the end point) even if this parameter is missing", false); commandLine.add("allowedInactivityTime", anna::CommandLine::Argument::Optional, "Milliseconds for the maximum allowed inactivity time on server sessions born over the local server before being reset. If missing, default value of 90000 will be assigned"); @@ -70,3 +70,4 @@ int main(int argc, const char** argv) { return 0; } + diff --git a/example/diameter/launcher/resources/hex_examples/aar-bad.hex b/example/diameter/launcher/resources/hex_examples/aar-bad.hex new file mode 100644 index 0000000..7588fa1 --- /dev/null +++ b/example/diameter/launcher/resources/hex_examples/aar-bad.hex @@ -0,0 +1 @@ +01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000021000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/resources/hex_examples/aar.hex b/example/diameter/launcher/resources/hex_examples/aar.hex new file mode 100644 index 0000000..9a2aeb9 --- /dev/null +++ b/example/diameter/launcher/resources/hex_examples/aar.hex @@ -0,0 +1 @@ +01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/resources/hex_examples/aar2-bad.hex b/example/diameter/launcher/resources/hex_examples/aar2-bad.hex new file mode 100644 index 0000000..4b5c1ed --- /dev/null +++ b/example/diameter/launcher/resources/hex_examples/aar2-bad.hex @@ -0,0 +1 @@ +0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc000000a000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/resources/hex_examples/aar3-bad.hex b/example/diameter/launcher/resources/hex_examples/aar3-bad.hex new file mode 100644 index 0000000..62f45ba --- /dev/null +++ b/example/diameter/launcher/resources/hex_examples/aar3-bad.hex @@ -0,0 +1 @@ +0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc0000010000028af00000010000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152 diff --git a/example/diameter/launcher/resources/hex_examples/readme.txt b/example/diameter/launcher/resources/hex_examples/readme.txt new file mode 100644 index 0000000..6b66557 --- /dev/null +++ b/example/diameter/launcher/resources/hex_examples/readme.txt @@ -0,0 +1,16 @@ +Bad messages: + +aar-bad.hex: comes from ../xml_examples/aar.xml + Consists in a deliberated bad length encoded on grouped Subscription-Id length field (not multiple of 4). + +aar2-bad.hex: comes from ../xml_examples/aar2.xml + Consists in a deliberated bad length encoded on enumerated Flow-Status avp 2-level nested inside Media-Component-Description: + -> Media-Component-Description (grouped) + -> Media-Sub-Component (grouped) + -> Flow-Status (enumerated) + +aar3-bad.hex: comes from ../xml_examples/aar2.xml + Consists in a deliberated bad value (16) encoded on enumerated Flow-Status avp (range 0-15) 2-level nested inside Media-Component-Description: + -> Media-Component-Description (grouped) + -> Media-Sub-Component (grouped) + -> Flow-Status (enumerated) diff --git a/example/diameter/launcher/resources/hex_examples/tspCCA.hex b/example/diameter/launcher/resources/hex_examples/tspCCA.hex new file mode 100644 index 0000000..401687a --- /dev/null +++ b/example/diameter/launcher/resources/hex_examples/tspCCA.hex @@ -0,0 +1 @@ +0100018c4000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b33000000010c4000000c000007d10000010840000019657063322e6570637265616c6d2e636f6d00000000000128400000146570637265616c6d2e636f6d000001026000000c01000016000001a06000000c000000010000019f6000000c00000000000003f8c000002c000028af00000410c0000010000028af004e200000000411c0000010000028af0007d00000000419c0000058000028af00000404c0000010000028af000000060000040ac000003c000028af00000416c0000010000028af000000030000041780000010000028af000000010000041880000010000028af000000000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003000003ffc0000010000028af00000002000001164000000c00000005 diff --git a/example/diameter/launcher/resources/hex_examples/tspCCR.hex b/example/diameter/launcher/resources/hex_examples/tspCCR.hex new file mode 100644 index 0000000..492384a --- /dev/null +++ b/example/diameter/launcher/resources/hex_examples/tspCCR.hex @@ -0,0 +1 @@ +010002e8c000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b3300000001026000000c01000016000001084000003263302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e736500000000012840000018766570632e6572696373736f6e2e73650000011b600000146570637265616c6d2e636f6d000001a06000000c000000010000019f6000000c0000000000000017c000000e000028af80010000000001166000000c00000000000001bb60000028000001c26000000c00000000000001bc60000013343637303139343034313800000000086000000c0a46ee6200000403c0000010000028af0000000500000015e000000d000028af060000000000040880000010000028af000003ec000001ca6000002c000001cb2000000c00000000000001cc2000001833353734373330343030363632383030000003f8c000002c000028af0000041080000010000028af08f0d1800000041180000010000028af02faf0800000041980000058000028af00000404c0000010000028af000000090000040ac000003c000028af0000041680000010000028af000000020000041780000010000028af000000010000041880000010000028af0000000000000012e0000011000028af32343039390000000000041a80000012000028af00010a46ee3a000000000016c0000019000028af8242f099006742f0990186a4010000000000001e6000000d7665706731000000000003e8c0000010000028af0000000000000400c0000010000028af00000001000001f5c0000012000028af00010a46ee3a0000000003fec0000020000028af000001f7c0000013000028af34383030303438000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003 diff --git a/example/diameter/launcher/resources/pcap2diameterHex.sh b/example/diameter/launcher/resources/pcap2diameterHex.sh deleted file mode 100755 index 355b70f..0000000 --- a/example/diameter/launcher/resources/pcap2diameterHex.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/bin/bash - -# ANNA - Anna is Not Nothingness Anymore -# -# (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo -# -# http://redmine.teslayout.com/projects/anna-suite -# -# 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 the copyright holder 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 - - -############# -# VARIABLES # -############# -tmpdir=$(mktemp -d) - -############# -# FUNCTIONS # -############# - -usage () { - echo "Usage: $0 [results_dir]" - echo - echo " pcap_file: pcap formatted file to be processed." - echo " results_dir: directory where results are stored." - echo " By default, pcap file dirname is used." - echo - echo " The utility, dumps the extracted hexadecimal content" - echo " and useful information as timestamps, source and" - echo " destination:" - echo " /.hex" - echo " /.metadata" - echo - _exit -} - -_exit () { - echo - echo -e $1 - echo - - # Cleanup - rm -rf $tmpdir - - rc=1 - [ -n "$2" ] && rc=$2 - exit $rc -} - - -############# -# EXECUTION # -############# - -echo -echo "============================================" -echo "Diameter buffer extractor from PCAP raw file" -echo "============================================" -echo - -# Usage: -[ "$1" = "" ] && usage - -# Pcap file: -PCAP_FILE=$1 -[ ! -f $PCAP_FILE ] && _exit "Cannot found provided pcap file '$1' !!" - -# Optional result dir: -RESULTS_DIR=`dirname $PCAP_FILE` -[ "$2" != "" ] && RESULTS_DIR=$2 -[ ! -d $RESULTS_DIR ] && _exit "The results directory '$RESULTS_DIR' must exists !!" - -# Get the frames with diameter content (take care about '-2' two-pass option and don't add it, because we need to get reassembled parts in their corresponding frames): -# Fields needed (we won't need diameter.hopbyhopid & diameter.endtoendid to verify diameter message as hint patterns; length management will be enough): -FIELDS_DIAMETER="-e diameter.cmd.code -e diameter.flags.request -e diameter.applicationId -e diameter.hopbyhopid -e diameter.endtoendid -e diameter.length" -FIELDS="-e frame.number -e frame.time_epoch -e ip.src_host -e ip.dst_host $FIELDS_DIAMETER -e tcp.len -e frame.protocols -e tcp.segment" -tshark -E separator="|" -r $PCAP_FILE -N mntC -Tfields $FIELDS 2>/dev/null | grep -i diameter > $tmpdir/diameter_frames -# Example output: -# /length\ -# frame timestamp src dst code R App-ID HopByHop EndToEnd DIAM TCP protocol segments -# 1|1427215933.697904000|gt_traf|vcbavipt|272|1|16777238|0x0004e6e6|0x000bd986|432|432|eth:ip:tcp:diameter:diameter:diameter3gpp| -# 3|1427215934.449523000|vcbavipt|gt_traf|272|0|16777238|0x0004e6e6|0x000bd986|292|292|eth:ip:tcp:diameter:diameter:diameter3gpp| -# 5|1427215934.456160000|gt_traf|vcbavipt|||||||1400|eth:ip:tcp:diameter| -# 6|1427215934.456204000|gt_traf|vcbavipt|265|1|16777236|0x000c73c3|0x0004cee4|1972|572|eth:ip:tcp:diameter:diameter:diameter3gpp|5,6 -# 8|1427215935.123559000|vcbavipt|gt_traf|265|0|16777236|0x000c73c3|0x0004cee4|248|248|eth:ip:tcp:diameter:diameter:diameter3gpp| -all_frames=( $(cat $tmpdir/diameter_frames | cut -d\| -f1) ) -needs_join=( $(cat $tmpdir/diameter_frames | cut -d\| -f13) ) -main_frames=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($11 != "") print $1 }') ) - -# Reassemble procedure (using frame 1 as example): -# (for non segmented frames, it is enough with tcp or diameter length within the frame content itself) -# 1) Get the TCP length: 432 bytes. 432*2 = 864 characters per byte in hexadecimal string format -# 2) Get the frame length: `wc -c $tmpdir/block.$frame` => 997 -# 3) Get 864 from the tail: `cat $tmpdir/block.$frame | cut -c133 - -# Dump the hex blocks for all the diameter frames: -cat $PCAP_FILE | rawshark -s -r - -d proto:diameter -F data 2>/dev/null > $tmpdir/all_hex_data -for frame in ${all_frames[@]}; do - grep "^$frame " $tmpdir/all_hex_data | cut -d\" -f2 | sed 's/://g' > $tmpdir/block.$frame - frame_info=$(grep "^${frame}|" $tmpdir/diameter_frames) - - # Get the diameter part: - tcp_len=$(echo $frame_info | cut -d\| -f11) - frm_len=$(wc -c $tmpdir/block.$frame | awk '{ print $1 }') - cut_len=$((frm_len-2*tcp_len)) - cat $tmpdir/block.$frame | cut -c${cut_len}- > $RESULTS_DIR/$frame.hex - echo -n "Created $RESULTS_DIR/$frame.hex" - - # Metadata: - ts=$(echo $frame_info | cut -d\| -f2) - date=$(date -d @$ts) - src=$(echo $frame_info | cut -d\| -f3) - dst=$(echo $frame_info | cut -d\| -f4) - code=$(echo $frame_info | cut -d\| -f5) - isreq=$(echo $frame_info | cut -d\| -f6) - appid=$(echo $frame_info | cut -d\| -f7) - hbh=$(echo $frame_info | cut -d\| -f8) - e2e=$(echo $frame_info | cut -d\| -f9) - # To decimal: - hbh=$(printf "%d\n" $hbh) - e2e=$(printf "%d\n" $e2e) - echo "date=$date" > $RESULTS_DIR/$frame.metadata - echo "timestamp=$ts" >> $RESULTS_DIR/$frame.metadata - echo "src=$src" >> $RESULTS_DIR/$frame.metadata - echo "dst=$dst" >> $RESULTS_DIR/$frame.metadata - echo "code=$code" >> $RESULTS_DIR/$frame.metadata - echo "isrequest=$isreq" >> $RESULTS_DIR/$frame.metadata - echo "applicationid=$appid" >> $RESULTS_DIR/$frame.metadata - #echo "sequence=${hbh}.${e2e}" >> $RESULTS_DIR/$frame.metadata -# echo "hopbyhop=$hbh" >> $RESULTS_DIR/$frame.metadata -# echo "endtoend=$e2e" >> $RESULTS_DIR/$frame.metadata - - echo " and $RESULTS_DIR/$frame.metadata" -done - -# Join frames which need to be reassembled: -for group in ${needs_join[@]}; do - echo "Grouping frames $group ..." - group_array=( $(echo $group | sed 's/,/ /g') ) - for frame in ${group_array[@]}; do - cat $RESULTS_DIR/$frame.hex >> $tmpdir/diam.$group - done - cat $tmpdir/diam.$group | tr -d '\n' > $RESULTS_DIR/$frame.hex -done - -# Delete superfluous metadata: -echo "Deleting superfluous buffers & metadata ..." -segments=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($10 == "") print $1 }') ) -for s in ${segments[@]}; do rm $RESULTS_DIR/$s.*; done - - -_exit "Done!" 0 - diff --git a/example/diameter/launcher/resources/scripts/operation_curl.sh b/example/diameter/launcher/resources/scripts/operation_curl.sh new file mode 100755 index 0000000..5cff3c7 --- /dev/null +++ b/example/diameter/launcher/resources/scripts/operation_curl.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +############# +# FUNCTIONS # +############# +_exit () { + echo -e "\n$1\n" + exit 1 +} + +############# +# EXECUTION # +############# +cd `dirname $0` +echo +# Get the HTTP Server: +[ ! -f .httpServer ] && _exit "Can't found '`pwd`/.httpServer' to use with curl tool." +SERVER=`cat .httpServer` + +# Send operation: +[ "$1" = "" ] && _exit "Usage: $0 ; i.e.: $0 help" +#> curl_log.txt +#TRACE="--trace-ascii curl_log.txt" +curl -m 1 --data "$1" $SERVER + diff --git a/example/diameter/launcher/resources/scripts/operation_signal.sh b/example/diameter/launcher/resources/scripts/operation_signal.sh new file mode 100755 index 0000000..c462a7e --- /dev/null +++ b/example/diameter/launcher/resources/scripts/operation_signal.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +############# +# FUNCTIONS # +############# +_exit () { + echo -e "\n$1\n" + exit 1 +} + +############# +# EXECUTION # +############# +cd `dirname $0` +echo +# Get the PID: +[ ! -f .pid ] && _exit "Can't found '`pwd`/.pid'.\nTry to pgrep your process name and dump pid to that file." +PID=`cat .pid` + +# Send operation: +[ "$1" = "" ] && _exit "Usage: $0 ; i.e.: $0 help" +echo $1 > sigusr2.tasks.input +kill -s SIGUSR2 $PID + +sleep 1 +echo +echo +echo "You could see results on '`pwd`/sigusr2.tasks.output' file." +echo +echo + diff --git a/example/diameter/launcher/resources/scripts/operation_tps.sh b/example/diameter/launcher/resources/scripts/operation_tps.sh new file mode 100755 index 0000000..29f41eb --- /dev/null +++ b/example/diameter/launcher/resources/scripts/operation_tps.sh @@ -0,0 +1,66 @@ +#!/bin/bash + echo " sendXS [amount: default -1 (no limit)]:" + echo " send messages from burst list with the TPS provided. User could hot change" + echo " speed by mean 'echo > .tps' at another shell. You can stop the load" + echo " removing that hidden file or using CTRL+C from the shell where you launched" + echo " the burst command. Real tps is dumped on '.real_tps' file during testing." + echo " You could limit the amount of messages sent by mean the second parameter." + echo " No limit is established by default (-1 or negative value)." +> curl_log.txt +TRACE="--trace-ascii curl_log.txt" +SERVER=`cat .httpServer` + +use () { + + echo "Use: $0 [2c]" + echo + echo "Sends 'xml_file' to the diameter server or to the client when '2c' parameter is provided." + echo + exit +} + + sendXS) [[ "$2" = "" ]] && uso + limit=$3 + [[ "$limit" = "" ]] && limit=-1 + entero $2 + entero $limit + TPS=0 + count=0 + amount=1 + echo $2 > .tps + while test -f .tps + do + [[ "$count" = "$limit" ]] && break + BEFORE_ns=`date +%s%N` + READ_TPS=`cat .tps` + # Hot change could make .tps still unavailable: + [[ "$READ_TPS" = "" ]] && READ_TPS=$TPS + # Volvemos a calcular medias (REAL_TPS) cada 10 segundos o cuando cambia el TPS en caliente: + [[ "$READ_TPS" != "$TPS" ]] && { BEGIN_ns=$BEFORE_ns ; count=0 ; } + [[ $count = $((10*TPS)) ]] && { BEGIN_ns=$BEFORE_ns ; count=0 ; } + TPS=$READ_TPS + [[ "$TPS" = "0" ]] && salir "Test stopped due to 0-tps value read" + # Background: + _curl "burst|send|$amount" & + count=$((count+amount)) + AFTER_ns=`date +%s%N` + # Real tps: + REAL_TPS=$(calc "1000000000 * $count / ($AFTER_ns - $BEGIN_ns)") + echo $REAL_TPS > .real_tps + + COEF=1 + [[ $(calc "$TPS > $REAL_TPS") = "1" ]] && COEF=$(calc "$REAL_TPS / $TPS") + K=$(calc "$COEF ^ 10") + amount=$(calc "scale=0;1/$K") + usleep $(calc "$K * 1000000/$TPS") + done + ;; +echo +[[ "$1" = "" ]] && use +[[ ! -f "$1" ]] && { echo "ERROR: file '$1' not found" ; echo; echo; exit ; } +echo +operation="sendxml|$1" +[[ "$2" = "2c" ]] && operation="sendxml2c|$1" + +curl -m 1 --data "$operation" $TRACE ${SERVER} + diff --git a/example/diameter/launcher/resources/scripts/pcap2diameterHex.sh b/example/diameter/launcher/resources/scripts/pcap2diameterHex.sh new file mode 100755 index 0000000..355b70f --- /dev/null +++ b/example/diameter/launcher/resources/scripts/pcap2diameterHex.sh @@ -0,0 +1,180 @@ +#!/bin/bash + +# ANNA - Anna is Not Nothingness Anymore +# +# (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo +# +# http://redmine.teslayout.com/projects/anna-suite +# +# 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 the copyright holder 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 + + +############# +# VARIABLES # +############# +tmpdir=$(mktemp -d) + +############# +# FUNCTIONS # +############# + +usage () { + echo "Usage: $0 [results_dir]" + echo + echo " pcap_file: pcap formatted file to be processed." + echo " results_dir: directory where results are stored." + echo " By default, pcap file dirname is used." + echo + echo " The utility, dumps the extracted hexadecimal content" + echo " and useful information as timestamps, source and" + echo " destination:" + echo " /.hex" + echo " /.metadata" + echo + _exit +} + +_exit () { + echo + echo -e $1 + echo + + # Cleanup + rm -rf $tmpdir + + rc=1 + [ -n "$2" ] && rc=$2 + exit $rc +} + + +############# +# EXECUTION # +############# + +echo +echo "============================================" +echo "Diameter buffer extractor from PCAP raw file" +echo "============================================" +echo + +# Usage: +[ "$1" = "" ] && usage + +# Pcap file: +PCAP_FILE=$1 +[ ! -f $PCAP_FILE ] && _exit "Cannot found provided pcap file '$1' !!" + +# Optional result dir: +RESULTS_DIR=`dirname $PCAP_FILE` +[ "$2" != "" ] && RESULTS_DIR=$2 +[ ! -d $RESULTS_DIR ] && _exit "The results directory '$RESULTS_DIR' must exists !!" + +# Get the frames with diameter content (take care about '-2' two-pass option and don't add it, because we need to get reassembled parts in their corresponding frames): +# Fields needed (we won't need diameter.hopbyhopid & diameter.endtoendid to verify diameter message as hint patterns; length management will be enough): +FIELDS_DIAMETER="-e diameter.cmd.code -e diameter.flags.request -e diameter.applicationId -e diameter.hopbyhopid -e diameter.endtoendid -e diameter.length" +FIELDS="-e frame.number -e frame.time_epoch -e ip.src_host -e ip.dst_host $FIELDS_DIAMETER -e tcp.len -e frame.protocols -e tcp.segment" +tshark -E separator="|" -r $PCAP_FILE -N mntC -Tfields $FIELDS 2>/dev/null | grep -i diameter > $tmpdir/diameter_frames +# Example output: +# /length\ +# frame timestamp src dst code R App-ID HopByHop EndToEnd DIAM TCP protocol segments +# 1|1427215933.697904000|gt_traf|vcbavipt|272|1|16777238|0x0004e6e6|0x000bd986|432|432|eth:ip:tcp:diameter:diameter:diameter3gpp| +# 3|1427215934.449523000|vcbavipt|gt_traf|272|0|16777238|0x0004e6e6|0x000bd986|292|292|eth:ip:tcp:diameter:diameter:diameter3gpp| +# 5|1427215934.456160000|gt_traf|vcbavipt|||||||1400|eth:ip:tcp:diameter| +# 6|1427215934.456204000|gt_traf|vcbavipt|265|1|16777236|0x000c73c3|0x0004cee4|1972|572|eth:ip:tcp:diameter:diameter:diameter3gpp|5,6 +# 8|1427215935.123559000|vcbavipt|gt_traf|265|0|16777236|0x000c73c3|0x0004cee4|248|248|eth:ip:tcp:diameter:diameter:diameter3gpp| +all_frames=( $(cat $tmpdir/diameter_frames | cut -d\| -f1) ) +needs_join=( $(cat $tmpdir/diameter_frames | cut -d\| -f13) ) +main_frames=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($11 != "") print $1 }') ) + +# Reassemble procedure (using frame 1 as example): +# (for non segmented frames, it is enough with tcp or diameter length within the frame content itself) +# 1) Get the TCP length: 432 bytes. 432*2 = 864 characters per byte in hexadecimal string format +# 2) Get the frame length: `wc -c $tmpdir/block.$frame` => 997 +# 3) Get 864 from the tail: `cat $tmpdir/block.$frame | cut -c133 + +# Dump the hex blocks for all the diameter frames: +cat $PCAP_FILE | rawshark -s -r - -d proto:diameter -F data 2>/dev/null > $tmpdir/all_hex_data +for frame in ${all_frames[@]}; do + grep "^$frame " $tmpdir/all_hex_data | cut -d\" -f2 | sed 's/://g' > $tmpdir/block.$frame + frame_info=$(grep "^${frame}|" $tmpdir/diameter_frames) + + # Get the diameter part: + tcp_len=$(echo $frame_info | cut -d\| -f11) + frm_len=$(wc -c $tmpdir/block.$frame | awk '{ print $1 }') + cut_len=$((frm_len-2*tcp_len)) + cat $tmpdir/block.$frame | cut -c${cut_len}- > $RESULTS_DIR/$frame.hex + echo -n "Created $RESULTS_DIR/$frame.hex" + + # Metadata: + ts=$(echo $frame_info | cut -d\| -f2) + date=$(date -d @$ts) + src=$(echo $frame_info | cut -d\| -f3) + dst=$(echo $frame_info | cut -d\| -f4) + code=$(echo $frame_info | cut -d\| -f5) + isreq=$(echo $frame_info | cut -d\| -f6) + appid=$(echo $frame_info | cut -d\| -f7) + hbh=$(echo $frame_info | cut -d\| -f8) + e2e=$(echo $frame_info | cut -d\| -f9) + # To decimal: + hbh=$(printf "%d\n" $hbh) + e2e=$(printf "%d\n" $e2e) + echo "date=$date" > $RESULTS_DIR/$frame.metadata + echo "timestamp=$ts" >> $RESULTS_DIR/$frame.metadata + echo "src=$src" >> $RESULTS_DIR/$frame.metadata + echo "dst=$dst" >> $RESULTS_DIR/$frame.metadata + echo "code=$code" >> $RESULTS_DIR/$frame.metadata + echo "isrequest=$isreq" >> $RESULTS_DIR/$frame.metadata + echo "applicationid=$appid" >> $RESULTS_DIR/$frame.metadata + #echo "sequence=${hbh}.${e2e}" >> $RESULTS_DIR/$frame.metadata +# echo "hopbyhop=$hbh" >> $RESULTS_DIR/$frame.metadata +# echo "endtoend=$e2e" >> $RESULTS_DIR/$frame.metadata + + echo " and $RESULTS_DIR/$frame.metadata" +done + +# Join frames which need to be reassembled: +for group in ${needs_join[@]}; do + echo "Grouping frames $group ..." + group_array=( $(echo $group | sed 's/,/ /g') ) + for frame in ${group_array[@]}; do + cat $RESULTS_DIR/$frame.hex >> $tmpdir/diam.$group + done + cat $tmpdir/diam.$group | tr -d '\n' > $RESULTS_DIR/$frame.hex +done + +# Delete superfluous metadata: +echo "Deleting superfluous buffers & metadata ..." +segments=( $(cat $tmpdir/diameter_frames | awk -F\| '{ if ($10 == "") print $1 }') ) +for s in ${segments[@]}; do rm $RESULTS_DIR/$s.*; done + + +_exit "Done!" 0 + diff --git a/example/diameter/launcher/resources/xml_examples/aaa.xml b/example/diameter/launcher/resources/xml_examples/aaa.xml new file mode 100644 index 0000000..4892138 --- /dev/null +++ b/example/diameter/launcher/resources/xml_examples/aaa.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/example/diameter/launcher/resources/xml_examples/aar.xml b/example/diameter/launcher/resources/xml_examples/aar.xml new file mode 100644 index 0000000..1201655 --- /dev/null +++ b/example/diameter/launcher/resources/xml_examples/aar.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/diameter/launcher/resources/xml_examples/aar2.xml b/example/diameter/launcher/resources/xml_examples/aar2.xml new file mode 100644 index 0000000..c163fb4 --- /dev/null +++ b/example/diameter/launcher/resources/xml_examples/aar2.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/diameter/launcher/resources/xml_examples/ccr.xml b/example/diameter/launcher/resources/xml_examples/ccr.xml new file mode 100644 index 0000000..46483a2 --- /dev/null +++ b/example/diameter/launcher/resources/xml_examples/ccr.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/anna/diameter/codec/EngineImpl.hpp b/include/anna/diameter/codec/EngineImpl.hpp index bb7c6f5..1884083 100644 --- a/include/anna/diameter/codec/EngineImpl.hpp +++ b/include/anna/diameter/codec/EngineImpl.hpp @@ -178,6 +178,7 @@ 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) @@ -322,7 +323,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; } + /** + * 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; } /** DTD document for xml message parsing diff --git a/source/diameter/codec/EngineImpl.cpp b/source/diameter/codec/EngineImpl.cpp index 5d24eb9..c25bec0 100644 --- a/source/diameter/codec/EngineImpl.cpp +++ b/source/diameter/codec/EngineImpl.cpp @@ -116,6 +116,7 @@ EngineImpl::EngineImpl(const char* className) : a_dictionary(NULL), a_validationDepth(ValidationDepth::FirstError), a_validationMode(ValidationMode::AfterDecoding), + a_singleFailedAVP(true), a_ignoreFlags(false), a_selectStackWithApplicationId(false), a_fixMode(FixMode::BeforeEncoding) { @@ -191,6 +192,8 @@ std::string EngineImpl::asString(void) const throw() { result += asText(a_validationDepth); result += "\nValidationMode: "; result += asText(a_validationMode); + result += "\nSingle Failed-AVP: "; + result += a_singleFailedAVP ? "yes" : "no"; result += "\nIgnore flags: "; result += a_ignoreFlags ? "yes" : "no"; result += "\nFixMode: "; @@ -209,6 +212,7 @@ throw() { anna::xml::Node* result = parent->createChild("diameter.codec.EngineImpl"); result->createAttribute("ValidationDepth", asText(a_validationDepth)); result->createAttribute("ValidationMode", asText(a_validationMode)); + result->createAttribute("SingleFailedAVP", a_singleFailedAVP ? "yes" : "no"); result->createAttribute("IgnoreFlags", a_ignoreFlags ? "yes" : "no"); result->createAttribute("FixMode", asText(a_fixMode)); anna::xml::Node* dictionary = result->createChild("EngineImpl.ActivatedDictionary"); diff --git a/source/diameter/codec/Message.cpp b/source/diameter/codec/Message.cpp index b9c4fbd..35db129 100644 --- a/source/diameter/codec/Message.cpp +++ b/source/diameter/codec/Message.cpp @@ -471,11 +471,13 @@ void Message::setFailedAvp(const parent_t &parent, AvpId wrong, const char *wron // 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