+void Launcher::run()
+throw(anna::RuntimeException) {
+ LOGMETHOD(anna::TraceMethod tm("Launcher", "run", ANNA_FILE_LOCATION));
+ CommandLine& cl(anna::CommandLine::instantiate());
+ // Start time:
+ a_start_time.setNow();
+ // Statistics:
+ anna::statistics::Engine::instantiate().enable();
+ ///////////////////////////////
+ // Diameter library COUNTERS //
+ ///////////////////////////////
+ anna::diameter::comm::OamModule & oamDiameterComm = anna::diameter::comm::OamModule::instantiate();
+ oamDiameterComm.initializeCounterScope(1); // 1000 - 1999
+ anna::diameter::codec::OamModule & oamDiameterCodec = anna::diameter::codec::OamModule::instantiate();
+ oamDiameterCodec.initializeCounterScope(2); // 2000 - 2999
+ /////////////////
+ // COMM MODULE //
+ /////////////////
+ /* Main events */
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestReceived, "" /* get defaults for enum type*/, 0 /*1000*/);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerReceived, "", 1 /*1001*/);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestReceivedOnClientSession, "", 2 /*1002*/);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerReceivedOnClientSession, "", 3 /*1003*/);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestReceivedOnServerSession, "", 4 /* etc. */);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerReceivedOnServerSession, "", 5);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentOK, "", 6);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentNOK, "", 7);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerSentOK, "", 8);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerSentNOK, "", 9);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentOnClientSessionOK, "", 10);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentOnClientSessionNOK, "", 11);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerSentOnClientSessionOK, "", 12);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerSentOnClientSessionNOK, "", 13);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentOnServerSessionOK, "", 14);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentOnServerSessionNOK, "", 15);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerSentOnServerSessionOK, "", 16);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerSentOnServerSessionNOK, "", 17);
+ /* Diameter Base (capabilities exchange & keep alive) */
+ // as client
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::CERSentOK, "", 18);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::CERSentNOK, "", 19);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::CEAReceived, "", 20);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DWRSentOK, "", 21);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DWRSentNOK, "", 22);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DWAReceived, "", 23);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DPRSentOK, "", 24);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DPRSentNOK, "", 25);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DPAReceived, "", 26);
+ // as server
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::CERReceived, "", 27);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::CEASentOK, "", 28);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::CEASentNOK, "", 29);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DWRReceived, "", 30);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DWASentOK, "", 31);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DWASentNOK, "", 32);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DPRReceived, "", 33);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DPASentOK, "", 34);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::DPASentNOK, "", 35);
+ /* server socket operations (enable/disable listening port for any local server) */
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::ServerSocketsOpened, "", 36);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::ServerSocketsClosed, "", 37);
+ /* Connectivity */
+ // clients
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::UnableToDeliverOverEntity, "", 38);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::LostAvailabilityOverClientSession, "", 39);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RecoveredAvailabilityOverClientSession, "", 40);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::LostAvailabilityOverServer, "", 41);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RecoveredAvailabilityOverServer, "", 42);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::LostAvailabilityOverEntity, "", 43);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RecoveredAvailabilityOverEntity, "", 44);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::LostAvailabilityOverEngineForEntities, "", 45);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RecoveredAvailabilityOverEngineForEntities, "", 46);
+ // servers
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::UnableToDeliverToClient, "", 47);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::LostConnectionForServerSession, "", 48);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::UnbindConnectionForServerSessionDueToInactivityTimeAnomaly, "", 49);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::CreatedConnectionForServerSession, "", 50);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::LostAvailabilityOverLocalServer, "", 51);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RecoveredAvailabilityOverLocalServer, "", 52);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::LostAvailabilityOverEngineForLocalServers, "", 53);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RecoveredAvailabilityOverEngineForLocalServers, "", 54);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentExpired, "", 55);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentOnClientSessionExpired, "", 56);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::RequestSentOnServerSessionExpired, "", 57);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerReceivedUnknown, "", 58);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerReceivedOnClientSessionUnknown, "", 59);
+ oamDiameterComm.registerCounter(anna::diameter::comm::OamModule::Counter::AnswerReceivedOnServerSessionUnknown, "", 60);
+ //////////////////
+ // CODEC MODULE //
+ //////////////////
+ /* Avp decoding */
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::AvpDecode__NotEnoughBytesToCoverAvpHeaderLength, "", 0 /*2000*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::AvpDecode__IncoherenceBetweenActivatedVBitAndZeroedVendorIDValueReceived, "", 1 /*2001*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::AvpDecode__IncorrectLength, "", 2 /*2002*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::AvpDecode__DataPartInconsistence, "", 3 /*2003*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::AvpDecode__UnknownAvpWithMandatoryBit, "", 4 /*2004*/);
+ /* Message decoding */
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::MessageDecode__NotEnoughBytesToCoverMessageHeaderLength, "", 5 /*2005*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::MessageDecode__NotEnoughBytesToCoverMessageLength, "", 6 /*2006*/);
+ /* Avp validation */
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::AvpValidation__EnumeratedAvpWithValueDoesNotComplyRestriction, "", 10 /*2010*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::AvpValidation__AvpFlagsDoesNotFulfillTheDefinedFlagRules, "", 11 /*2011*/);
+ /* Message validation */
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::MessageValidation__UnknownOperationUnableToValidate, "", 12 /*2012*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::MessageValidation__OperationHaveIncoherentFlags, "", 13 /*2013*/);
+ /* Level validation */
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__MissingFixedRule, "", 14 /*2014*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedRuleForCardinality, "", 15 /*2015*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedRuleForCardinalityLessThanNeeded, "", 16 /*2016*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedRuleForCardinalityMoreThanNeeded, "", 17 /*2017*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedGenericAvpRuleForCardinalityFoundDisregardedItem, "", 18 /*2018*/);
+ oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FoundDisregardedItemsAndGenericAVPWasNotSpecified, "", 19 /*2019*/);
+
+ /////////////////////////////////
+ // Counter recorder associated //
+ /////////////////////////////////
+ if(a_counterRecorderClock) {
+ oamDiameterComm.setCounterRecorder(a_counterRecorder);
+ oamDiameterCodec.setCounterRecorder(a_counterRecorder);
+ a_timeEngine->activate(a_counterRecorderClock); // start clock
+ }
+
+ // Checking command line parameters
+ if(cl.exists("sessionBasedModelsClientSocketSelection")) {
+ std::string type = cl.getValue("sessionBasedModelsClientSocketSelection");
+
+ if((type != "SessionIdHighPart") && (type != "SessionIdOptionalPart") && (type != "RoundRobin")) {
+ throw anna::RuntimeException("Commandline option '-sessionBasedModelsClientSocketSelection' only accepts 'SessionIdHighPart'/'SessionIdOptionalPart'/'RoundRobin' as parameter values", ANNA_FILE_LOCATION);
+ }
+ }
+
+ // Tracing:
+ if(cl.exists("trace"))
+ anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace")));
+
+ LOGINFORMATION(
+ // Help on startup traces:
+ anna::Logger::information(help(), ANNA_FILE_LOCATION);
+ // Test messages dtd:
+ std::string msg = "\n ------------- TESTMESSAGES DTD -------------\n";
+ msg += anna::diameter::codec::MessageDTD;
+ anna::Logger::information(msg, ANNA_FILE_LOCATION);
+ );
+
+ // HTTP Server:
+ if(cl.exists("httpServer")) {
+ anna::comm::Network& network = anna::comm::Network::instantiate();
+ std::string address;
+ int port;
+ anna::functions::getAddressAndPortFromSocketLiteral(cl.getValue("httpServer"), address, port);
+ //const anna::comm::Device* device = network.find(Device::asAddress(address)); // here provide IP
+ const anna::comm::Device* device = *((network.resolve(address)->device_begin())); // trick to solve
+ a_httpServerSocket = new anna::comm::ServerSocket(anna::comm::INetAddress(device, port), cl.exists("httpServerShared") /* shared bind */, &anna::http::Transport::getFactory());
+ }
+
+ // Stack:
+ anna::diameter::codec::Engine *codecEngine = new anna::diameter::codec::Engine();
+ anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
+ anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* stack id; its value don't mind, is not used (ADL is monostack) */);
+ // Analyze comma-separated list:
+ anna::Tokenizer lst;
+ std::string dictionaryParameter = cl.getValue("dictionary");
+ lst.apply(dictionaryParameter, ",");
+
+ if(lst.size() >= 1) { // always true (at least one, because -dictionary is mandatory)
+ anna::Tokenizer::const_iterator tok_min(lst.begin());
+ anna::Tokenizer::const_iterator tok_max(lst.end());
+ anna::Tokenizer::const_iterator tok_iter;
+ std::string pathFile;
+ d->allowUpdates();
+
+ for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) {
+ pathFile = anna::Tokenizer::data(tok_iter);
+ d->load(pathFile);
+ }
+ }
+
+ codecEngine->setDictionary(d);
+ LOGDEBUG(anna::Logger::debug(codecEngine->asString(), ANNA_FILE_LOCATION));
+
+ if(lst.size() > 1) {
+ std::string all_in_one = "./dictionary-all-in-one.xml";
+ std::ofstream out(all_in_one.c_str(), std::ifstream::out);
+ std::string buffer = d->asXMLString();
+ out.write(buffer.c_str(), buffer.size());
+ out.close();
+ std::cout << "Written accumulated '" << all_in_one << "' (provide it next time to be more comfortable)." << std::endl;
+ }
+
+
+
+ // Integration (validation 'Complete' for receiving messages) and debugging (validation also before encoding: 'Always').
+ // If missing 'integrationAndDebugging', default behaviour at engine is: mode 'AfterDecoding', depth 'FirstError':
+ if(cl.exists("integrationAndDebugging")) {
+ codecEngine->setValidationMode(anna::diameter::codec::Engine::ValidationMode::Always);
+ codecEngine->setValidationDepth(anna::diameter::codec::Engine::ValidationDepth::Complete);
+ }
+
+ codecEngine->ignoreFlagsOnValidation(cl.exists("ignoreFlags"));
+
+ // Diameter Server:
+ if(cl.exists("diameterServer"))
+ startDiameterServer(cl.exists("diameterServerSessions") ? cl.getIntegerValue("diameterServerSessions") : 1);
+
+ // Optional command line parameters ////////////////////////////////////////////////////////
+ checkTimeMeasure("allowedInactivityTime");
+ checkTimeMeasure("tcpConnectDelay");
+ checkTimeMeasure("answersTimeout");
+ checkTimeMeasure("ceaTimeout");
+ checkTimeMeasure("watchdogPeriod");
+ checkTimeMeasure("reconnectionPeriod");
+ int tcpConnectDelay = 200; // ms
+ anna::Millisecond answersTimeout = (anna::Millisecond)10000; // ms
+ anna::Millisecond ceaTimeout;
+ anna::Millisecond watchdogPeriod = (anna::Millisecond)30000; // ms
+ int reconnectionPeriod = 10000; // ms
+
+ if(cl.exists("tcpConnectDelay")) tcpConnectDelay = cl.getIntegerValue("tcpConnectDelay");
+
+ if(cl.exists("answersTimeout")) answersTimeout = cl.getIntegerValue("answersTimeout");
+
+ if(cl.exists("ceaTimeout")) ceaTimeout = cl.getIntegerValue("ceaTimeout");
+ else ceaTimeout = answersTimeout;
+
+ if(cl.exists("watchdogPeriod")) watchdogPeriod = cl.getIntegerValue("watchdogPeriod");
+
+ if(cl.exists("reconnectionPeriod")) reconnectionPeriod = cl.getIntegerValue("reconnectionPeriod");
+
+ a_myDiameterEngine->setMaxConnectionDelay((anna::Millisecond)tcpConnectDelay);
+ a_myDiameterEngine->setWatchdogPeriod(watchdogPeriod);
+ std::string originHost = "";
+ std::string originRealm = "";
+
+ if(cl.exists("cer")) a_cerPathfile = cl.getValue("cer");
+
+ if(cl.exists("dwr")) a_dwrPathfile = cl.getValue("dwr");
+
+ if(cl.exists("originHost")) originHost = cl.getValue("originHost");
+
+ if(cl.exists("originRealm")) originRealm = cl.getValue("originRealm");
+
+ a_myDiameterEngine->setHost(originHost);
+ a_myDiameterEngine->setRealm(originRealm);
+
+ // Diameter entity:
+ if(cl.exists("entity")) {
+ int entityServerSessions = cl.exists("entityServerSessions") ? cl.getIntegerValue("entityServerSessions") : 1;
+
+ if(entityServerSessions > 0) {
+ baseProtocolSetupAsClient(); // Same CER/CEA, DWR/DWA for all diameter servers
+ anna::socket_v servers = anna::functions::getSocketVectorFromString(cl.getValue("entity"));
+ a_myDiameterEngine->setNumberOfClientSessionsPerServer(entityServerSessions);
+ a_entity = a_myDiameterEngine->createEntity(servers, "Launcher diameter entity");
+ a_entity->setClassCodeTimeout(anna::diameter::comm::ClassCode::Bind, ceaTimeout);
+ a_entity->setClassCodeTimeout(anna::diameter::comm::ClassCode::ApplicationMessage, answersTimeout);
+ a_entity->bind();
+ }
+ }