Fix local server for multiple applications
[anna.git] / source / diameter.comm / Engine.cpp
index 94c7d2d..f860a15 100644 (file)
@@ -52,8 +52,8 @@ comm::Engine::Engine(const char *className, const stack::Dictionary *baseProtoco
   a_autoBind(true),
   a_availableForEntities(false),
   a_availableForLocalServers(false),
-  a_cer(true),
-  a_dwr(true),
+  a_client_cer(true),
+  a_client_dwr(true),
 //      a_cea(true),
 //      a_dwa(true),
   a_watchdogPeriod(ClientSession::DefaultWatchdogPeriod),
@@ -71,7 +71,7 @@ comm::Engine::Engine(const char *className, const stack::Dictionary *baseProtoco
 }
 
 
-void comm::Engine::assertBaseProtocolHealth() noexcept(false) {
+void comm::Engine::assertBaseProtocolHealth() const noexcept(false) {
   if (!getBaseProtocolCodecEngine()->getDictionary())
     throw anna::RuntimeException("Invalid diameter::comm::Engine object: base protocol dictionary provided on constructor was NULL", ANNA_FILE_LOCATION);
   // it would be interesting to check and identify certain base protocol elements in the dictionary ...
@@ -84,21 +84,72 @@ void comm::Engine::releaseServer(Server *server) { a_serversRecycler.release(ser
 comm::ClientSession* comm::Engine::allocateClientSession() { return a_clientSessionsRecycler.create(); }
 void comm::Engine::releaseClientSession(ClientSession *clientSession) { a_clientSessionsRecycler.release(clientSession); }
 
-
-void comm::Engine::setClientCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) noexcept(false) {
+void comm::Engine::setClientCER(const anna::DataBlock & cer) noexcept(false) {
   if(codec::functions::getCommandId(cer) != helpers::base::COMMANDID__Capabilities_Exchange_Request) {
     throw anna::RuntimeException("The message provided as 'CER' is not a Capabilities-Exchange-Request", ANNA_FILE_LOCATION);
   }
 
+  a_client_cer = cer;
+}
+
+void comm::Engine::setClientDWR(const anna::DataBlock & dwr) noexcept(false) {
   if(codec::functions::getCommandId(dwr) != helpers::base::COMMANDID__Device_Watchdog_Request) {
     throw anna::RuntimeException("The message provided as 'DWR' is not a Device-Watchdog-Request", ANNA_FILE_LOCATION);
   }
 
-  a_cer = cer;
-  a_dwr = dwr;
+  a_client_dwr = dwr;
+}
+
+void comm::Engine::setClientCER(const std::string & cerPathfile) noexcept(false) {
+
+  // Check for base protocol codec engine health:
+  assertBaseProtocolHealth();
+
+  anna::diameter::codec::Message diameterCER(getBaseProtocolCodecEngine());
+  try {
+    diameterCER.loadXMLFile(cerPathfile);
+  } catch(anna::RuntimeException &ex) {
+    anna::Logger::error("CER file not found or unable to parse. Nothing done !", ANNA_FILE_LOCATION);
+    return;
+  }
+
+  // Assignment for internal encoded version:
+  setClientCER(diameterCER.code());
 }
 
-void comm::Engine::setClientCERandDWR(const std::string & cer, const std::string & dwr) noexcept(false) {
+void comm::Engine::setClientDWR(const std::string & dwrPathfile) noexcept(false) {
+
+  // Check for base protocol codec engine health:
+  assertBaseProtocolHealth();
+
+  anna::diameter::codec::Message diameterDWR(getBaseProtocolCodecEngine());
+  std::string OH = getOriginHostName();
+  std::string OR = getOriginRealmName();
+
+  if (!dwrPathfile.empty()) {
+    try {
+      diameterDWR.loadXMLFile(dwrPathfile);
+    } catch(anna::RuntimeException &ex) {
+      anna::Logger::error("DWR file not found or unable to parse. Nothing done !", ANNA_FILE_LOCATION);
+      return;
+    }
+  }
+
+  // DEFAULT VERSION:
+  // Build DWR
+  //   <DWR>  ::= < Diameter Header: 280, REQ >
+  //              { Origin-Host }
+  //              { Origin-Realm }
+  diameterDWR.setId(anna::diameter::helpers::base::COMMANDID__Device_Watchdog_Request);
+  diameterDWR.setApplicationId(0); // base protocol
+  diameterDWR.addAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->setValue(OH);
+  diameterDWR.addAvp(anna::diameter::helpers::base::AVPID__Origin_Realm)->getDiameterIdentity()->setValue(OR);
+
+  // Assignment for internal encoded version:
+  setClientDWR(diameterDWR.code());
+}
+
+void comm::Engine::setClientCER(const anna::U32 &applicationId) noexcept(false) {
 
   // Check for base protocol codec engine health:
   assertBaseProtocolHealth();
@@ -115,67 +166,23 @@ void comm::Engine::setClientCERandDWR(const std::string & cer, const std::string
   //           * [ Auth-Application-Id ] 258 Unsigned32
   //           * [Acct-Application-Id]  259 Unsigned32
   anna::diameter::codec::Message diameterCER(getBaseProtocolCodecEngine());
-  int applicationId = 0 /*anna::diameter::helpers::APPID__3GPP_Rx*/; // Unsigned32
   std::string OH = getOriginHostName();
   std::string OR = getOriginRealmName();
   std::string hostIP = anna::functions::getHostnameIP(); // Address
   int vendorId = anna::diameter::helpers::VENDORID__tgpp; // Unsigned32
   std::string productName = "ANNA Diameter Client"; // UTF8String
-  bool encodeDefault = false;
-
-  if (cer != "") {
-    try {
-      diameterCER.loadXMLFile(cer);
-    } catch(anna::RuntimeException &ex) {
-      //ex.trace();
-      encodeDefault = true;
-      LOGWARNING(anna::Logger::warning("CER file not found or unable to parse. Encoding harcoded default version ...", ANNA_FILE_LOCATION));
-    }
-  }
-  else {
-    encodeDefault = true;
-  }
-
-  if(encodeDefault) {
-    diameterCER.setId(anna::diameter::helpers::base::COMMANDID__Capabilities_Exchange_Request);
-    diameterCER.setApplicationId(applicationId);
-    diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->setValue(OH);
-    diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Origin_Realm)->getDiameterIdentity()->setValue(OR);
-    diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Host_IP_Address)->getAddress()->fromPrintableString(hostIP.c_str()); // supported by Address class, anyway is better to provide "1|<ip address>"
-    diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Vendor_Id)->getUnsigned32()->setValue(vendorId);
-    diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Product_Name)->getUTF8String()->setValue(productName);
-    diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Auth_Application_Id)->getUnsigned32()->setValue(applicationId);
-  }
-
-  // Build DWR
-  //   <DWR>  ::= < Diameter Header: 280, REQ >
-  //              { Origin-Host }
-  //              { Origin-Realm }
-  anna::diameter::codec::Message diameterDWR(getBaseProtocolCodecEngine());
-  encodeDefault = false;
 
-  if (dwr != "") {
-    try {
-      diameterDWR.loadXMLFile(dwr);
-    } catch(anna::RuntimeException &ex) {
-      //ex.trace();
-      encodeDefault = true;
-      LOGWARNING(anna::Logger::warning("DWR file not found or unable to parse. Encoding harcoded default version ...", ANNA_FILE_LOCATION));
-    }
-  }
-  else {
-    encodeDefault = true;
-  }
-
-  if(encodeDefault) {
-    diameterDWR.setId(anna::diameter::helpers::base::COMMANDID__Device_Watchdog_Request);
-    diameterDWR.setApplicationId(applicationId);
-    diameterDWR.addAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->setValue(OH);
-    diameterDWR.addAvp(anna::diameter::helpers::base::AVPID__Origin_Realm)->getDiameterIdentity()->setValue(OR);
-  }
+  diameterCER.setId(anna::diameter::helpers::base::COMMANDID__Capabilities_Exchange_Request);
+  diameterCER.setApplicationId(0); // base protocol
+  diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->setValue(OH);
+  diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Origin_Realm)->getDiameterIdentity()->setValue(OR);
+  diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Host_IP_Address)->getAddress()->fromPrintableString(hostIP.c_str()); // supported by Address class, anyway is better to provide "1|<ip address>"
+  diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Vendor_Id)->getUnsigned32()->setValue(vendorId);
+  diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Product_Name)->getUTF8String()->setValue(productName);
+  diameterCER.addAvp(anna::diameter::helpers::base::AVPID__Auth_Application_Id)->getUnsigned32()->setValue(applicationId);
 
   // Assignment for internal encoded versions:
