//#include <anna/diameter/codec/EngineManager.hpp>
//#include <anna/http/Transport.hpp>
//#include <anna/diameter/stack/Engine.hpp>
-//#include <anna/diameter/helpers/base/functions.hpp>
+#include <anna/diameter/helpers/base/functions.hpp>
//#include <anna/time/functions.hpp>
//#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
//#include <anna/testing/defines.hpp>
#include <anna/xml/xml.hpp>
//#include <anna/diameter.comm/OriginHost.hpp>
//#include <anna/diameter.comm/OriginHostManager.hpp>
+#include <anna/diameter.comm/Message.hpp>
//
//// Process
//#include <Launcher.hpp>
/////////////////////
// Flow operations //
/////////////////////
-bool EventOperation::sendmsg2e(std::string &response, const std::string & diameterJson) {
+bool EventOperation::sendmsg_hex_2e(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
+ anna::diameter::codec::Message codecMsg; // auxiliary codec message
+ bool success;
+ anna::diameter::comm::Message *msg;
+ if(msg_or_hex) {
+ std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
+ if (!success) {
+ response += "json to xml failed, unable to send message !";
+ return false;
+ }
+ codecMsg.loadXMLString(diameterXml);
+ try {
+ my_app.updateOperatedOriginHostWithMessage(codecMsg);
+ msg = my_app.getOperatedHost()->createCommMessage();
+ msg->clearBody();
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response += "invalid operated host";
+ return false;
+ }
+ try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
+ msg->setBody(codecMsg.code());
+ } else {
+ // Get DataBlock from hex content:
+ anna::DataBlock db_aux(true);
+ std::string hexString = diameterJson_or_Hex;
+ hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
+ LOGDEBUG(
+ std::string msg = "Hex string (remove colons if exists): ";
+ msg += hexString;
+ anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+ );
+ anna::functions::fromHexString(hexString, db_aux); // could launch exception
+ try {
+ my_app.updateOperatedOriginHostWithMessage(db_aux);
+ msg = my_app.getOperatedHost()->createCommMessage();
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response += "invalid operated host";
+ return false;
+ }
+ msg->setBody(db_aux);
+ try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
+ }
+ success = my_app.getOperatedEntity()->send(msg);
+ my_app.getOperatedHost()->releaseCommMessage(msg);
- return true; // OK
-}
-
-bool EventOperation::sendmsg2c(std::string &response, const std::string & diameterJson) {
-
- Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-
+ // Detailed log:
+ if(my_app.getOperatedHost()->logEnabled()) {
+ anna::diameter::comm::Server *usedServer = my_app.getOperatedEntity()->getLastUsedResource();
+ anna::diameter::comm::ClientSession *usedClientSession = usedServer ? usedServer->getLastUsedResource() : NULL;
+ std::string detail = usedClientSession ? usedClientSession->asString() : "<null client session>"; // shouldn't happen
+ my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2e" : "send2eError"), detail);
+ }
- return true; // OK
+ response = "Operation processed"; // could be failed
+ return success;
}
-bool EventOperation::answermsg2e(std::string &response, const std::string & diameterJson) {
+bool EventOperation::sendmsg_hex_2c(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
+ anna::diameter::codec::Message codecMsg; // auxiliary codec message
+ bool success;
+ anna::diameter::comm::Message *msg;
+ if(msg_or_hex) {
+ std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
+ if (!success) {
+ response += "json to xml failed, unable to send message !";
+ return false;
+ }
+ codecMsg.loadXMLString(diameterXml);
+ try {
+ my_app.updateOperatedOriginHostWithMessage(codecMsg);
+ msg = my_app.getOperatedHost()->createCommMessage();
+ msg->clearBody();
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response += "invalid operated host";
+ return false;
+ }
+ try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
+ msg->setBody(codecMsg.code());
+ } else {
+ // Get DataBlock from hex content:
+ anna::DataBlock db_aux(true);
+ std::string hexString = diameterJson_or_Hex;
+ hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
+ LOGDEBUG(
+ std::string msg = "Hex string (remove colons if exists): ";
+ msg += hexString;
+ anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+ );
+ anna::functions::fromHexString(hexString, db_aux); // could launch exception
+ try {
+ my_app.updateOperatedOriginHostWithMessage(db_aux);
+ msg = my_app.getOperatedHost()->createCommMessage();
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response += "invalid operated host";
+ return false;
+ }
+ msg->setBody(db_aux);
+ try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
+ }
+ success = my_app.getOperatedServer()->send(msg);
+ my_app.getOperatedHost()->releaseCommMessage(msg);
- return true; // OK
-}
-
-bool EventOperation::answermsg2c(std::string &response, const std::string & diameterJson) {
-
- Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-
+ // Detailed log:
+ if(my_app.getOperatedHost()->logEnabled()) {
+ anna::diameter::comm::ServerSession *usedServerSession = my_app.getOperatedServer()->getLastUsedResource();
+ std::string detail = usedServerSession ? usedServerSession->asString() : "<null server session>"; // shouldn't happen
+ my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
+ }
- return true; // OK
+ response = "Operation processed"; // could be failed
+ return success;
}
-bool EventOperation::answermsg2e_action(std::string &response, const std::string & action) {
+bool EventOperation::answermsg_action_2e(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
+ anna::diameter::codec::Message codecMsg; // auxiliary codec message
+ anna::diameter::codec::Message *message;
+ bool success;
+ if (msg_or_action) {
+ std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
+ if (!success) {
+ response += "json to xml failed, unable to send message !";
+ return false;
+ }
+ codecMsg.loadXMLString(diameterXml);
+ try {
+ my_app.updateOperatedOriginHostWithMessage(codecMsg);
+ message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
+ LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response += "invalid operated host";
+ return false;
+ }
- return true; // OK
-}
-
-bool EventOperation::answermsg2c_action(std::string &response, const std::string & action) {
-
- Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
+ if(message->isRequest()) {
+ response += "cannot program diameter requests. Answer type must be provided";
+ return false;
+ }
+ int code = message->getId().first;
+ LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
+ response = "Added 'answer to entity' to the FIFO queue corresponding to its message code";
+ my_app.getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
+ }
+ else { // action
+
+ if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
+ response = anna::functions::encodeBase64(my_app.getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY"));
+ } else if (diameterJson_or_action == "rotate") {
+ my_app.getOperatedEntity()->getReactingAnswers()->rotate(true);
+ response = "rotate";
+ } else if (diameterJson_or_action == "exhaust") {
+ my_app.getOperatedEntity()->getReactingAnswers()->rotate(false);
+ response = "exhaust";
+ } else if (diameterJson_or_action == "clear") {
+ my_app.getOperatedEntity()->getReactingAnswers()->clear();
+ response = "clear";
+ } else if (diameterJson_or_action == "dump") {
+ my_app.getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
+ response = "dump";
+ }
+ }
return true; // OK
}
-bool EventOperation::sendhex2e(std::string &response, const std::string & diameterHex) {
+bool EventOperation::answermsg_action_2c(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
+ anna::diameter::codec::Message codecMsg; // auxiliary codec message
+ anna::diameter::codec::Message *message;
+ bool success;
+ if (msg_or_action) {
+ std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
+ if (!success) {
+ response += "json to xml failed, unable to send message !";
+ return false;
+ }
+ codecMsg.loadXMLString(diameterXml);
+ try {
+ my_app.updateOperatedOriginHostWithMessage(codecMsg);
+ message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
+ LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response += "invalid operated host";
+ return false;
+ }
- return true; // OK
-}
-
-bool EventOperation::sendhex2c(std::string &response, const std::string & diameterHex) {
-
- Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
+ if(message->isRequest()) {
+ response += "cannot program diameter requests. Answer type must be provided";
+ return false;
+ }
+ int code = message->getId().first;
+ LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
+ my_app.getOperatedServer()->getReactingAnswers()->addMessage(code, message);
+ response = "Added 'answer to client' to the FIFO queue corresponding to its message code";
+ }
+ else { // action
+
+ if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
+ response = anna::functions::encodeBase64(my_app.getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT"));
+ } else if (diameterJson_or_action == "rotate") {
+ my_app.getOperatedServer()->getReactingAnswers()->rotate(true);
+ response = "rotate";
+ } else if (diameterJson_or_action == "exhaust") {
+ my_app.getOperatedServer()->getReactingAnswers()->rotate(false);
+ response = "exhaust";
+ } else if (diameterJson_or_action == "clear") {
+ my_app.getOperatedServer()->getReactingAnswers()->clear();
+ response = "clear";
+ } else if (diameterJson_or_action == "dump") {
+ my_app.getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
+ response = "dump";
+ }
+ }
return true; // OK
}
-
/////////////////
// FSM testing //
/////////////////
bool show_stats(std::string &response);
// Flow operations
- bool sendmsg2e(std::string &response, const std::string & diameterJson);
- bool sendmsg2c(std::string &response, const std::string & diameterJson);
- bool answermsg2e(std::string &response, const std::string & diameterJson);
- bool answermsg2c(std::string &response, const std::string & diameterJson);
- bool answermsg2e_action(std::string &response, const std::string & action = "list");
- bool answermsg2c_action(std::string &response, const std::string & action = "list");
- bool sendhex2e(std::string &response, const std::string & diameterHex);
- bool sendhex2c(std::string &response, const std::string & diameterHex);
+ bool sendmsg_hex_2e(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex);
+ bool sendmsg_hex_2c(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex);
+ bool answermsg_action_2e(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action);
+ bool answermsg_action_2c(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action);
// FSM testing
// test_id__<command>
a_counterRecorderClock = NULL;
a_workingNode = NULL;
+ a_operatedHost = NULL;
a_httpServerSocket = NULL;
}
return (getOriginHost(originHost));
}
+anna::diameter::comm::OriginHost *Launcher::getOriginHost(const anna::DataBlock &messageDataBlock) const throw(anna::RuntimeException) {
+ std::string originHost = anna::diameter::helpers::base::functions::getOriginHost(messageDataBlock);
+ return (getOriginHost(originHost));
+}
+
bool Launcher::uniqueOriginHost() const throw() {
anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
return (ohm.size() == 1);
}
-
void Launcher::updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException) {
if (!a_operatedHost) // priority for working node by mean 'node' operation
a_operatedHost = getOriginHost(message);
}
+void Launcher::updateOperatedOriginHostWithMessage(const anna::DataBlock &messageDataBlock) throw(anna::RuntimeException) {
+ if (!a_operatedHost) // priority for working node by mean 'node' operation
+ a_operatedHost = getOriginHost(messageDataBlock);
+}
+
anna::diameter::comm::OriginHost *Launcher::getWorkingNode() const throw(anna::RuntimeException) {
if(!a_workingNode)
throw anna::RuntimeException("Working node not identified (try to load services)", ANNA_FILE_LOCATION);
// Get DataBlock from file with hex content:
if(!getDataBlockFromHexFile(param1, db_aux))
throw anna::RuntimeException("Error reading hex file provided", ANNA_FILE_LOCATION);
+ updateOperatedOriginHostWithMessage(db_aux);
msg = getOperatedHost()->createCommMessage();
msg->setBody(db_aux);
try { if(getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
std::string detail = usedClientSession ? usedClientSession->asString() : "<null client session>"; // shouldn't happen
getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2e" : "send2eError"), detail);
}
+ } else if((opType == "sendxml2c") || (opType == "sendhex2c")) {
+ anna::diameter::comm::Message *msg;
+
+ if(opType == "sendxml2c") {
+ codecMsg.loadXMLFile(param1);
+ updateOperatedOriginHostWithMessage(codecMsg);
+ msg = getOperatedHost()->createCommMessage();
+ msg->clearBody();
+ try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
+
+ msg->setBody(codecMsg.code());
+ } else {
+ // Get DataBlock from file with hex content:
+ if(!getDataBlockFromHexFile(param1, db_aux))
+ throw anna::RuntimeException("Error reading hex file provided", ANNA_FILE_LOCATION);
+ updateOperatedOriginHostWithMessage(db_aux);
+ msg = getOperatedHost()->createCommMessage();
+ msg->setBody(db_aux);
+ }
+
+ bool success = getOperatedServer()->send(msg);
+ getOperatedHost()->releaseCommMessage(msg);
+
+ // Detailed log:
+ if(getOperatedHost()->logEnabled()) {
+ anna::diameter::comm::ServerSession *usedServerSession = getOperatedServer()->getLastUsedResource();
+ std::string detail = usedServerSession ? usedServerSession->asString() : "<null server session>"; // shouldn't happen
+ getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
+ }
+ } else if(opType == "answerxml2e") {
+
+ if(param1 == "") { // programmed answers FIFO's to stdout
+ response = getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY");
+ return true; // OK
+ } else if (param1 == "rotate") {
+ getOperatedEntity()->getReactingAnswers()->rotate(true);
+ } else if (param1 == "exhaust") {
+ getOperatedEntity()->getReactingAnswers()->rotate(false);
+ } else if (param1 == "clear") {
+ getOperatedEntity()->getReactingAnswers()->clear();
+ } else if (param1 == "dump") {
+ getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
+ } else {
+ codecMsg.loadXMLFile(param1);
+ updateOperatedOriginHostWithMessage(codecMsg);
+ anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
+ LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
+
+ if(message->isRequest())
+ throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
+
+ int code = message->getId().first;
+ LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
+ getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
+ }
+ } else if(opType == "answerxml2c") {
+
+ if(param1 == "") { // programmed answers FIFO's to stdout
+ response = getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT");
+ return true; // OK
+ } else if (param1 == "rotate") {
+ getOperatedServer()->getReactingAnswers()->rotate(true);
+ } else if (param1 == "exhaust") {
+ getOperatedServer()->getReactingAnswers()->rotate(false);
+ } else if (param1 == "clear") {
+ getOperatedServer()->getReactingAnswers()->clear();
+ } else if (param1 == "dump") {
+ getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
+ } else {
+ codecMsg.loadXMLFile(param1);
+ updateOperatedOriginHostWithMessage(codecMsg);
+ anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
+ LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
+
+ if(message->isRequest())
+ throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
+
+ int code = message->getId().first;
+ LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
+ getOperatedServer()->getReactingAnswers()->addMessage(code, message);
+ }
} else if((opType == "burst")) {
if (!uniqueOriginHost())
}
}
- } else if((opType == "sendxml2c") || (opType == "sendhex2c")) {
- anna::diameter::comm::Message *msg;
-
- if(opType == "sendxml2c") {
- codecMsg.loadXMLFile(param1);
- updateOperatedOriginHostWithMessage(codecMsg);
- msg = getOperatedHost()->createCommMessage();
- msg->clearBody();
- try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
-
- msg->setBody(codecMsg.code());
- } else {
- // Get DataBlock from file with hex content:
- if(!getDataBlockFromHexFile(param1, db_aux))
- throw anna::RuntimeException("Error reading hex file provided", ANNA_FILE_LOCATION);
- msg = getOperatedHost()->createCommMessage();
- msg->setBody(db_aux);
- }
-
- bool success = getOperatedServer()->send(msg);
- getOperatedHost()->releaseCommMessage(msg);
-
- // Detailed log:
- if(getOperatedHost()->logEnabled()) {
- anna::diameter::comm::ServerSession *usedServerSession = getOperatedServer()->getLastUsedResource();
- std::string detail = usedServerSession ? usedServerSession->asString() : "<null server session>"; // shouldn't happen
- getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
- }
} else if(opType == "loadxml") {
codecMsg.loadXMLFile(param1);
response = codecMsg.asXMLString();
int diameterServerSessions = atoi(param1.c_str());
getOperatedServer()->setMaxConnections(diameterServerSessions);
- } else if(opType == "answerxml2c") {
- if(param1 == "") { // programmed answers FIFO's to stdout
- response = getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT");
- return true; // OK
- } else if (param1 == "rotate") {
- getOperatedServer()->getReactingAnswers()->rotate(true);
- } else if (param1 == "exhaust") {
- getOperatedServer()->getReactingAnswers()->rotate(false);
- } else if (param1 == "clear") {
- getOperatedServer()->getReactingAnswers()->clear();
- } else if (param1 == "dump") {
- getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
- } else {
- codecMsg.loadXMLFile(param1);
- updateOperatedOriginHostWithMessage(codecMsg);
- anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
- LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
- if(message->isRequest())
- throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
- int code = message->getId().first;
- LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
- getOperatedServer()->getReactingAnswers()->addMessage(code, message);
- }
- } else if(opType == "answerxml2e") {
-
- if(param1 == "") { // programmed answers FIFO's to stdout
- response = getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY");
- return true; // OK
- } else if (param1 == "rotate") {
- getOperatedEntity()->getReactingAnswers()->rotate(true);
- } else if (param1 == "exhaust") {
- getOperatedEntity()->getReactingAnswers()->rotate(false);
- } else if (param1 == "clear") {
- getOperatedEntity()->getReactingAnswers()->clear();
- } else if (param1 == "dump") {
- getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
- } else {
- codecMsg.loadXMLFile(param1);
- updateOperatedOriginHostWithMessage(codecMsg);
- anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
- LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
-
- if(message->isRequest())
- throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
-
- int code = message->getId().first;
- LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
- getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
- }
} else {
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
}
+
+
// HTTP response
response = "Operation correctly processed: "; response += operation;
if (opt_response != "") {
void setNodeAuto() { a_workingNode = NULL; a_operatedHost = NULL; }
anna::diameter::comm::OriginHost *getOriginHost(const std::string &name) const throw(anna::RuntimeException);
anna::diameter::comm::OriginHost *getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException);
+ anna::diameter::comm::OriginHost *getOriginHost(const anna::DataBlock &messageDataBlock) const throw(anna::RuntimeException);
+
bool uniqueOriginHost() const throw();
// Operated host for communication resources smart assignment ////////////////////////////////////////////////////////////
void updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException);
+ void updateOperatedOriginHostWithMessage(const anna::DataBlock &messageDataBlock) throw(anna::RuntimeException);
anna::diameter::comm::OriginHost *getWorkingNode() const throw(anna::RuntimeException);
anna::diameter::comm::OriginHost *getOperatedHost() const throw(anna::RuntimeException);
void setOperatedHost(anna::diameter::comm::OriginHost *);
}
catch(anna::RuntimeException &ex) {
ex.trace();
- LOGINFORMATION(anna::Logger::information("XXXXXXXXXXXX EXCEPCION PENDIENTE DE CATCHEAR ABAJO !!! XXXXXXXXXXXXXXXXX", ANNA_FILE_LOCATION));
+ LOGINFORMATION(anna::Logger::information("doPOST exception: TODO control in inner method. Check traces", ANNA_FILE_LOCATION));
}
}
// Flow operations
else if ((opType == "/sendmsg2e")||(opType == "/sendmsg2c")) {
- auto it = j.find("diameterJson");
- if (it != j.end())
+ auto itJ = j.find("diameterJson");
+ if (itJ != j.end()) {
if (opType == "/sendmsg2e")
- result = eop.sendmsg2e(response, it->dump(4)); // get the object as string (always indentation = 4)
+ result = eop.sendmsg_hex_2e(response, itJ->dump(4), true); // get the object as string (always indentation = 4)
else
- result = eop.sendmsg2c(response, it->dump(4)); // get the object as string (always indentation = 4)
+ result = eop.sendmsg_hex_2c(response, itJ->dump(4), true); // get the object as string (always indentation = 4)
+ }
else
response += "missing 'diameterJson' object field";
}
+ else if ((opType == "/sendhex2e")||(opType == "/sendhex2c")) {
+ auto itH = j.find("diameterHex");
+ if (itH != j.end())
+ if (opType == "/sendhex2e")
+ result = eop.sendmsg_hex_2e(response, *itH, false);
+ else
+ result = eop.sendmsg_hex_2c(response, *itH, false);
+ else
+ response += "missing 'diameterHex' string field";
+ }
else if ((opType == "/answermsg2e")||(opType == "/answermsg2c")) {
auto itJ = j.find("diameterJson");
auto itA = j.find("action");
bool hasA = (itA != j.end());
if (hasJ != hasA) { // XOR
-
- if (opType == "/answermsg2e") {
- if (hasJ)
- result = eop.answermsg2e(response, itJ->dump(4)); // get the object as string (always indentation = 4)
- else
- result = eop.answermsg2e_action(response, *itA);
- }
- else {
- if (hasJ)
- result = eop.answermsg2c(response, itJ->dump(4)); // get the object as string (always indentation = 4)
- else
- result = eop.answermsg2c_action(response, *itA);
+ std::string action;
+ if (hasA) {
+ action = *itA;
+ if (action == "") action = "list"; // default if missing
}
+
+ if (opType == "/answermsg2e")
+ result = eop.answermsg_action_2e(response, (hasJ ? itJ->dump(4) : action), hasJ); // itJ: get the object as string (always indentation = 4)
+ else
+ result = eop.answermsg_action_2c(response, (hasJ ? itJ->dump(4) : action), hasJ); // itJ: get the object as string (always indentation = 4)
}
else
response += "missing 'diameterJson' object or 'action' string field (only one accepted)";
}
- else if ((opType == "/sendhex2e")||(opType == "/sendhex2c")) {
- auto it = j.find("diameterHex");
- if (it != j.end())
- if (opType == "/sendhex2e")
- result = eop.sendhex2e(response, *it);
- else
- result = eop.sendhex2c(response, *it);
- else
- response += "missing 'diameterHex' string field";
- }
// FSM testing
// test_id__<command>
rm -f counters/* test-reports/* *.csv
export LD_LIBRARY_PATH=$PWD/dynlibs
args=$(eval echo $(grep -v ^# $ARGS))
+#ulimit -c unlimited
./ADML ${args} &
echo $! > .pid
echo "Done !"
```
{
"result":"<true or false>",
- "response":"<response>"
+ "response":"<response or base64-encoded output for 'list' action>"
}
```
```
{
"result":"<true or false>",
- "response":"<response>"
+ "response":"<response or base64-encoded output for 'list' action>"
}
```
--- /dev/null
+import pytest
+
+
+def test_001_given_diameter_answer_json_representation_i_want_to_provision_it_to_reacts_to_diameter_client_requests(resources, admlc):
+
+ requestBody = { "name":"ownHostId.operatorRealm.com" }
+ responseBodyRef = { "success":"true", "response":"Forced node is now 'ownHostId.operatorRealm.com'" }
+
+ # Send POST
+ response = admlc.postDict("/node", requestBody)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ requestBody = resources("aaa-diameterJson-request.json")
+ responseBodyRef = { "success":"true", "response":"Added 'answer to client' to the FIFO queue corresponding to its message code" }
+
+ # Send POST
+ response = admlc.post("/answermsg2c", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_002_i_want_to_list_the_answer_to_client_FIFO_queue(b64_decode, mylogger, admlc):
+
+ requestBody = { "action":"list" } # also empty action is interpreted as "list"
+
+ # Send POST
+ response = admlc.postDict("/answermsg2c", requestBody)
+
+ # Verify response is ok (omit response content because it is dynamic: will be logged)
+ assert response["status"] == 200
+ assert response["body"]["success"] == "true"
+ body_response = b64_decode(response["body"]["response"])
+ mylogger.info("\nBASE64 DECODED RESPONSE: \n\n" + body_response)
+
+def test_003_i_want_to_dump_the_answer_to_client_FIFO_queue(admlc):
+
+ requestBody = { "action":"dump" }
+ responseBodyRef = { "success":"true", "response":"dump" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2c", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_004_i_want_to_clear_the_answer_to_client_FIFO_queue(admlc):
+
+ requestBody = { "action":"clear" }
+ responseBodyRef = { "success":"true", "response":"clear" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2c", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_005_i_want_to_exhaust_the_answer_to_client_FIFO_queue(admlc):
+
+ requestBody = { "action":"exhaust" }
+ responseBodyRef = { "success":"true", "response":"exhaust" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2c", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_006_i_want_to_rotate_the_answer_to_client_FIFO_queue(admlc):
+
+ requestBody = { "action":"rotate" }
+ responseBodyRef = { "success":"true", "response":"rotate" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2c", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
--- /dev/null
+import pytest
+
+
+def test_001_given_diameter_answer_json_representation_i_want_to_provision_it_to_reacts_to_diameter_entity_requests(resources, admlc):
+
+ requestBody = { "name":"afHost.afRealm.com" }
+ responseBodyRef = { "success":"true", "response":"Forced node is now 'afHost.afRealm.com'" }
+
+ # Send POST
+ response = admlc.postDict("/node", requestBody)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ requestBody = resources("aaa-diameterJson-request.json")
+ responseBodyRef = { "success":"true", "response":"Added 'answer to entity' to the FIFO queue corresponding to its message code" }
+
+ # Send POST
+ response = admlc.post("/answermsg2e", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_002_i_want_to_list_the_answer_to_entity_FIFO_queue(b64_decode, mylogger, admlc):
+
+ requestBody = { "action":"list" } # also empty action is interpreted as "list"
+
+ # Send POST
+ response = admlc.postDict("/answermsg2e", requestBody)
+
+ # Verify response is ok (omit response content because it is dynamic: will be logged)
+ assert response["status"] == 200
+ assert response["body"]["success"] == "true"
+ body_response = b64_decode(response["body"]["response"])
+ mylogger.info("\nBASE64 DECODED RESPONSE: \n\n" + body_response)
+
+def test_003_i_want_to_dump_the_answer_to_entity_FIFO_queue(admlc):
+
+ requestBody = { "action":"dump" }
+ responseBodyRef = { "success":"true", "response":"dump" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2e", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_004_i_want_to_clear_the_answer_to_entity_FIFO_queue(admlc):
+
+ requestBody = { "action":"clear" }
+ responseBodyRef = { "success":"true", "response":"clear" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2e", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_005_i_want_to_exhaust_the_answer_to_entity_FIFO_queue(admlc):
+
+ requestBody = { "action":"exhaust" }
+ responseBodyRef = { "success":"true", "response":"exhaust" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2e", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+def test_006_i_want_to_rotate_the_answer_to_entity_FIFO_queue(admlc):
+
+ requestBody = { "action":"rotate" }
+ responseBodyRef = { "success":"true", "response":"rotate" }
+
+ # Send POST
+ response = admlc.postDict("/answermsg2e", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
--- /dev/null
+import pytest
+
+def test_001_given_diameter_hex_representation_i_want_to_send_message_to_diameter_entity_and_check_it_fails_for_auto_node(resources, admlc):
+
+ responseBodyRef = { "success":"true", "response":"Working node has been set to automatic" }
+
+ # Send POST
+ response = admlc.post("/node-auto")
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ diameterHex = resources("aar.hex")
+ #requestBody = resources("aaa-diameterHex.json.in", diameterHex=diameterHex.rstrip())
+ requestBodyDict = { "diameterHex":"{}".format(diameterHex.rstrip()) }
+
+ responseBodyRef = { "success":"false", "response":"Internal error (check ADML traces): invalid operated host" }
+
+ # Send POST
+ response = admlc.postDict("/sendhex2e", requestBodyDict)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ # IT FAILS BECAUSE MESSAGE SENT HAS OCS3 AS ORIGIN HOST, AND THIS IS NOT REGISTERED, SO node-auto COULD NOT DEDUCE THE CORRECT RESOURCE
+
+@pytest.mark.xfail(reason="Server must receive client connection to be available. Component test is very fast and this could fail the first time. Wait and test again. TODO: wait for available status after 'services' loading.")
+def test_002_given_diameter_hex_representation_i_want_to_send_message_to_diameter_entity_and_check_it_succeed_for_correct_node(resources, admlc):
+
+ requestBody = { "name":"afHost.afRealm.com" }
+ responseBodyRef = { "success":"true", "response":"Forced node is now 'afHost.afRealm.com'" }
+
+ # Send POST
+ response = admlc.postDict("/node", requestBody)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ diameterHex = resources("aar.hex")
+ #requestBody = resources("aaa-diameterHex.json.in", diameterHex=diameterHex.rstrip())
+ requestBodyDict = { "diameterHex":"{}".format(diameterHex.rstrip()) }
+
+ responseBodyRef = { "success":"true", "response":"Operation processed" }
+
+ # Send POST
+ response = admlc.postDict("/sendhex2e", requestBodyDict)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+@pytest.mark.xfail(reason="Server must receive client connection to be available. Component test is very fast and this could fail the first time. Wait and test again. TODO: wait for available status after 'services' loading.")
+def test_003_given_diameter_hex_representation_i_want_to_send_message_to_diameter_client_and_check_it_succeed_for_correct_node(resources, admlc):
+
+# # WE HAVE TO CONFIGURE THE CLIENT AS OPERATED HOST, BECAUSE HEX SENDING PROCEDURE IS NOT GOING TO UPDATE OPERATED HOST WITH CODEC:
+# requestBody = { "name":"afHost.afRealm.com" }
+# responseBodyRef = { "success":"true", "response":"Forced node is now 'afHost.afRealm.com'" }
+ requestBody = { "name":"ownHostId.operatorRealm.com" }
+ responseBodyRef = { "success":"true", "response":"Forced node is now 'ownHostId.operatorRealm.com'" }
+
+ # Send POST
+ response = admlc.postDict("/node", requestBody)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ # NORMALLY, AAR IS NOT THE KIND OF MESSAGE TO SEND AS DIAMETER SERVER BUT RAR, etc, BUT THIS IS VALID FOR OUR TESTING
+
+ # We will use a message which origin-host and destination-host fits the real configured ones in services, and also is ready
+ # to be sent from local diameter server to the client:
+ diameterHex = resources("aarFromOwnToAF.hex")
+ #requestBody = resources("aaa-diameterHex.json.in", diameterHex=diameterHex.rstrip())
+ requestBodyDict = { "diameterHex":"{}".format(diameterHex.rstrip()) }
+
+ responseBodyRef = { "success":"true", "response":"Operation processed" }
+
+ # Send POST
+ response = admlc.postDict("/sendhex2c", requestBodyDict)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
--- /dev/null
+import pytest
+
+def test_001_given_diameter_json_representation_i_want_to_send_message_to_diameter_entity_and_check_it_fails_for_auto_node(resources, admlc):
+
+ responseBodyRef = { "success":"true", "response":"Working node has been set to automatic" }
+
+ # Send POST
+ response = admlc.post("/node-auto")
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ requestBody = resources("aar-diameterJson-request.json")
+ responseBodyRef = { "success":"false", "response":"Internal error (check ADML traces): invalid operated host" }
+
+ # Send POST
+ response = admlc.post("/sendmsg2e", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ # IT FAILS BECAUSE MESSAGE SENT HAS OCS3 AS ORIGIN HOST, AND THIS IS NOT REGISTERED, SO node-auto COULD NOT DEDUCE THE CORRECT RESOURCE
+
+@pytest.mark.xfail(reason="Server must receive client connection to be available. Component test is very fast and this could fail the first time. Wait and test again. TODO: wait for available status after 'services' loading.")
+def test_002_given_diameter_json_representation_i_want_to_send_message_to_diameter_entity_and_check_it_succeed_for_forced_node(resources, admlc):
+
+ requestBody = { "name":"afHost.afRealm.com" }
+ responseBodyRef = { "success":"true", "response":"Forced node is now 'afHost.afRealm.com'" }
+
+ # Send POST
+ response = admlc.postDict("/node", requestBody)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ requestBody = resources("aar-diameterJson-request.json")
+ responseBodyRef = { "success":"true", "response":"Operation processed" }
+
+ # Send POST
+ response = admlc.post("/sendmsg2e", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+@pytest.mark.xfail(reason="Server must receive client connection to be available. Component test is very fast and this could fail the first time. Wait and test again. TODO: wait for available status after 'services' loading.")
+def test_003_given_diameter_json_representation_i_want_to_send_message_to_diameter_client_and_check_it_succeed_for_auto_node(resources, admlc):
+
+ responseBodyRef = { "success":"true", "response":"Working node has been set to automatic" }
+
+ # Send POST
+ response = admlc.post("/node-auto")
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+ # NORMALLY, AAR IS NOT THE KIND OF MESSAGE TO SEND AS DIAMETER SERVER BUT RAR, etc, BUT THIS IS VALID FOR OUR TESTING
+
+ # We will use a message which origin-host and destination-host fits the real configured ones in services, and also is ready
+ # to be sent from local diameter server to the client:
+ requestBody = resources("aar-diameterJsonFromOwnToAF-request.json")
+ responseBodyRef = { "success":"true", "response":"Operation processed" }
+
+ # Send POST
+ response = admlc.post("/sendmsg2c", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
def test_001_given_diameter_json_representation_i_want_to_encode_it_through_adml_service(resources, admlc):
- requestBody = resources("diameterJson-request.json")
+ requestBody = resources("aar-diameterJson-request.json")
# reponse field in response body, should carry the diameter encoding for json message sent to ADML:
diameterHex = resources("aar.hex")
def test_001_given_diameter_hex_representation_i_want_to_decode_it_through_adml_service(b64_encode, resources, admlc):
diameterHex = resources("aaa.hex")
- #requestBody = resources("diameterHex.json.in", diameterHex=diameterHex.rstrip())
+ #requestBody = resources("aaa-diameterHex.json.in", diameterHex=diameterHex.rstrip())
requestBodyDict = { "diameterHex":"{}".format(diameterHex.rstrip()) }
# reponse field in response body, should carry the base64 encoding for xml message decoded by ADML:
def test_001_given_diameter_json_representation_i_want_to_load_it_through_adml_service(b64_encode, resources, admlc):
- requestBody = resources("diameterJson-request.json")
+ requestBody = resources("aar-diameterJson-request.json")
# reponse field in response body, should carry the base64 encoding for xml message loaded by ADML:
xmlExpected = resources("aar.xml")
--- /dev/null
+{{
+ "diameterHex":"{diameterHex}"
+}}
--- /dev/null
+{
+ "diameterJson": {
+ "message": {
+ "@application-id": "16777236",
+ "@end-to-end-id": "315108",
+ "@hop-by-hop-id": "816067",
+ "@name": "AA-Answer",
+ "@version": "1",
+ "avp": [
+ {
+ "@data": "tc_01_FullAVPs;afNodeHostname.afNodeHostRealm.com;1;859608",
+ "@name": "Session-Id"
+ },
+ {
+ "@data": "16777236",
+ "@name": "Auth-Application-Id"
+ },
+ {
+ "@data": "sapcOwnHostId.operatorRealm.com",
+ "@name": "Origin-Host"
+ },
+ {
+ "@data": "operatorRealm.com",
+ "@name": "Origin-Realm"
+ },
+ {
+ "@alias": "DIAMETER_SUCCESS",
+ "@data": "2001",
+ "@name": "Result-Code"
+ },
+ {
+ "@name": "Supported-Features",
+ "avp": [
+ {
+ "@data": "10415",
+ "@name": "Vendor-Id"
+ },
+ {
+ "@data": "1",
+ "@name": "Feature-List-ID"
+ },
+ {
+ "@data": "19",
+ "@name": "Feature-List"
+ }
+ ]
+ },
+ {
+ "@data": "1427215015",
+ "@name": "Origin-State-Id"
+ }
+ ]
+ }
+ }
+}
--- /dev/null
+{
+ "diameterJson": {
+ "message": {
+ "@application-id": "16777236",
+ "@end-to-end-id": "0",
+ "@hop-by-hop-id": "0",
+ "@name": "AA-Request",
+ "@p-bit": "yes",
+ "@version": "1",
+ "avp": [
+ {
+ "@data": "ocs3;1332774430;1;1332774430",
+ "@name": "Session-Id"
+ },
+ {
+ "@data": "16777236",
+ "@name": "Auth-Application-Id"
+ },
+ {
+ "@data": "OCS3",
+ "@name": "Origin-Host"
+ },
+ {
+ "@data": "OCS3",
+ "@name": "Origin-Realm"
+ },
+ {
+ "@data": "OCS3",
+ "@name": "Destination-Realm"
+ },
+ {
+ "@data": "OCS3",
+ "@name": "Destination-Host"
+ },
+ {
+ "@hex-data": "313232",
+ "@name": "AF-Application-Identifier"
+ },
+ {
+ "@name": "Media-Component-Description",
+ "avp": [
+ {
+ "@data": "0",
+ "@name": "Media-Component-Number"
+ },
+ {
+ "@hex-data": "313232",
+ "@name": "AF-Application-Identifier"
+ },
+ {
+ "@data": "127",
+ "@name": "Max-Requested-Bandwidth-UL"
+ },
+ {
+ "@data": "133",
+ "@name": "Max-Requested-Bandwidth-DL"
+ },
+ {
+ "@alias": "ENABLED",
+ "@data": "2",
+ "@name": "Flow-Status"
+ },
+ {
+ "@alias": "DEFAULT",
+ "@data": "0",
+ "@name": "Reservation-Priority"
+ }
+ ]
+ },
+ {
+ "@alias": "FINAL_SERVICE_INFORMATION",
+ "@data": "0",
+ "@name": "Service-Info-Status"
+ },
+ {
+ "@name": "Subscription-Id",
+ "avp": [
+ {
+ "@alias": "END_USER_E164",
+ "@data": "0",
+ "@name": "Subscription-Id-Type"
+ },
+ {
+ "@data": "626037099",
+ "@name": "Subscription-Id-Data"
+ }
+ ]
+ },
+ {
+ "@hex-data": "3139322e3136382e302e31",
+ "@name": "Framed-IP-Address"
+ },
+ {
+ "@hex-data": "5741502e4d4f564953544152",
+ "@name": "Called-Station-Id"
+ }
+ ]
+ }
+ }
+}
--- /dev/null
+{
+ "diameterJson": {
+ "message": {
+ "@application-id": "16777236",
+ "@end-to-end-id": "0",
+ "@hop-by-hop-id": "0",
+ "@name": "AA-Request",
+ "@p-bit": "yes",
+ "@version": "1",
+ "avp": [
+ {
+ "@data": "ocs3;1332774430;1;1332774430",
+ "@name": "Session-Id"
+ },
+ {
+ "@data": "16777236",
+ "@name": "Auth-Application-Id"
+ },
+ {
+ "@data": "ownHostId.operatorRealm.com",
+ "@name": "Origin-Host"
+ },
+ {
+ "@data": "operatorRealm.com",
+ "@name": "Origin-Realm"
+ },
+ {
+ "@data": "afRealm.com",
+ "@name": "Destination-Realm"
+ },
+ {
+ "@data": "afHost.afRealm.com",
+ "@name": "Destination-Host"
+ },
+ {
+ "@hex-data": "313232",
+ "@name": "AF-Application-Identifier"
+ },
+ {
+ "@name": "Media-Component-Description",
+ "avp": [
+ {
+ "@data": "0",
+ "@name": "Media-Component-Number"
+ },
+ {
+ "@hex-data": "313232",
+ "@name": "AF-Application-Identifier"
+ },
+ {
+ "@data": "127",
+ "@name": "Max-Requested-Bandwidth-UL"
+ },
+ {
+ "@data": "133",
+ "@name": "Max-Requested-Bandwidth-DL"
+ },
+ {
+ "@alias": "ENABLED",
+ "@data": "2",
+ "@name": "Flow-Status"
+ },
+ {
+ "@alias": "DEFAULT",
+ "@data": "0",
+ "@name": "Reservation-Priority"
+ }
+ ]
+ },
+ {
+ "@alias": "FINAL_SERVICE_INFORMATION",
+ "@data": "0",
+ "@name": "Service-Info-Status"
+ },
+ {
+ "@name": "Subscription-Id",
+ "avp": [
+ {
+ "@alias": "END_USER_E164",
+ "@data": "0",
+ "@name": "Subscription-Id-Type"
+ },
+ {
+ "@data": "626037099",
+ "@name": "Subscription-Id-Data"
+ }
+ ]
+ },
+ {
+ "@hex-data": "3139322e3136382e302e31",
+ "@name": "Framed-IP-Address"
+ },
+ {
+ "@hex-data": "5741502e4d4f564953544152",
+ "@name": "Called-Station-Id"
+ }
+ ]
+ }
+ }
+}
--- /dev/null
+01000190c000010901000014000000000000000000000107400000246f6373333b313333323737343433303b313b31333332373734343330000001024000000c0100001400000108400000236f776e486f737449642e6f70657261746f725265616c6d2e636f6d0000000128400000196f70657261746f725265616c6d2e636f6d0000000000011b4000001361665265616c6d2e636f6d00000001254000001a6166486f73742e61665265616c6d2e636f6d0000000001f8c000000f000028af3132320000000205c000006c000028af00000206c0000010000028af00000000000001f8c000000f000028af3132320000000204c0000010000028af0000007f00000203c0000010000028af00000085000001ffc0000010000028af00000002000001ca80000010000032db000000000000020fc0000010000028af00000000000001bb40000028000001c24000000c00000000000001bc4000001136323630333730393900000000000008400000133139322e3136382e302e31000000001e400000145741502e4d4f564953544152
--- /dev/null
+<message version="1" name="AA-Request" p-bit="yes" application-id="16777236" hop-by-hop-id="0" end-to-end-id="0">
+ <avp name="Session-Id" data="ocs3;1332774430;1;1332774430"/>
+ <avp name="Auth-Application-Id" data="16777236"/>
+ <avp name="Origin-Host" data="ownHostId.operatorRealm.com"/>
+ <avp name="Origin-Realm" data="operatorRealm.com"/>
+ <avp name="Destination-Realm" data="afRealm.com"/>
+ <avp name="Destination-Host" data="afHost.afRealm.com"/>
+ <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" hex-data="5741502e4d4f564953544152"/>
+</message>
+++ /dev/null
-{{
- "diameterHex":"{diameterHex}"
-}}
+++ /dev/null
-{
- "diameterJson": {
- "message": {
- "@application-id": "16777236",
- "@end-to-end-id": "0",
- "@hop-by-hop-id": "0",
- "@name": "AA-Request",
- "@p-bit": "yes",
- "@version": "1",
- "avp": [
- {
- "@data": "ocs3;1332774430;1;1332774430",
- "@name": "Session-Id"
- },
- {
- "@data": "16777236",
- "@name": "Auth-Application-Id"
- },
- {
- "@data": "OCS3",
- "@name": "Origin-Host"
- },
- {
- "@data": "OCS3",
- "@name": "Origin-Realm"
- },
- {
- "@data": "OCS3",
- "@name": "Destination-Realm"
- },
- {
- "@data": "OCS3",
- "@name": "Destination-Host"
- },
- {
- "@hex-data": "313232",
- "@name": "AF-Application-Identifier"
- },
- {
- "@name": "Media-Component-Description",
- "avp": [
- {
- "@data": "0",
- "@name": "Media-Component-Number"
- },
- {
- "@hex-data": "313232",
- "@name": "AF-Application-Identifier"
- },
- {
- "@data": "127",
- "@name": "Max-Requested-Bandwidth-UL"
- },
- {
- "@data": "133",
- "@name": "Max-Requested-Bandwidth-DL"
- },
- {
- "@alias": "ENABLED",
- "@data": "2",
- "@name": "Flow-Status"
- },
- {
- "@alias": "DEFAULT",
- "@data": "0",
- "@name": "Reservation-Priority"
- }
- ]
- },
- {
- "@alias": "FINAL_SERVICE_INFORMATION",
- "@data": "0",
- "@name": "Service-Info-Status"
- },
- {
- "@name": "Subscription-Id",
- "avp": [
- {
- "@alias": "END_USER_E164",
- "@data": "0",
- "@name": "Subscription-Id-Type"
- },
- {
- "@data": "626037099",
- "@name": "Subscription-Id-Data"
- }
- ]
- },
- {
- "@hex-data": "3139322e3136382e302e31",
- "@name": "Framed-IP-Address"
- },
- {
- "@hex-data": "5741502e4d4f564953544152",
- "@name": "Called-Station-Id"
- }
- ]
- }
- }
-}
--- /dev/null
+<message version="1" name="AA-Answer" application-id="16777236" hop-by-hop-id="816067" end-to-end-id="315108">
+ <avp name="Session-Id" data="tc_01_FullAVPs;afNodeHostname.afNodeHostRealm.com;1;859608"/>
+ <avp name="Auth-Application-Id" data="16777236"/>
+ <avp name="Origin-Host" data="sapcOwnHostId.operatorRealm.com"/>
+ <avp name="Origin-Realm" data="operatorRealm.com"/>
+ <avp name="Result-Code" data="2001" alias="DIAMETER_SUCCESS"/>
+ <avp name="Supported-Features">
+ <avp name="Vendor-Id" data="10415"/>
+ <avp name="Feature-List-ID" data="1"/>
+ <avp name="Feature-List" data="19"/>
+ </avp>
+ <avp name="Origin-State-Id" data="1427215015"/>
+</message>
/**
- Loads an xml file representing a diameter message base in a DTD document (#getDTD)
+ Loads an xml file/string representing a diameter message base in a DTD document (#getDTD)
- @param xmlPathFile Complete path file to the xml document which represents the diameter message
+ @param xmlPathFile_or_string Complete path file or string representation for the xml document which represents the diameter message
+ @param pathfile_or_string boolean about the interpretation of the previous argument
*/
- Message *createMessage(const std::string & xmlPathFile) throw(anna::RuntimeException);
+ Message *createMessage(const std::string & xmlPathFile_or_string, bool pathfile_or_string = true) throw(anna::RuntimeException);
/**
U32 dummy2, dummy3;
return (getSessionId(db, dummy1, dummy2, dummy3, dummy4));
}
+
+
+ /**
+ * Gets the fixed Origin-Host AVP (DiameterIdentity) from datablock provided.
+ *
+ * @param db Provided Message DataBlock
+ *
+ * @return Origin-Host
+ */
+ static std::string getOriginHost(const anna::DataBlock &db) throw(anna::RuntimeException);
};
//------------------------------------------------------------------------------
//-------------------------------------------------- EngineImpl::createMessage()
//------------------------------------------------------------------------------
-Message *EngineImpl::createMessage(const std::string & xmlPathFile) throw(anna::RuntimeException) {
+Message *EngineImpl::createMessage(const std::string & xmlPathFile_or_string, bool pathfile_or_string) throw(anna::RuntimeException) {
Message *result = createMessage();
- result->loadXMLFile(xmlPathFile);
+ if (pathfile_or_string)
+ result->loadXMLFile(xmlPathFile_or_string);
+ else
+ result->loadXMLString(xmlPathFile_or_string);
+
return result;
}
return result;
}
+
+std::string anna::diameter::helpers::base::functions::getOriginHost(const anna::DataBlock & db) throw(anna::RuntimeException) {
+ if(db.getSize() < Message::HeaderLength)
+ throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION);
+
+ const char *avpsDB = db.getData() + Message::HeaderLength;
+ int avpsLen = db.getSize() - Message::HeaderLength;
+ const char * originHostPtr = anna::diameter::codec::functions::findAVP(avpsDB, avpsLen, AVPID__Origin_Host);
+
+
+ if(originHostPtr == NULL)
+ throw anna::RuntimeException("Origin-Host AVP not found in DataBlock provided", ANNA_FILE_LOCATION);
+
+ // Decoded avp information:
+ AvpId _id;
+ char _flags;
+ int _length;
+ std::string result;
+ anna::diameter::codec::functions::decodeAVP(originHostPtr, _id, _flags, _length, result);
+ return result;
+}
+