Multistack launcher
[anna.git] / example / diameter / launcher / MyDiameterEntity.cpp
index d16974b..6a27607 100644 (file)
@@ -11,6 +11,8 @@
 #include <anna/diameter/functions.hpp>
 #include <anna/time/functions.hpp>
 #include <anna/diameter.comm/Response.hpp>
+#include <anna/diameter/helpers/base/functions.hpp>
+#include <anna/diameter/helpers/dcca/functions.hpp>
 
 // Process
 #include "MyDiameterEntity.hpp"
@@ -45,6 +47,50 @@ void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::Cl
 }
 
 
+int MyDiameterEntity::readSocketId(const anna::diameter::comm::Message* message, int maxClientSessions) const throw() {
+  CommandLine& cl(anna::CommandLine::instantiate());
+  std::string sessionBasedModelsType = (cl.exists("sessionBasedModelsClientSocketSelection") ? cl.getValue("sessionBasedModelsClientSocketSelection") : "SessionIdLowPart");
+
+  if(sessionBasedModelsType == "RoundRobin") return -1;  // IEC also would return -1
+
+  try {
+    // Service-Context-Id:
+    anna::diameter::helpers::dcca::ChargingContext::_v chargingContext;
+    std::string scid = anna::diameter::helpers::dcca::functions::getServiceContextId(message->getBody(), chargingContext);
+
+    switch(chargingContext) {
+    case anna::diameter::helpers::dcca::ChargingContext::Data:
+    case anna::diameter::helpers::dcca::ChargingContext::Voice:
+    case anna::diameter::helpers::dcca::ChargingContext::Content: {
+      // Session-Id: '<DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>="">]'
+      std::string sid = anna::diameter::helpers::base::functions::getSessionId(message->getBody());
+      std::string diameterIdentity, optional;
+      anna::U32 high, low;
+      anna::diameter::helpers::base::functions::decodeSessionId(sid, diameterIdentity, high, low /* context-teid */, optional);
+
+      if(sessionBasedModelsType == "SessionIdLowPart") return (low % maxClientSessions);
+
+      if(sessionBasedModelsType == "SessionIdHighPart") return (high % maxClientSessions);
+
+      if(sessionBasedModelsType == "SessionIdOptionalPart") return (atoi(optional.c_str()) % maxClientSessions);
+    }
+    case anna::diameter::helpers::dcca::ChargingContext::SMS:
+    case anna::diameter::helpers::dcca::ChargingContext::MMS:
+    case anna::diameter::helpers::dcca::ChargingContext::Unknown:
+    default:
+       return -1; // IEC model and Unknown traffic types
+    }
+  } catch(anna::RuntimeException &ex) {
+    LOGDEBUG(
+      std::string msg = ex.getText();
+      msg += " | Round-robin between sessions will be used to send";
+      anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+    );
+  }
+
+  return -1;
+}
+
 void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message)
 throw(anna::RuntimeException) {
   LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventRequest", ANNA_FILE_LOCATION));