X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=example%2Fdiameter%2Flauncher%2FEventOperation.cpp;h=4d80410f542953b23c02be25899777b16cf91a03;hb=e782294456d0877aa8fc05aa931291ac79808eb3;hp=2b80529f606d3dc31a2dbe9e41d533f42a575ff3;hpb=8b8309d46e9ccc968d3a315e86e70c5a806706d0;p=anna.git diff --git a/example/diameter/launcher/EventOperation.cpp b/example/diameter/launcher/EventOperation.cpp index 2b80529..4d80410 100644 --- a/example/diameter/launcher/EventOperation.cpp +++ b/example/diameter/launcher/EventOperation.cpp @@ -11,9 +11,1222 @@ // Process #include +#include +#include +#include +#include +#include -std::string EventOperation::json2piped(const json &j) { - std::string result = "operacion piped"; +// Standard +#include +#include // chdir + +// Project +#include +#include +#include +#include +#include +#include +#include +#include + + +///////////////////// +// Node management // +///////////////////// +bool EventOperation::node(std::string &response, const std::string & name) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + anna::diameter::comm::OriginHost *workingNode; + try { workingNode = my_app.getWorkingNode(); } catch(anna::RuntimeException &ex) { ex.trace(); } + + if (name != "") { + if (my_app.setWorkingNode(name)) { + response = anna::functions::asString("Forced node is now '%s'", name.c_str()); + my_app.setOperatedHost(my_app.getWorkingNode()); // now is the new one + } + else { + response = anna::functions::asString("Node '%s' invalid. Nothing done", name.c_str()); + } + } + else { + if (workingNode) { + if (a_http) { + response = anna::functions::encodeBase64(workingNode->asXMLString()); + } + else { + response = workingNode->asXMLString(); + } + } + else { + response = "Working node is automatic"; + } + } + return true; // OK +} + +bool EventOperation::node_auto(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + my_app.setNodeAuto(); + response = "Working node has been set to automatic"; + + return true; // OK +} + +//////////////////////// +// Parsing operations // +//////////////////////// +bool EventOperation::code(std::string &response, const std::string & diameterJson) { + + bool success; + std::string diameterXml = anna::json::functions::json2xml(diameterJson, success); + if (!success) { + response += "json to xml failed, unable to encode !"; + return false; + } + anna::diameter::codec::Message codecMsg; // auxiliary codec message + codecMsg.loadXMLString(diameterXml); + response = anna::functions::asHexString(codecMsg.code()); + + return true; // OK +} + +bool EventOperation::decode(std::string &response, const std::string & diameterHex) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + anna::DataBlock db_aux(true); + anna::functions::fromHexString(diameterHex, db_aux); + anna::diameter::codec::Message codecMsg; // auxiliary codec message + try { + codecMsg.decode(db_aux); + std::string xmlString = codecMsg.asXMLString(); + response = anna::functions::encodeBase64(xmlString); + } + catch(anna::RuntimeException &ex) { ex.trace(); } + + return true; // OK +} + +bool EventOperation::loadmsg(std::string &response, const std::string & diameterJson) { + + 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); + response = anna::functions::encodeBase64(codecMsg.asXMLString()); + + return true; // OK +} + +///////////////// +// Hot changes // +///////////////// +bool EventOperation::services(std::string &response, const std::string & servicesJson) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + bool success; + std::string servicesXml = anna::json::functions::json2xml(servicesJson, success); + if (!success) { + response += "json to xml failed, unable to load services !"; + return false; + } + + try { + my_app.loadServicesFromXMLString(servicesXml, true /* bind entities */); + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "loaded services with errors"; + return false; + } + response = "loaded services correctly"; + + return true; // OK +} + +bool EventOperation::diameterServerSessions(std::string &response, int sessions) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + try { + my_app.getOperatedServer()->setMaxConnections(sessions); + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += "fail to operate the server"; + return false; + } + response = "new sessions successfully established on operated diameter server"; + + return true; // OK +} + +bool EventOperation::change_dir(std::string &response, const std::string & directory) { + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + std::string dir = directory; + if (dir == "") dir = my_app.getInitialWorkingDirectory(); + bool result = (chdir(dir.c_str()) == 0); + + if (result) + response = "New execution directory configured: "; + else + response = "Cannot assign provided execution directory: "; + + response += dir; return result; } + +//////////////////////////////// +// Client sessions visibility // +//////////////////////////////// +bool EventOperation::visibility(std::string &response, const std::string & action, const std::string &addressPort, int socket) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + response = ""; + + if(addressPort != "") { + if(socket != -1) { + std::string key = addressPort; + key += "|"; + key += anna::functions::asString(socket); + + if(action == "hide") my_app.getOperatedEngine()->findClientSession(key)->hide(); + if(action == "show") my_app.getOperatedEngine()->findClientSession(key)->show(); + if(action == "hidden") response = my_app.getOperatedEngine()->findClientSession(key)->hidden() ? "true" : "false"; + if(action == "shown") response = my_app.getOperatedEngine()->findClientSession(key)->shown() ? "true" : "false"; + } else { + std::string address; + int port; + anna::functions::getAddressAndPortFromSocketLiteral(addressPort, address, port); + + if(action == "hide") my_app.getOperatedEngine()->findServer(address, port)->hide(); + if(action == "show") my_app.getOperatedEngine()->findServer(address, port)->show(); + if(action == "hidden") response = my_app.getOperatedEngine()->findServer(address, port)->hidden() ? "true" : "false"; + if(action == "shown") response = my_app.getOperatedEngine()->findServer(address, port)->shown() ? "true" : "false"; + } + } else { + if(action == "hide") my_app.getOperatedEntity()->hide(); + if(action == "show") my_app.getOperatedEntity()->show(); + if(action == "hidden") response = my_app.getOperatedEntity()->hidden() ? "true" : "false"; + if(action == "shown") response = my_app.getOperatedEntity()->shown() ? "true" : "false"; + } + + return true; // OK +} + + +/////////////// +// Snapshots // +/////////////// +bool EventOperation::collect(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + my_app.resetCounters(); + my_app.resetStatistics(); + response = "All process counters & statistic information have been reset"; + + return true; // OK +} + +bool EventOperation::context(std::string &response, const std::string & targetFile) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + std::string contextFile = (targetFile != "") ? targetFile : anna::functions::asString("/var/tmp/anna.context.%05d", my_app.getPid()); + my_app.writeContext(contextFile); + response = anna::functions::asString("Context dumped on file '%s'", contextFile.c_str()); + + return true; // OK +} + +bool EventOperation::forceCountersRecord(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + my_app.forceCountersRecord(); + response = "Current counters have been dump to disk"; + + return true; // OK +} + +bool EventOperation::log_statistics_samples(std::string &response, const std::string & list) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + my_app.logStatisticsSamples(list); + response = anna::functions::asString("Log statistics samples for '%s' concepts", list.c_str()); + + return true; // OK +} + +bool EventOperation::show_oam(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + anna::xml::Node root("root"); + response = anna::xml::Compiler().apply(my_app.oamAsXML(&root)); + if (a_http) + response = anna::functions::encodeBase64(response); + + return true; // OK +} + +bool EventOperation::show_stats(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + anna::xml::Node root("root"); + response = anna::xml::Compiler().apply(my_app.statsAsXML(&root)); + if (a_http) + response = anna::functions::encodeBase64(response); + + return true; // OK +} + +///////////////////// +// Flow operations // +///////////////////// +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); + + // 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); + } + + + response = "Operation processed"; // could be failed + return success; +} + +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); + + // 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); + } + + + response = "Operation processed"; // could be failed + return success; +} + +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; + } + + 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::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; + } + + 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 +} + +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 +} + +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_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); + ); + + 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 +} + +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 +} + +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(); + + 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__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}"); + + 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__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 += "$"; + } + + 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__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 +} + +///////////////////////// +// Testcases execution // +///////////////////////// +bool EventOperation::test__ttps(std::string &response, int amount) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + bool success = testManager.configureTTPS(amount); + if (success) { + response = "Assigned new test launch rate to "; + response += anna::functions::asString(amount); + response += " events per second"; + } + else { + response += "unable to configure the test rate provided"; + } + + return success; // OK +} + +bool EventOperation::test__next(std::string &response, int syncAmount) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + if (syncAmount < 1) { + response += "the parameter 'sync-amount' must be a positive integer value"; + return false; + } + + bool success = testManager.execTestCases(syncAmount); + + response = (success ? "P" : "Not completely p" /* completed cycle and no repeats, rare case */); + response += "rocessed "; + response += anna::functions::asString(syncAmount); + response += ((syncAmount > 1) ? " test cases synchronously" : " test case"); + + return success; +} + +bool EventOperation::test__ip_limit(std::string &response, int amount) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + if (amount > -2) { + testManager.setInProgressLimit(amount); + response = "New in-progress limit: "; + response += (amount != -1) ? anna::functions::asString(amount) : "[no limit]"; + } + else { + response = "In-progress limit amount: "; + int limit = testManager.getInProgressLimit(); + response += (limit != -1) ? anna::functions::asString(limit) : "[no limit]"; + response += "; currently there are "; + response += anna::functions::asString(testManager.getInProgressCount()); + response += " test cases running"; + } + + return true; // OK +} + +bool EventOperation::test__goto(std::string &response, int id) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + bool success = testManager.gotoTestCase(id); + + if (success) { + response = "Position updated for id provided ("; + } + else { + response += "cannot found test id ("; + } + response += anna::functions::asString(id); + response += ")"; + + return success; +} + +bool EventOperation::test__run(std::string &response, int id) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + bool success = testManager.runTestCase(id); + + if (success) { + response = "Test executed for id provided ("; + } + else { + response += "cannot found test id ("; + } + response += anna::functions::asString(id); + response += ")"; + + return success; +} + +bool EventOperation::test__look(std::string &response, int id) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + anna::testing::TestCase *testCase = testManager.findTestCase(id); + if (!testCase) { + if (id == -1) { + response += "no current test case detected (testing started ?)"; + } + else { + response += "cannot found test id ("; + response += anna::functions::asString(id); + response += ")"; + } + + return false; + } + + if (a_http) + response = anna::functions::encodeBase64(testCase->asXMLString()); + else + response = testCase->asXMLString(); + + return true; // OK +} + +bool EventOperation::test__state(std::string &response, int id) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + anna::testing::TestCase *testCase = testManager.findTestCase(id); + if (!testCase) { + if (id == -1) { + response += "no current test case detected (testing started ?)"; + } + else { + response += "cannot found test id ("; + response += anna::functions::asString(id); + response += ")"; + } + + return false; + } + + response = anna::testing::TestCase::asText(testCase->getState()); + return testCase->isSuccess(); +} + +bool EventOperation::test__interact(std::string &response, int amount, unsigned int id) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + if (amount < -1) { + response += "interactive amount must be -1 (to disable interactive mode) or a positive number."; + return false; + } + + anna::testing::TestCase *testCase = testManager.findTestCase(id); + if (testCase) { + if (amount == -1) { + testCase->makeInteractive(false); + response = "Interactive mode disabled"; + } + else { + testCase->addInteractiveAmount(amount); + response = "Added interactive amount of "; + response += anna::functions::asString(amount); + response += " units"; + if (amount == 0) response += " (0: freezing a non-interactive testcase, no effect on already interactive)"; + } + response += " for test case id "; + response += anna::functions::asString(id); + } + else { + response += "cannot found test id ("; + response += anna::functions::asString(id); + response += ")"; + return false; + } + + return true; // OK +} + +bool EventOperation::test__reset(std::string &response, bool soft_hard, int id) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + anna::testing::TestCase *testCase = ((id != -1) ? testManager.findTestCase(id) : NULL); + if (testCase) { + bool done = testCase->reset(!soft_hard); + response = "Test "; + response += (soft_hard ? "soft":"hard"); + response += " reset for id "; + response += anna::functions::asString(id); + response += done ? ": done": ": not done"; + } + else { + if (id == -1) { + bool anyReset = testManager.resetPool(!soft_hard); + response = (soft_hard ? "Soft":"Hard"); + response += " reset have been sent to all programmed tests: "; response += anyReset ? "some/all have been reset" : "nothing was reset"; + } + else { + response += "cannot found test id ("; + response += anna::functions::asString(id); + response += ")"; + return false; + } + } + + return true; // OK +} + +bool EventOperation::test__repeats(std::string &response, int amount) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + if (amount < 0) amount = -1; + testManager.setPoolRepeats(amount); + std::string nolimit = (amount != -1) ? "":" [no limit]"; + response = anna::functions::asString("Pool repeats: %d%s (current cycle: %d)", amount, nolimit.c_str(), testManager.getPoolCycle()); + + return true; // OK +} + +bool EventOperation::test__auto_reset(std::string &response, bool soft_hard) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + testManager.setAutoResetHard(!soft_hard); + response = anna::functions::asString("Auto-reset configured to '%s'", (soft_hard ? "soft":"hard")); + + return true; // OK +} + +bool EventOperation::test__initialized(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + response = anna::functions::asString("%lu", testManager.getInitializedCount()); + + return true; // OK +} + +bool EventOperation::test__finished(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + response = anna::functions::asString("%lu", testManager.getFinishedCount()); + + return true; // OK +} + +bool EventOperation::test__clear(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + return testManager.clearPool(response); +} + +bool EventOperation::test__junit(std::string &response, const std::string & targetFile) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + std::ofstream out; + out.open(targetFile.c_str()); + + if(out.is_open() == false) { + response += "error opening '"; + response += targetFile; + response += "'"; + return false; + } + + out << testManager.junitAsXMLString() << std::endl; + out.close(); + + response = "Junit report written on '"; + response += targetFile; + response += "'"; + + return true; // OK +} + +bool EventOperation::test__summary_counts(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + response = anna::functions::encodeBase64(testManager.summaryCounts()); + + return true; // OK +} + +bool EventOperation::test__summary_states(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + response = anna::functions::encodeBase64(testManager.summaryStates()); + + return true; // OK +} + +bool EventOperation::test__summary(std::string &response) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + response = anna::functions::encodeBase64(testManager.asXMLString()); + + return true; // OK +} + +bool EventOperation::test__report(std::string &response, const std::string & state, bool enable) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + std::string _state = state; + + if(_state == "initialized") + testManager.setDumpInitializedReports(enable); + else if(_state == "in-progress") + testManager.setDumpInProgressReports(enable); + else if(_state == "failed") + testManager.setDumpFailedReports(enable); + else if(_state == "success") + testManager.setDumpSuccessReports(enable); + else if(_state == "all") { + _state = "any"; + testManager.setDumpAllReports(enable); + } + else if(_state == "none") { + enable = !enable; + _state = "any"; + testManager.setDumpAllReports(enable); + } + else { + response += "invalid state (allowed: initialized|in-progress|failed|success|[all]|none)"; + return false; + } + + response = (enable ? "Report enabled " : "Report disabled "); + response += "for tests in '"; + response += _state; + response += "' state"; + + return true; // OK +} + +bool EventOperation::test__report_hex(std::string &response, bool enable) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + testManager.setDumpHex(enable); + response = (testManager.getDumpHex() ? "Report includes hexadecimal messages" : "Report excludes hexadecimal messages"); + + return true; // OK +} + +bool EventOperation::test__dump_stdout(std::string &response, bool enable) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + + testManager.setDumpStdout(enable); + response = (testManager.getDumpStdout() ? "Test manager dumps progress into stdout" : "Test manager does not dump progress into stdout"); + + return true; // OK +} + +bool EventOperation::test__dynamic(std::string &response, const nlohmann::json &arguments) { + + Launcher& my_app = static_cast (anna::app::functions::getApp()); + + Procedure p(&my_app); + try { + p.execute(arguments, response); + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response += ex.asString(); + return false; + } + + return true; // OK +} + +