Fix local server for multiple applications master
authoreramos <diametersuite@gmail.com>
Sat, 19 Aug 2023 23:29:34 +0000 (01:29 +0200)
committereramos <diametersuite@gmail.com>
Sat, 19 Aug 2023 23:41:06 +0000 (01:41 +0200)
There was a historic bug/limitation, due to the
diameter.comm module design. We were not able to
set two (or more) origin hosts sharing the same
local server. So, we needed to set different ports
(3868, 3869, etc.) to listen for different diameter
applications as a server.

This was because a poor design where LocalServer was
tied to specific engine, and then, depending on when
the service was registered (services.xml), one engine
or the other was enabled to manage traffic. So, the
server was unable to respond correctly one of the
applications.

We have implemented a map of remote origin hosts
with local origin hosts, and when we have a
reception, we check the origin host of the
message and retrieve the own origin host which was
configured for it. This is primarly done at CER/CEA
exchange. When the CER arrives, we get the
Auth-Application-Id, and we know the corresponding
stack and answer in consequence. Also, we store
the relation remote-local origin host in the
origin host manager map.

All the virtual methods must carry the origin host
which applies, to operate. Also, many virtuals with
default empty implementation but not used have been
removed.

Reacting answers are now stored in specific origin
host. We could even improve the fact that operated
host is not needed to be set when programming
reacting answers, because all depends on the origin
host for those answers. But this way, we allow to
do rare things (tests).

CER and DWR configuration have been separated.
And setClientCER now have specific prototype for
default CER, which needs the application-id which
will be set as Auth-Application-Id.

Entity and client sessions, still keep a_engine
most of the cases.

Component Test have been tested OK.

New version will be 1.0.6

34 files changed:
CMakeLists.txt
docker-images/anna-adml-http/Dockerfile
example/diameter/launcher/EventOperation.cpp
example/diameter/launcher/Launcher.cpp
example/diameter/launcher/MyDiameterEntity.cpp
example/diameter/launcher/MyDiameterEntity.hpp
example/diameter/launcher/MyLocalServer.cpp
example/diameter/launcher/MyLocalServer.hpp
example/diameter/launcher/resources/rest_api/ct/ct.sh
example/diameter/launcher/resources/scripts/tinyTestcase.sh
example/diameter/rxSimpleTest/MyDiameterEntity.cpp
example/diameter/rxSimpleTest/MyDiameterEntity.hpp
example/diameter/rxSimpleTest/MyLocalServer.cpp
example/diameter/rxSimpleTest/MyLocalServer.hpp
example/diameter/rxSimpleTest/rxSimpleTest.cpp
include/anna/diameter.comm/ClientSession.hpp
include/anna/diameter.comm/Engine.hpp
include/anna/diameter.comm/Entity.hpp
include/anna/diameter.comm/LocalServer.hpp
include/anna/diameter.comm/OriginHost.hpp
include/anna/diameter.comm/OriginHostManager.hpp
include/anna/diameter.comm/Server.hpp
include/anna/diameter.comm/ServerSession.hpp
include/anna/diameter.comm/Session.hpp
source/diameter.comm/ClientSession.cpp
source/diameter.comm/Engine.cpp
source/diameter.comm/Entity.cpp
source/diameter.comm/LocalServer.cpp
source/diameter.comm/MessageStatistics.cpp
source/diameter.comm/OriginHost.cpp
source/diameter.comm/OriginHostManager.cpp
source/diameter.comm/Server.cpp
source/diameter.comm/ServerSession.cpp
source/diameter.comm/Session.cpp

index e28115d..fcaf4ad 100644 (file)
@@ -12,7 +12,7 @@ enable_language(C CXX)
 # Project version
 set(VERSION_MAJOR 1)
 set(VERSION_MINOR 0)
-set(VERSION_PATCH 5)
+set(VERSION_PATCH 6)
 
 # Dynamic libraries not linked to build tree:
 set(CMAKE_SKIP_RPATH TRUE)
index 2e395c9..59fb2fb 100644 (file)
@@ -5,6 +5,7 @@ COPY opt/adml/ /opt/adml
 RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y tshark
 
 RUN apt-get update && apt-get install -y \
+   vim \
    net-tools \
    procps \
    jq \
index 8b45e61..cab0e83 100644 (file)
@@ -465,23 +465,23 @@ bool EventOperation::answermsg_action_2e(std::string &response, const std::strin
     int code = message->getId().first;
     LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
     response = "Added 'answer to entity' to the FIFO queue corresponding to its message code";
-    my_app.getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
+    my_app.getOperatedHost()->getReactingAnswers()->addMessage(code, message);
   }
   else { // action
 
     if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
-      response = anna::functions::encodeBase64(my_app.getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY"));
+      response = anna::functions::encodeBase64(my_app.getOperatedHost()->getReactingAnswers()->asString("ANSWERS TO ENTITY"));
     } else if (diameterJson_or_action == "rotate") {
-      my_app.getOperatedEntity()->getReactingAnswers()->rotate(true);
+      my_app.getOperatedHost()->getReactingAnswers()->rotate(true);
       response = "rotate";
     } else if (diameterJson_or_action == "exhaust") {
-      my_app.getOperatedEntity()->getReactingAnswers()->rotate(false);
+      my_app.getOperatedHost()->getReactingAnswers()->rotate(false);
       response = "exhaust";
     } else if (diameterJson_or_action == "clear") {
-      my_app.getOperatedEntity()->getReactingAnswers()->clear();
+      my_app.getOperatedHost()->getReactingAnswers()->clear();
       response = "clear";
     } else if (diameterJson_or_action == "dump") {
-      my_app.getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
+      my_app.getOperatedHost()->getReactingAnswers()->dump("programmed_answer");
       response = "dump";
     }
   }
@@ -523,24 +523,24 @@ bool EventOperation::answermsg_action_2c(std::string &response, const std::strin
 
     int code = message->getId().first;
     LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
-    my_app.getOperatedServer()->getReactingAnswers()->addMessage(code, message);
+    my_app.getOperatedHost()->getReactingAnswers()->addMessage(code, message);
     response = "Added 'answer to client' to the FIFO queue corresponding to its message code";
   }
   else { // action
 
     if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
-      response = anna::functions::encodeBase64(my_app.getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT"));
+      response = anna::functions::encodeBase64(my_app.getOperatedHost()->getReactingAnswers()->asString("ANSWERS TO CLIENT"));
     } else if (diameterJson_or_action == "rotate") {
-      my_app.getOperatedServer()->getReactingAnswers()->rotate(true);
+      my_app.getOperatedHost()->getReactingAnswers()->rotate(true);
       response = "rotate";
     } else if (diameterJson_or_action == "exhaust") {
-      my_app.getOperatedServer()->getReactingAnswers()->rotate(false);
+      my_app.getOperatedHost()->getReactingAnswers()->rotate(false);
       response = "exhaust";
     } else if (diameterJson_or_action == "clear") {
-      my_app.getOperatedServer()->getReactingAnswers()->clear();
+      my_app.getOperatedHost()->getReactingAnswers()->clear();
       response = "clear";
     } else if (diameterJson_or_action == "dump") {
-      my_app.getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
+      my_app.getOperatedHost()->getReactingAnswers()->dump("programmed_answer");
       response = "dump";
     }
   }
index d3a9373..54fb750 100644 (file)
@@ -362,7 +362,7 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool bindRes
       }
 
       /////////////////////////////////////////////////////////////////////////////////////////////
-      // Diameter communication engine:
+      // Diameter communication engine: ONE ENGINE PER OWN ORIGIN HOST
       std::string commEngineName = originHost->getValue() + "_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.
@@ -372,7 +372,7 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool bindRes
       if (originRealm) commEngine->setOriginRealmName(originRealm->getValue());
 
       // Origin host node:
-      a_workingNode = new anna::diameter::comm::OriginHost((anna::diameter::comm::Engine*)commEngine, applicationId);
+      a_workingNode = new anna::diameter::comm::OriginHost((anna::diameter::comm::Engine*)commEngine, applicationId /* OriginHost constructor extracts corresponding stack codec engine */);
       a_workingNode->setRequestRetransmissions(retransmissions);
       /////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -386,9 +386,13 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool bindRes
           commEngine->setNumberOfClientSessionsPerServer(sessions);
 
           // Client CER and DWR
-          std::string cerPathfile = cer ? cer->getValue() : "";
-          std::string dwrPathfile = dwr ? dwr->getValue() : "";
-          commEngine->setClientCERandDWR(cerPathfile, dwrPathfile);
+          if (cer) { // pathfile provided
+            commEngine->setClientCER(cer->getValue());
+          }
+          else {
+            commEngine->setClientCER(applicationId); // default engine CER
+          }
+          commEngine->setClientDWR(dwr ? dwr->getValue() : "" /* default DWR */);
 
           // Register one entity for this engine:
           a_workingNode->createEntity(entity->getValue(), ceaTimeoutMs, answersTimeoutMs);
