X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=example%2Fdiameter%2Flauncher%2FEventOperation.cpp;h=7709fb1864a2087f895531d4c90e1a6eb36f522b;hb=43e1ef25edd9bd4d3de10f24ffc6a8381b3f1f73;hp=be0c1683f14e0df49f6752c0cea552c8f169340f;hpb=c881c12ed7e116f1d43760a0d9873f860c10a357;p=anna.git diff --git a/example/diameter/launcher/EventOperation.cpp b/example/diameter/launcher/EventOperation.cpp index be0c168..7709fb1 100644 --- a/example/diameter/launcher/EventOperation.cpp +++ b/example/diameter/launcher/EventOperation.cpp @@ -35,13 +35,15 @@ //#include //#include //#include -//#include -//#include +#include +#include +#include //#include //#include #include //#include //#include +#include // //// Process //#include @@ -49,7 +51,7 @@ //#include #include #include -//#include +#include //#include @@ -321,87 +323,272 @@ bool EventOperation::show_stats(std::string &response) { ///////////////////// // 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 (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 (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() : ""; // 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 (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 (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() : ""; // 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 (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 (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 (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 (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 EventOperation::test_id__description(std::string &response, unsigned int id, const std::string & description) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - + try { + testManager.getTestCase(id)->setDescription(description); // creates / reuses + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "invalid ip-limit"; + return false; + } return true; // OK } @@ -409,8 +596,17 @@ bool EventOperation::test_id__description(std::string &response, unsigned int id bool EventOperation::test_id__ip_limit(std::string &response, unsigned int id, int amount) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - + try { + testManager.getTestCase(id)->addIpLimit(amount); // creates / reuses + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "invalid ip-limit"; + return false; + } return true; // OK } @@ -418,26 +614,55 @@ bool EventOperation::test_id__ip_limit(std::string &response, unsigned int id, i bool EventOperation::test_id__timeout(std::string &response, unsigned int id, int msecs) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - + try { + anna::Millisecond timeout = my_app.checkTimeMeasure("Test case timeout", anna::functions::asString(msecs)); + testManager.getTestCase(id)->addTimeout(timeout); // creates / reuses + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "invalid timeout"; + return false; + } return true; // OK } -bool EventOperation::test_id__sendmsg2e(std::string &response, unsigned int id, const std::string & diameterJson, int stepNumber) { +bool EventOperation::test_id__sendmsg2e_2c(std::string &response, unsigned int id, bool _2e_or_2c, const std::string & diameterJson, int stepNumber) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + bool success; + std::string diameterXml = anna::json::functions::json2xml(diameterJson, success); + if (!success) { + response += "json to xml failed, unable to load message !"; + return false; + } + anna::diameter::codec::Message codecMsg; // auxiliary codec message + codecMsg.loadXMLString(diameterXml); + LOGWARNING( + if (!codecMsg.isRequest() && (stepNumber == -1)) + anna::Logger::warning("Step number has not been provided. Take into account that this answer message will be sent 'as is' and sequence information could be wrong at the remote peer", ANNA_FILE_LOCATION); + ); - return true; // OK -} - -bool EventOperation::test_id__sendmsg2c(std::string &response, unsigned int id, const std::string & diameterJson, int stepNumber) { - - Launcher& my_app = static_cast (anna::app::functions::getApp()); - + try { + my_app.updateOperatedOriginHostWithMessage(codecMsg); + if (_2e_or_2c) + testManager.getTestCase(id)->addSendDiameterXml2e(codecMsg.code(), my_app.getOperatedHost(), stepNumber); // creates / reuses + else + testManager.getTestCase(id)->addSendDiameterXml2c(codecMsg.code(), my_app.getOperatedHost(), stepNumber); // creates / reuses + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "failed"; + return false; + } return true; // OK } @@ -445,8 +670,18 @@ bool EventOperation::test_id__sendmsg2c(std::string &response, unsigned int id, bool EventOperation::test_id__delay(std::string &response, unsigned int id, int msecs) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - + try { + anna::Millisecond delay = ((msecs == 0 /* special case */) ? (anna::Millisecond)0 : my_app.checkTimeMeasure("Test case delay step", anna::functions::asString(msecs))); + testManager.getTestCase(id)->addDelay(delay); // creates / reuses + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "invalid delay"; + return false; + } return true; // OK } @@ -454,62 +689,164 @@ bool EventOperation::test_id__delay(std::string &response, unsigned int id, int bool EventOperation::test_id__sh_command(std::string &response, unsigned int id, const std::string & script) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - - - return true; // OK -} - -bool EventOperation::test_id__waitfe_hex(std::string &response, unsigned int id, const std::string & hex, bool strict) { - - Launcher& my_app = static_cast (anna::app::functions::getApp()); - - + try { + testManager.getTestCase(id)->addCommand(script); // creates / reuses + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "failed"; + return false; + } return true; // OK } -bool EventOperation::test_id__waitfc_hex(std::string &response, unsigned int id, const std::string & hex, bool strict) { +bool EventOperation::test_id__waitfefc_hex(std::string &response, unsigned int id, bool fe_or_fc, const std::string & hex, bool strict) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + // Get DataBlock from hex content: + anna::DataBlock db_aux(true); + std::string hexString = 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); + ); + + std::string regexp; + try { + anna::functions::fromHexString(hexString, db_aux); // could launch exception + regexp = anna::functions::asHexString(db_aux); + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "failed"; + return false; + } + // optional 'full': + if(!strict) { + //// If request, we will ignore sequence data: + //if (anna::diameter::codec::functions::requestBit(db_aux)) + regexp.replace (24, 16, "[0-9A-Fa-f]{16}"); - return true; // OK -} - -bool EventOperation::test_id__waitfe_msg(std::string &response, unsigned int id, const std::string & diameterJson, bool strict) { - - Launcher& my_app = static_cast (anna::app::functions::getApp()); - + regexp.insert(0, "^"); + regexp += "$"; + } + try { + testManager.getTestCase(id)->addWaitDiameterRegexpHex(fe_or_fc, regexp); + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "failed"; + return false; + } return true; // OK } -bool EventOperation::test_id__waitfc_msg(std::string &response, unsigned int id, const std::string & diameterJson, bool strict) { +bool EventOperation::test_id__waitfefc_msg(std::string &response, unsigned int id, bool fe_or_fc, const std::string & diameterJson, bool strict) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + bool success; + std::string diameterXml = anna::json::functions::json2xml(diameterJson, success); + if (!success) { + response += "json to xml failed, unable to load message !"; + return false; + } + try { + anna::diameter::codec::Message codecMsg; // auxiliary codec message + codecMsg.loadXMLString(diameterXml); + std::string regexp = codecMsg.asXMLString(true /* normalization */); + + // Now we must insert regular expressions in hop-by-hop, end-to-end and Origin-State-Id: + + // optional 'full': + if(!strict) { + std::string::size_type pos, pos_1, pos_2; + + pos = regexp.find("end-to-end-id=", 0u); + pos = regexp.find("\"", pos); + pos_1 = pos; + pos = regexp.find("\"", pos+1); + pos_2 = pos; + regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+"); + + pos = regexp.find("hop-by-hop-id=", 0u); + pos = regexp.find("\"", pos); + pos_1 = pos; + pos = regexp.find("\"", pos+1); + pos_2 = pos; + regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+"); + + // For this representation: + //pos = regexp.find("Origin-State-Id", 0u); + //pos = regexp.find("\"", pos); + //pos = regexp.find("\"", pos+1); + //pos_1 = pos; + //pos = regexp.find("\"", pos+1); + //pos_2 = pos; + //regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+"); + // But we have this one: + pos = regexp.find("Origin-State-Id", 0u); + pos = regexp.rfind("\"", pos); + pos = regexp.rfind("\"", pos-1); + pos = regexp.rfind("\"", pos-1); + pos_1 = pos; + pos = regexp.find("\"", pos+1); + pos_2 = pos; + regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+"); + + //regexp.insert(0, "^"); + //regexp += "$"; + } - return true; // OK -} - -bool EventOperation::test_id__waitfe(std::string &response, unsigned int id, const std::string & condition) { - - Launcher& my_app = static_cast (anna::app::functions::getApp()); - - + testManager.getTestCase(id)->addWaitDiameterRegexpXml(fe_or_fc, regexp); + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "failed"; + return false; + } return true; // OK } -bool EventOperation::test_id__waitfc(std::string &response, unsigned int id, const std::string & condition) { +bool EventOperation::test_id__waitfefc(std::string &response, unsigned int id, bool fe_or_fc, + const std::string & code, + const std::string & bitR, + const std::string & hopByHop, + const std::string & applicationId, + const std::string & sessionId, + const std::string & resultCode, + const std::string & msisdn, + const std::string & imsi, + const std::string & serviceContextId) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - + try { // [code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId] + testManager.getTestCase(id)->addWaitDiameter(fe_or_fc, code, bitR, hopByHop, applicationId, sessionId, resultCode, msisdn, imsi, serviceContextId); + response = "Done"; + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "failed"; + return false; + } return true; // OK } @@ -637,8 +974,21 @@ bool EventOperation::test__finished(std::string &response) { bool EventOperation::test__clear(std::string &response) { Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - + try { + if (testManager.clearPool()) { + response = "All the programmed test cases have been dropped"; + } + else { + response = "There are not programmed test cases to be removed"; + } + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "failed"; + return false; + } return true; // OK }