From a4a2ff4e20ddc4c6de7f2d3efd3acfb16c0d91c1 Mon Sep 17 00:00:00 2001 From: Eduardo Ramos Testillano Date: Mon, 26 Jun 2017 12:21:17 +0200 Subject: [PATCH] OriginHostManager to abstract Procedure (dyamic) from knowing the OriginHost node --- dynamic/launcher/default/Procedure.cpp | 2 +- dynamic/launcher/default/Procedure.hpp | 10 +- dynamic/launcher/gx/00001/Procedure.cpp | 11 +- dynamic/launcher/gx/00001/Procedure.hpp | 10 +- example/diameter/launcher/Launcher.cpp | 54 +++++---- example/diameter/launcher/Launcher.hpp | 5 +- .../anna/diameter.comm/OriginHostManager.hpp | 105 ++++++++++++++++++ source/diameter.comm/OriginHostManager.cpp | 46 ++++++++ 8 files changed, 198 insertions(+), 45 deletions(-) create mode 100644 include/anna/diameter.comm/OriginHostManager.hpp create mode 100644 source/diameter.comm/OriginHostManager.cpp diff --git a/dynamic/launcher/default/Procedure.cpp b/dynamic/launcher/default/Procedure.cpp index 62b0ce2..598912e 100644 --- a/dynamic/launcher/default/Procedure.cpp +++ b/dynamic/launcher/default/Procedure.cpp @@ -16,7 +16,7 @@ // Local #include "Procedure.hpp" -void Procedure::execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException) { +void Procedure::execute(const std::string &args, std::string &response) throw(anna::RuntimeException) { response = "Empty default implementation. Make dynamic library and reimplement this method."; if (args != "" ) { response += " Provided argument(s) ignored: "; diff --git a/dynamic/launcher/default/Procedure.hpp b/dynamic/launcher/default/Procedure.hpp index c96ab07..b8096bc 100644 --- a/dynamic/launcher/default/Procedure.hpp +++ b/dynamic/launcher/default/Procedure.hpp @@ -13,21 +13,13 @@ #include -namespace anna { - namespace diameter { - namespace comm { - class OriginHost; - } - } -} - class Procedure { anna::comm::Application *a_app; public: Procedure(anna::comm::Application *app) : a_app(app) {;} - virtual void execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException); + virtual void execute(const std::string &args, std::string &response) throw(anna::RuntimeException); }; #endif diff --git a/dynamic/launcher/gx/00001/Procedure.cpp b/dynamic/launcher/gx/00001/Procedure.cpp index 086a074..20af42c 100644 --- a/dynamic/launcher/gx/00001/Procedure.cpp +++ b/dynamic/launcher/gx/00001/Procedure.cpp @@ -18,6 +18,7 @@ #include #include #include +#include // Local #include "Procedure.hpp" @@ -47,7 +48,7 @@ namespace { } } -void Procedure::execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException) { +void Procedure::execute(const std::string &args, std::string &response) throw(anna::RuntimeException) { response = "Dynamic procedure failed to process '"; response += args; response += "': "; @@ -93,6 +94,7 @@ void Procedure::execute(const std::string &args, std::string &response, anna::di anna::diameter::codec::Message ccri, ccrt; anna::diameter::codec::Avp *ccri_sessionId, *ccrt_sessionId, *ccri_framedIPAddress, *ccrt_framedIPAddress, *ccri_msisdn, *ccri_imsi; anna::diameter::codec::Avp *si1, *si2, *sidata1, *sidata2, *sitype1; + anna::diameter::codec::Avp *ccri_originHost; ///////// CCR-Initial: ccri.loadXML(ccr_i); @@ -100,6 +102,7 @@ void Procedure::execute(const std::string &args, std::string &response, anna::di // Session-Id & Framed-Ip-Address AVPs ccri_sessionId = ccri.getAvp("Session-Id"); ccri_framedIPAddress = ccri.getAvp("Framed-IP-Address"); + ccri_originHost = ccri.getAvp("Origin-Host"); // Subscription-Id AVPs if (ccri.countAvp("Subscription-Id") != 2) { @@ -206,6 +209,12 @@ void Procedure::execute(const std::string &args, std::string &response, anna::di char cad_framed[16]; anna::testing::TestCase *tc; + // Origin host manager: + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + // Assume the oh name from CCR-I (same as CCR-T): + std::string originHostName = ccri_originHost->getDiameterIdentity()->getValue(); + anna::diameter::comm::OriginHost *originHost = ohm.getOriginHost(originHostName); + for (ll_index = 0; ll_index < ll_seq_size; ll_index++) { // Calculate next values //////////////////////////////////////////////////////////// diff --git a/dynamic/launcher/gx/00001/Procedure.hpp b/dynamic/launcher/gx/00001/Procedure.hpp index b46ef74..d6afe5b 100644 --- a/dynamic/launcher/gx/00001/Procedure.hpp +++ b/dynamic/launcher/gx/00001/Procedure.hpp @@ -13,21 +13,13 @@ #include -namespace anna { - namespace diameter { - namespace comm { - class OriginHost; - } - } -} - class Procedure { anna::comm::Application *a_app; public: Procedure(anna::comm::Application *app) : a_app(app) {;} - virtual void execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException); + virtual void execute(const std::string &args, std::string &response) throw(anna::RuntimeException); }; #endif diff --git a/example/diameter/launcher/Launcher.cpp b/example/diameter/launcher/Launcher.cpp index 871fcb3..cd20991 100644 --- a/example/diameter/launcher/Launcher.cpp +++ b/example/diameter/launcher/Launcher.cpp @@ -28,12 +28,13 @@ #include #include #include +#include +#include #include // Process #include #include -#include #include #include @@ -141,7 +142,6 @@ Launcher::Launcher() : anna::comm::Application("launcher", "DiameterLauncher", " //a_admlMinResolution = (anna::Millisecond)100; a_counterRecorderClock = NULL; - // a_originHosts.clear(); a_workingNode = NULL; a_httpServerSocket = NULL; @@ -302,8 +302,9 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp burstLog = (*it)->getAttribute("burstLog", false /* no exception */); // (yes | no) // Basic checkings: - origin_hosts_it nodeIt = a_originHosts.find(originHost->getValue()); - if (nodeIt != a_originHosts.end()) { + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + anna::diameter::comm::OriginHost *oh = ohm.getOriginHost(originHost->getValue()); + if (oh) { std::string msg = "Already registered such Origin-Host: "; msg += originHost->getValue(); throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); } @@ -416,7 +417,7 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp if (eventOperation) commEngine->lazyInitialize(); // Node and Codec Engine registration /////////////////////////////////////////////////////// - a_originHosts[originHost->getValue()] = a_workingNode; + ohm.registerOriginHost(originHost->getValue(), a_workingNode); ///////////////////////////////////////////////////////////////////////////////////////////// } } @@ -515,25 +516,25 @@ anna::Millisecond Launcher::checkTimeMeasure(const std::string ¶meter, const bool Launcher::setWorkingNode(const std::string &name) throw() { bool result = false; - origin_hosts_it nodeIt = a_originHosts.find(name); - if (nodeIt == a_originHosts.end()) { - LOGWARNING( - std::string msg = "Unknown node with name '"; msg += name; msg += "'. Ignoring ..."; - anna::Logger::warning(msg, ANNA_FILE_LOCATION); - ); - } - else { - a_workingNode = const_cast(nodeIt->second); + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + anna::diameter::comm::OriginHost *oh = ohm.getOriginHost(name); + + if (oh) { + a_workingNode = const_cast(oh); result = true; } return result; } -anna::diameter::comm::OriginHost *Launcher::getOriginHost(const std::string &oh) const throw(anna::RuntimeException) { - origin_hosts_it it = a_originHosts.find(oh); - if (it != a_originHosts.end()) return it->second; - throw anna::RuntimeException(anna::functions::asString("There is no origin host registered as '%s' (set Origin-Host avp correctly or force a specific host with 'node' operation)", oh.c_str()), ANNA_FILE_LOCATION); +anna::diameter::comm::OriginHost *Launcher::getOriginHost(const std::string &name) const throw(anna::RuntimeException) { + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + anna::diameter::comm::OriginHost *result = ohm.getOriginHost(name); + + if (!result) + throw anna::RuntimeException(anna::functions::asString("There is no origin host registered as '%s' (set Origin-Host avp correctly or force a specific host with 'node' operation)", name.c_str()), ANNA_FILE_LOCATION); + + return result; } anna::diameter::comm::OriginHost *Launcher::getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException) { @@ -541,6 +542,12 @@ anna::diameter::comm::OriginHost *Launcher::getOriginHost(const anna::diameter:: return (getOriginHost(originHost)); } +bool Launcher::uniqueOriginHost() const throw() { + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + return (ohm.size() == 1); +} + + void Launcher::updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException) { if (!a_operatedHost) // priority for working node by mean 'node' operation a_operatedHost = getOriginHost(message); @@ -779,7 +786,8 @@ throw(anna::RuntimeException) { // Start client connections ////////////////////////////////////////////////////////////////////////////////// MyDiameterEntity *entity; - for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) { + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) { entity = (MyDiameterEntity *)(it->second->getEntity()); if (entity) entity->bind(); } @@ -839,7 +847,8 @@ void Launcher::resetStatistics() throw() { a_workingNode->getCommEngine()->resetStatistics(); } else { - for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) { + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) { it->second->getCommEngine()->resetStatistics(); } } @@ -1593,7 +1602,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons if (args == "" && op_size != 7) throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION); try { - p.execute(args, response_content, getWorkingNode()); + p.execute(args, response_content); } catch(anna::RuntimeException &ex) { ex.trace(); @@ -2455,7 +2464,8 @@ throw() { result->createAttribute("InitialWorkingDirectory", a_initialWorkingDirectory); result->createAttribute("SecondsLifeTime", anna::time::functions::lapsedMilliseconds() / 1000); // Diameter: - for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) { + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) { it->second->asXML(result); } diff --git a/example/diameter/launcher/Launcher.hpp b/example/diameter/launcher/Launcher.hpp index 7c3596c..1070e40 100644 --- a/example/diameter/launcher/Launcher.hpp +++ b/example/diameter/launcher/Launcher.hpp @@ -65,7 +65,6 @@ class Launcher : public anna::comm::Application { MyCounterRecorderClock *a_counterRecorderClock; // Nodes deployment: - origin_hosts_t a_originHosts; anna::diameter::comm::OriginHost *a_workingNode; anna::diameter::comm::OriginHost *a_operatedHost; // auxiliary for eventOperation @@ -90,9 +89,9 @@ public: void startServices() throw(anna::RuntimeException); bool setWorkingNode(const std::string &name) throw(); - anna::diameter::comm::OriginHost *getOriginHost(const std::string &oh) const throw(anna::RuntimeException); + anna::diameter::comm::OriginHost *getOriginHost(const std::string &name) const throw(anna::RuntimeException); anna::diameter::comm::OriginHost *getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException); - bool uniqueOriginHost() const throw() { return (a_originHosts.size() == 1); } + bool uniqueOriginHost() const throw(); // Operated host for communication resources smart assignment //////////////////////////////////////////////////////////// void updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException); diff --git a/include/anna/diameter.comm/OriginHostManager.hpp b/include/anna/diameter.comm/OriginHostManager.hpp new file mode 100644 index 0000000..af5793b --- /dev/null +++ b/include/anna/diameter.comm/OriginHostManager.hpp @@ -0,0 +1,105 @@ +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // + + +#ifndef anna_diameter_comm_OriginHostManager_hpp +#define anna_diameter_comm_OriginHostManager_hpp + + +// Project +#include +#include + +// Standard +#include +#include + + +namespace anna { + +namespace xml { + class Node; + +} +namespace diameter { + +namespace comm { + +class OriginHost; + +typedef std::map origin_hosts_t; +typedef std::map::const_iterator origin_hosts_it; +typedef std::map::iterator origin_hosts_nc_it; + + +/** + * Helper class to centralize application Origin Host Nodes + * + */ +class OriginHostManager : public anna::Singleton { + +private: + + origin_hosts_t a_origin_hosts; + + // private constructor + OriginHostManager() {}; + +public: + + virtual ~OriginHostManager() {;} + + /** + * First element iterator + */ + origin_hosts_it begin() const throw() { return a_origin_hosts.begin(); } + + /** + * Last element iterator + */ + origin_hosts_it end() const throw() { return a_origin_hosts.end(); } + + /** + * Number of registered origin hosts + */ + int size() const throw() { return a_origin_hosts.size(); } + + /** + * Registers a new origin host node (externally allocated) associated to a name. + * If the name exists, the new origin host pointer will replace the existing one. + * + * @param name Origin Host Name + * @param originHost Associated Origin Host node + */ + void registerOriginHost(const std::string &name, OriginHost* originHost) throw(); + + /** + * Get the associated origin host node for a provided name. + * + * @param name Origin Host Name + * + * @return Found origin host node, NULL if not found + */ + OriginHost *getOriginHost(const std::string &name) const throw(); + + /** + Class XML representation. + \param parent XML node over which we will put instance information. + \return XML with class content. + */ + virtual anna::xml::Node* asXML(anna::xml::Node* parent) const throw(); + + + friend class anna::Singleton ; +}; + +} +} +} + +#endif + diff --git a/source/diameter.comm/OriginHostManager.cpp b/source/diameter.comm/OriginHostManager.cpp new file mode 100644 index 0000000..067444d --- /dev/null +++ b/source/diameter.comm/OriginHostManager.cpp @@ -0,0 +1,46 @@ +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // + + +// Project +#include +#include +#include +#include + + +using namespace anna::diameter::comm; + +OriginHost *OriginHostManager::getOriginHost(const std::string &name) const throw() { + origin_hosts_it it = a_origin_hosts.find(name); + if (it != a_origin_hosts.end()) + return it->second; + + LOGWARNING( + std::string msg = "Unknown origin host node with name '"; msg += name; msg += "'"; + anna::Logger::warning(msg, ANNA_FILE_LOCATION); + ); + + return NULL; +} + +void OriginHostManager::registerOriginHost(const std::string &name, OriginHost* originHost) throw() { + if (!originHost) return; // nothing done + a_origin_hosts[name] = originHost; +} + +anna::xml::Node* OriginHostManager::asXML(anna::xml::Node* parent) const +throw() { + anna::xml::Node* result = parent->createChild("OriginHostManager"); + origin_hosts_it it_min(a_origin_hosts.begin()); + origin_hosts_it it_max(a_origin_hosts.end()); + for (origin_hosts_it it = it_min; it != it_max; it++) + it->second->asXML(result); + + return result; +} + -- 2.20.1