@@ -1236,16 +1240,16 @@ bool Launcher::eventOperation(const std::string &operation, std::string &respons
   } else if(opType == "answerxml2e") {
 
     if(param1 == "") { // programmed answers FIFO's to stdout
-      response = getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY");
+      response = getOperatedHost()->getReactingAnswers()->asString("ANSWERS TO ENTITY");
       return true; // OK
     } else if (param1 == "rotate") {
-      getOperatedEntity()->getReactingAnswers()->rotate(true);
+      getOperatedHost()->getReactingAnswers()->rotate(true);
     } else if (param1 == "exhaust") {
-      getOperatedEntity()->getReactingAnswers()->rotate(false);
+      getOperatedHost()->getReactingAnswers()->rotate(false);
     } else if (param1 == "clear") {
-      getOperatedEntity()->getReactingAnswers()->clear();
+      getOperatedHost()->getReactingAnswers()->clear();
     } else if (param1 == "dump") {
-      getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
+      getOperatedHost()->getReactingAnswers()->dump("programmed_answer");
     } else {
       codecMsg.loadXMLFile(param1);
       updateOperatedOriginHostWithMessage(codecMsg);
@@ -1257,21 +1261,21 @@ bool Launcher::eventOperation(const std::string &operation, std::string &respons
 
       int code = message->getId().first;
       LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
-      getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
+      getOperatedHost()->getReactingAnswers()->addMessage(code, message);
     }
   } else if(opType == "answerxml2c") {
 
     if(param1 == "") { // programmed answers FIFO's to stdout
-      response = getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT");
+      response = getOperatedHost()->getReactingAnswers()->asString("ANSWERS TO CLIENT");
       return true; // OK
     } else if (param1 == "rotate") {
-      getOperatedServer()->getReactingAnswers()->rotate(true);
+      getOperatedHost()->getReactingAnswers()->rotate(true);
     } else if (param1 == "exhaust") {
-      getOperatedServer()->getReactingAnswers()->rotate(false);
+      getOperatedHost()->getReactingAnswers()->rotate(false);
     } else if (param1 == "clear") {
-      getOperatedServer()->getReactingAnswers()->clear();
+      getOperatedHost()->getReactingAnswers()->clear();
     } else if (param1 == "dump") {
-      getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
+      getOperatedHost()->getReactingAnswers()->dump("programmed_answer");
     } else {
       codecMsg.loadXMLFile(param1);
       updateOperatedOriginHostWithMessage(codecMsg);
@@ -1283,7 +1287,7 @@ bool Launcher::eventOperation(const std::string &operation, std::string &respons
 
       int code = message->getId().first;
       LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
-      getOperatedServer()->getReactingAnswers()->addMessage(code, message);
+      getOperatedHost()->getReactingAnswers()->addMessage(code, message);
     }
   } else if((opType == "burst")) {
 
index 7bac08a..cba726a 100644 (file)
@@ -52,7 +52,7 @@ void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::Cl
 }
 
 
-void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message)
+void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventRequest", ANNA_FILE_LOCATION));
   // Performance stats:
@@ -77,7 +77,7 @@ noexcept(false) {
 
   // Lookup reacting answers list:
   int code = cid.first;
-  anna::diameter::codec::Message *answer_message = a_reactingAnswers.getMessage(code);
+  anna::diameter::codec::Message *answer_message = my_node->getReactingAnswers()->getMessage(code);
   if (answer_message) {
     // Prepare answer:
     my_app.getCommunicator()->prepareAnswer(answer_message, message);
@@ -99,7 +99,7 @@ noexcept(false) {
     my_node->releaseCommMessage(msg);
 
     // Pop front the reacting answer:
-    a_reactingAnswers.nextMessage(code);
+    my_node->getReactingAnswers()->nextMessage(code);
     return;
   }
 
@@ -137,7 +137,7 @@ noexcept(false) {
   anna::testing::TestManager::instantiate().receiveDiameterMessage(message, clientSession);
 }
 
-void MyDiameterEntity::eventResponse(const anna::diameter::comm::Response &response)
+void MyDiameterEntity::eventResponse(const anna::diameter::comm::Response &response, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventResponse", ANNA_FILE_LOCATION));
   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
@@ -230,7 +230,7 @@ noexcept(false) {
   if(isOK) anna::testing::TestManager::instantiate().receiveDiameterMessage(*message, clientSession);
 }
 
-void MyDiameterEntity::eventUnknownResponse(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message)
+void MyDiameterEntity::eventUnknownResponse(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventUnknownResponse", ANNA_FILE_LOCATION));
   // Performance stats:
@@ -253,7 +253,7 @@ noexcept(false) {
   if(my_node->logEnabled()) my_node->writeLogFile(message, "recvfe-ans-unknown", clientSession->asString());
 }
 
-void MyDiameterEntity::eventDPA(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message)
+void MyDiameterEntity::eventDPA(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventDPA", ANNA_FILE_LOCATION));
   // Performance stats:
index 554267b..bf474f9 100644 (file)
@@ -11,7 +11,6 @@
 
 // Project
 #include <anna/diameter.comm/Entity.hpp>
-#include <anna/diameter/codec/MessagesDeque.hpp>
 
 
 namespace anna {
@@ -25,18 +24,15 @@ namespace anna {
 class MyDiameterEntity : public anna::diameter::comm::Entity {
 
   void eventRequestRetransmission(const anna::diameter::comm::ClientSession *, anna::diameter::comm::Message*) ;
-  void eventResponse(const anna::diameter::comm::Response&) noexcept(false);
-  void eventRequest(anna::diameter::comm::ClientSession *, const anna::DataBlock&) noexcept(false);
-  void eventUnknownResponse(anna::diameter::comm::ClientSession *, const anna::DataBlock&) noexcept(false);
-  void eventDPA(anna::diameter::comm::ClientSession *, const anna::DataBlock&) noexcept(false);
+  void eventResponse(const anna::diameter::comm::Response&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventRequest(anna::diameter::comm::ClientSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventUnknownResponse(anna::diameter::comm::ClientSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventDPA(anna::diameter::comm::ClientSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
 
 public:
 
   MyDiameterEntity() {;}
   virtual ~MyDiameterEntity() {;}
-
-  anna::diameter::codec::MessagesDeque a_reactingAnswers;
-  anna::diameter::codec::MessagesDeque *getReactingAnswers() { return (anna::diameter::codec::MessagesDeque*)&a_reactingAnswers; }
 };
 
 #endif
index 42b8b1e..31873c6 100644 (file)
 #include <anna/testing/TestManager.hpp>
 
 
-void MyLocalServer::eventRequest(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message)
+void MyLocalServer::eventRequest(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventRequest", ANNA_FILE_LOCATION));
+
+  // Protection:
+  if (!myNode) return;
+
   // Performance stats:
   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
-  anna::diameter::codec::Engine *codecEngine = my_node->getCodecEngine();
+  anna::diameter::codec::Engine *codecEngine = myNode->getCodecEngine();
 
   // CommandId:
   anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message);
@@ -46,27 +49,28 @@ noexcept(false) {
   );
 
   // Write reception
-  if(my_node->logEnabled()) my_node->writeLogFile(message, "recvfc", serverSession->asString());
+  if(myNode->logEnabled()) myNode->writeLogFile(message, "recvfc", serverSession->asString());
 
   // If no answer is programmed and entity is configured, the failed request would be forwarded even being wrong (delegates at the end point)
   int code = cid.first;
-  anna::diameter::codec::Message *programmed_answer = a_reactingAnswers.getMessage(code);
+  anna::diameter::codec::Message *programmed_answer = (const_cast<anna::diameter::comm::OriginHost*>(myNode))->getReactingAnswers()->getMessage(code);
+
   bool programmed = (programmed_answer != NULL);
 
-  anna::diameter::comm::Entity *entity = my_node->getEntity();
+  anna::diameter::comm::Entity *entity = myNode->getEntity();
   if(!programmed && entity) {  // forward condition (no programmed answer + entity available)
-    anna::diameter::comm::Message *msg = my_node->createCommMessage();
+    anna::diameter::comm::Message *msg = (const_cast<anna::diameter::comm::OriginHost*>(myNode))->createCommMessage();
     msg->forwardEndToEnd(); // end-to-end will be kept
     msg->setBody(message);
     msg->setRequestServerSessionKey(serverSession->getKey());
     bool success = entity->send(msg);
 
     // Detailed log:
-    if(my_node->logEnabled()) {
+    if(myNode->logEnabled()) {
       anna::diameter::comm::Server *usedServer = entity->getLastUsedResource();
       anna::diameter::comm::ClientSession *usedClientSession = usedServer ? usedServer->getLastUsedResource() : NULL;
       std::string detail = usedClientSession ? usedClientSession->asString() : "[null client session]"; // esto no deberia ocurrir
-      my_node->writeLogFile(message, (success ? "fwd2e" : "fwd2eError"), detail); // forwarded
+      myNode->writeLogFile(message, (success ? "fwd2e" : "fwd2eError"), detail); // forwarded
     }
 
 
@@ -90,7 +94,7 @@ noexcept(false) {
     // Decode
     try { codecMsg.decode(message, answer_message); } catch(anna::RuntimeException &ex) { ex.trace(); }
 
-    answer_message->setStandardToAnswer(codecMsg, my_node->getCommEngine()->getOriginHostName(), my_node->getCommEngine()->getOriginRealmName());
+    answer_message->setStandardToAnswer(codecMsg, myNode->getCommEngine()->getOriginHostName(), myNode->getCommEngine()->getOriginRealmName());
     analysisOK = (answer_message->getResultCode() == anna::diameter::helpers::base::AVPVALUES__Result_Code::DIAMETER_SUCCESS);
   }
 
@@ -116,34 +120,33 @@ noexcept(false) {
 
   anna::diameter::comm::Message *msg;
   try {
-    msg = my_node->createCommMessage();
+    msg = (const_cast<anna::diameter::comm::OriginHost*>(myNode))->createCommMessage();
     msg->setBody(answer_message->code());
     /* response = NULL =*/serverSession->send(msg);
 
-    if(my_node->logEnabled()) my_node->writeLogFile(*answer_message, "sent2c", serverSession->asString());
+    if(myNode->logEnabled()) myNode->writeLogFile(*answer_message, "sent2c", serverSession->asString());
   } catch(anna::RuntimeException &ex) {
     ex.trace();
-    if(my_node->logEnabled()) my_node->writeLogFile(*answer_message, "send2cError", serverSession->asString());
+    if(myNode->logEnabled()) myNode->writeLogFile(*answer_message, "send2cError", serverSession->asString());
   }
 
   // release msg
-  my_node->releaseCommMessage(msg);
+  (const_cast<anna::diameter::comm::OriginHost*>(myNode))->releaseCommMessage(msg);
 
   // Restore validation mode
   codecEngine->setValidationMode(backupVM);
 
   // Pop front the reacting answer:
-  if(analysisOK && programmed) a_reactingAnswers.nextMessage(code);
+  if(analysisOK && programmed) (const_cast<anna::diameter::comm::OriginHost*>(myNode))->getReactingAnswers()->nextMessage(code);
 
   // Testing:
   anna::testing::TestManager::instantiate().receiveDiameterMessage(message, serverSession);
 }
 
-void MyLocalServer::eventResponse(const anna::diameter::comm::Response &response)
+void MyLocalServer::eventResponse(const anna::diameter::comm::Response &response, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventResponse", ANNA_FILE_LOCATION));
   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
   anna::diameter::comm::ClassCode::_v code = response.getClassCode();
   anna::diameter::comm::Response::ResultCode::_v result = response.getResultCode();
   anna::diameter::comm::Message* request = const_cast<anna::diameter::comm::Message*>(response.getRequest());
@@ -168,6 +171,9 @@ noexcept(false) {
     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
   );
 
+  // Protection:
+  if (!myNode) return;
+
   if(isUnavailable) {
     //if (isApplicationMessage)
     LOGWARNING(anna::Logger::warning("Diameter client unavailable for Diameter Request", ANNA_FILE_LOCATION));
@@ -178,7 +184,7 @@ noexcept(false) {
     LOGWARNING(anna::Logger::warning("Context Expired for Diameter Request which was sent to the client", ANNA_FILE_LOCATION));
 
     if(request_cid != anna::diameter::helpers::base::COMMANDID__Capabilities_Exchange_Request) {  // don't trace CEA
-      if(my_node->logEnabled()) my_node->writeLogFile(*request, "req2c-expired", serverSession->asString());
+      if(myNode->logEnabled()) myNode->writeLogFile(*request, "req2c-expired", serverSession->asString());
     }
   }
 
@@ -190,20 +196,20 @@ noexcept(false) {
     );
 
     // Write reception
-    if(my_node->logEnabled()) my_node->writeLogFile(*message, "recvfc", serverSession->asString());
+    if(myNode->logEnabled()) myNode->writeLogFile(*message, "recvfc", serverSession->asString());
 
     // This is not very usual, but answers could arrive from clients:
-    anna::diameter::comm::Entity *entity = my_node->getEntity();
+    anna::diameter::comm::Entity *entity = myNode->getEntity();
 
     if(entity) {
-      anna::diameter::comm::ClientSession *usedClientSession = my_node->getCommEngine()->findClientSession(request->getRequestClientSessionKey());
+      anna::diameter::comm::ClientSession *usedClientSession = myNode->getCommEngine()->findClientSession(request->getRequestClientSessionKey());
       std::string detail;
 
-      if(my_node->logEnabled()) detail = usedClientSession ? usedClientSession->asString() : "[null client session]";  // this should not happen
+      if(myNode->logEnabled()) detail = usedClientSession ? usedClientSession->asString() : "[null client session]";  // this should not happen
       anna::diameter::comm::Message *msg;
 
       try {
-        msg = my_node->createCommMessage();
+        msg = (const_cast<anna::diameter::comm::OriginHost*>(myNode))->createCommMessage();
         msg->forwardEndToEnd(); // end-to-end will be kept
         msg->setBody(*message);
 
@@ -214,15 +220,15 @@ noexcept(false) {
         //msg->setRequestClientSessionKey(request->getRequestClientSessionKey());
         //bool success = entity->send(msg);
 
-        if(my_node->logEnabled()) my_node->writeLogFile(*message, "fwd2e", detail);  // forwarded
+        if(myNode->logEnabled()) myNode->writeLogFile(*message, "fwd2e", detail);  // forwarded
       } catch(anna::RuntimeException &ex) {
         ex.trace();
-        if(my_node->logEnabled()) my_node->writeLogFile(*message, "fwd2eError", detail);  // forwarded
+        if(myNode->logEnabled()) myNode->writeLogFile(*message, "fwd2eError", detail);  // forwarded
       }
 
       // release msgs
-      my_node->releaseCommMessage(msg);
-      my_node->releaseCommMessage(request);
+      (const_cast<anna::diameter::comm::OriginHost*>(myNode))->releaseCommMessage(msg);
+      (const_cast<anna::diameter::comm::OriginHost*>(myNode))->releaseCommMessage(request);
     }
   }
 
@@ -230,12 +236,11 @@ noexcept(false) {
   if(isOK) anna::testing::TestManager::instantiate().receiveDiameterMessage(*message, serverSession);
 }
 
-void MyLocalServer::eventUnknownResponse(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message)
+void MyLocalServer::eventUnknownResponse(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventUnknownResponse", ANNA_FILE_LOCATION));
   // Performance stats:
   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
   // CommandId:
   anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message);
   LOGDEBUG
@@ -249,15 +254,17 @@ noexcept(false) {
     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
   );
 
-  if(my_node->logEnabled()) my_node->writeLogFile(message, "recvfc-ans-unknown", serverSession->asString());
+  // Protection:
+  if (!myNode) return;
+
+  if(myNode->logEnabled()) myNode->writeLogFile(message, "recvfc-ans-unknown", serverSession->asString());
 }
 
-void MyLocalServer::eventDPA(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message)
+void MyLocalServer::eventDPA(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventDPA", ANNA_FILE_LOCATION));
   // Performance stats:
   Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
   // CommandId:
   anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message);
   LOGDEBUG
@@ -271,8 +278,11 @@ noexcept(false) {
     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
   );
 
+  // Protection:
+  if (!myNode) return;
+
   // Write reception
-  if(my_node->logEnabled()) my_node->writeLogFile(message, "recvfc", serverSession->asString());
+  if(myNode->logEnabled()) myNode->writeLogFile(message, "recvfc", serverSession->asString());
 
   // Testing:
   anna::testing::TestManager::instantiate().receiveDiameterMessage(message, serverSession);
index 17caf35..2ada2f4 100644 (file)
@@ -11,7 +11,6 @@
 
 // Project
 #include <anna/diameter.comm/LocalServer.hpp>
-#include <anna/diameter/codec/MessagesDeque.hpp>
 
 
 namespace anna {
@@ -24,16 +23,13 @@ namespace anna {
 
 class MyLocalServer : public anna::diameter::comm::LocalServer {
 
-  void eventResponse(const anna::diameter::comm::Response&) noexcept(false);
-  void eventRequest(anna::diameter::comm::ServerSession *, const anna::DataBlock&) noexcept(false);
-  void eventUnknownResponse(anna::diameter::comm::ServerSession *, const anna::DataBlock&) noexcept(false);
-  void eventDPA(anna::diameter::comm::ServerSession *, const anna::DataBlock&) noexcept(false);
+  void eventResponse(const anna::diameter::comm::Response&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventRequest(anna::diameter::comm::ServerSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventUnknownResponse(anna::diameter::comm::ServerSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventDPA(anna::diameter::comm::ServerSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
 
 public:
   virtual ~MyLocalServer() {;}
-
-  anna::diameter::codec::MessagesDeque a_reactingAnswers;
-  anna::diameter::codec::MessagesDeque *getReactingAnswers() { return (anna::diameter::codec::MessagesDeque*)&a_reactingAnswers; }
 };
 
 #endif
index a6e0d75..ac28e53 100755 (executable)
@@ -34,9 +34,9 @@ nghttp --version 2>/dev/null
 echo "Requirement found !"
 
 echo
-echo "Rebuild ADML HTTP service image (y/n) [y]:"
+echo "Rebuild ADML HTTP service image (y/n) [n]:"
 read opt
-[ -z "${opt}" ] && opt=y
+[ -z "${opt}" ] && opt=n
 if [ "${opt}" = "y" ]
 then
   ${REPO_DIR}/tools/build-anna-adml-http ${VARIANT}
index 01674c2..ba867b2 100755 (executable)
@@ -128,7 +128,7 @@ search_xml () {
 
   return 1
 }
+
 # $1: metadata file; $2: xml file; $3: check Result-Code indicator; $4: client/server (ADML node role)
 update_testcase () {
   # metadata aspect:
@@ -193,7 +193,7 @@ update_testcase () {
       local ans_xml=${hbh_matchs[1]}
       local rc=2001
       if [ -n "$ans_xml" ]
-      then 
+      then
         _rc=$(getResultCode $ans_xml)
         [ -n "$_rc" ] && rc=$_rc
       fi
@@ -304,7 +304,7 @@ do
   # Ignore keep alives:
   grep -q "^code=280$" $mtd
   [ $? -eq 0 ] && continue
-  
+
   grep -q "^isrequest=1$" $mtd
   if [ $? -eq 0 ]
   then
@@ -320,7 +320,7 @@ do
     fi
     # Other requests:
     echo $frame >> requests_4_sending
-    
+
     # client or server:
     adml_type=$(grep -w "$originHost" $ohs_file | awk '{ print $NF }')
     update_testcase $mtd $xml check_result_code $adml_type
index 69ccab2..9acd8fd 100755 (executable)
@@ -49,7 +49,7 @@ void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::Cl
 }
 
 
-void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message)
+void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventRequest", ANNA_FILE_LOCATION));
   // Performance stats:
@@ -70,7 +70,7 @@ noexcept(false) {
   );
 }
 
-void MyDiameterEntity::eventResponse(const anna::diameter::comm::Response &response)
+void MyDiameterEntity::eventResponse(const anna::diameter::comm::Response &response, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventResponse", ANNA_FILE_LOCATION));
   RxSimpleTest& my_app = static_cast <RxSimpleTest&>(anna::app::functions::getApp());
@@ -155,7 +155,7 @@ noexcept(false) {
       anna::diameter::comm::Message *msg;
 
       try {
-        msg = my_node->createCommMessage();
+        msg = (const_cast<anna::diameter::comm::OriginHost*>(myNode))->createCommMessage();
         msg->setBody(aar.code());
         /* response = NULL =*/clientSession->send(msg);
       } catch(anna::RuntimeException &ex) {
@@ -163,7 +163,7 @@ noexcept(false) {
       }
 
       // release msg
-      my_node->releaseCommMessage(msg);
+      (const_cast<anna::diameter::comm::OriginHost*>(myNode))->releaseCommMessage(msg);
     }
     else if(request_cid == anna::diameter::helpers::nas::COMMANDID__AA_Request) {
       // Decode
@@ -179,7 +179,7 @@ noexcept(false) {
   }
 }
 
-void MyDiameterEntity::eventUnknownResponse(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message)
+void MyDiameterEntity::eventUnknownResponse(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventUnknownResponse", ANNA_FILE_LOCATION));
   // Performance stats:
@@ -199,7 +199,7 @@ noexcept(false) {
   );
 }
 
-void MyDiameterEntity::eventDPA(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message)
+void MyDiameterEntity::eventDPA(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventDPA", ANNA_FILE_LOCATION));
   // Performance stats:
index d42016d..2c7f8d5 100755 (executable)
@@ -23,10 +23,10 @@ namespace anna {
 class MyDiameterEntity : public anna::diameter::comm::Entity {
 
   void eventRequestRetransmission(const anna::diameter::comm::ClientSession *, anna::diameter::comm::Message*) ;
-  void eventResponse(const anna::diameter::comm::Response&) noexcept(false);
-  void eventRequest(anna::diameter::comm::ClientSession *, const anna::DataBlock&) noexcept(false);
-  void eventUnknownResponse(anna::diameter::comm::ClientSession *, const anna::DataBlock&) noexcept(false);
-  void eventDPA(anna::diameter::comm::ClientSession *, const anna::DataBlock&) noexcept(false);
+  void eventResponse(const anna::diameter::comm::Response&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventRequest(anna::diameter::comm::ClientSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventUnknownResponse(anna::diameter::comm::ClientSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventDPA(anna::diameter::comm::ClientSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
 
 public:
 
index 1327dd1..a3809a1 100755 (executable)
 #include <rxSimpleTest.hpp>
 
 
-void MyLocalServer::eventRequest(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message)
+void MyLocalServer::eventRequest(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventRequest", ANNA_FILE_LOCATION));
+
+  // Protection:
+  if (!myNode) return;
+
   // Performance stats:
   RxSimpleTest& my_app = static_cast <RxSimpleTest&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
-  anna::diameter::codec::Engine *codecEngine = my_node->getCodecEngine();
+  anna::diameter::codec::Engine *codecEngine = myNode->getCodecEngine();
 
   // CommandId:
   anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message);
@@ -51,7 +54,7 @@ noexcept(false) {
 
   anna::diameter::comm::Message *msg;
   try {
-    msg = my_node->createCommMessage();
+    msg = (const_cast<anna::diameter::comm::OriginHost*>(myNode))->createCommMessage();
     msg->setBody(answer_message->code());
     /* response = NULL =*/serverSession->send(msg);
   } catch(anna::RuntimeException &ex) {
@@ -59,14 +62,13 @@ noexcept(false) {
   }
 
   // release msg
-  my_node->releaseCommMessage(msg);
+  (const_cast<anna::diameter::comm::OriginHost*>(myNode))->releaseCommMessage(msg);
 }
 
-void MyLocalServer::eventResponse(const anna::diameter::comm::Response &response)
+void MyLocalServer::eventResponse(const anna::diameter::comm::Response &response, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventResponse", ANNA_FILE_LOCATION));
   RxSimpleTest& my_app = static_cast <RxSimpleTest&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
   anna::diameter::comm::ClassCode::_v code = response.getClassCode();
   anna::diameter::comm::Response::ResultCode::_v result = response.getResultCode();
   anna::diameter::comm::Message* request = const_cast<anna::diameter::comm::Message*>(response.getRequest());
@@ -110,12 +112,11 @@ noexcept(false) {
   }
 }
 
-void MyLocalServer::eventUnknownResponse(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message)
+void MyLocalServer::eventUnknownResponse(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventUnknownResponse", ANNA_FILE_LOCATION));
   // Performance stats:
   RxSimpleTest& my_app = static_cast <RxSimpleTest&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
   // CommandId:
   anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message);
   LOGDEBUG
@@ -130,12 +131,11 @@ noexcept(false) {
   );
 }
 
-void MyLocalServer::eventDPA(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message)
+void MyLocalServer::eventDPA(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message, const anna::diameter::comm::OriginHost *myNode)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventDPA", ANNA_FILE_LOCATION));
   // Performance stats:
   RxSimpleTest& my_app = static_cast <RxSimpleTest&>(anna::app::functions::getApp());
-  anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName());
   // CommandId:
   anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message);
   LOGDEBUG
index 4f25615..6893c67 100755 (executable)
@@ -23,10 +23,10 @@ namespace anna {
 
 class MyLocalServer : public anna::diameter::comm::LocalServer {
 
-  void eventResponse(const anna::diameter::comm::Response&) noexcept(false);
-  void eventRequest(anna::diameter::comm::ServerSession *, const anna::DataBlock&) noexcept(false);
-  void eventUnknownResponse(anna::diameter::comm::ServerSession *, const anna::DataBlock&) noexcept(false);
-  void eventDPA(anna::diameter::comm::ServerSession *, const anna::DataBlock&) noexcept(false);
+  void eventResponse(const anna::diameter::comm::Response&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventRequest(anna::diameter::comm::ServerSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventUnknownResponse(anna::diameter::comm::ServerSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
+  void eventDPA(anna::diameter::comm::ServerSession *, const anna::DataBlock&, const anna::diameter::comm::OriginHost*) noexcept(false);
 
 public:
   virtual ~MyLocalServer() {;}
index 12fde94..ecde7ef 100755 (executable)
@@ -130,8 +130,8 @@ void RxSimpleTest::startService() noexcept(false) {
 
   // Diameter entity:
   commEngine->setNumberOfClientSessionsPerServer(1);
-  //commEngine->setClientCERandDWR("./cer.xml", "./dwr.xml");
-  commEngine->setClientCERandDWR();
+  commEngine->setClientCER(anna::diameter::helpers::APPID__3GPP_Rx);
+  commEngine->setClientDWR(); // default
 
   // Register one entity for this engine:
   a_workingNode->createEntity("localhost:3868", ceaTimeoutMs, answersTimeoutMs);
index f653ee5..6df8a85 100644 (file)
@@ -133,14 +133,6 @@ public:
   */
   const anna::Millisecond & getMaxConnectionDelay() { return a_server->getMaxConnectionDelay(); }
 
-  /**
-   * Sets CER and DWR diameter messages to be used over created client-sessions
-   *
-   * @param cer Capabilities-Exchange-Request message (encoded) for the client-sessions bind.
-   * @param dwr Device-Watchdog-Request message (encoded) for the client-sessions keep-alive.
-   */
-  void setCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) noexcept(false);
-
   // Internal
   void bind() noexcept(false);
 
@@ -192,6 +184,7 @@ private:
   Server *a_parent;
 
   // ClientSession messages:
+  Engine *a_engine; // it is unique for a client session (not in server session, which have one per origin host)
   Message a_cer;
   Message a_dwr;
 
@@ -243,30 +236,34 @@ private:
      Handler for diameter server (client-session) responses
 
      \param response Answer container object for corresponding diameter request
+     \param myNode Own origin host
   */
-  void eventResponse(const Response& response) noexcept(false);
+  void eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
   /**
      Handler for diameter server (client-session) requests
 
      \param request Request data block object for corresponding diameter reception
+     \param myNode Own origin host
   */
-  void eventRequest(const anna::DataBlock& request) noexcept(false);
+  void eventRequest(const anna::DataBlock& request, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
   //void eventRequest(const Message& request) noexcept(false);
 
   /**
      Handler for diameter server (client-session) responses out of context
 
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  void eventUnknownResponse(const anna::DataBlock& response) noexcept(false);
+  void eventUnknownResponse(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
   /**
      Handler for diameter server (client-session) Disconnect-Peer-Answer messages
 
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  void eventDPA(const anna::DataBlock& response) noexcept(false);
+  void eventDPA(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
 
 
index e8febc4..8da4a6b 100644 (file)
@@ -25,6 +25,8 @@
 #include <anna/config/defines.hpp>
 #include <anna/diameter.comm/ClientSession.hpp>
 #include <anna/diameter.comm/ServerSession.hpp>
+#include <anna/core/util/defines.hpp> // U32
+
 
 // Standard
 #include <time.h>
@@ -184,22 +186,40 @@ public:
   bool bind() noexcept(false);
 
   /**
-   * Sets CER and DWR diameter messages to be used over created client-sessions.
-   * Its recommended to set this global configuration although it is possible to configure each client-session separately.
+   * Sets CER diameter messages to be used over created client-sessions.
    *
    * @param cer Capabilities-Exchange-Request message (encoded) for the client-sessions bind.
+   */
+  void setClientCER(const anna::DataBlock & cer) noexcept(false);
+
+  /**
+   * Sets CER diameter messages to be used over created client-sessions.
+   *
+   * @param cerPathFile Capabilities-Exchange-Request xml message path file for the client-sessions bind.
+   */
+  void setClientCER(const std::string & cerPathFile) noexcept(false);
+
+  /**
+   * Sets DEFAULT CER diameter messages to be used over created client-sessions.
+   *
+   * @param applicationId Application-Id for the Auth-Application-Id AVP.
+   */
+  void setClientCER(const anna::U32 &applicationId) noexcept(false);
+
+  /**
+   * Sets DWR for diameter keep-alive over client-sessions
+   *
    * @param dwr Device-Watchdog-Request message (encoded) for the client-sessions keep-alive.
    */
-  void setClientCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) noexcept(false);
+  void setClientDWR(const anna::DataBlock & dwr) noexcept(false);
 
   /**
-   * Sets CER and DWR diameter messages to be used over created client-sessions. If empty string is provided for CER and/or DWR, default version will be configured.
-   * Its recommended to set this global configuration although it is possible to configure each client-session separately.
+   * Sets DWR for diameter keep-alive over client-sessions
    *
-   * @param cer Capabilities-Exchange-Request xml message path file for the client-sessions bind. If empty string is provided (default), a default version for CER will be encoded.
-   * @param dwr Device-Watchdog-Request xml message path file for the client-sessions keep-alive. If empty string is provided (default), a default version for DWR will be encoded.
+   * @param cerPathFile Device-Watchdog-Request xml message path file for the client-sessions keep-alive.
+   * If empty provided, a DEFAULT DWR will be built.
    */
-  void setClientCERandDWR(const std::string & cer = "", const std::string & dwr = "") noexcept(false);
+  void setClientDWR(const std::string & dwrPathFile = "") noexcept(false);
 
   /**
    * Sets the watchdog period (DWR) for client-sessions.
@@ -492,71 +512,6 @@ public:
   */
   virtual anna::xml::Node* asXML(anna::xml::Node* parent) const ;
 
-
-  /**
-     When there is not bound server session over the engine, this virtual method will be invoked.
-     Applications must decide to do any other tasks at this idle/isolated situation.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLostForLocalServers(Engine *) const {;}
-
-  /**
-     When there is any bound server session over the engine, this virtual method will be invoked.
-     Applications must decide to do be ready for incoming traffic.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecoveredForLocalServers(Engine *) const {;}
-
-  /**
-     When there is not bound entity over the engine, this virtual method will be invoked.
-     Many applications must change communicator status to Unavailable when no engines are available.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLostForEntities(Engine *) const {;}
-
-  /**
-     When there is any bound entity over the engine, this virtual method will be invoked.
-     Many applications must recover communicator status to Available when any engine are available.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecoveredForEntities(Engine *) const {;}
-
-  /**
-     When there is not bound server-session over the local server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLost(LocalServer *) const {;}
-
-  /**
-     When there is any bound server-session over the local server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecovered(LocalServer *) const {;}
-
-  /**
-     When there is not bound server over the entity, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLost(Entity *) const {;}
-
-  /**
-     When there is any bound server over the entity, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecovered(Entity *) const {;}
-
-  /**
-     When there is not bound client-session over the server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLost(Server *) const {;}
-
-  /**
-     When there is any bound client-session over the server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecovered(Server *) const {;}
-
   /**
      When a subyacent client session is going to be bound, this method is invoked before.
      Default implementation do nothing.
@@ -573,7 +528,7 @@ public:
    * @param dpa DPA datablock passed as reference
    * @param dpr Corresponding DPR received (sequence values must be taken into account in order to build DPA)
   */
-  virtual void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) ;
+  virtual void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) const;
 
   /**
    * Sets optional CEA from file, when default is not enough
@@ -582,6 +537,13 @@ public:
    */
   void setCEA(const std::string &ceaPathfile) { a_ceaPathfile = ceaPathfile; }
 
+  /**
+   * Gets optional CEA from file, when default is not enough
+   *
+   * @return Path file for the CEA xml message provided
+   */
+  const std::string & getCEA() const { return a_ceaPathfile; }
+
   /**
    * Class user should implement this method in order to define Capabilities-Exchange-Answer for received CER over server socket.
    * Origin-Host and Origin-Realm are configured at comm::Engine with hostname and FQDN (Fully Qualified Domain Name).
@@ -611,7 +573,7 @@ public:
    * @param cea CEA datablock passed as reference. Empty cea implies to discard CER received.
    * @param cer Corresponding CER received (sequence values must be taken into account in order to build CEA)
   */
-  virtual void readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) ;
+  virtual void readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) const;
 
   /**
    * Class user should implement this method in order to define Device-Watchdog-Answer for received DWR over server socket.
@@ -622,7 +584,7 @@ public:
    * @param dwa DWA datablock passed as reference
    * @param dwr Corresponding DWR received (sequence values must be taken into account in order to build DWA)
   */
-  virtual void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) ;
+  virtual void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) const;
 
   /**
    * DRA basics: CER information is gathered on every server session managed by the diameter comm engine. You could send the message to a
@@ -661,7 +623,7 @@ protected:
      @param baseProtocolDictionary This will be used internally when calling \@readCEA, \@readDPA and \@readDWA on
      servers, and also used during base protocol messages tracing (if debug traces are enabled). You could provide
      NULL, but you must be sure that neither of the former situations are going to happen or an exception will be
-     thrown (using setClientCERandDWR with DataBlock arguments, expects externally encoded messages and could help).
+     thrown (using setClientCER and setClientDWR with DataBlock arguments, expects externally encoded messages and could help).
      It is recommended to set a base protocol dictionary loading 'source/diameter/stack/setups' dictionaries (for
      example 'avps_ietf.xml' plus 'commands_baseProtocol.xml'), or using the dictionary creation API. The dictionary
      could also be an application stack, the only condition is containing the resources to build base protocol messages.
@@ -734,14 +696,12 @@ private:
 
 
   // ClientSessions messages:
-  anna::DataBlock a_cer;
-  anna::DataBlock a_dwr;
+  anna::DataBlock a_client_cer;
+  anna::DataBlock a_client_dwr;
   anna::Millisecond a_watchdogPeriod;
 
-//   // ServerSessions messages:
+  // ServerSessions messages: no need for DWA and DPA templates, they are built on the fly (enough information).
   std::string a_ceaPathfile; // path file to optional CEA (diameter local server configuration)
-//   anna::DataBlock a_cea;
-//   anna::DataBlock a_dwa;
 
   // Client connectivity
   anna::Millisecond a_maxConnectionDelay;
@@ -766,7 +726,7 @@ private:
 
   // Integrity:
   void checkEntityCollision(const socket_v &) noexcept(false);
-  void assertBaseProtocolHealth() noexcept(false); // checks the dictionary
+  void assertBaseProtocolHealth() const noexcept(false); // checks the dictionary
 
 
   //////////////////////////
index b8ade9b..351b3e0 100644 (file)
@@ -475,16 +475,18 @@ protected:
      Handler for diameter server (server) responses
 
      \param response Answer container object for corresponding diameter request
+     \param myNode Own origin host
   */
-  virtual void eventResponse(const Response& response) noexcept(false) = 0;
+  virtual void eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
   /**
      Handler for diameter server (server) requests
 
      \param clientSession ClientSession from which request has been received
      \param request Diameter request message received
+     \param myNode Own origin host
   */
-  virtual void eventRequest(ClientSession* clientSession, const anna::DataBlock &request) noexcept(false) = 0;
+  virtual void eventRequest(ClientSession* clientSession, const anna::DataBlock &request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
   //virtual void eventRequest(ClientSession* clientSession, const Message& request) noexcept(false) = 0;
 
   /**
@@ -492,16 +494,18 @@ protected:
 
      \param clientSession ClientSession from which request has been received
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response) noexcept(false) = 0;
+  virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
   /**
      Handler for diameter session Disconnect-Peer-Answer messages
 
      \param clientSession ClientSession from which request has been received
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response) noexcept(false) = 0;
+  virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
 
 
index ba1d494..6a63a7c 100644 (file)
@@ -43,10 +43,10 @@ namespace diameter {
 
 namespace comm {
 
-class Engine;
 class Response;
 class ServerSocket;
 class Message;
+class Engine;
 
 
 /**
@@ -65,7 +65,7 @@ class LocalServer {
   bool a_lock;
 
   // Engine
-  Engine *a_engine;
+  Engine *a_engine; // only for refresh availability
 
   // Statistics
   MessageStatistics a_messageStatistics;
@@ -186,12 +186,6 @@ public:
 
   // getters
 
-  /**
-  * Gets the diameter::comm::Engine
-  * @return Diameter::comm::Engine
-  */
-  Engine *getEngine() const { return a_engine; }
-
   /**
   * Gets the local server key
   * @return LocalServer key
@@ -380,16 +374,18 @@ protected:
      Handler for diameter client responses
 
      \param response Answer container object for corresponding diameter request
+     \param myNode Own origin host
   */
-  virtual void eventResponse(const Response& response) noexcept(false) = 0;
+  virtual void eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
   /**
      Handler for diameter client requests
 
      \param serverSession ServerSession from which request has been received
      \param request Request data block object for corresponding diameter reception
+     \param myNode Own origin host
   */
-  virtual void eventRequest(ServerSession* serverSession, const anna::DataBlock& request) noexcept(false) = 0;
+  virtual void eventRequest(ServerSession* serverSession, const anna::DataBlock& request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
   //void eventRequest(ServerSession* serverSession, const Message& request) noexcept(false);
 
   /**
@@ -397,16 +393,18 @@ protected:
 
      \param serverSession ServerSession from which request has been received
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  virtual void eventUnknownResponse(ServerSession* serverSession, const anna::DataBlock& response) noexcept(false) = 0;
+  virtual void eventUnknownResponse(ServerSession* serverSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
   /**
      Handler for diameter client Disconnect-Peer-Answer messages
 
      \param serverSession ServerSession from which request has been received
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  virtual void eventDPA(ServerSession* serverSession, const anna::DataBlock& response) noexcept(false) = 0;
+  virtual void eventDPA(ServerSession* serverSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
 
   friend class anna::diameter::comm::Timer;
index 55f729d..30562ca 100644 (file)
@@ -19,6 +19,7 @@
 #include <anna/core/DataBlock.hpp>
 #include <anna/diameter/codec/Message.hpp>
 #include <anna/diameter.comm/Message.hpp>
+#include <anna/diameter/codec/MessagesDeque.hpp>
 
 
 namespace anna {
@@ -65,6 +66,8 @@ class OriginHost {
   int a_otaRequest;
   int a_burstPopCounter;
 
+  anna::diameter::codec::MessagesDeque a_reactingAnswers;
+
 public:
   OriginHost(anna::diameter::comm::Engine* commEngine, unsigned int applicationId);
   ~OriginHost() {;}
@@ -117,6 +120,8 @@ public:
 
   anna::xml::Node* asXML(anna::xml::Node* parent) const ;
   std::string asXMLString() const ;
+
+  anna::diameter::codec::MessagesDeque *getReactingAnswers() { return (anna::diameter::codec::MessagesDeque*)&a_reactingAnswers; }
 };
 
 }
index 82c0979..9051052 100644 (file)
@@ -13,6 +13,8 @@
 // Project
 #include <anna/core/Singleton.hpp>
 #include <anna/diameter/defines.hpp>
+#include <anna/core/util/defines.hpp> // U32
+
 
 // Standard
 #include <map>
@@ -45,6 +47,8 @@ class OriginHostManager : public anna::Singleton <OriginHostManager> {
 private:
 
   origin_hosts_t a_origin_hosts;
+  std::map<std::string /* remove OH name */, std::string /* own OH name */> a_remote_to_own_origin_hosts{};
+
 
   // private constructor
   OriginHostManager() {};
@@ -77,6 +81,15 @@ public:
    */
   void registerOriginHost(const std::string &name, OriginHost* originHost) ;
 
+  /**
+   * Registers  the relation between Origin Host for incoming request and
+   * own origin host.
+   *
+   * @param remoteName origin host name for the received CER
+   * @param ownName Own origin host name
+   */
+  void registerRemoteOriginHost(const std::string &remoteName, const std::string &ownName);
+
   /**
    * Get the associated origin host node for a provided name.
    *
@@ -86,6 +99,28 @@ public:
    */
   OriginHost *getOriginHost(const std::string &name) const ;
 
+  /**
+   * Get the associated origin host name for a provided remote origin host name.
+   * This relation was established on CER reception.
+   *
+   * @param name remote origin host name
+   *
+   * @return own origin host, NULL if not found
+   */
+  OriginHost * getOriginHostForRemoteOriginHost(const std::string &name) const;
+
+  /**
+   * Get the associated origin host node for a specific application id
+   * No indexed map by application id, so this search is sequential, but
+   * performance is not required as this is used when receiving CER.
+   *
+   * @applicationId application id to search
+   *
+   * @return Found origin host node, NULL if not found
+   */
+  OriginHost *getOriginHost(const anna::U32 &applicationId) const;
+
+
   /**
      Class XML representation.
      \param parent XML node over which we will put instance information.
index 711fdcd..514ce39 100644 (file)
@@ -45,6 +45,7 @@ class Entity;
 class ClientSession;
 class Response;
 class Message;
+class OriginHost;
 
 
 /**
@@ -297,7 +298,7 @@ protected:
 
      \param response Answer container object for corresponding diameter request
   */
-  virtual void eventResponse(const Response & response) noexcept(false);
+  virtual void eventResponse(const Response & response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
   /**
      Handler for diameter server (client-session) requests
@@ -305,8 +306,7 @@ protected:
      \param clientSession ClientSession from which request has been received
      \param request Diameter request message received
   */
-  virtual void eventRequest(ClientSession *clientSession, const anna::DataBlock &request) noexcept(false);
-  //virtual void eventRequest(ClientSession *clientSession, const Message & request) noexcept(false);
+  virtual void eventRequest(ClientSession *clientSession, const anna::DataBlock &request, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
   /**
      Handler for diameter server (client-session) responses out of context
@@ -314,7 +314,7 @@ protected:
      \param clientSession ClientSession from which request has been received
      \param response Answer data block object without context match
   */
-  virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response) noexcept(false);
+  virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
   /**
      Handler for diameter server (client-session) Disconnect-Peer-Answer messages
@@ -322,7 +322,7 @@ protected:
      \param clientSession ClientSession from which request has been received
      \param response Answer data block object without context match
   */
-  virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response) noexcept(false);
+  virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
 
 
index 937cbf9..64997c4 100644 (file)
@@ -14,6 +14,7 @@
 #include <string>
 
 #include <anna/core/util/Millisecond.hpp>
+#include <anna/core/util/defines.hpp> // U32
 #include <anna/core/RuntimeException.hpp>
 
 #include <anna/diameter.comm/Session.hpp>
@@ -43,6 +44,7 @@ namespace comm {
 
 
 class LocalServer;
+class OriginHost;
 
 
 /**
@@ -104,19 +106,6 @@ public:
   */
   anna::comm::ClientSocket *getClientSocket() { return a_clientSocket; }
 
-//   /**
-//      Sets deprecated state to this server session
-//   */
-//   void setDeprecated(bool deprecated = true) { a_deprecated = deprecated; }
-
-//   /**
-//    * Sets CEA and DWA diameter messages to be used over created server-sessions
-//    *
-//    * @param cea Capabilities-Exchange-Answer message (encoded) for the server-sessions bind.
-//    * @param dwa Device-Watchdog-Answer message (encoded) for the server-sessions keep-alive.
-//    */
-//   void setCEAandDWA(const anna::DataBlock & cea, const anna::DataBlock & dwa) noexcept(false);
-
   /* virtual */const Response* send(const Message* message) noexcept(false);
   /* virtual */bool unbind(bool forceDisconnect /* se usa en timer, para el actionTimer del tipo SessionUnbind, etc. */ = false) noexcept(false); // returns true if done at call time (no pendings or ignore pendings, except Disconnecting state by mean DPR/DPA)
 
@@ -151,9 +140,6 @@ private:
   // Client Socket
   anna::comm::ClientSocket *a_clientSocket;
 
-  // Auxiliary messages:
-  Message a_cer, a_dwr;
-
   /* virtual */void expire(anna::timex::Engine *timeController) noexcept(false);
 
   // Activity:
@@ -180,30 +166,34 @@ private:
      Handler for diameter client responses
 
      \param response Answer container object for corresponding diameter request
+     \param myNode Own origin host
   */
-  void eventResponse(const Response& response) noexcept(false);
+  void eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
   /**
      Handler for diameter client requests
 
      \param request Request data block object for corresponding diameter reception
+     \param myNode Own origin host
   */
-  void eventRequest(const anna::DataBlock& request) noexcept(false);
+  void eventRequest(const anna::DataBlock& request, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
   //void eventRequest(const Message& request) noexcept(false);
 
   /**
      Handler for diameter client responses out of context
 
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  void eventUnknownResponse(const anna::DataBlock& response) noexcept(false);
+  void eventUnknownResponse(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
   /**
      Handler for diameter client Disconnect-Peer-Answer messages
 
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  void eventDPA(const anna::DataBlock& response) noexcept(false);
+  void eventDPA(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false);
 
 
 
@@ -214,8 +204,11 @@ private:
   /* virtual */void finalize() ;
 
   /* virtual */void expireResponse(Response*) ;
-  void sendCEA() noexcept(false);
-  void sendDWA() noexcept(false);
+
+  anna::U32 getAuthApplicationIdFromCER(const anna::DataBlock &cer, bool &found) const;
+
+  void sendCEA(const Engine*, const anna::DataBlock &cerDataBlock) noexcept(false);
+  void sendDWA(const Engine*, const anna::DataBlock &dwrDataBlock) noexcept(false);
 
 
   friend class anna::diameter::comm::Timer;
index 6507229..de7e569 100644 (file)
@@ -45,6 +45,7 @@ namespace comm {
 class Timer;
 class Engine;
 class Response;
+class OriginHost;
 
 
 
@@ -265,9 +266,6 @@ public:
 
 protected:
 
-  // Auxiliary messages:
-  Message a_dpr;
-
   // Internal, traces, etc.
   const char *a_className;
 
@@ -275,7 +273,6 @@ protected:
   int a_socketId; // multiple connection functionality
   State::_v a_state;
   OnDisconnect::_v a_onDisconnect;
-  Engine *a_engine;
   anna::diameter::comm::Timer *a_actionTimer;
 
   // Sequencing
@@ -339,15 +336,17 @@ protected:
      Handler for diameter session responses
 
      \param response Answer data block object for corresponding diameter request
+     \param myNode Own origin host
   */
-  virtual void eventResponse(const Response& response) noexcept(false) = 0;
+  virtual void eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
   /**
      Handler for diameter session requests
 
      \param request Request container object for corresponding diameter reception
+     \param myNode Own origin host
   */
-  virtual void eventRequest(const anna::DataBlock& request) noexcept(false) = 0;
+  virtual void eventRequest(const anna::DataBlock& request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
   //void eventRequest(const Message& request) noexcept(false);
 
 
@@ -355,15 +354,17 @@ protected:
      Handler for diameter session responses out of context
 
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  virtual void eventUnknownResponse(const anna::DataBlock& response) noexcept(false) = 0;
+  virtual void eventUnknownResponse(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
   /**
      Handler for diameter session Disconnect-Peer-Answer messages
 
      \param response Answer data block object without context match
+     \param myNode Own origin host
   */
-  virtual void eventDPA(const anna::DataBlock& response) noexcept(false) = 0;
+  virtual void eventDPA(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
 
 
 
@@ -389,7 +390,7 @@ protected:
 
 
   virtual void expireResponse(Response*) ;
-  void sendDPA() noexcept(false);
+  void sendDPA(const Engine *commEngine, const anna::DataBlock &dprDataBlock) noexcept(false);
   void activateActionTimer(const anna::diameter::comm::Timer::Type::_v type) ;
   void cancelActionTimer() ;
   void activateTimer() ; // Session timer
@@ -409,7 +410,6 @@ protected:
 
 
   friend class anna::diameter::comm::Timer;
-  friend class Engine;
   friend class Response;
 };
 
index fa4a9c3..9db3ca7 100644 (file)
@@ -125,25 +125,6 @@ void ClientSession::bind() noexcept(false) {
 }
 
 
-void ClientSession::setCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) 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);
-  }
-
-  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);
-  }
-
-  // La verificacion ya se hace implicitamente antes
-  //   if ((a_cer.isEmpty()) || (a_dwr.isEmpty())) {
-  //      LOGDEBUG (anna::Logger::debug ("Must define valid CER and DWR messages before use bind !", ANNA_FILE_LOCATION));
-  //      return;
-  //   }
-  a_cer.setBody(cer);
-  a_dwr.setBody(dwr);
-}
-
-
 const Response* ClientSession::send(const Message* message) noexcept(false) {
   LOGMETHOD(anna::TraceMethod traceMethod(a_className, "send", ANNA_FILE_LOCATION));
 
@@ -458,24 +439,24 @@ void ClientSession::eventRequestRetransmission(Message *request) {
   a_parent->eventRequestRetransmission(this, request);
 }
 
-void ClientSession::eventResponse(const Response& response) noexcept(false) {
+void ClientSession::eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventResponse(response);
+  a_parent->eventResponse(response, myNode);
 }
 
-void ClientSession::eventRequest(const anna::DataBlock &request) noexcept(false) {
+void ClientSession::eventRequest(const anna::DataBlock &request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventRequest(this, request);
+  a_parent->eventRequest(this, request, myNode);
 }
 
-void ClientSession::eventUnknownResponse(const anna::DataBlock& response) noexcept(false) {
+void ClientSession::eventUnknownResponse(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventUnknownResponse(this, response);
+  a_parent->eventUnknownResponse(this, response, myNode);
 }
 
-void ClientSession::eventDPA(const anna::DataBlock& response) noexcept(false) {
+void ClientSession::eventDPA(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventDPA(this, response);
+  a_parent->eventDPA(this, response, myNode);
 }
 
 
@@ -542,11 +523,10 @@ noexcept(false) {
       oamModule.count(OamModule::Counter::DPRReceived);
 
       if(a_state == State::Bound) {
-        a_dpr.setBody(db);
         setState(State::Disconnecting);
         LOGWARNING(anna::Logger::warning("DPR has been received from peer (diameter server)", ANNA_FILE_LOCATION));
 
-        if(getOTARequests() == 0) sendDPA();
+        if(getOTARequests() == 0) sendDPA(a_engine, db);
 
         return; // DPR won't be informed because virtual readDPA is available for this
       }
@@ -556,7 +536,7 @@ noexcept(false) {
       // application message counters
       ApplicationMessageOamModule::instantiate().count(cid.first, -1 /* no result code */, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Request_Received_AsClient);
 
-      eventRequest(db);
+      eventRequest(db, nullptr /* client classes have a valid engine usage to distinguish, and get origin host from */);
     } catch(anna::RuntimeException& ex) {
       ex.trace();
     }
@@ -661,7 +641,7 @@ noexcept(false) {
     // application message counters
     ApplicationMessageOamModule::instantiate().count(cid.first, resultCode, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_UnknownReceived_AsClient);
 
-    eventUnknownResponse(db);
+    eventUnknownResponse(db, nullptr /* client classes have a valid engine usage to distinguish, and get origin host from */);
     string msg(asString());
     msg += anna::functions::asString(" | Response received from entity, for non registered context (HopByHop: %u)", hopByHop);
     throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
@@ -711,7 +691,7 @@ noexcept(false) {
       if(cid != helpers::base::COMMANDID__Capabilities_Exchange_Answer)
         ApplicationMessageOamModule::instantiate().count(cid.first, resultCode, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_Received_AsClient);
 
-      eventResponse(*response);
+      eventResponse(*response, nullptr /* client classes have a valid engine usage to distinguish, and get origin host from */);
     } catch(anna::RuntimeException& ex) {
       ex.trace();
     }
@@ -719,7 +699,7 @@ noexcept(false) {
   else { // DPA
     // unbind is automatically performed, anyway we can inform to the application just in case some additional
     //  procedure could be issued:
-    eventDPA(db);
+    eventDPA(db, nullptr /* client classes have a valid engine usage to distinguish, and get origin host from */);
   }
 
   response_erase(response);
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();
index d48b139..eb4893c 100644 (file)
@@ -442,7 +442,6 @@ void Entity::availabilityLost() {
     oamModule.count(OamModule::Counter::LostAvailabilityOverEntity);
   }
 
-  a_engine->availabilityLost(this);
   a_engine->refreshAvailabilityForEntities();
 }
 
@@ -467,7 +466,6 @@ void Entity::availabilityRecovered() {
     oamModule.count(OamModule::Counter::RecoveredAvailabilityOverEntity);
   }
 
-  a_engine->availabilityRecovered(this);
   a_engine->refreshAvailabilityForEntities();
 }
 
index a445245..703dc66 100644 (file)
@@ -7,10 +7,10 @@
 
 
 #include <anna/diameter.comm/OamModule.hpp>
-#include <anna/diameter.comm/Engine.hpp>
 #include <anna/diameter.comm/LocalServer.hpp>
 #include <anna/diameter.comm/ServerSession.hpp>
 #include <anna/diameter.comm/ServerSocket.hpp>
+#include <anna/diameter.comm/Engine.hpp>
 #include <anna/core/functions.hpp>
 #include <anna/statistics/Engine.hpp>
 #include <anna/diameter.comm/TimerManager.hpp>
@@ -38,7 +38,6 @@ LocalServer::LocalServer() :
   a_maxConnections(-1),
   a_currentConnections(0),
   a_allowedInactivityTime(ServerSession::DefaultAllowedInactivityTime),
-  a_engine(NULL),
   a_serverSocket(NULL),
   a_category(0),
   a_lock(false),
@@ -49,10 +48,6 @@ LocalServer::LocalServer() :
 void LocalServer::initializeStatisticResources() {
   std::string accName = "local server '";
   accName += anna::functions::socketLiteralAsString(a_key.first, a_key.second);
-  accName += "' on origin-realm '";
-  accName += a_engine ? a_engine->getOriginRealmName() : "unknown"; // it should be known (createServer)
-  accName += "' and origin-host '";
-  accName += a_engine ? a_engine->getOriginHostName() : "unknown"; // it should be known (createServer)
   accName += "'";
   a_messageStatistics.initialize(accName);
 }
@@ -98,7 +93,6 @@ void LocalServer::availabilityLost() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.activateAlarm(OamModule::Alarm::c_LostAvailabilityOverLocalServerDefinedAs__s__, socket.c_str());
   oamModule.count(OamModule::Counter::LostAvailabilityOverLocalServer);
-  a_engine->availabilityLost(this);
   a_engine->refreshAvailabilityForLocalServers();
 }
 
@@ -116,7 +110,6 @@ void LocalServer::availabilityRecovered() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.cancelAlarm(OamModule::Alarm::c_LostAvailabilityOverLocalServerDefinedAs__s__, socket.c_str());
   oamModule.count(OamModule::Counter::RecoveredAvailabilityOverLocalServer);
-  a_engine->availabilityRecovered(this);
   a_engine->refreshAvailabilityForLocalServers();
 }
 
@@ -275,7 +268,6 @@ ServerSession *LocalServer::createServerSession(const anna::comm::ClientSocket &
   result->a_parent = this;
   result->a_socketId = key; // de momento...
   result->initializeSequences(); // despues de asignar el LocalServer y el socketId (sequences are seed-based by mean exclusive hash)
-  result->a_engine = a_engine;
   a_serverSessions.insert(serverSession_value_type(key, result));
   newConnection();
   a_deliveryIterator = serverSession_begin();
@@ -552,7 +544,9 @@ void LocalServer::eventRequestRetransmission(const ServerSession* serverSession,
 
 std::string LocalServer::asString() const {
   std::string result("diameter::comm::LocalServer { ");
-  result += "Description: ";
+  result += "Key: ";
+  result += anna::functions::socketLiteralAsString(getKey().first, getKey().second);
+  result += " | Description: ";
   result += (a_description != "") ? a_description : "undefined";
   result += " | Available (any server session bound): ";
   result += a_available ? "yes" : "no";
index 8a87291..00861a8 100644 (file)
 
 
 void anna::diameter::comm::MessageStatistics::initialize(const std::string &name) noexcept(false) {
-  a_accumulator = anna::statistics::Engine::instantiate().createAccumulator(name);
+
+  // Avoid exception if already created (happens for 2 origin hosts with same local server)
+  a_accumulator = anna::statistics::Engine::instantiate().getAccumulator(name);
+
+  if (!a_accumulator)
+    a_accumulator = anna::statistics::Engine::instantiate().createAccumulator(name);
 }
 
 
index 42f1ab3..a518292 100644 (file)
@@ -71,6 +71,7 @@ void OriginHost::createDiameterServer(const std::string &serverRepresentation, i
   anna::functions::getAddressAndPortFromSocketLiteral(serverRepresentation, address, port);
   std::string serverDescription = "Launcher diameter local server for "; serverDescription += getName();
   a_commEngine->setCEA(ceaPathfile);
+
   a_diameterServer = (anna::diameter::comm::LocalServer*)(a_commEngine->createLocalServer(address, port, sessions));
           // we could set sessions = 0, and after application run(), use setMaxConnections(real sessions)
           // over the local server in order to start it.
index ff929bf..d5482c1 100644 (file)
@@ -28,6 +28,10 @@ void OriginHostManager::registerOriginHost(const std::string &name, OriginHost*
   a_origin_hosts[name] = originHost;
 }
 
+void OriginHostManager::registerRemoteOriginHost(const std::string &remoteName, const std::string &ownName) {
+  a_remote_to_own_origin_hosts[remoteName] = ownName;
+}
+
 anna::xml::Node* OriginHostManager::asXML(anna::xml::Node* parent) const
 {
   anna::xml::Node* result = parent->createChild("OriginHostManager");
@@ -39,3 +43,25 @@ anna::xml::Node* OriginHostManager::asXML(anna::xml::Node* parent) const
   return result;
 }
 
+
+OriginHost *OriginHostManager::getOriginHost(const anna::U32 &applicationId) const {
+
+  OriginHost *result{};
+
+  for (auto it: a_origin_hosts) {
+    result = it.second;
+    if (result->getApplicationId() == applicationId) return result;
+  }
+
+  return NULL;
+}
+
+OriginHost *OriginHostManager::getOriginHostForRemoteOriginHost(const std::string &name) const {
+   auto it = a_remote_to_own_origin_hosts.find(name);
+
+   if (it != a_remote_to_own_origin_hosts.end())
+     return getOriginHost(it->second);
+
+  return NULL;
+}
+
index 4721b10..9cbeb74 100644 (file)
@@ -321,24 +321,24 @@ void Server::eventRequestRetransmission(const ClientSession* clientSession, Mess
   a_parent->eventRequestRetransmission(clientSession, request);
 }
 
-void Server::eventResponse(const Response& response) noexcept(false) {
+void Server::eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father entity:
-  a_parent->eventResponse(response);
+  a_parent->eventResponse(response, myNode);
 }
 
-void Server::eventRequest(ClientSession *clientSession, const anna::DataBlock & request) noexcept(false) {
+void Server::eventRequest(ClientSession *clientSession, const anna::DataBlock & request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father entity:
-  a_parent->eventRequest(clientSession, request);
+  a_parent->eventRequest(clientSession, request, myNode);
 }
 
-void Server::eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock & response) noexcept(false) {
+void Server::eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock & response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father entity:
-  a_parent->eventUnknownResponse(clientSession, response);
+  a_parent->eventUnknownResponse(clientSession, response, myNode);
 }
 
-void Server::eventDPA(ClientSession *clientSession, const anna::DataBlock & response) noexcept(false) {
+void Server::eventDPA(ClientSession *clientSession, const anna::DataBlock & response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father entity:
-  a_parent->eventDPA(clientSession, response);
+  a_parent->eventDPA(clientSession, response, myNode);
 }
 
 
@@ -355,7 +355,6 @@ void Server::availabilityLost() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.activateAlarm(OamModule::Alarm::c_LostAvailabilityOverServerDefinedAs__s__, socket.c_str());
   oamModule.count(OamModule::Counter::LostAvailabilityOverServer);
-  a_engine->availabilityLost(this);
   a_parent->refreshAvailability();
 }
 
@@ -373,7 +372,6 @@ void Server::availabilityRecovered() {
   OamModule &oamModule = OamModule::instantiate();
   oamModule.cancelAlarm(OamModule::Alarm::c_LostAvailabilityOverServerDefinedAs__s__, socket.c_str());
   oamModule.count(OamModule::Counter::RecoveredAvailabilityOverServer);
-  a_engine->availabilityRecovered(this);
   a_parent->refreshAvailability();
 }
 
index b88da8d..ab7ca11 100644 (file)
@@ -28,6 +28,8 @@
 #include <anna/diameter.comm/LocalServer.hpp>
 #include <anna/diameter.comm/ServerSessionReceiver.hpp>
 #include <anna/diameter.comm/ReceiverFactoryImpl.hpp>
+#include <anna/diameter.comm/OriginHostManager.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
 
 #include <anna/app/functions.hpp>
 #include <anna/comm/ClientSocket.hpp>
@@ -53,9 +55,7 @@ const anna::Millisecond ServerSession::DefaultAllowedInactivityTime(90000); // I
 
 
 ServerSession::ServerSession() : Session("diameter::comm::ServerSession", "Diameter Inactivity Detection Timer"),
-  a_receiverFactory(this),
-  a_cer(ClassCode::Bind),
-  a_dwr(ClassCode::ApplicationMessage) // not actually needed; Message is application type by default
+  a_receiverFactory(this)
 { initialize(); }
 
 void ServerSession::initialize() {
@@ -211,22 +211,6 @@ const Response* ServerSession::send(const Message* message) noexcept(false) {
     updateOutgoingActivityTime();
     // OAM
     countSendings(cid, aid, true /* send ok */);
-    // Trace non-application messages:
-    LOGDEBUG(
-
-      if( (cid == helpers::base::COMMANDID__Device_Watchdog_Request) ||
-          (cid == helpers::base::COMMANDID__Disconnect_Peer_Request)) {
-        anna::Logger::debug("Sent DataBlock to XML representation:", ANNA_FILE_LOCATION);
-        try {
-          anna::diameter::codec::Message msg(a_engine->getBaseProtocolCodecEngine()); msg.decode(message->getBody()); /* decode to be traced */
-        }
-        catch(anna::RuntimeException &ex) {
-          std::string msg = ex.getText();
-          msg += " | Use diameter::comm::Engine::setBaseProtocolCodecEngine() to allow internal base protocol messages full tracing";
-          anna::Logger::debug(msg, ANNA_FILE_LOCATION);
-        }
-      }
-    );
 
     // Restore sequences:
     if(fixed) message_nc->restoreSequencesAfterFix();  // restore to application sequences after fix
@@ -323,24 +307,54 @@ void ServerSession::eventRequestRetransmission(Message *request) {
   a_parent->eventRequestRetransmission(this, request);
 }
 
-void ServerSession::eventResponse(const Response& response) noexcept(false) {
+void ServerSession::eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventResponse(response);
+  a_parent->eventResponse(response, myNode);
 }
 
-void ServerSession::eventRequest(const anna::DataBlock &request) noexcept(false) {
+void ServerSession::eventRequest(const anna::DataBlock &request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventRequest(this, request);
+  a_parent->eventRequest(this, request, myNode);
 }
 
-void ServerSession::eventUnknownResponse(const anna::DataBlock& response) noexcept(false) {
+void ServerSession::eventUnknownResponse(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventUnknownResponse(this, response);
+  a_parent->eventUnknownResponse(this, response, myNode);
 }
 
-void ServerSession::eventDPA(const anna::DataBlock& response) noexcept(false) {
+void ServerSession::eventDPA(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) {
   // Inform father server:
-  a_parent->eventDPA(this, response);
+  a_parent->eventDPA(this, response, myNode);
+}
+
+
+anna::U32 ServerSession::getAuthApplicationIdFromCER(const anna::DataBlock &cer, bool &found) const {
+
+  anna::U32 result{};
+  found = true;
+
+  anna::diameter::codec::Message codecMsg; // codec engine to pre-assigned, but will be inferred from ApplicationId during decoding:
+  try { codecMsg.decode(cer); } catch(anna::RuntimeException &ex) { ex.trace(); found = false; return result; }
+
+  // Look at first level:
+  try {
+    result = codecMsg.getAvp(helpers::base::AVPID__Auth_Application_Id)->getUnsigned32()->getValue();
+  }
+  catch(anna::RuntimeException &ex) {
+    found = false;
+  }
+
+  // Look within Vendor-Specific-Application-Id:
+  if (!found) {
+    try {
+      result = codecMsg.getAvp(helpers::base::AVPID__Vendor_Specific_Application_Id)->getAvp(helpers::base::AVPID__Auth_Application_Id)->getUnsigned32()->getValue();
+    }
+    catch(anna::RuntimeException &ex) {
+      found = false;
+    }
+  }
+
+  return result;
 }
 
 //------------------------------------------------------------------------------------------
@@ -349,6 +363,8 @@ void ServerSession::eventDPA(const anna::DataBlock& response) noexcept(false) {
 void ServerSession::receive(const anna::comm::Message& message)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod traceMethod(a_className, "receive", ANNA_FILE_LOCATION));
+
+
   // Activity:
   updateIncomingActivityTime();
   activateTimer();
@@ -360,18 +376,6 @@ noexcept(false) {
     std::string msg = "Received diameter message: ";
     msg += anna::diameter::functions::commandIdAsPairString(cid);
     anna::Logger::debug(msg, ANNA_FILE_LOCATION);
-
-    if( (cid == helpers::base::COMMANDID__Capabilities_Exchange_Request) ||
-        (cid.first == helpers::base::COMMANDID__Device_Watchdog_Request.first)) {
-      try {
-        anna::diameter::codec::Message dmsg(a_engine->getBaseProtocolCodecEngine()); dmsg.decode(db); /* decode to be traced */
-      }
-      catch(anna::RuntimeException &ex) {
-        std::string msg = ex.getText();
-        msg += " | Use diameter::comm::Engine::setBaseProtocolCodecEngine() to allow internal base protocol messages full tracing";
-        anna::Logger::debug(msg, ANNA_FILE_LOCATION);
-      }
-    }
   );
   // Main counters:
   OamModule &oamModule = OamModule::instantiate();
@@ -380,6 +384,16 @@ noexcept(false) {
   // Statistic (size)
   a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize(), cid); // only on reception (application could manage sent sizes)
 
+  // OriginHostManager (to register remote origin host in order to associate with specific comm engine):
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+
+  // Extract OriginHost from datablock (db):
+  std::string remoteOriginHost = anna::diameter::helpers::base::functions::getOriginHost(db);
+  LOGDEBUG(anna::Logger::debug(anna::functions::asString("REMOTE ORIGIN HOST FOR THE MESSAGE RECEIVED: %s", remoteOriginHost.c_str()), ANNA_FILE_LOCATION));
+
+  // Now, get the corresponding own origin host for it; in case of CER received, this will be unkonwn:
+  const anna::diameter::comm::OriginHost *originHost = ohm.getOriginHostForRemoteOriginHost(remoteOriginHost);
+
   if(isRequest) {
     // Si recibo un request, el message solo tiene fiable el DataBlock. Como por defecto se construye como ApplicationMessage,
     // el unico caso que no cuadraria seria la recepcion de un CER. Lo que hacemos es NO PROGRESAR NUNCA un CER (*).
@@ -390,17 +404,35 @@ noexcept(false) {
 
     // Received CER
     if(cid == helpers::base::COMMANDID__Capabilities_Exchange_Request) {
+
+      // For CERs, we need to extract the Auth-Application-Id:
+      bool found;
+      anna::U32 authApplicationId = getAuthApplicationIdFromCER(db, found);
+
+      // Now, sequential search in OriginHostManager for that id:
+      anna::diameter::comm::OriginHost *originHost = ohm.getOriginHost(authApplicationId);
+
+      if (!originHost) {
+        LOGWARNING(anna::Logger::warning("DIAMETER_NO_COMMON_APPLICATION with received CER. TODO: send CEA with that result code", ANNA_FILE_LOCATION));
+        unbind(true /* always immediate */);
+        return;
+      }
+
+      // Map origin host of received CER, to own OriginHost pointer. This will be used in future: DWR, DPR, normal messages
+      ohm.registerRemoteOriginHost(remoteOriginHost, originHost->getName());
+
+
+      // OAM
       oamModule.count(OamModule::Counter::CERReceived);
 
       if(a_state == State::Bound) {
         LOGWARNING(anna::Logger::warning("Received another CER over already bound connection. Anyway, will be replied with CEA", ANNA_FILE_LOCATION));
       }
 
-      a_cer.setBody(db);
       // Basic DRA:
-      getParent()->getEngine()->manageDrDhServerSession(this, true /* register */);
+      originHost->getCommEngine()->manageDrDhServerSession(this, true /* register */);
 
-      sendCEA();
+      sendCEA(originHost->getCommEngine(), db);
       //activateTimer(); // Ya se invoca al inicio de este metodo ::receive
       //bool changes = a_parent->refreshAvailability();
       return; // (*)
@@ -408,20 +440,23 @@ noexcept(false) {
     // Received DWR
     else if(cid == helpers::base::COMMANDID__Device_Watchdog_Request) {
       oamModule.count(OamModule::Counter::DWRReceived);
-      a_dwr.setBody(db);
-      sendDWA();
+
+      if (!originHost) return; // TODO, responding DWA with result code error
+
+      sendDWA(originHost->getCommEngine(), db);
       return; // (**)
     }
     // Received DPR
     else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) {
       oamModule.count(OamModule::Counter::DPRReceived);
 
+      if (!originHost) return; // TODO, responding DPA with result code error
+
       if(a_state == State::Bound) {
-        a_dpr.setBody(db);
         setState(State::Disconnecting);
         LOGWARNING(anna::Logger::warning("DPR has been received from peer (diameter client)", ANNA_FILE_LOCATION));
         // Ignore pending on server sessions:
-        /*if (getOTARequests() == 0) */sendDPA();
+        /*if (getOTARequests() == 0) */sendDPA(originHost->getCommEngine(), db);
         return; // DPR won't be informed because virtual readDPA is available for this
       }
     }
@@ -430,7 +465,9 @@ noexcept(false) {
       // application message counters
       ApplicationMessageOamModule::instantiate().count(cid.first, -1 /* no result code */, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Request_Received_AsServer);
 
-      eventRequest(db);
+      if (!originHost) return; // TODO, responding DWA with result code error
+
+      eventRequest(db, originHost);
     } catch(anna::RuntimeException& ex) {
       ex.trace();
     }
@@ -464,7 +501,8 @@ noexcept(false) {
       }
     }
 
-    eventDPA(db);
+    if (originHost)
+      eventDPA(db, originHost);
 
   } else if(cid == helpers::base::COMMANDID__Device_Watchdog_Answer) {  // non usual (server should not send DWR's)
     oamModule.count(OamModule::Counter::DWAReceived);
@@ -483,7 +521,8 @@ noexcept(false) {
     // application message counters
     ApplicationMessageOamModule::instantiate().count(cid.first, resultCode, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_UnknownReceived_AsServer);
 
-    eventUnknownResponse(db);
+    if (originHost)
+      eventUnknownResponse(db, originHost);
 
     string msg(asString());
     msg += anna::functions::asString(" | Response received from client, for non registered context (HopByHop: %u)", hopByHop);
@@ -534,7 +573,8 @@ noexcept(false) {
       // application message counters
       ApplicationMessageOamModule::instantiate().count(cid.first, resultCode, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_Received_AsServer);
 
-      eventResponse(*response);
+      if (originHost)
+        eventResponse(*response, originHost);
 
     } catch(anna::RuntimeException& ex) {
       ex.trace();
@@ -584,11 +624,12 @@ void ServerSession::finalize() {
 
 
 
-void ServerSession::sendCEA()
+void ServerSession::sendCEA(const Engine *commEngine, const anna::DataBlock &cerDataBlock)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod traceMethod(a_className, "sendCEA", ANNA_FILE_LOCATION));
+
   anna::DataBlock cea(true);
-  a_engine->readCEA(cea, a_cer.getBody()); // Asume that CEA is valid ...
+  commEngine->readCEA(cea, cerDataBlock); // Asume that CEA is valid ...
   // If one peer sends a CER message to another Peer and receiver does not have support for
   //
   //  1) any common application then it must return the CEA with Result-Code Avp set to DIAMETER_NO_COMMON_APPLICATION
@@ -635,11 +676,11 @@ noexcept(false) {
   }
 }
 
-void ServerSession::sendDWA()
+void ServerSession::sendDWA(const Engine *commEngine, const anna::DataBlock &dwrDataBlock)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod traceMethod(a_className, "sendDWA", ANNA_FILE_LOCATION));
   anna::DataBlock dwa(true);
-  a_engine->readDWA(dwa, a_dwr.getBody()); // Asume that DWA is valid ...
+  commEngine->readDWA(dwa, dwrDataBlock); // Asume that DWA is valid ...
 
   if(dwa.isEmpty())
     throw anna::RuntimeException("This diameter agent defines an empty DWA message. Remote client never will validate this connection health", ANNA_FILE_LOCATION);
index 4fb5ab4..d80175f 100644 (file)
@@ -24,6 +24,8 @@
 #include <anna/diameter.comm/Message.hpp>
 #include <anna/diameter.comm/TimerManager.hpp>
 #include <anna/diameter.comm/Timer.hpp>
+#include <anna/diameter.comm/OriginHostManager.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
 
 #include <anna/comm/Network.hpp>
 #include <anna/comm/ClientSocket.hpp>
@@ -53,10 +55,8 @@ const int Session::DefaultPort(3868);
 Session::Session(const char *className, const char *timerName) : anna::timex::Timer(timerName, (anna::Millisecond)0) /* not assigned */,
   a_className(className),
   a_timeController(NULL),
-  a_engine(NULL),
   a_notifyOrphansOnExpiration(true),
-  a_actionTimer(NULL),
-  a_dpr(ClassCode::ApplicationMessage) { // realmente no es necesario, los Message son por defecto de aplicacion
+  a_actionTimer(NULL) {
   initialize();
 }
 
@@ -114,11 +114,11 @@ void Session::initializeSequences() {
   a_nextEndToEnd = ((::time(NULL) & 0xFFF) << 20) + (rand() & 0xFFFFF);
 }
 
-void Session::sendDPA()
+void Session::sendDPA(const Engine *commEngine, const anna::DataBlock &dprDataBlock)
 noexcept(false) {
   LOGMETHOD(anna::TraceMethod traceMethod("anna::diameter::comm::Session", "sendDPA", ANNA_FILE_LOCATION));
   anna::DataBlock dpa(true);
-  a_engine->readDPA(dpa, a_dpr.getBody()); // Asume that DPA is valid ...
+  commEngine->readDPA(dpa, dprDataBlock); // Asume that DPA is valid ...
 
   if(dpa.isEmpty()) {
     LOGWARNING(anna::Logger::warning("This diameter agent defines an empty DPA message. Remote disconnection DPR will be ignored going to the Bound state", ANNA_FILE_LOCATION));
@@ -252,9 +252,17 @@ void Session::expireResponse(diameter::comm::Response* response)
     doUnbind = true; // (*)
 
 
+  // Get origin host corresponding to the message:
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+
+  // Extract OriginHost from datablock (db):
+  std::string originHostName = anna::diameter::helpers::base::functions::getOriginHost(response->getRequest()->getBody());
+  LOGDEBUG(anna::Logger::debug(anna::functions::asString("ORIGIN HOST FOR THE MESSAGE WHICH WAS EXPIRED: %s", originHostName.c_str()), ANNA_FILE_LOCATION));
+  anna::diameter::comm::OriginHost *originHost = ohm.getOriginHost(originHostName);
+
   try {
     response->setMessage(NULL);
-    eventResponse(*response);
+    eventResponse(*response, originHost);
   } catch(anna::RuntimeException& ex) {
     ex.trace();
   }
@@ -338,7 +346,9 @@ void Session::finalize() {
 
       try {
         response->setMessage(NULL);
-        eventResponse(*response);
+        eventResponse(*response, nullptr); // upstream, we need to check second argument to know if comes from here.
+                                           // If originHost is NULL, and we are client, we could access through engine: a_engine->getOriginHostName(), and then ohm.getOriginHost(name). BUT CLIENTS DO NOTHING WITH THIS ARGUMENT.
+                                           // If server, we must return there: add protection for second argument.
       } catch(anna::RuntimeException& ex) {
         ex.trace();
       }
@@ -370,7 +380,10 @@ void Session::response_erase(Response* response)
   Response::release(response);
 
   if(a_state == State::Disconnecting)  // only OnDisconnect::WaitPendings arrives here (the other disconnect suddently)
-    if(getOTARequests() == 0) sendDPA();
+    if(getOTARequests() == 0) {
+      // TODO: decode response->getRequest(), which is a comm message, so we get Origin-Host, and then, from OriginHostManager, we get the commEngine to provide:
+      //sendDPA(commEngine, dprDataBlock);
+    }
 
   if(a_state == State::Closing)  // only OnDisconnect::WaitPendings arrives here (the other disconnect suddently)
     if(getOTARequests() == 0) unbind();