-  setClientCERandDWR(diameterCER.code(), diameterDWR.code());
+  setClientCER(diameterCER.code());
 }
 
 void comm::Engine::setWatchdogPeriod(const anna::Millisecond & wp) noexcept(false) {
@@ -263,13 +270,14 @@ noexcept(false) {
   // Proteccion antes de reservar memoria para un LocalServer
   socket_t key(addr, port);
 
-  if(a_localServers.find(key) != a_localServers.end())
+  if(a_localServers.find(key) != a_localServers.end()) {
     throw anna::RuntimeException("LocalServer is already reserved by a former created access point. Cannot create again", ANNA_FILE_LOCATION);
+  }
 
   if((result = allocateLocalServer()) == NULL)
     throw anna::RuntimeException("diameter::comm::Engine::allocateLocalServer returns NULL (perhaps virtual method was not implemented)", ANNA_FILE_LOCATION);
 
-  result->setEngine(this); // lo podia haber asignado en el allocateLocalServer (no importa)
+  result->setEngine(this); // only to refresh availability
   result->setKey(key);
   result->setCategory(category);
   result->setDescription(description);
@@ -286,6 +294,7 @@ noexcept(false) {
   );
 //   // Listen: (*)
 //   /*if (a_autoListen) */result->enable(); // creates server socket
+  // ENABLE THE SERVER: if already open (other comm engine for another origin host in the same address), nothing done. But the reference to the server is doubled along 2 comm engines ...
   result->setMaxConnections(maxConnections); // (*) this enables the listen port ... or not
   return result;
 }
@@ -314,9 +323,9 @@ noexcept(false) {
   result->a_parent = entity;
   result->a_socket = socket;
   result->setMaxClientSessions(a_numberOfClientSessionsPerServer /* engine */);
-  result->a_engine = this;
   result->initializeStatisticResources();
 
+  result->a_engine = this;
   for(int k = 0; k < a_numberOfClientSessionsPerServer; k++)
     result->addClientSession(k);
 
@@ -344,11 +353,11 @@ noexcept(false) {
   result->initialize(); // warning: recycler does not initialize its objects and at least...
   // Assignments (it could be done at allocate):
 
-  if((a_cer.isEmpty()) || (a_dwr.isEmpty()))
-    throw anna::RuntimeException("Must define valid CER and DWR messages by mean setClientCERandDWR()", ANNA_FILE_LOCATION);
+  if((a_client_cer.isEmpty()) || (a_client_dwr.isEmpty()))
+    throw anna::RuntimeException("Must define valid CER and DWR messages by mean setClientCER and setClientDWR()", ANNA_FILE_LOCATION);
 
-  result->a_cer.setBody(a_cer);
-  result->a_dwr.setBody(a_dwr);
+  result->a_cer.setBody(a_client_cer);
+  result->a_dwr.setBody(a_client_dwr);
   result->setWatchdogPeriod(a_watchdogPeriod);
   result->a_parent = server;
   result->a_socketId = socketId;
@@ -936,8 +945,6 @@ void comm::Engine::availabilityLostForEntities() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.activateAlarm(OamModule::Alarm::c_LostAvailabilityOverEntitiesForEngineWithClassName__s__, getClassName());
   oamModule.count(OamModule::Counter::LostAvailabilityOverEngineForEntities);
-  // Virtual
-  availabilityLostForEntities(this);
 }
 
 
@@ -955,8 +962,6 @@ void comm::Engine::availabilityRecoveredForEntities() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.cancelAlarm(OamModule::Alarm::c_LostAvailabilityOverEntitiesForEngineWithClassName__s__, getClassName());
   oamModule.count(OamModule::Counter::RecoveredAvailabilityOverEngineForEntities);
-  // Virtual
-  availabilityRecoveredForEntities(this);
 }
 
 
@@ -974,8 +979,6 @@ void comm::Engine::availabilityLostForLocalServers() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.activateAlarm(OamModule::Alarm::c_LostAvailabilityOverLocalServersForEngineWithClassName__s__, getClassName());
   oamModule.count(OamModule::Counter::LostAvailabilityOverEngineForLocalServers);
-  // Virtual
-  availabilityLostForLocalServers(this);
 }
 
 
