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 //
10 #include <sstream> // std::istringstream
11 #include <iostream> // std::cout
12 #include <math.h> // ceil
14 #include <unistd.h> // chdir
15 //#include <regex> TODO: use this from gcc4.9.0: http://stackoverflow.com/questions/8060025/is-this-c11-regex-error-me-or-the-compiler
19 #include <anna/timex/Engine.hpp>
20 #include <anna/statistics/Engine.hpp>
21 #include <anna/diameter/codec/functions.hpp>
22 #include <anna/diameter/codec/Engine.hpp>
23 #include <anna/diameter/codec/EngineManager.hpp>
24 #include <anna/diameter/stack/Engine.hpp>
25 #include <anna/diameter/helpers/base/functions.hpp>
26 #include <anna/time/functions.hpp>
27 #include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
28 #include <anna/testing/defines.hpp>
29 #include <anna/xml/xml.hpp>
30 #include <anna/diameter.comm/OriginHost.hpp>
31 #include <anna/diameter.comm/OriginHostManager.hpp>
34 #include <rxSimpleTest.hpp>
35 #include <MyDiameterEngine.hpp>
37 RxSimpleTest::RxSimpleTest() : anna::comm::Application("rxSimpleTest", "RxSimpleTest", "1.1"), a_communicator(NULL) {
39 a_admlMinResolution = 2 * anna::timex::Engine::minResolution; // 2*10 = 20 ms; 1000/20 = 50 ticks per second;
40 //a_admlMinResolution = (anna::Millisecond)100;
44 void RxSimpleTest::startService() throw(anna::RuntimeException) {
47 anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
48 anna::diameter::stack::Dictionary *d;
49 const anna::diameter::stack::Dictionary *bpd = NULL; // base protocol dictionary
51 // Codec engine manager:
52 anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate();
53 anna::diameter::codec::Engine *ce;
55 ///////////////////////////////////////////
56 // APPLICATION MESSAGE OAM MODULE SCOPES //
57 ///////////////////////////////////////////
58 // We will register a scope per stack id registered. The counters will be dynamically registered at count method.
59 anna::diameter::comm::ApplicationMessageOamModule & appMsgOamModule = anna::diameter::comm::ApplicationMessageOamModule::instantiate();
60 appMsgOamModule.enableCounters(); // this special module is disabled by default (the only)
62 unsigned int id_value = anna::diameter::helpers::APPID__3GPP_Rx; // 16777236
65 d = stackEngine.createDictionary(id_value, "./dictionaryRx.xml");
66 LOGDEBUG(anna::Logger::debug(anna::functions::asString("Created dictionary (%p) for stack id %llu", d, id_value), ANNA_FILE_LOCATION));
68 // OAM module for counters:
69 appMsgOamModule.createStackCounterScope(scope_id, id_value /* application-id */);
71 } catch(anna::RuntimeException &ex) {
72 //_exit(ex.asString());
76 bpd = d; // base protocol dictionary in case of monostack
78 // Create codec engine and register it in the codec engine manager:
79 std::string codecEngineName = anna::functions::asString("CodecEngineForStackId_%llu", id_value);
80 ce = new anna::diameter::codec::Engine(codecEngineName.c_str(), d);
81 em.registerCodecEngine(id_value, ce);
83 // Codec engine configuration:
85 // Validation mode: BeforeEncoding, AfterDecoding, Always, Never
86 ce->setValidationMode(anna::diameter::codec::Engine::ValidationMode::AfterDecoding);
88 // Validation depth: Complete, FirstError
89 ce->setValidationDepth(anna::diameter::codec::Engine::ValidationDepth::FirstError);
91 // Fix mode: BeforeEncoding, AfterDecoding, Always, Never
92 ce->setFixMode(anna::diameter::codec::Engine::FixMode::BeforeEncoding);
94 // Ignore validation flags:
95 ce->ignoreFlagsOnValidation(true);
97 // Show loaded stacks:
98 std::cout << "Stacks currently loaded:" << std::endl;
99 std::cout << anna::functions::tab(stackEngine.asString(false /* light */)) << std::endl;
102 unsigned int applicationId = id_value;
103 if (!stackEngine.getDictionary(applicationId)) {
104 std::string msg = anna::functions::asString("Cannot found a registered stack id with the value of applicationId provided: %u", applicationId);
105 throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
108 // Engine time measures checking & assignment:
109 anna::Millisecond allowedInactivityTimeMs(90000);
110 anna::Millisecond tcpConnectDelayMs(200);
111 anna::Millisecond answersTimeoutMs(10000);
112 anna::Millisecond ceaTimeoutMs(10000);
113 anna::Millisecond watchdogPeriodMs(30000);
115 /////////////////////////////////////////////////////////////////////////////////////////////
116 // Diameter communication engine:
117 std::string originHostRealm = "nodeHostRealm";
118 std::string originHostName = "afNodeHostname."; originHostName += originHostRealm; originHostName += ".com";
119 std::string commEngineName = originHostName + "_DiameterCommEngine";
120 MyDiameterEngine *commEngine = new MyDiameterEngine(commEngineName.c_str(), bpd);
121 commEngine->setAutoBind(false); // allow to create client-sessions without binding them, in order to set timeouts.
122 commEngine->setMaxConnectionDelay(tcpConnectDelayMs);
123 commEngine->setWatchdogPeriod(watchdogPeriodMs);
124 commEngine->setOriginHostName(originHostName);
125 commEngine->setOriginRealmName(originHostRealm);
128 a_workingNode = new anna::diameter::comm::OriginHost((anna::diameter::comm::Engine*)commEngine, applicationId);
129 // a_workingNode->setRequestRetransmissions(0);
132 commEngine->setNumberOfClientSessionsPerServer(1);
133 //commEngine->setClientCERandDWR("./cer.xml", "./dwr.xml");
134 commEngine->setClientCERandDWR();
136 // Register one entity for this engine:
137 a_workingNode->createEntity("localhost:3868", ceaTimeoutMs, answersTimeoutMs);
138 a_workingNode->getEntity()->bind();
141 //a_workingNode->createDiameterServer("localhost:3869", 1, allowedInactivityTimeMs, answersTimeoutMs, "./cea.xml");
143 commEngine->lazyInitialize();
145 // Node and Codec Engine registration ///////////////////////////////////////////////////////
146 anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
147 ohm.registerOriginHost(originHostName, a_workingNode);
150 anna::diameter::comm::OriginHost *RxSimpleTest::getOriginHost(const std::string &name) const throw(anna::RuntimeException) {
151 anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
152 anna::diameter::comm::OriginHost *result = ohm.getOriginHost(name);
155 throw anna::RuntimeException(anna::functions::asString("There is no origin host registered as '%s' (set Origin-Host avp correctly or force a specific host with 'node' operation)", name.c_str()), ANNA_FILE_LOCATION);
160 MyDiameterEntity *RxSimpleTest::getEntity() const throw(anna::RuntimeException) {
161 MyDiameterEntity *result = (MyDiameterEntity *)(a_workingNode->getEntity());
163 throw anna::RuntimeException("No entity created", ANNA_FILE_LOCATION);
167 MyLocalServer *RxSimpleTest::getServer() const throw(anna::RuntimeException) {
168 MyLocalServer *result = (MyLocalServer *)(a_workingNode->getDiameterServer());
170 throw anna::RuntimeException("No local server created", ANNA_FILE_LOCATION);
174 void RxSimpleTest::initialize()
175 throw(anna::RuntimeException) {
176 anna::comm::Application::initialize();
177 CommandLine& cl(anna::CommandLine::instantiate());
178 anna::comm::Communicator::WorkMode::_v workMode(anna::comm::Communicator::WorkMode::Single);
179 a_communicator = new MyCommunicator(workMode);
180 a_timeEngine = new anna::timex::Engine((anna::Millisecond)600000, a_admlMinResolution);
185 void RxSimpleTest::run()
186 throw(anna::RuntimeException) {
187 LOGMETHOD(anna::TraceMethod tm("RxSimpleTest", "run", ANNA_FILE_LOCATION));
188 anna::diameter::stack::Engine::instantiate();
191 a_start_time.setNow();
193 // Initial working directory:
195 if (getcwd(cwd, sizeof(cwd)) == NULL)
196 throw anna::RuntimeException("Cannot retrieve initial working directory !!", ANNA_FILE_LOCATION);
197 a_initialWorkingDirectory = cwd;
200 anna::statistics::Engine::instantiate().enable();
202 // Start client connections //////////////////////////////////////////////////////////////////////////////////
203 MyDiameterEntity *entity;
204 anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
205 for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) {
206 entity = (MyDiameterEntity *)(it->second->getEntity());
207 if (entity) entity->bind();
210 // Go into communicator poll
211 // Reconnection period (tcp reconnect retry time):
212 anna::Millisecond reconnectionPeriod = (anna::Millisecond)10000;
214 a_communicator->setRecoveryTime(reconnectionPeriod);
215 a_communicator->accept();
218 anna::xml::Node* RxSimpleTest::asXML(anna::xml::Node* parent) const
220 anna::xml::Node* result = parent->createChild("rxSimpleTest");
221 anna::comm::Application::asXML(result);
223 result->createAttribute("StartTime", a_start_time.asString());
224 result->createAttribute("InitialWorkingDirectory", a_initialWorkingDirectory);
225 result->createAttribute("SecondsLifeTime", anna::time::functions::lapsedMilliseconds() / 1000);
227 anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
228 for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) {
229 it->second->asXML(result);
232 // Registered codec engines:
233 anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate();