--- /dev/null
+// ANNA - Anna is Not Nothingness Anymore //
+// //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
+// //
+// See project site at http://redmine.teslayout.com/projects/anna-suite //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
+// Standard
+#include <sstream> // std::istringstream
+#include <iostream> // std::cout
+#include <math.h> // ceil
+#include <climits>
+#include <unistd.h> // chdir
+//#include <regex> TODO: use this from gcc4.9.0: http://stackoverflow.com/questions/8060025/is-this-c11-regex-error-me-or-the-compiler
+#include <stdio.h>
+
+// Project
+#include <anna/timex/Engine.hpp>
+#include <anna/statistics/Engine.hpp>
+#include <anna/diameter/codec/functions.hpp>
+#include <anna/diameter/codec/Engine.hpp>
+#include <anna/diameter/codec/EngineManager.hpp>
+#include <anna/diameter/stack/Engine.hpp>
+#include <anna/diameter/helpers/base/functions.hpp>
+#include <anna/time/functions.hpp>
+#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
+#include <anna/testing/defines.hpp>
+#include <anna/xml/xml.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
+#include <anna/diameter.comm/OriginHostManager.hpp>
+
+// Process
+#include <rxSimpleTest.hpp>
+#include <MyDiameterEngine.hpp>
+
+RxSimpleTest::RxSimpleTest() : anna::comm::Application("rxSimpleTest", "RxSimpleTest", "1.1"), a_communicator(NULL) {
+ a_timeEngine = NULL;
+ a_admlMinResolution = 2 * anna::timex::Engine::minResolution; // 2*10 = 20 ms; 1000/20 = 50 ticks per second;
+ //a_admlMinResolution = (anna::Millisecond)100;
+ a_workingNode = NULL;
+}
+
+void RxSimpleTest::startService() throw(anna::RuntimeException) {
+
+ // Stacks
+ anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
+ anna::diameter::stack::Dictionary *d;
+ const anna::diameter::stack::Dictionary *bpd = NULL; // base protocol dictionary
+
+ // Codec engine manager:
+ anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate();
+ anna::diameter::codec::Engine *ce;
+
+ ///////////////////////////////////////////
+ // APPLICATION MESSAGE OAM MODULE SCOPES //
+ ///////////////////////////////////////////
+ // We will register a scope per stack id registered. The counters will be dynamically registered at count method.
+ anna::diameter::comm::ApplicationMessageOamModule & appMsgOamModule = anna::diameter::comm::ApplicationMessageOamModule::instantiate();
+ appMsgOamModule.enableCounters(); // this special module is disabled by default (the only)
+ int scope_id = 3;
+ unsigned int id_value = anna::diameter::helpers::APPID__3GPP_Rx; // 16777236
+
+ try {
+ d = stackEngine.createDictionary(id_value, "./dictionaryRx.xml");
+ LOGDEBUG(anna::Logger::debug(anna::functions::asString("Created dictionary (%p) for stack id %llu", d, id_value), ANNA_FILE_LOCATION));
+
+ // OAM module for counters:
+ appMsgOamModule.createStackCounterScope(scope_id, id_value /* application-id */);
+
+ } catch(anna::RuntimeException &ex) {
+ //_exit(ex.asString());
+ throw ex;
+ }
+
+ bpd = d; // base protocol dictionary in case of monostack
+
+ // Create codec engine and register it in the codec engine manager:
+ std::string codecEngineName = anna::functions::asString("CodecEngineForStackId_%llu", id_value);
+ ce = new anna::diameter::codec::Engine(codecEngineName.c_str(), d);
+ em.registerCodecEngine(id_value, ce);
+
+ // Codec engine configuration:
+
+ // Validation mode: BeforeEncoding, AfterDecoding, Always, Never
+ ce->setValidationMode(anna::diameter::codec::Engine::ValidationMode::AfterDecoding);
+
+ // Validation depth: Complete, FirstError
+ ce->setValidationDepth(anna::diameter::codec::Engine::ValidationDepth::FirstError);
+
+ // Fix mode: BeforeEncoding, AfterDecoding, Always, Never
+ ce->setFixMode(anna::diameter::codec::Engine::FixMode::BeforeEncoding);
+
+ // Ignore validation flags:
+ ce->ignoreFlagsOnValidation(true);
+
+ // Show loaded stacks:
+ std::cout << "Stacks currently loaded:" << std::endl;
+ std::cout << anna::functions::tab(stackEngine.asString(false /* light */)) << std::endl;
+
+ // REALMS:
+ unsigned int applicationId = id_value;
+ if (!stackEngine.getDictionary(applicationId)) {
+ std::string msg = anna::functions::asString("Cannot found a registered stack id with the value of applicationId provided: %u", applicationId);
+ throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
+ }
+
+ // Engine time measures checking & assignment:
+ anna::Millisecond allowedInactivityTimeMs(90000);
+ anna::Millisecond tcpConnectDelayMs(200);
+ anna::Millisecond answersTimeoutMs(10000);
+ anna::Millisecond ceaTimeoutMs(10000);
+ anna::Millisecond watchdogPeriodMs(30000);
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ // Diameter communication engine:
+ std::string originHostRealm = "nodeHostRealm";
+ std::string originHostName = "afNodeHostname."; originHostName += originHostRealm; originHostName += ".com";
+ std::string commEngineName = originHostName + "_DiameterCommEngine";
+ MyDiameterEngine *commEngine = new MyDiameterEngine(commEngineName.c_str(), bpd);
+ commEngine->setAutoBind(false); // allow to create client-sessions without binding them, in order to set timeouts.
+ commEngine->setMaxConnectionDelay(tcpConnectDelayMs);
+ commEngine->setWatchdogPeriod(watchdogPeriodMs);
+ commEngine->setOriginHostName(originHostName);
+ commEngine->setOriginRealmName(originHostRealm);
+
+ // Origin host node:
+ a_workingNode = new anna::diameter::comm::OriginHost((anna::diameter::comm::Engine*)commEngine, applicationId);
+ // a_workingNode->setRequestRetransmissions(0);
+
+ // Diameter entity:
+ commEngine->setNumberOfClientSessionsPerServer(1);
+ //commEngine->setClientCERandDWR("./cer.xml", "./dwr.xml");
+ commEngine->setClientCERandDWR();
+
+ // Register one entity for this engine:
+ a_workingNode->createEntity("localhost:3868", ceaTimeoutMs, answersTimeoutMs);
+ a_workingNode->getEntity()->bind();
+
+ // Diameter server:
+ //a_workingNode->createDiameterServer("localhost:3869", 1, allowedInactivityTimeMs, answersTimeoutMs, "./cea.xml");
+
+ commEngine->lazyInitialize();
+
+ // Node and Codec Engine registration ///////////////////////////////////////////////////////
+ anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+ ohm.registerOriginHost(originHostName, a_workingNode);
+}
+
+anna::diameter::comm::OriginHost *RxSimpleTest::getOriginHost(const std::string &name) const throw(anna::RuntimeException) {
+ anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+ anna::diameter::comm::OriginHost *result = ohm.getOriginHost(name);
+
+ if (!result)
+ 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);
+
+ return result;
+}
+
+MyDiameterEntity *RxSimpleTest::getEntity() const throw(anna::RuntimeException) {
+ MyDiameterEntity *result = (MyDiameterEntity *)(a_workingNode->getEntity());
+ if (!result)
+ throw anna::RuntimeException("No entity created", ANNA_FILE_LOCATION);
+ return result;
+}
+
+MyLocalServer *RxSimpleTest::getServer() const throw(anna::RuntimeException) {
+ MyLocalServer *result = (MyLocalServer *)(a_workingNode->getDiameterServer());
+ if (!result)
+ throw anna::RuntimeException("No local server created", ANNA_FILE_LOCATION);
+ return result;
+}
+
+void RxSimpleTest::initialize()
+throw(anna::RuntimeException) {
+ anna::comm::Application::initialize();
+ CommandLine& cl(anna::CommandLine::instantiate());
+ anna::comm::Communicator::WorkMode::_v workMode(anna::comm::Communicator::WorkMode::Single);
+ a_communicator = new MyCommunicator(workMode);
+ a_timeEngine = new anna::timex::Engine((anna::Millisecond)600000, a_admlMinResolution);
+
+ startService();
+}
+
+void RxSimpleTest::run()
+throw(anna::RuntimeException) {
+ LOGMETHOD(anna::TraceMethod tm("RxSimpleTest", "run", ANNA_FILE_LOCATION));
+ anna::diameter::stack::Engine::instantiate();
+
+ // Start time:
+ a_start_time.setNow();
+
+ // Initial working directory:
+ char cwd[1024];
+ if (getcwd(cwd, sizeof(cwd)) == NULL)
+ throw anna::RuntimeException("Cannot retrieve initial working directory !!", ANNA_FILE_LOCATION);
+ a_initialWorkingDirectory = cwd;
+
+ // Statistics:
+ anna::statistics::Engine::instantiate().enable();
+
+ // Start client connections //////////////////////////////////////////////////////////////////////////////////
+ MyDiameterEntity *entity;
+ anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+ for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) {
+ entity = (MyDiameterEntity *)(it->second->getEntity());
+ if (entity) entity->bind();
+ }
+
+ // Go into communicator poll
+ // Reconnection period (tcp reconnect retry time):
+ anna::Millisecond reconnectionPeriod = (anna::Millisecond)10000;
+
+ a_communicator->setRecoveryTime(reconnectionPeriod);
+ a_communicator->accept();
+}
+
+anna::xml::Node* RxSimpleTest::asXML(anna::xml::Node* parent) const
+throw() {
+ anna::xml::Node* result = parent->createChild("rxSimpleTest");
+ anna::comm::Application::asXML(result);
+ // Timming:
+ result->createAttribute("StartTime", a_start_time.asString());
+ result->createAttribute("InitialWorkingDirectory", a_initialWorkingDirectory);
+ result->createAttribute("SecondsLifeTime", anna::time::functions::lapsedMilliseconds() / 1000);
+ // Diameter:
+ anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+ for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) {
+ it->second->asXML(result);
+ }
+
+ // Registered codec engines:
+ anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate();
+ em.asXML(result);
+
+ return result;
+}
+