#include <anna/http/Transport.hpp>
#include <anna/diameter/stack/Engine.hpp>
#include <anna/diameter/helpers/base/functions.hpp>
-#include <anna/diameter/helpers/dcca/functions.hpp>
#include <anna/time/functions.hpp>
#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
#define SIGUSR2_TASKS_OUTPUT_FILENAME "./sigusr2.tasks.output"
#define DIAMETER_CODEC_ENGINE_NAME_PREFIX "MyCodecEngine"
+const char *ServicesDTD = "\
+<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<!-- Diameter services DTD -->\n\
+\n\
+<!ELEMENT services (stack*, node*)>\n\
+\n\
+<!ELEMENT stack EMPTY>\n\
+<!ATTLIST stack id CDATA #REQUIRED dictionary CDATA #REQUIRED>\n\
+<!--\n\
+ Stack record\n\
+\n\
+ id: Normally the id corresponds to the Application-Id for which the dictionary provided is designed\n\
+ dictionary: Path to the dictionary file\n\
+-->\n\
+\n\
+<!ELEMENT node EMPTY>\n\
+<!ATTLIST node name CDATA #REQUIRED application-id CDATA #REQUIRED cer CDATA #IMPLIED dwr CDATA #IMPLIED entity CDATA #IMPLIED entityServerSessions CDATA #IMPLIED diameterServer CDATA #IMPLIED diameterServerSessions CDATA #IMPLIED balance (yes | no) #IMPLIED sessionBasedModelsClientSocketSelection (SessionIdHighPart | SessionIdOptionalPart | RoundRobin) #IMPLIED ignoreFlags (yes | no) #IMPLIED ignoreErrors (yes | no) #IMPLIED>\n\
+<!--\n\
+ Node record\n\
+\n\
+ name: Each node will be named normally with the Origin-Realm value\n\
+ application-id: The Application-Id provided must exists as a registered 'stack id'\n\
+ cer: User defined CER path file to be encoded to establish diameter connections. If missing, will be harcoded\n\
+ dwr: User defined DWR path file to be encoded for diameter protocol keep alive. If missing, will be harcoded\n\
+ entity: Target diameter entity (comma-separated '<address>:<port>' format). For example: 10.20.30.40:3868,10.20.30.41:3868. If missing, no entity will be enabled\n\
+ entityServerSessions: Diameter entity server sessions (0: diameter entity disabled). Default value of 1\n\
+ diameterServer: Diameter own server address in '<address>:<port>' format. For example: 10.20.30.40:3868. If missing, no local server will be enabled\n\
+ diameterServerSessions: Diameter own server available connections (0: diameter server disabled). Default value of 1\n\
+ balance: Balance over entity servers instead of doing standard behaviour (first primary, secondary if fails, etc.). Default value 'no'\n\
+ ignoreErrors: 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. Default value 'no'\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");
a_diameterLocalServer = NULL;
a_cerPathfile = "cer.xml";
a_dwrPathfile = "dwr.xml";
+ a_workingStackId = 0;
+
// Burst
a_burstCycle = 1;
a_burstRepeat = false;
// 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 '<application-id>,<xml dictionary pathfile>'", 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 //
result += "\n vi /var/tmp/anna.context.<pid>";
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.";
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 <path to dictionary file>";
+ result += "\nAs mandatory, the stacks enabled given through the application-id and the xml dictionary:";
+ result += "\n --stacks <appid1,dictionary1#appid2,dictionary2#...#appidN,dictionaryN>";
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";
result += "\n";
result += "\nhelp This help. Startup information-level traces also dump this help.";
result += "\n";
+ result += "\n--------------------------------------------------------------------------------------- Stack selection";
+ result += "\n";
+ result += "\nstack|<id> 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|<source_file>|<target_file> Encodes source file (pathfile) into target file (pathfile).";
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)";
result += "\n burst|push|<load amount> Sends specific non-aynchronous load.";
result += "\n burst|pop|<release amount> 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.";
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";
anna::statistics::Engine::instantiate().asXML(result);
return result;
}
+
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<int, anna::diameter::comm::Message*>::const_iterator a_burstDeliveryIt;
int a_otaRequest;
anna::Recycler<anna::diameter::comm::Message> 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);
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);
#include <anna/diameter/functions.hpp>
#include <anna/time/functions.hpp>
#include <anna/diameter.comm/Response.hpp>
+#include <anna/diameter/helpers/base/functions.hpp>
+#include <anna/diameter/helpers/dcca/functions.hpp>
// Process
#include "MyDiameterEntity.hpp"
}
+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: '<DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>="">]'
+ 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));
--- /dev/null
+// 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 <string>
+
+// Project
+//#include <anna/diameter/codec/Engine.hpp>
+
+// 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 <Engine> (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.<code>.<sequence>
+ 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 <Engine> (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;
+}
--- /dev/null
+// 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 <string>
+
+// 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
--- /dev/null
+../../resources/hex_examples/
\ No newline at end of file
+++ /dev/null
-01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000021000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152
+++ /dev/null
-01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152
+++ /dev/null
-0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc000000a000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152
+++ /dev/null
-0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc0000010000028af00000010000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152
+++ /dev/null
-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)
+++ /dev/null
-0100018c4000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b33000000010c4000000c000007d10000010840000019657063322e6570637265616c6d2e636f6d00000000000128400000146570637265616c6d2e636f6d000001026000000c01000016000001a06000000c000000010000019f6000000c00000000000003f8c000002c000028af00000410c0000010000028af004e200000000411c0000010000028af0007d00000000419c0000058000028af00000404c0000010000028af000000060000040ac000003c000028af00000416c0000010000028af000000030000041780000010000028af000000010000041880000010000028af000000000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003000003ffc0000010000028af00000002000001164000000c00000005
+++ /dev/null
-010002e8c000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b3300000001026000000c01000016000001084000003263302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e736500000000012840000018766570632e6572696373736f6e2e73650000011b600000146570637265616c6d2e636f6d000001a06000000c000000010000019f6000000c0000000000000017c000000e000028af80010000000001166000000c00000000000001bb60000028000001c26000000c00000000000001bc60000013343637303139343034313800000000086000000c0a46ee6200000403c0000010000028af0000000500000015e000000d000028af060000000000040880000010000028af000003ec000001ca6000002c000001cb2000000c00000000000001cc2000001833353734373330343030363632383030000003f8c000002c000028af0000041080000010000028af08f0d1800000041180000010000028af02faf0800000041980000058000028af00000404c0000010000028af000000090000040ac000003c000028af0000041680000010000028af000000020000041780000010000028af000000010000041880000010000028af0000000000000012e0000011000028af32343039390000000000041a80000012000028af00010a46ee3a000000000016c0000019000028af8242f099006742f0990186a4010000000000001e6000000d7665706731000000000003e8c0000010000028af0000000000000400c0000010000028af00000001000001f5c0000012000028af00010a46ee3a0000000003fec0000020000028af000001f7c0000013000028af34383030303438000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003
+++ /dev/null
-#!/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 <operation string>; 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
-
--- /dev/null
+../../resources/scripts/operation_signal.sh
\ No newline at end of file
--- /dev/null
+../../resources/xml_examples
\ No newline at end of file
+++ /dev/null
-<message version="1" name="AA-Answer" application-id="16777236" hop-by-hop-id="202475" end-by-end-id="509476">
- <avp name="Auth-Application-Id" data="16777236"/>
- <avp name="Session-Id" data="test1;afNodeHostname.afNodeHostRealm.com;1;8033450"/>
- <avp name="Origin-Host" data="sapcOwnHostId.operatorRealm.com"/>
- <avp name="Origin-State-Id" data="1428633668"/>
- <avp name="Origin-Realm" data="operatorRealm.com"/>
- <avp name="Experimental-Result">
- <avp name="Vendor-Id" data="10415"/>
- <avp name="Experimental-Result-Code" data="5063"/>
- </avp>
-</message>
+++ /dev/null
-<message version="1" name="AA-Request" p-bit="yes" application-id="16777236" hop-by-hop-id="0" end-by-end-id="0">
- <avp name="Session-Id" data="ocs3;1332774430;1;1332774430"/>
- <avp name="Auth-Application-Id" data="16777236"/>
- <avp name="Origin-Host" data="OCS3"/>
- <avp name="Origin-Realm" data="OCS3"/>
- <avp name="Destination-Realm" data="OCS3"/>
- <avp name="Destination-Host" data="OCS3"/>
- <avp name="AF-Application-Identifier" hex-data="313232"/>
- <avp name="Media-Component-Description">
- <avp name="Media-Component-Number" data="0"/>
- <avp name="AF-Application-Identifier" hex-data="313232"/>
- <avp name="Max-Requested-Bandwidth-UL" data="127"/>
- <avp name="Max-Requested-Bandwidth-DL" data="133"/>
- <avp name="Flow-Status" data="2" alias="ENABLED"/>
- <avp name="Reservation-Priority" data="0" alias="DEFAULT"/>
- </avp>
- <avp name="Service-Info-Status" data="0" alias="FINAL_SERVICE_INFORMATION"/>
- <avp name="Subscription-Id">
- <avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
- <avp name="Subscription-Id-Data" data="626037099"/>
- </avp>
- <avp name="Framed-IP-Address" hex-data="3139322e3136382e302e31"/>
- <avp name="Called-Station-Id" data="WAP.MOVISTAR"/>
-</message>
+++ /dev/null
-<message version="1" name="AA-Request" p-bit="yes" application-id="16777236" hop-by-hop-id="0" end-by-end-id="0">
- <avp name="Session-Id" data="ocs3;1332774430;1;1332774430"/>
- <avp name="Auth-Application-Id" data="16777236"/>
- <avp name="Origin-Host" data="OCS3"/>
- <avp name="Origin-Realm" data="OCS3"/>
- <avp name="Destination-Realm" data="OCS3"/>
- <avp name="Destination-Host" data="OCS3"/>
- <avp name="AF-Application-Identifier" hex-data="313232"/>
- <avp name="Media-Component-Description">
- <avp name="Media-Component-Number" data="0"/>
- <avp name="Media-Sub-Component">
- <avp name="Flow-Number" data="55"/>
- <avp name="Flow-Status" data="0" alias="ENABLED-UPLINK"/>
- </avp>
- <avp name="AF-Application-Identifier" hex-data="313232"/>
- <avp name="Max-Requested-Bandwidth-UL" data="127"/>
- <avp name="Max-Requested-Bandwidth-DL" data="133"/>
- <avp name="Flow-Status" data="2" alias="ENABLED"/>
- <avp name="Reservation-Priority" data="0" alias="DEFAULT"/>
- </avp>
- <avp name="Service-Info-Status" data="0" alias="FINAL_SERVICE_INFORMATION"/>
- <avp name="Subscription-Id">
- <avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
- <avp name="Subscription-Id-Data" data="626037099"/>
- </avp>
- <avp name="Framed-IP-Address" hex-data="3139322e3136382e302e31"/>
- <avp name="Called-Station-Id" data="WAP.MOVISTAR"/>
-</message>
+++ /dev/null
-<message version="1" name="Credit-Control-Request" p-bit="yes" application-id="4" hop-by-hop-id="1" end-by-end-id="1">
- <avp name="Session-Id" data="module-2.PTS2-BOG.sandvine.com;1287115741;0;0"/>
- <avp name="Origin-Host" data="module-2.PTS2-BOG.sandvine.com"/>
- <avp name="Origin-Realm" data="sandvine.com"/>
- <avp name="Destination-Realm" data="telefonica.com.co"/>
- <avp name="Auth-Application-Id" data="4"/>
- <avp name="Service-Context-Id" data="770.32251@3gpp.org"/>
- <avp name="CC-Request-Type" data="1" alias="INITIAL_REQUEST"/>
- <avp name="CC-Request-Number" data="0"/>
- <avp name="User-Name" data="50583211675"/>
- <avp name="Origin-State-Id" data="1339077627"/>
- <avp name="Event-Timestamp" data="3548171033"/>
- <avp name="Subscription-Id">
- <avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
- <avp name="Subscription-Id-Data" data="50583211675"/>
- </avp>
- <avp name="Multiple-Services-Indicator" data="1" alias="MULTIPLE_SERVICES_SUPPORTED"/>
- <avp name="User-Equipment-Info">
- <avp name="User-Equipment-Info-Type" data="0" alias="IMEISV"/>
- <avp name="User-Equipment-Info-Value" hex-data="33353430343630343130363438333030"/>
- </avp>
- <avp name="Service-Information">
- <avp name="PS-Information">
- <avp name="3GPP-Charging-Id" data="29"/>
- <avp name="3GPP-PDP-Type" data="0" alias="IPV4"/>
- <avp name="PDP-Address" data="10.193.49.133"/>
- <avp name="3GPP-GPRS-Neg-QoS-Profile" data="05-1b921f7196fefe74fbfefe00"/>
- <avp name="SGSN-Address" data="190.98.183.240"/>
- <avp name="GGSN-Address" data="190.98.183.243"/>
- <avp name="CG-Address" data="10.193.249.1"/>
- <avp name="3GPP-IMSI-MCC-MNC" data="71204"/>
- <avp name="3GPP-GGSN-MCC-MNC" data="71204"/>
- <avp name="3GPP-NSAPI" data="5"/>
- <avp name="Called-Station-Id" data="internet.movistar.ni"/>
- <avp name="3GPP-Selection-Mode" data="0"/>
- <avp name="3GPP-Charging-Characteristics" data="0800"/>
- <avp name="3GPP-SGSN-MCC-MNC" data="33403"/>
- <avp name="3GPP-MS-TimeZone" hex-data="4a00"/>
- <avp name="3GPP-User-Location-Info" hex-data="0117f240a4780218"/>
- <avp name="3GPP-Rat-Type" hex-data="01"/>
- <avp name="PDP-Context-Type" data="0"/>
- </avp>
- </avp>
-</message>
-../basic/hex_examples
\ No newline at end of file
+../../resources/hex_examples
\ No newline at end of file
-../basic/operation.sh
\ No newline at end of file
+../../resources/scripts/operation_signal.sh
\ No newline at end of file
-../basic/xml_examples
\ No newline at end of file
+../../resources/xml_examples
\ No newline at end of file
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, "<appid1,dictionary1#appid2,dictionary2#...#appidN,dictionaryN>: this is a list of #-separated stacks defined by a comma-separated pair <application-id,xml dictionary pathfile>. 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");
return 0;
}
+
--- /dev/null
+01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000021000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152
--- /dev/null
+01000150c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152
--- /dev/null
+0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc000000a000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152
--- /dev/null
+0100017cc000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c01000014000001084000000c4f435333000001284000000c4f4353330000011b4000000c4f435333000001254000000c4f435333000001f8c000000f000028af3132320000000205c0000098000028af00000206c0000010000028af0000000000000207c000002c000028af000001fdc0000010000028af00000037000001ffc0000010000028af00000010000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008000000133139322e3136382e302e31000000001e000000145741502e4d4f564953544152
--- /dev/null
+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)
--- /dev/null
+0100018c4000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b33000000010c4000000c000007d10000010840000019657063322e6570637265616c6d2e636f6d00000000000128400000146570637265616c6d2e636f6d000001026000000c01000016000001a06000000c000000010000019f6000000c00000000000003f8c000002c000028af00000410c0000010000028af004e200000000411c0000010000028af0007d00000000419c0000058000028af00000404c0000010000028af000000060000040ac000003c000028af00000416c0000010000028af000000030000041780000010000028af000000010000041880000010000028af000000000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003000003ffc0000010000028af00000002000001164000000c00000005
--- /dev/null
+010002e8c000011001000016ff7f245e9b81ce71000001074000003f63302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e73653b313430323932373534343b3300000001026000000c01000016000001084000003263302d31302d37302d3233382d37342d7735703176657067312e766570632e6572696373736f6e2e736500000000012840000018766570632e6572696373736f6e2e73650000011b600000146570637265616c6d2e636f6d000001a06000000c000000010000019f6000000c0000000000000017c000000e000028af80010000000001166000000c00000000000001bb60000028000001c26000000c00000000000001bc60000013343637303139343034313800000000086000000c0a46ee6200000403c0000010000028af0000000500000015e000000d000028af060000000000040880000010000028af000003ec000001ca6000002c000001cb2000000c00000000000001cc2000001833353734373330343030363632383030000003f8c000002c000028af0000041080000010000028af08f0d1800000041180000010000028af02faf0800000041980000058000028af00000404c0000010000028af000000090000040ac000003c000028af0000041680000010000028af000000020000041780000010000028af000000010000041880000010000028af0000000000000012e0000011000028af32343039390000000000041a80000012000028af00010a46ee3a000000000016c0000019000028af8242f099006742f0990186a4010000000000001e6000000d7665706731000000000003e8c0000010000028af0000000000000400c0000010000028af00000001000001f5c0000012000028af00010a46ee3a0000000003fec0000020000028af000001f7c0000013000028af34383030303438000000027480000038000028af0000010a4000000c000028af0000027580000010000028af000000010000027680000010000028af00000003
+++ /dev/null
-#!/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 <pcap_file> [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 " <results_dir>/<frame sequence>.hex"
- echo " <results_dir>/<frame sequence>.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
-
--- /dev/null
+#!/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 <operation string>; i.e.: $0 help"
+#> curl_log.txt
+#TRACE="--trace-ascii curl_log.txt"
+curl -m 1 --data "$1" $SERVER
+
--- /dev/null
+#!/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 <operation string>; 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
+
--- /dev/null
+#!/bin/bash
+ echo " sendXS <requests per second> [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> > .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 <xml_file> [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}
+
--- /dev/null
+#!/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 <pcap_file> [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 " <results_dir>/<frame sequence>.hex"
+ echo " <results_dir>/<frame sequence>.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
+
--- /dev/null
+<message version="1" name="AA-Answer" application-id="16777236" hop-by-hop-id="202475" end-by-end-id="509476">
+ <avp name="Auth-Application-Id" data="16777236"/>
+ <avp name="Session-Id" data="test1;afNodeHostname.afNodeHostRealm.com;1;8033450"/>
+ <avp name="Origin-Host" data="sapcOwnHostId.operatorRealm.com"/>
+ <avp name="Origin-State-Id" data="1428633668"/>
+ <avp name="Origin-Realm" data="operatorRealm.com"/>
+ <avp name="Experimental-Result">
+ <avp name="Vendor-Id" data="10415"/>
+ <avp name="Experimental-Result-Code" data="5063"/>
+ </avp>
+</message>
--- /dev/null
+<message version="1" name="AA-Request" p-bit="yes" application-id="16777236" hop-by-hop-id="0" end-by-end-id="0">
+ <avp name="Session-Id" data="ocs3;1332774430;1;1332774430"/>
+ <avp name="Auth-Application-Id" data="16777236"/>
+ <avp name="Origin-Host" data="OCS3"/>
+ <avp name="Origin-Realm" data="OCS3"/>
+ <avp name="Destination-Realm" data="OCS3"/>
+ <avp name="Destination-Host" data="OCS3"/>
+ <avp name="AF-Application-Identifier" hex-data="313232"/>
+ <avp name="Media-Component-Description">
+ <avp name="Media-Component-Number" data="0"/>
+ <avp name="AF-Application-Identifier" hex-data="313232"/>
+ <avp name="Max-Requested-Bandwidth-UL" data="127"/>
+ <avp name="Max-Requested-Bandwidth-DL" data="133"/>
+ <avp name="Flow-Status" data="2" alias="ENABLED"/>
+ <avp name="Reservation-Priority" data="0" alias="DEFAULT"/>
+ </avp>
+ <avp name="Service-Info-Status" data="0" alias="FINAL_SERVICE_INFORMATION"/>
+ <avp name="Subscription-Id">
+ <avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
+ <avp name="Subscription-Id-Data" data="626037099"/>
+ </avp>
+ <avp name="Framed-IP-Address" hex-data="3139322e3136382e302e31"/>
+ <avp name="Called-Station-Id" data="WAP.MOVISTAR"/>
+</message>
--- /dev/null
+<message version="1" name="AA-Request" p-bit="yes" application-id="16777236" hop-by-hop-id="0" end-by-end-id="0">
+ <avp name="Session-Id" data="ocs3;1332774430;1;1332774430"/>
+ <avp name="Auth-Application-Id" data="16777236"/>
+ <avp name="Origin-Host" data="OCS3"/>
+ <avp name="Origin-Realm" data="OCS3"/>
+ <avp name="Destination-Realm" data="OCS3"/>
+ <avp name="Destination-Host" data="OCS3"/>
+ <avp name="AF-Application-Identifier" hex-data="313232"/>
+ <avp name="Media-Component-Description">
+ <avp name="Media-Component-Number" data="0"/>
+ <avp name="Media-Sub-Component">
+ <avp name="Flow-Number" data="55"/>
+ <avp name="Flow-Status" data="0" alias="ENABLED-UPLINK"/>
+ </avp>
+ <avp name="AF-Application-Identifier" hex-data="313232"/>
+ <avp name="Max-Requested-Bandwidth-UL" data="127"/>
+ <avp name="Max-Requested-Bandwidth-DL" data="133"/>
+ <avp name="Flow-Status" data="2" alias="ENABLED"/>
+ <avp name="Reservation-Priority" data="0" alias="DEFAULT"/>
+ </avp>
+ <avp name="Service-Info-Status" data="0" alias="FINAL_SERVICE_INFORMATION"/>
+ <avp name="Subscription-Id">
+ <avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
+ <avp name="Subscription-Id-Data" data="626037099"/>
+ </avp>
+ <avp name="Framed-IP-Address" hex-data="3139322e3136382e302e31"/>
+ <avp name="Called-Station-Id" data="WAP.MOVISTAR"/>
+</message>
--- /dev/null
+<message version="1" name="Credit-Control-Request" p-bit="yes" application-id="4" hop-by-hop-id="1" end-by-end-id="1">
+ <avp name="Session-Id" data="module-2.PTS2-BOG.sandvine.com;1287115741;0;0"/>
+ <avp name="Origin-Host" data="module-2.PTS2-BOG.sandvine.com"/>
+ <avp name="Origin-Realm" data="sandvine.com"/>
+ <avp name="Destination-Realm" data="telefonica.com.co"/>
+ <avp name="Auth-Application-Id" data="4"/>
+ <avp name="Service-Context-Id" data="770.32251@3gpp.org"/>
+ <avp name="CC-Request-Type" data="1" alias="INITIAL_REQUEST"/>
+ <avp name="CC-Request-Number" data="0"/>
+ <avp name="User-Name" data="50583211675"/>
+ <avp name="Origin-State-Id" data="1339077627"/>
+ <avp name="Event-Timestamp" data="3548171033"/>
+ <avp name="Subscription-Id">
+ <avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
+ <avp name="Subscription-Id-Data" data="50583211675"/>
+ </avp>
+ <avp name="Multiple-Services-Indicator" data="1" alias="MULTIPLE_SERVICES_SUPPORTED"/>
+ <avp name="User-Equipment-Info">
+ <avp name="User-Equipment-Info-Type" data="0" alias="IMEISV"/>
+ <avp name="User-Equipment-Info-Value" hex-data="33353430343630343130363438333030"/>
+ </avp>
+ <avp name="Service-Information">
+ <avp name="PS-Information">
+ <avp name="3GPP-Charging-Id" data="29"/>
+ <avp name="3GPP-PDP-Type" data="0" alias="IPV4"/>
+ <avp name="PDP-Address" data="10.193.49.133"/>
+ <avp name="3GPP-GPRS-Neg-QoS-Profile" data="05-1b921f7196fefe74fbfefe00"/>
+ <avp name="SGSN-Address" data="190.98.183.240"/>
+ <avp name="GGSN-Address" data="190.98.183.243"/>
+ <avp name="CG-Address" data="10.193.249.1"/>
+ <avp name="3GPP-IMSI-MCC-MNC" data="71204"/>
+ <avp name="3GPP-GGSN-MCC-MNC" data="71204"/>
+ <avp name="3GPP-NSAPI" data="5"/>
+ <avp name="Called-Station-Id" data="internet.movistar.ni"/>
+ <avp name="3GPP-Selection-Mode" data="0"/>
+ <avp name="3GPP-Charging-Characteristics" data="0800"/>
+ <avp name="3GPP-SGSN-MCC-MNC" data="33403"/>
+ <avp name="3GPP-MS-TimeZone" hex-data="4a00"/>
+ <avp name="3GPP-User-Location-Info" hex-data="0117f240a4780218"/>
+ <avp name="3GPP-Rat-Type" hex-data="01"/>
+ <avp name="PDP-Context-Type" data="0"/>
+ </avp>
+ </avp>
+</message>
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)
*/
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
a_dictionary(NULL),
a_validationDepth(ValidationDepth::FirstError),
a_validationMode(ValidationMode::AfterDecoding),
+ a_singleFailedAVP(true),
a_ignoreFlags(false),
a_selectStackWithApplicationId(false),
a_fixMode(FixMode::BeforeEncoding) {
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: ";
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");
// 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