1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
13 #include <EventOperation.hpp>
14 #include <Launcher.hpp>
17 #include <anna/diameter.comm/OriginHost.hpp>
21 //#include <sstream> // std::istringstream
22 //#include <iostream> // std::cout
23 //#include <math.h> // ceil
25 #include <unistd.h> // chdir
29 #include <anna/json/functions.hpp>
30 #include <anna/diameter/codec/Message.hpp>
31 //#include <anna/timex/Engine.hpp>
32 //#include <anna/statistics/Engine.hpp>
33 //#include <anna/diameter/codec/functions.hpp>
34 //#include <anna/diameter/codec/Engine.hpp>
35 //#include <anna/diameter/codec/EngineManager.hpp>
36 //#include <anna/http/Transport.hpp>
37 //#include <anna/diameter/stack/Engine.hpp>
38 #include <anna/diameter/helpers/base/functions.hpp>
39 //#include <anna/time/functions.hpp>
40 //#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
41 //#include <anna/testing/defines.hpp>
42 #include <anna/xml/xml.hpp>
43 //#include <anna/diameter.comm/OriginHost.hpp>
44 //#include <anna/diameter.comm/OriginHostManager.hpp>
45 #include <anna/diameter.comm/Message.hpp>
48 //#include <Launcher.hpp>
49 //#include <Procedure.hpp>
50 //#include <EventOperation.hpp>
51 #include <MyDiameterEngine.hpp>
52 #include <MyLocalServer.hpp>
53 //#include <anna/testing/TestManager.hpp>
54 //#include <anna/testing/TestCase.hpp>
60 bool EventOperation::node(std::string &response, const std::string & name) {
62 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
64 anna::diameter::comm::OriginHost *workingNode;
65 try { workingNode = my_app.getWorkingNode(); } catch(anna::RuntimeException &ex) { ex.trace(); }
68 if (my_app.setWorkingNode(name)) {
69 response = anna::functions::asString("Forced node is now '%s'", name.c_str());
70 my_app.setOperatedHost(my_app.getWorkingNode()); // now is the new one
73 response = anna::functions::asString("Node '%s' invalid. Nothing done", name.c_str());
79 response = anna::functions::encodeBase64(workingNode->asXMLString());
82 response = workingNode->asXMLString();
86 response = "Working node is automatic";
92 bool EventOperation::node_auto(std::string &response) {
94 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
97 response = "Working node has been set to automatic";
102 ////////////////////////
103 // Parsing operations //
104 ////////////////////////
105 bool EventOperation::code(std::string &response, const std::string & diameterJson) {
108 std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
110 response += "json to xml failed, unable to encode !";
113 anna::diameter::codec::Message codecMsg; // auxiliary codec message
114 codecMsg.loadXMLString(diameterXml);
115 response = anna::functions::asHexString(codecMsg.code());
120 bool EventOperation::decode(std::string &response, const std::string & diameterHex) {
122 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
124 anna::DataBlock db_aux(true);
125 anna::functions::fromHexString(diameterHex, db_aux);
126 anna::diameter::codec::Message codecMsg; // auxiliary codec message
128 codecMsg.decode(db_aux);
129 std::string xmlString = codecMsg.asXMLString();
130 response = anna::functions::encodeBase64(xmlString);
132 catch(anna::RuntimeException &ex) { ex.trace(); }
137 bool EventOperation::loadmsg(std::string &response, const std::string & diameterJson) {
140 std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
142 response += "json to xml failed, unable to load message !";
145 anna::diameter::codec::Message codecMsg; // auxiliary codec message
146 codecMsg.loadXMLString(diameterXml);
147 response = anna::functions::encodeBase64(codecMsg.asXMLString());
155 bool EventOperation::services(std::string &response, const std::string & servicesJson) {
157 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
160 std::string servicesXml = anna::json::functions::json2xml(servicesJson, success);
162 response += "json to xml failed, unable to load services !";
167 my_app.loadServicesFromXMLString(servicesXml, true /* bind entities */);
169 catch(anna::RuntimeException &ex) {
171 response += "loaded services with errors";
174 response = "loaded services correctly";
179 bool EventOperation::diameterServerSessions(std::string &response, int sessions) {
181 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
184 my_app.getOperatedServer()->setMaxConnections(sessions);
186 catch(anna::RuntimeException &ex) {
188 response += "fail to operate the server";
191 response = "new sessions successfully established on operated diameter server";
196 bool EventOperation::change_dir(std::string &response, const std::string & directory) {
198 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
200 std::string dir = directory;
201 if (dir == "") dir = my_app.getInitialWorkingDirectory();
202 bool result = (chdir(dir.c_str()) == 0);
205 response = "New execution directory configured: ";
207 response = "Cannot assign provided execution directory: ";
213 ////////////////////////////////
214 // Client sessions visibility //
215 ////////////////////////////////
216 bool EventOperation::visibility(std::string &response, const std::string & action, const std::string &addressPort, int socket) {
218 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
222 if(addressPort != "") {
224 std::string key = addressPort;
226 key += anna::functions::asString(socket);
228 if(action == "hide") my_app.getOperatedEngine()->findClientSession(key)->hide();
229 if(action == "show") my_app.getOperatedEngine()->findClientSession(key)->show();
230 if(action == "hidden") response = my_app.getOperatedEngine()->findClientSession(key)->hidden() ? "true" : "false";
231 if(action == "shown") response = my_app.getOperatedEngine()->findClientSession(key)->shown() ? "true" : "false";
235 anna::functions::getAddressAndPortFromSocketLiteral(addressPort, address, port);
237 if(action == "hide") my_app.getOperatedEngine()->findServer(address, port)->hide();
238 if(action == "show") my_app.getOperatedEngine()->findServer(address, port)->show();
239 if(action == "hidden") response = my_app.getOperatedEngine()->findServer(address, port)->hidden() ? "true" : "false";
240 if(action == "shown") response = my_app.getOperatedEngine()->findServer(address, port)->shown() ? "true" : "false";
243 if(action == "hide") my_app.getOperatedEntity()->hide();
244 if(action == "show") my_app.getOperatedEntity()->show();
245 if(action == "hidden") response = my_app.getOperatedEntity()->hidden() ? "true" : "false";
246 if(action == "shown") response = my_app.getOperatedEntity()->shown() ? "true" : "false";
256 bool EventOperation::collect(std::string &response) {
258 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
260 my_app.resetCounters();
261 my_app.resetStatistics();
262 response = "All process counters & statistic information have been reset";
267 bool EventOperation::context(std::string &response, const std::string & targetFile) {
269 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
271 std::string contextFile = (targetFile != "") ? targetFile : anna::functions::asString("/var/tmp/anna.context.%05d", my_app.getPid());
272 my_app.writeContext(contextFile);
273 response = anna::functions::asString("Context dumped on file '%s'", contextFile.c_str());
278 bool EventOperation::forceCountersRecord(std::string &response) {
280 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
282 my_app.forceCountersRecord();
283 response = "Current counters have been dump to disk";
288 bool EventOperation::log_statistics_samples(std::string &response, const std::string & list) {
290 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
292 my_app.logStatisticsSamples(list);
293 response = anna::functions::asString("Log statistics samples for '%s' concepts", list.c_str());
298 bool EventOperation::show_oam(std::string &response) {
300 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
302 anna::xml::Node root("root");
303 response = anna::xml::Compiler().apply(my_app.oamAsXML(&root));
305 response = anna::functions::encodeBase64(response);
310 bool EventOperation::show_stats(std::string &response) {
312 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
314 anna::xml::Node root("root");
315 response = anna::xml::Compiler().apply(my_app.statsAsXML(&root));
317 response = anna::functions::encodeBase64(response);
322 /////////////////////
323 // Flow operations //
324 /////////////////////
325 bool EventOperation::sendmsg_hex_2e(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
327 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
328 anna::diameter::codec::Message codecMsg; // auxiliary codec message
330 anna::diameter::comm::Message *msg;
333 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
335 response += "json to xml failed, unable to send message !";
338 codecMsg.loadXMLString(diameterXml);
340 my_app.updateOperatedOriginHostWithMessage(codecMsg);
341 msg = my_app.getOperatedHost()->createCommMessage();
344 catch(anna::RuntimeException &ex) {
346 response += "invalid operated host";
349 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)
350 msg->setBody(codecMsg.code());
352 // Get DataBlock from hex content:
353 anna::DataBlock db_aux(true);
354 std::string hexString = diameterJson_or_Hex;
355 hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
357 std::string msg = "Hex string (remove colons if exists): ";
359 anna::Logger::debug(msg, ANNA_FILE_LOCATION);
361 anna::functions::fromHexString(hexString, db_aux); // could launch exception
363 my_app.updateOperatedOriginHostWithMessage(db_aux);
364 msg = my_app.getOperatedHost()->createCommMessage();
366 catch(anna::RuntimeException &ex) {
368 response += "invalid operated host";
371 msg->setBody(db_aux);
372 try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
375 success = my_app.getOperatedEntity()->send(msg);
376 my_app.getOperatedHost()->releaseCommMessage(msg);
379 if(my_app.getOperatedHost()->logEnabled()) {
380 anna::diameter::comm::Server *usedServer = my_app.getOperatedEntity()->getLastUsedResource();
381 anna::diameter::comm::ClientSession *usedClientSession = usedServer ? usedServer->getLastUsedResource() : NULL;
382 std::string detail = usedClientSession ? usedClientSession->asString() : "<null client session>"; // shouldn't happen
383 my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2e" : "send2eError"), detail);
387 response = "Operation processed"; // could be failed
391 bool EventOperation::sendmsg_hex_2c(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
393 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
394 anna::diameter::codec::Message codecMsg; // auxiliary codec message
396 anna::diameter::comm::Message *msg;
399 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
401 response += "json to xml failed, unable to send message !";
404 codecMsg.loadXMLString(diameterXml);
406 my_app.updateOperatedOriginHostWithMessage(codecMsg);
407 msg = my_app.getOperatedHost()->createCommMessage();
410 catch(anna::RuntimeException &ex) {
412 response += "invalid operated host";
415 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)
416 msg->setBody(codecMsg.code());
418 // Get DataBlock from hex content:
419 anna::DataBlock db_aux(true);
420 std::string hexString = diameterJson_or_Hex;
421 hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
423 std::string msg = "Hex string (remove colons if exists): ";
425 anna::Logger::debug(msg, ANNA_FILE_LOCATION);
427 anna::functions::fromHexString(hexString, db_aux); // could launch exception
429 my_app.updateOperatedOriginHostWithMessage(db_aux);
430 msg = my_app.getOperatedHost()->createCommMessage();
432 catch(anna::RuntimeException &ex) {
434 response += "invalid operated host";
437 msg->setBody(db_aux);
438 try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
441 success = my_app.getOperatedServer()->send(msg);
442 my_app.getOperatedHost()->releaseCommMessage(msg);
445 if(my_app.getOperatedHost()->logEnabled()) {
446 anna::diameter::comm::ServerSession *usedServerSession = my_app.getOperatedServer()->getLastUsedResource();
447 std::string detail = usedServerSession ? usedServerSession->asString() : "<null server session>"; // shouldn't happen
448 my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
452 response = "Operation processed"; // could be failed
456 bool EventOperation::answermsg_action_2e(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
458 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
459 anna::diameter::codec::Message codecMsg; // auxiliary codec message
460 anna::diameter::codec::Message *message;
465 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
467 response += "json to xml failed, unable to send message !";
470 codecMsg.loadXMLString(diameterXml);
472 my_app.updateOperatedOriginHostWithMessage(codecMsg);
473 message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
474 LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
476 catch(anna::RuntimeException &ex) {
478 response += "invalid operated host";
482 if(message->isRequest()) {
483 response += "cannot program diameter requests. Answer type must be provided";
487 int code = message->getId().first;
488 LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
489 response = "Added 'answer to entity' to the FIFO queue corresponding to its message code";
490 my_app.getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
494 if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
495 response = anna::functions::encodeBase64(my_app.getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY"));
496 } else if (diameterJson_or_action == "rotate") {
497 my_app.getOperatedEntity()->getReactingAnswers()->rotate(true);
499 } else if (diameterJson_or_action == "exhaust") {
500 my_app.getOperatedEntity()->getReactingAnswers()->rotate(false);
501 response = "exhaust";
502 } else if (diameterJson_or_action == "clear") {
503 my_app.getOperatedEntity()->getReactingAnswers()->clear();
505 } else if (diameterJson_or_action == "dump") {
506 my_app.getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
515 bool EventOperation::answermsg_action_2c(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
517 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
518 anna::diameter::codec::Message codecMsg; // auxiliary codec message
519 anna::diameter::codec::Message *message;
524 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
526 response += "json to xml failed, unable to send message !";
529 codecMsg.loadXMLString(diameterXml);
531 my_app.updateOperatedOriginHostWithMessage(codecMsg);
532 message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
533 LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
535 catch(anna::RuntimeException &ex) {
537 response += "invalid operated host";
541 if(message->isRequest()) {
542 response += "cannot program diameter requests. Answer type must be provided";
546 int code = message->getId().first;
547 LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
548 my_app.getOperatedServer()->getReactingAnswers()->addMessage(code, message);
549 response = "Added 'answer to client' to the FIFO queue corresponding to its message code";
553 if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
554 response = anna::functions::encodeBase64(my_app.getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT"));
555 } else if (diameterJson_or_action == "rotate") {
556 my_app.getOperatedServer()->getReactingAnswers()->rotate(true);
558 } else if (diameterJson_or_action == "exhaust") {
559 my_app.getOperatedServer()->getReactingAnswers()->rotate(false);
560 response = "exhaust";
561 } else if (diameterJson_or_action == "clear") {
562 my_app.getOperatedServer()->getReactingAnswers()->clear();
564 } else if (diameterJson_or_action == "dump") {
565 my_app.getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
577 bool EventOperation::test_id__description(std::string &response, unsigned int id, const std::string & description) {
579 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
586 bool EventOperation::test_id__ip_limit(std::string &response, unsigned int id, int amount) {
588 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
595 bool EventOperation::test_id__timeout(std::string &response, unsigned int id, int msecs) {
597 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
604 bool EventOperation::test_id__sendmsg2e(std::string &response, unsigned int id, const std::string & diameterJson, int stepNumber) {
606 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
613 bool EventOperation::test_id__sendmsg2c(std::string &response, unsigned int id, const std::string & diameterJson, int stepNumber) {
615 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
622 bool EventOperation::test_id__delay(std::string &response, unsigned int id, int msecs) {
624 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
631 bool EventOperation::test_id__sh_command(std::string &response, unsigned int id, const std::string & script) {
633 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
640 bool EventOperation::test_id__waitfe_hex(std::string &response, unsigned int id, const std::string & hex, bool strict) {
642 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
649 bool EventOperation::test_id__waitfc_hex(std::string &response, unsigned int id, const std::string & hex, bool strict) {
651 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
658 bool EventOperation::test_id__waitfe_msg(std::string &response, unsigned int id, const std::string & diameterJson, bool strict) {
660 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
667 bool EventOperation::test_id__waitfc_msg(std::string &response, unsigned int id, const std::string & diameterJson, bool strict) {
669 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
676 bool EventOperation::test_id__waitfe(std::string &response, unsigned int id, const std::string & condition) {
678 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
685 bool EventOperation::test_id__waitfc(std::string &response, unsigned int id, const std::string & condition) {
687 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
694 /////////////////////////
695 // Testcases execution //
696 /////////////////////////
697 bool EventOperation::test__ttps(std::string &response, int amount) {
699 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
706 bool EventOperation::test__next(std::string &response, int syncAmount) {
708 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
715 bool EventOperation::test__ip_limit(std::string &response, int amount) {
717 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
724 bool EventOperation::test__goto(std::string &response, int id) {
726 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
733 bool EventOperation::test__run(std::string &response, int id) {
735 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
742 bool EventOperation::test__look(std::string &response, int id) {
744 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
751 bool EventOperation::test__state(std::string &response, int id) {
753 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
760 bool EventOperation::test__interact(std::string &response, int amount, unsigned int id) {
762 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
769 bool EventOperation::test__reset(std::string &response, bool soft_hard, unsigned int id) {
771 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
778 bool EventOperation::test__repeats(std::string &response, int amount) {
780 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
787 bool EventOperation::test__auto_reset(std::string &response, bool soft_hard) {
789 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
796 bool EventOperation::test__initialized(std::string &response) {
798 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
805 bool EventOperation::test__finished(std::string &response) {
807 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
814 bool EventOperation::test__clear(std::string &response) {
816 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
823 bool EventOperation::test__junit(std::string &response, const std::string & targetFile) {
825 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
832 bool EventOperation::test__summary_counts(std::string &response) {
834 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
841 bool EventOperation::test__summary_states(std::string &response) {
843 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
850 bool EventOperation::test__summary(std::string &response) {
852 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
859 bool EventOperation::test__report(std::string &response, const std::string & state, bool enable) {
861 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
868 bool EventOperation::test__report_hex(std::string &response, bool enable) {
870 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
877 bool EventOperation::test__dump_stdout(std::string &response, bool enable) {
879 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());