Add third work package for REST API implementation
[anna.git] / example / diameter / launcher / EventOperation.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
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 //
7
8
9 // Standard
10 #include <string>
11
12 // Process
13 #include <EventOperation.hpp>
14 #include <Launcher.hpp>
15
16 // Project
17 #include <anna/diameter.comm/OriginHost.hpp>
18
19
20 //// Standard
21 //#include <sstream>      // std::istringstream
22 //#include <iostream>     // std::cout
23 //#include <math.h> // ceil
24 //#include <climits>
25 #include <unistd.h> // chdir
26 //#include <stdio.h>
27 //
28 //// Project
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/core/functions.hpp>
41 //#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
42 //#include <anna/testing/defines.hpp>
43 #include <anna/xml/xml.hpp>
44 //#include <anna/diameter.comm/OriginHost.hpp>
45 //#include <anna/diameter.comm/OriginHostManager.hpp>
46 #include <anna/diameter.comm/Message.hpp>
47 //
48 //// Process
49 //#include <Launcher.hpp>
50 //#include <Procedure.hpp>
51 //#include <EventOperation.hpp>
52 #include <MyDiameterEngine.hpp>
53 #include <MyLocalServer.hpp>
54 #include <anna/testing/TestManager.hpp>
55 //#include <anna/testing/TestCase.hpp>
56
57
58 /////////////////////
59 // Node management //
60 /////////////////////
61 bool EventOperation::node(std::string &response, const std::string & name) {
62
63   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
64
65   anna::diameter::comm::OriginHost *workingNode;
66   try { workingNode = my_app.getWorkingNode(); } catch(anna::RuntimeException &ex) { ex.trace(); }
67
68   if (name != "") {
69     if (my_app.setWorkingNode(name)) {
70       response = anna::functions::asString("Forced node is now '%s'", name.c_str());
71       my_app.setOperatedHost(my_app.getWorkingNode()); // now is the new one
72     }
73     else {
74       response = anna::functions::asString("Node '%s' invalid. Nothing done", name.c_str());
75     }
76   }
77   else {
78     if (workingNode) {
79       if (a_http) {
80         response = anna::functions::encodeBase64(workingNode->asXMLString());
81       }
82       else {
83         response = workingNode->asXMLString();
84       }
85     }
86     else {
87       response = "Working node is automatic";
88     }
89   }
90   return true; // OK
91 }
92
93 bool EventOperation::node_auto(std::string &response) {
94
95   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
96
97   my_app.setNodeAuto();
98   response = "Working node has been set to automatic";
99
100   return true; // OK
101 }
102
103 ////////////////////////
104 // Parsing operations //
105 ////////////////////////
106 bool EventOperation::code(std::string &response, const std::string & diameterJson) {
107
108   bool success;
109   std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
110   if (!success) {
111     response += "json to xml failed, unable to encode !";
112     return false;
113   }
114   anna::diameter::codec::Message codecMsg; // auxiliary codec message
115   codecMsg.loadXMLString(diameterXml);
116   response = anna::functions::asHexString(codecMsg.code());
117
118   return true; // OK
119 }
120
121 bool EventOperation::decode(std::string &response, const std::string & diameterHex) {
122
123   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
124
125   anna::DataBlock db_aux(true);
126   anna::functions::fromHexString(diameterHex, db_aux);
127   anna::diameter::codec::Message codecMsg; // auxiliary codec message
128   try {
129     codecMsg.decode(db_aux);
130     std::string xmlString = codecMsg.asXMLString();
131     response = anna::functions::encodeBase64(xmlString);
132   }
133   catch(anna::RuntimeException &ex) { ex.trace(); }
134
135   return true; // OK
136 }
137
138 bool EventOperation::loadmsg(std::string &response, const std::string & diameterJson) {
139
140   bool success;
141   std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
142   if (!success) {
143     response += "json to xml failed, unable to load message !";
144     return false;
145   }
146   anna::diameter::codec::Message codecMsg; // auxiliary codec message
147   codecMsg.loadXMLString(diameterXml);
148   response = anna::functions::encodeBase64(codecMsg.asXMLString());
149
150   return true; // OK
151 }
152
153 /////////////////
154 // Hot changes //
155 /////////////////
156 bool EventOperation::services(std::string &response, const std::string & servicesJson) {
157
158   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
159
160   bool success;
161   std::string servicesXml = anna::json::functions::json2xml(servicesJson, success);
162   if (!success) {
163     response += "json to xml failed, unable to load services !";
164     return false;
165   }
166
167   try {
168     my_app.loadServicesFromXMLString(servicesXml, true /* bind entities */);
169   }
170   catch(anna::RuntimeException &ex) {
171     ex.trace();
172     response += "loaded services with errors";
173     return false;
174   }
175   response = "loaded services correctly";
176
177   return true; // OK
178 }
179
180 bool EventOperation::diameterServerSessions(std::string &response, int sessions) {
181
182   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
183
184   try {
185     my_app.getOperatedServer()->setMaxConnections(sessions);
186   }
187   catch(anna::RuntimeException &ex) {
188     ex.trace();
189     response += "fail to operate the server";
190     return false;
191   }
192   response = "new sessions successfully established on operated diameter server";
193
194   return true; // OK
195 }
196
197 bool EventOperation::change_dir(std::string &response, const std::string & directory) {
198
199   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
200
201   std::string dir = directory;
202   if (dir == "") dir = my_app.getInitialWorkingDirectory();
203   bool result = (chdir(dir.c_str()) == 0);
204
205   if (result)
206     response = "New execution directory configured: ";
207   else
208     response = "Cannot assign provided execution directory: ";
209
210   response += dir;
211   return result;
212 }
213
214 ////////////////////////////////
215 // Client sessions visibility //
216 ////////////////////////////////
217 bool EventOperation::visibility(std::string &response, const std::string & action, const std::string &addressPort, int socket) {
218
219   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
220
221   response = "";
222
223   if(addressPort != "") {
224     if(socket != -1) {
225       std::string key = addressPort;
226       key += "|";
227       key += anna::functions::asString(socket);
228
229       if(action == "hide") my_app.getOperatedEngine()->findClientSession(key)->hide();
230       if(action == "show") my_app.getOperatedEngine()->findClientSession(key)->show();
231       if(action == "hidden") response = my_app.getOperatedEngine()->findClientSession(key)->hidden() ? "true" : "false";
232       if(action == "shown") response = my_app.getOperatedEngine()->findClientSession(key)->shown() ? "true" : "false";
233     } else {
234       std::string address;
235       int port;
236       anna::functions::getAddressAndPortFromSocketLiteral(addressPort, address, port);
237
238       if(action == "hide") my_app.getOperatedEngine()->findServer(address, port)->hide();
239       if(action == "show") my_app.getOperatedEngine()->findServer(address, port)->show();
240       if(action == "hidden") response = my_app.getOperatedEngine()->findServer(address, port)->hidden() ? "true" : "false";
241       if(action == "shown") response = my_app.getOperatedEngine()->findServer(address, port)->shown() ? "true" : "false";
242     }
243   } else {
244     if(action == "hide") my_app.getOperatedEntity()->hide();
245     if(action == "show") my_app.getOperatedEntity()->show();
246     if(action == "hidden") response = my_app.getOperatedEntity()->hidden() ? "true" : "false";
247     if(action == "shown") response = my_app.getOperatedEntity()->shown() ? "true" : "false";
248   }
249
250   return true; // OK
251 }
252
253
254 ///////////////
255 // Snapshots //
256 ///////////////
257 bool EventOperation::collect(std::string &response) {
258
259   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
260
261   my_app.resetCounters();
262   my_app.resetStatistics();
263   response = "All process counters & statistic information have been reset";
264
265   return true; // OK
266 }
267
268 bool EventOperation::context(std::string &response, const std::string & targetFile) {
269
270   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
271
272   std::string contextFile = (targetFile != "") ? targetFile : anna::functions::asString("/var/tmp/anna.context.%05d", my_app.getPid());
273   my_app.writeContext(contextFile);
274   response = anna::functions::asString("Context dumped on file '%s'", contextFile.c_str());
275
276   return true; // OK
277 }
278
279 bool EventOperation::forceCountersRecord(std::string &response) {
280
281   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
282
283   my_app.forceCountersRecord();
284   response = "Current counters have been dump to disk";
285
286   return true; // OK
287 }
288
289 bool EventOperation::log_statistics_samples(std::string &response, const std::string & list) {
290
291   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
292
293   my_app.logStatisticsSamples(list);
294   response = anna::functions::asString("Log statistics samples for '%s' concepts", list.c_str());
295
296   return true; // OK
297 }
298
299 bool EventOperation::show_oam(std::string &response) {
300
301   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
302
303   anna::xml::Node root("root");
304   response = anna::xml::Compiler().apply(my_app.oamAsXML(&root));
305   if (a_http)
306      response = anna::functions::encodeBase64(response);
307
308   return true; // OK
309 }
310
311 bool EventOperation::show_stats(std::string &response) {
312
313   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
314
315   anna::xml::Node root("root");
316   response = anna::xml::Compiler().apply(my_app.statsAsXML(&root));
317   if (a_http)
318      response = anna::functions::encodeBase64(response);
319
320   return true; // OK
321 }
322
323 /////////////////////
324 // Flow operations //
325 /////////////////////
326 bool EventOperation::sendmsg_hex_2e(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
327
328   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
329   anna::diameter::codec::Message codecMsg; // auxiliary codec message
330   bool success;
331   anna::diameter::comm::Message *msg;
332
333   if(msg_or_hex) {
334     std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
335     if (!success) {
336       response += "json to xml failed, unable to send message !";
337       return false;
338     }
339     codecMsg.loadXMLString(diameterXml);
340     try {
341       my_app.updateOperatedOriginHostWithMessage(codecMsg);
342       msg = my_app.getOperatedHost()->createCommMessage();
343       msg->clearBody();
344     }
345     catch(anna::RuntimeException &ex) {
346       ex.trace();
347       response += "invalid operated host";
348       return false;
349     }
350     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)
351     msg->setBody(codecMsg.code());
352   } else {
353     // Get DataBlock from hex content:
354     anna::DataBlock db_aux(true);
355     std::string hexString = diameterJson_or_Hex;
356     hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
357     LOGDEBUG(
358         std::string msg = "Hex string (remove colons if exists): ";
359     msg += hexString;
360     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
361     );
362     anna::functions::fromHexString(hexString, db_aux); // could launch exception
363     try {
364       my_app.updateOperatedOriginHostWithMessage(db_aux);
365       msg = my_app.getOperatedHost()->createCommMessage();
366     }
367     catch(anna::RuntimeException &ex) {
368       ex.trace();
369       response += "invalid operated host";
370       return false;
371     }
372     msg->setBody(db_aux);
373     try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
374   }
375
376   success = my_app.getOperatedEntity()->send(msg);
377   my_app.getOperatedHost()->releaseCommMessage(msg);
378
379   // Detailed log:
380   if(my_app.getOperatedHost()->logEnabled()) {
381     anna::diameter::comm::Server *usedServer = my_app.getOperatedEntity()->getLastUsedResource();
382     anna::diameter::comm::ClientSession *usedClientSession = usedServer ? usedServer->getLastUsedResource() : NULL;
383     std::string detail = usedClientSession ? usedClientSession->asString() : "<null client session>"; // shouldn't happen
384     my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2e" : "send2eError"), detail);
385   }
386
387
388   response = "Operation processed"; // could be failed
389   return success;
390 }
391
392 bool EventOperation::sendmsg_hex_2c(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
393
394   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
395   anna::diameter::codec::Message codecMsg; // auxiliary codec message
396   bool success;
397   anna::diameter::comm::Message *msg;
398
399   if(msg_or_hex) {
400     std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
401     if (!success) {
402       response += "json to xml failed, unable to send message !";
403       return false;
404     }
405     codecMsg.loadXMLString(diameterXml);
406     try {
407       my_app.updateOperatedOriginHostWithMessage(codecMsg);
408       msg = my_app.getOperatedHost()->createCommMessage();
409       msg->clearBody();
410     }
411     catch(anna::RuntimeException &ex) {
412       ex.trace();
413       response += "invalid operated host";
414       return false;
415     }
416     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)
417     msg->setBody(codecMsg.code());
418   } else {
419     // Get DataBlock from hex content:
420     anna::DataBlock db_aux(true);
421     std::string hexString = diameterJson_or_Hex;
422     hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
423     LOGDEBUG(
424         std::string msg = "Hex string (remove colons if exists): ";
425     msg += hexString;
426     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
427     );
428     anna::functions::fromHexString(hexString, db_aux); // could launch exception
429     try {
430       my_app.updateOperatedOriginHostWithMessage(db_aux);
431       msg = my_app.getOperatedHost()->createCommMessage();
432     }
433     catch(anna::RuntimeException &ex) {
434       ex.trace();
435       response += "invalid operated host";
436       return false;
437     }
438     msg->setBody(db_aux);
439     try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
440   }
441
442   success = my_app.getOperatedServer()->send(msg);
443   my_app.getOperatedHost()->releaseCommMessage(msg);
444
445   // Detailed log:
446   if(my_app.getOperatedHost()->logEnabled()) {
447     anna::diameter::comm::ServerSession *usedServerSession = my_app.getOperatedServer()->getLastUsedResource();
448     std::string detail = usedServerSession ? usedServerSession->asString() : "<null server session>"; // shouldn't happen
449     my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
450   }
451
452
453   response = "Operation processed"; // could be failed
454   return success;
455 }
456
457 bool EventOperation::answermsg_action_2e(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
458
459   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
460   anna::diameter::codec::Message codecMsg; // auxiliary codec message
461   anna::diameter::codec::Message *message;
462   bool success;
463
464   if (msg_or_action) {
465
466     std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
467     if (!success) {
468       response += "json to xml failed, unable to send message !";
469       return false;
470     }
471     codecMsg.loadXMLString(diameterXml);
472     try {
473       my_app.updateOperatedOriginHostWithMessage(codecMsg);
474       message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
475       LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
476     }
477     catch(anna::RuntimeException &ex) {
478       ex.trace();
479       response += "invalid operated host";
480       return false;
481     }
482
483     if(message->isRequest()) {
484       response += "cannot program diameter requests. Answer type must be provided";
485       return false;
486     }
487
488     int code = message->getId().first;
489     LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
490     response = "Added 'answer to entity' to the FIFO queue corresponding to its message code";
491     my_app.getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
492   }
493   else { // action
494
495     if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
496       response = anna::functions::encodeBase64(my_app.getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY"));
497     } else if (diameterJson_or_action == "rotate") {
498       my_app.getOperatedEntity()->getReactingAnswers()->rotate(true);
499       response = "rotate";
500     } else if (diameterJson_or_action == "exhaust") {
501       my_app.getOperatedEntity()->getReactingAnswers()->rotate(false);
502       response = "exhaust";
503     } else if (diameterJson_or_action == "clear") {
504       my_app.getOperatedEntity()->getReactingAnswers()->clear();
505       response = "clear";
506     } else if (diameterJson_or_action == "dump") {
507       my_app.getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
508       response = "dump";
509     }
510   }
511
512
513   return true; // OK
514 }
515
516 bool EventOperation::answermsg_action_2c(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
517
518   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
519   anna::diameter::codec::Message codecMsg; // auxiliary codec message
520   anna::diameter::codec::Message *message;
521   bool success;
522
523   if (msg_or_action) {
524
525     std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
526     if (!success) {
527       response += "json to xml failed, unable to send message !";
528       return false;
529     }
530     codecMsg.loadXMLString(diameterXml);
531     try {
532       my_app.updateOperatedOriginHostWithMessage(codecMsg);
533       message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
534       LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
535     }
536     catch(anna::RuntimeException &ex) {
537       ex.trace();
538       response += "invalid operated host";
539       return false;
540     }
541
542     if(message->isRequest()) {
543       response += "cannot program diameter requests. Answer type must be provided";
544       return false;
545     }
546
547     int code = message->getId().first;
548     LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
549     my_app.getOperatedServer()->getReactingAnswers()->addMessage(code, message);
550     response = "Added 'answer to client' to the FIFO queue corresponding to its message code";
551   }
552   else { // action
553
554     if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
555       response = anna::functions::encodeBase64(my_app.getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT"));
556     } else if (diameterJson_or_action == "rotate") {
557       my_app.getOperatedServer()->getReactingAnswers()->rotate(true);
558       response = "rotate";
559     } else if (diameterJson_or_action == "exhaust") {
560       my_app.getOperatedServer()->getReactingAnswers()->rotate(false);
561       response = "exhaust";
562     } else if (diameterJson_or_action == "clear") {
563       my_app.getOperatedServer()->getReactingAnswers()->clear();
564       response = "clear";
565     } else if (diameterJson_or_action == "dump") {
566       my_app.getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
567       response = "dump";
568     }
569   }
570
571
572   return true; // OK
573 }
574
575 /////////////////
576 // FSM testing //
577 /////////////////
578 bool EventOperation::test_id__description(std::string &response, unsigned int id, const std::string & description) {
579
580   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
581   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
582
583   try {
584     testManager.getTestCase(id)->setDescription(description); // creates / reuses
585     response = "Done";
586   }
587   catch(anna::RuntimeException &ex) {
588     ex.trace();
589     response += "invalid ip-limit";
590     return false;
591   }
592
593   return true; // OK
594 }
595
596 bool EventOperation::test_id__ip_limit(std::string &response, unsigned int id, int amount) {
597
598   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
599   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
600
601   try {
602     testManager.getTestCase(id)->addIpLimit(amount); // creates / reuses
603     response = "Done";
604   }
605   catch(anna::RuntimeException &ex) {
606     ex.trace();
607     response += "invalid ip-limit";
608     return false;
609   }
610
611   return true; // OK
612 }
613
614 bool EventOperation::test_id__timeout(std::string &response, unsigned int id, int msecs) {
615
616   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
617   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
618
619   try {
620     anna::Millisecond timeout = my_app.checkTimeMeasure("Test case timeout", anna::functions::asString(msecs));
621     testManager.getTestCase(id)->addTimeout(timeout); // creates / reuses
622     response = "Done";
623   }
624   catch(anna::RuntimeException &ex) {
625     ex.trace();
626     response += "invalid timeout";
627     return false;
628   }
629
630   return true; // OK
631 }
632
633 bool EventOperation::test_id__sendmsg2e_2c(std::string &response, unsigned int id, bool _2e_or_2c, const std::string & diameterJson, int stepNumber) {
634
635   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
636   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
637
638   bool success;
639   std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
640   if (!success) {
641     response += "json to xml failed, unable to load message !";
642     return false;
643   }
644   anna::diameter::codec::Message codecMsg; // auxiliary codec message
645   codecMsg.loadXMLString(diameterXml);
646
647   LOGWARNING(
648      if (!codecMsg.isRequest() && (stepNumber == -1))
649       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);
650   );
651
652   try {
653     my_app.updateOperatedOriginHostWithMessage(codecMsg);
654     if (_2e_or_2c)
655       testManager.getTestCase(id)->addSendDiameterXml2e(codecMsg.code(), my_app.getOperatedHost(), stepNumber); // creates / reuses
656     else
657       testManager.getTestCase(id)->addSendDiameterXml2c(codecMsg.code(), my_app.getOperatedHost(), stepNumber); // creates / reuses
658
659     response = "Done";
660   }
661   catch(anna::RuntimeException &ex) {
662     ex.trace();
663     response += "failed";
664     return false;
665   }
666
667   return true; // OK
668 }
669
670 bool EventOperation::test_id__delay(std::string &response, unsigned int id, int msecs) {
671
672   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
673   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
674
675   try {
676     anna::Millisecond delay = ((msecs == 0 /* special case */) ? (anna::Millisecond)0 : my_app.checkTimeMeasure("Test case delay step", anna::functions::asString(msecs)));
677     testManager.getTestCase(id)->addDelay(delay); // creates / reuses
678     response = "Done";
679   }
680   catch(anna::RuntimeException &ex) {
681     ex.trace();
682     response += "invalid delay";
683     return false;
684   }
685
686   return true; // OK
687 }
688
689 bool EventOperation::test_id__sh_command(std::string &response, unsigned int id, const std::string & script) {
690
691   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
692   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
693
694   try {
695     testManager.getTestCase(id)->addCommand(script); // creates / reuses
696     response = "Done";
697   }
698   catch(anna::RuntimeException &ex) {
699     ex.trace();
700     response += "failed";
701     return false;
702   }
703
704   return true; // OK
705 }
706
707 bool EventOperation::test_id__waitfefc_hex(std::string &response, unsigned int id, bool fe_or_fc, const std::string & hex, bool strict) {
708
709   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
710   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
711
712   // Get DataBlock from hex content:
713   anna::DataBlock db_aux(true);
714   std::string hexString = hex;
715   hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
716   LOGDEBUG(
717       std::string msg = "Hex string (remove colons if exists): ";
718   msg += hexString;
719   anna::Logger::debug(msg, ANNA_FILE_LOCATION);
720   );
721
722   std::string regexp;
723   try {
724     anna::functions::fromHexString(hexString, db_aux); // could launch exception
725     regexp = anna::functions::asHexString(db_aux);
726   }
727   catch(anna::RuntimeException &ex) {
728     ex.trace();
729     response += "failed";
730     return false;
731   }
732
733   // optional 'full':
734   if(!strict) {
735     //// If request, we will ignore sequence data:
736     //if (anna::diameter::codec::functions::requestBit(db_aux))
737     regexp.replace (24, 16, "[0-9A-Fa-f]{16}");
738
739     regexp.insert(0, "^");
740     regexp += "$";
741   }
742
743   try {
744     testManager.getTestCase(id)->addWaitDiameterRegexpHex(fe_or_fc, regexp);
745     response = "Done";
746   }
747   catch(anna::RuntimeException &ex) {
748     ex.trace();
749     response += "failed";
750     return false;
751   }
752
753   return true; // OK
754 }
755
756 bool EventOperation::test_id__waitfefc_msg(std::string &response, unsigned int id, bool fe_or_fc, const std::string & diameterJson, bool strict) {
757
758   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
759   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
760
761   bool success;
762   std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
763   if (!success) {
764     response += "json to xml failed, unable to load message !";
765     return false;
766   }
767
768   try {
769     anna::diameter::codec::Message codecMsg; // auxiliary codec message
770     codecMsg.loadXMLString(diameterXml);
771     std::string regexp = codecMsg.asXMLString(true /* normalization */);
772
773     // Now we must insert regular expressions in hop-by-hop, end-to-end and Origin-State-Id:
774
775     // optional 'full':
776     if(!strict) {
777       std::string::size_type pos, pos_1, pos_2;
778
779       pos = regexp.find("end-to-end-id=", 0u);
780       pos = regexp.find("\"", pos);
781       pos_1 = pos;
782       pos = regexp.find("\"", pos+1);
783       pos_2 = pos;
784       regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
785
786       pos = regexp.find("hop-by-hop-id=", 0u);
787       pos = regexp.find("\"", pos);
788       pos_1 = pos;
789       pos = regexp.find("\"", pos+1);
790       pos_2 = pos;
791       regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
792
793       // For this representation: <avp name="Origin-State-Id" data="1428633668"/>
794       //pos = regexp.find("Origin-State-Id", 0u);
795       //pos = regexp.find("\"", pos);
796       //pos = regexp.find("\"", pos+1);
797       //pos_1 = pos;
798       //pos = regexp.find("\"", pos+1);
799       //pos_2 = pos;
800       //regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
801       // But we have this one: <avp data="1428633668" name="Origin-State-Id"/>
802       pos = regexp.find("Origin-State-Id", 0u);
803       pos = regexp.rfind("\"", pos);
804       pos = regexp.rfind("\"", pos-1);
805       pos = regexp.rfind("\"", pos-1);
806       pos_1 = pos;
807       pos = regexp.find("\"", pos+1);
808       pos_2 = pos;
809       regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
810
811       //regexp.insert(0, "^");
812       //regexp += "$";
813     }
814
815     testManager.getTestCase(id)->addWaitDiameterRegexpXml(fe_or_fc, regexp);
816     response = "Done";
817   }
818   catch(anna::RuntimeException &ex) {
819     ex.trace();
820     response += "failed";
821     return false;
822   }
823
824   return true; // OK
825 }
826
827 bool EventOperation::test_id__waitfefc(std::string &response, unsigned int id, bool fe_or_fc,
828                          const std::string & code,
829                          const std::string & bitR,
830                          const std::string & hopByHop,
831                          const std::string & applicationId,
832                          const std::string & sessionId,
833                          const std::string & resultCode,
834                          const std::string & msisdn,
835                          const std::string & imsi,
836                          const std::string & serviceContextId) {
837
838   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
839   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
840
841   try { // [code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId]
842     testManager.getTestCase(id)->addWaitDiameter(fe_or_fc, code, bitR, hopByHop, applicationId, sessionId, resultCode, msisdn, imsi, serviceContextId);
843     response = "Done";
844   }
845   catch(anna::RuntimeException &ex) {
846     ex.trace();
847     response += "failed";
848     return false;
849   }
850
851   return true; // OK
852 }
853
854 /////////////////////////
855 // Testcases execution //
856 /////////////////////////
857 bool EventOperation::test__ttps(std::string &response, int amount) {
858
859   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
860
861
862
863   return true; // OK
864 }
865
866 bool EventOperation::test__next(std::string &response, int syncAmount) {
867
868   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
869
870
871
872   return true; // OK
873 }
874
875 bool EventOperation::test__ip_limit(std::string &response, int amount) {
876
877   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
878
879
880
881   return true; // OK
882 }
883
884 bool EventOperation::test__goto(std::string &response, int id) {
885
886   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
887
888
889
890   return true; // OK
891 }
892
893 bool EventOperation::test__run(std::string &response, int id) {
894
895   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
896
897
898
899   return true; // OK
900 }
901
902 bool EventOperation::test__look(std::string &response, int id) {
903
904   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
905
906
907
908   return true; // OK
909 }
910
911 bool EventOperation::test__state(std::string &response, int id) {
912
913   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
914
915
916
917   return true; // OK
918 }
919
920 bool EventOperation::test__interact(std::string &response, int amount, unsigned int id) {
921
922   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
923
924
925
926   return true; // OK
927 }
928
929 bool EventOperation::test__reset(std::string &response, bool soft_hard, unsigned int id) {
930
931   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
932
933
934
935   return true; // OK
936 }
937
938 bool EventOperation::test__repeats(std::string &response, int amount) {
939
940   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
941
942
943
944   return true; // OK
945 }
946
947 bool EventOperation::test__auto_reset(std::string &response, bool soft_hard) {
948
949   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
950
951
952
953   return true; // OK
954 }
955
956 bool EventOperation::test__initialized(std::string &response) {
957
958   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
959
960
961
962   return true; // OK
963 }
964
965 bool EventOperation::test__finished(std::string &response) {
966
967   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
968
969
970
971   return true; // OK
972 }
973
974 bool EventOperation::test__clear(std::string &response) {
975
976   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
977   anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
978
979   try {
980     if (testManager.clearPool()) {
981       response = "All the programmed test cases have been dropped";
982     }
983     else {
984       response = "There are not programmed test cases to be removed";
985     }
986   }
987   catch(anna::RuntimeException &ex) {
988     ex.trace();
989     response += "failed";
990     return false;
991   }
992
993   return true; // OK
994 }
995
996 bool EventOperation::test__junit(std::string &response, const std::string & targetFile) {
997
998   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
999
1000
1001
1002   return true; // OK
1003 }
1004
1005 bool EventOperation::test__summary_counts(std::string &response) {
1006
1007   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1008
1009
1010
1011   return true; // OK
1012 }
1013
1014 bool EventOperation::test__summary_states(std::string &response) {
1015
1016   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1017
1018
1019
1020   return true; // OK
1021 }
1022
1023 bool EventOperation::test__summary(std::string &response) {
1024
1025   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1026
1027
1028
1029   return true; // OK
1030 }
1031
1032 bool EventOperation::test__report(std::string &response, const std::string & state, bool enable) {
1033
1034   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1035
1036
1037
1038   return true; // OK
1039 }
1040
1041 bool EventOperation::test__report_hex(std::string &response, bool enable) {
1042
1043   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1044
1045
1046
1047   return true; // OK
1048 }
1049
1050 bool EventOperation::test__dump_stdout(std::string &response, bool enable) {
1051
1052   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1053
1054
1055
1056   return true; // OK
1057 }
1058
1059