@@ -993,8 +996,6 @@ void comm::Engine::availabilityRecoveredForLocalServers() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.cancelAlarm(OamModule::Alarm::c_LostAvailabilityOverLocalServersForEngineWithClassName__s__, getClassName());
   oamModule.count(OamModule::Counter::RecoveredAvailabilityOverEngineForLocalServers);
-  // Virtual
-  availabilityRecoveredForLocalServers(this);
 }
 
 
@@ -1051,7 +1052,7 @@ bool comm::Engine::refreshAvailabilityForLocalServers() {
 }
 
 
-void comm::Engine::readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) {
+void comm::Engine::readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) const {
 
   // Check for base protocol codec engine health:
   try {
@@ -1107,16 +1108,16 @@ void comm::Engine::readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) {
 }
 
 
-void comm::Engine::readCEA(anna::DataBlock &cea, const anna::DataBlock &cer) {
+void comm::Engine::readCEA(anna::DataBlock &cea, const anna::DataBlock &cer) const {
 
   // Check for base protocol codec engine health:
   assertBaseProtocolHealth();
 
-  if (a_ceaPathfile != "") {
+  if (getCEA() != "") {
     anna::diameter::codec::Message diameterCEA(getBaseProtocolCodecEngine());
 
     try {
-      diameterCEA.loadXMLFile(a_ceaPathfile);
+      diameterCEA.loadXMLFile(getCEA());
       diameterCEA.setHopByHop(anna::diameter::codec::functions::getHopByHop(cer));
       diameterCEA.setEndToEnd(anna::diameter::codec::functions::getEndToEnd(cer));
       cea = diameterCEA.code();
@@ -1201,7 +1202,7 @@ void comm::Engine::manageDrDhServerSession(ServerSession *ss, bool register_or_d
   std::string destinationRealm, destinationHost;
   codec::Message codecMsg(getBaseProtocolCodecEngine());
   try {
-    codecMsg.decode(ss->a_cer);
+    codecMsg.decode(a_client_cer);
     destinationRealm = codecMsg.getAvp(anna::diameter::helpers::base::AVPID__Origin_Realm)->getDiameterIdentity()->getValue();
     destinationHost = codecMsg.getAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->getValue();
   }
@@ -1255,7 +1256,7 @@ void comm::Engine::manageDrDhServerSession(ServerSession *ss, bool register_or_d
   }
 }
 
-void comm::Engine::readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) {
+void comm::Engine::readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) const {
 
   // Check for base protocol codec engine health:
   assertBaseProtocolHealth();
@@ -1277,9 +1278,9 @@ void comm::Engine::readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) {
     // Message header
     diameterDWA.setId(anna::diameter::helpers::base::COMMANDID__Device_Watchdog_Answer);
     diameterDWA.setVersion(1);
-    diameterDWA.setApplicationId(codec::functions::getApplicationId(dwr));
-    diameterDWA.setHopByHop(codec::functions::getHopByHop(dwr));
-    diameterDWA.setEndToEnd(codec::functions::getEndToEnd(dwr));
+    diameterDWA.setApplicationId(anna::diameter::codec::functions::getApplicationId(dwr));
+    diameterDWA.setHopByHop(anna::diameter::codec::functions::getHopByHop(dwr));
+    diameterDWA.setEndToEnd(anna::diameter::codec::functions::getEndToEnd(dwr));
     // Result-Code
     avpRC.setId(anna::diameter::helpers::base::AVPID__Result_Code);
     avpRC.setMandatoryBit();