Fix local server for multiple applications
[anna.git] / source / diameter.comm / Session.cpp
index 736635c..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,14 +55,12 @@ 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();
 }
 
-void Session::initialize() throw() {
+void Session::initialize() {
   a_state = State::Closed;
   a_socketId = 0;
   a_lastIncomingActivityTime = (anna::Millisecond)0;
@@ -74,7 +74,7 @@ void Session::initialize() throw() {
 //Session::~Session() {;}
 
 
-void Session::initializeSequences() throw() {
+void Session::initializeSequences() {
   // Sequences
   //
   //   Hop-by-Hop Identifier
@@ -114,11 +114,11 @@ void Session::initializeSequences() throw() {
   a_nextEndToEnd = ((::time(NULL) & 0xFFF) << 20) + (rand() & 0xFFFFF);
 }
 
-void Session::sendDPA()
-throw(anna::RuntimeException) {
+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));
@@ -138,7 +138,7 @@ throw(anna::RuntimeException) {
   activateActionTimer(anna::diameter::comm::Timer::Type::SessionUnbind);
 }
 
-void Session::setState(State::_v state) throw() {
+void Session::setState(State::_v state) {
   LOGDEBUG(
 
   if(state != a_state) {
@@ -153,7 +153,7 @@ void Session::setState(State::_v state) throw() {
 }
 
 
-void Session::activateActionTimer(const anna::diameter::comm::Timer::Type::_v type) throw() {
+void Session::activateActionTimer(const anna::diameter::comm::Timer::Type::_v type) {
   LOGMETHOD(anna::TraceMethod traceMethod("anna::diameter::comm::Session", "activateActionTimer", ANNA_FILE_LOCATION));
   cancelTimer(); // Session timer
 
@@ -169,7 +169,7 @@ void Session::activateActionTimer(const anna::diameter::comm::Timer::Type::_v ty
 }
 
 
-void Session::cancelActionTimer() throw() {
+void Session::cancelActionTimer() {
   LOGMETHOD(anna::TraceMethod traceMethod("anna::diameter::comm::Session", "cancelActionTimer", ANNA_FILE_LOCATION));
 
   if(a_actionTimer) {
@@ -188,7 +188,7 @@ void Session::cancelActionTimer() throw() {
 }
 
 
-void Session::activateTimer() throw() {
+void Session::activateTimer() {
   LOGMETHOD(anna::TraceMethod traceMethod("anna::diameter::comm::Session", "activateTimer", ANNA_FILE_LOCATION));
   cancelActionTimer();
 
@@ -209,7 +209,7 @@ void Session::activateTimer() throw() {
 }
 
 
-void Session::cancelTimer() throw() {
+void Session::cancelTimer() {
   LOGMETHOD(anna::TraceMethod traceMethod("anna::diameter::comm::Session", "cancelTimer", ANNA_FILE_LOCATION));
 
   if(isActive()) {
@@ -235,7 +235,7 @@ void Session::cancelTimer() throw() {
 // Se invoca desde diameter::comm::Timer
 //-------------------------------------------------------------------------
 void Session::expireResponse(diameter::comm::Response* response)
-throw() {
+{
   LOGMETHOD(anna::TraceMethod traceMethod("anna::diameter::comm::Session", "expireResponse", ANNA_FILE_LOCATION));
   bool doUnbind = false;
   bool doRetransmission = false;
@@ -252,9 +252,17 @@ throw() {
     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();
   }
@@ -290,7 +298,7 @@ throw() {
   if(doUnbind) unbind();
 }
 
-void Session::finalize() throw() {
+void Session::finalize() {
   LOGMETHOD(anna::TraceMethod traceMethod("anna::diameter::comm::Session", "finalize", ANNA_FILE_LOCATION));
   setState(State::Closed);
   cancelTimer(); // Session timer
@@ -338,7 +346,9 @@ void Session::finalize() throw() {
 
       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();
       }
@@ -353,7 +363,7 @@ void Session::finalize() throw() {
 }
 
 void Session::response_add(Response* response)
-throw() {
+{
   a_responses.add(response);
   response->setSession(this);
 
@@ -365,19 +375,22 @@ throw() {
 }
 
 void Session::response_erase(Response* response)
-throw() {
+{
   a_responses.erase(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();
 }
 
 Response* Session::response_find(const HopByHop hopByHop)
-throw(anna::RuntimeException) {
+noexcept(false) {
   diameter::comm::Response* result = a_responses.find(hopByHop);
 //   if (result == NULL) {
 //      string msg(asString());
@@ -389,7 +402,7 @@ throw(anna::RuntimeException) {
 }
 
 std::string Session::asString() const
-throw() {
+{
   string result(a_className);
   result += " { ";
   result += anna::timex::Timer::asString();
@@ -420,7 +433,7 @@ throw() {
 }
 
 anna::xml::Node* Session::asXML(anna::xml::Node* parent) const
-throw() {
+{
   //parent = anna::timex::Timer::asXML(parent);
   anna::xml::Node* result = parent->createChild("diameter.comm.Session");
   result->createAttribute("SocketId", anna::functions::asString(a_socketId));
@@ -450,13 +463,13 @@ throw() {
 }
 
 const char* Session::asText(const State::_v state)
-throw() {
+{
   static const char* text [] = { "Closed", "WaitingBind", "Bound", "Failover", "Suspect", "WaitingDPA", "Disconnecting", "Closing" };
   return text [state];
 }
 
 const char* Session::asText(const OnDisconnect::_v onDisconnect)
-throw() {
+{
   static const char* text [] = { "IgnorePendings", "WaitPendings" };
   return text [onDisconnect];
 }
@@ -464,7 +477,7 @@ throw() {
 
 
 HopByHop Session::SortById::value(const Response* response)
-throw() {
+{
   return response->getHopByHop();
 }
 
@@ -472,7 +485,7 @@ throw() {
 //------------------------------------------------------------------------------
 //---------------------------------------- Session::updateIncomingActivityTime()
 //------------------------------------------------------------------------------
-void Session::updateIncomingActivityTime() throw() {
+void Session::updateIncomingActivityTime() {
   a_lastIncomingActivityTime = anna::functions::millisecond();
   LOGDEBUG
   (
@@ -486,7 +499,7 @@ void Session::updateIncomingActivityTime() throw() {
 //------------------------------------------------------------------------------
 //---------------------------------------- Session::updateOutgoingActivityTime()
 //------------------------------------------------------------------------------
-void Session::updateOutgoingActivityTime(void) throw() {
+void Session::updateOutgoingActivityTime(void) {
   a_lastOutgoingActivityTime = anna::functions::millisecond();
   LOGDEBUG
   (