From 26ae04c7e1eba19d02823bcc87c0ee9f6ce76186 Mon Sep 17 00:00:00 2001 From: "Eduardo Ramos Testillano (eramedu)" Date: Sun, 9 Jun 2019 05:25:43 +0200 Subject: [PATCH] New rxSimpleTest example API-implemented example for RX simple test --- .../diameter/rxSimpleTest/MyCommunicator.cpp | 82 ++ .../diameter/rxSimpleTest/MyCommunicator.hpp | 33 + .../rxSimpleTest/MyDiameterEngine.hpp | 60 ++ .../rxSimpleTest/MyDiameterEntity.cpp | 221 ++++++ .../rxSimpleTest/MyDiameterEntity.hpp | 37 + .../diameter/rxSimpleTest/MyLocalServer.cpp | 151 ++++ .../diameter/rxSimpleTest/MyLocalServer.hpp | 36 + example/diameter/rxSimpleTest/includes.txt | 1 + example/diameter/rxSimpleTest/libraries.txt | 13 + example/diameter/rxSimpleTest/main.cpp | 43 ++ .../diameter/rxSimpleTest/resources/README | 1 + .../resources/anna_diameter_rxSimpleTest | 1 + .../rxSimpleTest/resources/dictionaryRx.xml | 722 ++++++++++++++++++ .../diameter/rxSimpleTest/rxSimpleTest.cpp | 238 ++++++ .../diameter/rxSimpleTest/rxSimpleTest.hpp | 74 ++ 15 files changed, 1713 insertions(+) create mode 100755 example/diameter/rxSimpleTest/MyCommunicator.cpp create mode 100755 example/diameter/rxSimpleTest/MyCommunicator.hpp create mode 100755 example/diameter/rxSimpleTest/MyDiameterEngine.hpp create mode 100755 example/diameter/rxSimpleTest/MyDiameterEntity.cpp create mode 100755 example/diameter/rxSimpleTest/MyDiameterEntity.hpp create mode 100755 example/diameter/rxSimpleTest/MyLocalServer.cpp create mode 100755 example/diameter/rxSimpleTest/MyLocalServer.hpp create mode 100755 example/diameter/rxSimpleTest/includes.txt create mode 100755 example/diameter/rxSimpleTest/libraries.txt create mode 100755 example/diameter/rxSimpleTest/main.cpp create mode 100755 example/diameter/rxSimpleTest/resources/README create mode 120000 example/diameter/rxSimpleTest/resources/anna_diameter_rxSimpleTest create mode 100755 example/diameter/rxSimpleTest/resources/dictionaryRx.xml create mode 100755 example/diameter/rxSimpleTest/rxSimpleTest.cpp create mode 100755 example/diameter/rxSimpleTest/rxSimpleTest.hpp diff --git a/example/diameter/rxSimpleTest/MyCommunicator.cpp b/example/diameter/rxSimpleTest/MyCommunicator.cpp new file mode 100755 index 0000000..777ac2f --- /dev/null +++ b/example/diameter/rxSimpleTest/MyCommunicator.cpp @@ -0,0 +1,82 @@ +// 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 + +// Process +#include + + +void MyCommunicator::prepareAnswer(anna::diameter::codec::Message *answer, const anna::DataBlock &request) const throw() { + // Sequence values (hop-by-hop and end-to-end), session-id and subscription-id avps, are mirrored to the peer which sent the request. + // If user wants to test a specific answer without changing it, use send operations better than programming. + // Sequence substitution: + answer->setHopByHop(anna::diameter::codec::functions::getHopByHop(request)); + answer->setEndToEnd(anna::diameter::codec::functions::getEndToEnd(request)); + + // Session-Id substitution: + try { + std::string sessionId = anna::diameter::helpers::base::functions::getSessionId(request); + LOGDEBUG( + std::string msg = "Extracted Session-Id: "; + msg += sessionId; + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + answer->getAvp("Session-Id")->getUTF8String()->setValue(sessionId); + } catch(anna::RuntimeException &ex) { + ex.trace(); + } + + // Subscription-Id substitution: is not usual to carry Subscription-Id on answer messages, but if programmed answer have this information, + // then it will be adapted with the received data at request. + if(answer->countAvp("Subscription-Id") > 0) { + std::string msisdn = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(request, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164); + std::string imsi = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(request, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_IMSI); + + if((msisdn != "") || (imsi != "")) { // Both request & answer have SID: replace answer one with the request information: + answer->removeAvp("Subscription-Id", 0 /* remove all */); + } + + // Replacements: + if(msisdn != "") { + anna::diameter::codec::Avp *sid = answer->addAvp("Subscription-Id"); + sid->addAvp("Subscription-Id-Type")->getEnumerated()->setValue(anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164); + sid->addAvp("Subscription-Id-Data")->getUTF8String()->setValue(msisdn); + } + + if(imsi != "") { + anna::diameter::codec::Avp *sid = answer->addAvp("Subscription-Id"); // another + sid->addAvp("Subscription-Id-Type")->getEnumerated()->setValue(anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_IMSI); + sid->addAvp("Subscription-Id-Data")->getUTF8String()->setValue(imsi); + } + } +} + +// HTTP +void MyCommunicator::eventReceiveMessage(anna::comm::ClientSocket& clientSocket, const anna::comm::Message& message) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION)); +} + +void MyCommunicator::eventBreakConnection(Server* server) +throw() { + LOGMETHOD(anna::TraceMethod tm("MyCommunicator", "eventBreakConnection", ANNA_FILE_LOCATION)); + terminate(); + anna::comm::Communicator::eventBreakConnection(server); +} + +void MyCommunicator::terminate() +throw() { + if(hasRequestedStop() == true) + return; + + requestStop(); +} diff --git a/example/diameter/rxSimpleTest/MyCommunicator.hpp b/example/diameter/rxSimpleTest/MyCommunicator.hpp new file mode 100755 index 0000000..0d2efe5 --- /dev/null +++ b/example/diameter/rxSimpleTest/MyCommunicator.hpp @@ -0,0 +1,33 @@ +// 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 example_diameter_launcher_MyCommunicator_hpp +#define example_diameter_launcher_MyCommunicator_hpp + +// Project +#include +#include +#include + + +class MyCommunicator : public anna::comm::Communicator { +public: + MyCommunicator(const anna::comm::Communicator::WorkMode::_v acceptMode = anna::comm::Communicator::WorkMode::Single) : anna::comm::Communicator(acceptMode) + {;} + + void prepareAnswer(anna::diameter::codec::Message *answer, const anna::DataBlock &request) const throw(); + void terminate() throw(); + +private: + using anna::comm::Communicator::eventBreakConnection; + + void eventReceiveMessage(anna::comm::ClientSocket&, const anna::comm::Message&) throw(anna::RuntimeException); + void eventBreakConnection(Server* server) throw(); +}; + +#endif diff --git a/example/diameter/rxSimpleTest/MyDiameterEngine.hpp b/example/diameter/rxSimpleTest/MyDiameterEngine.hpp new file mode 100755 index 0000000..93f26e4 --- /dev/null +++ b/example/diameter/rxSimpleTest/MyDiameterEngine.hpp @@ -0,0 +1,60 @@ +// 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 example_diameter_rxSimpleTest_MyDiameterEngine_hpp +#define example_diameter_rxSimpleTest_MyDiameterEngine_hpp + +// Project +#include + +// Process +#include +#include + +// Standard +#include + + +namespace anna { + namespace diameter { + namespace stack { + class Dictionary; + } + } +} + +class MyDiameterEngine : public anna::diameter::comm::Engine { +public: + + MyDiameterEngine(const char *className, const anna::diameter::stack::Dictionary *baseProtocolDictionary) : Engine(className, baseProtocolDictionary) {;} + +// Default implementation is enough +// void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) throw() {;} // DPA is not replied +// void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) throw() {;} // DWA is not replied + +private: + anna::Recycler a_entitiesRecycler; + + anna::diameter::comm::Entity* allocateEntity() throw() { return a_entitiesRecycler.create(); } + + void releaseEntity(anna::diameter::comm::Entity* entity) throw() { + MyDiameterEntity* aux = static_cast (entity); + a_entitiesRecycler.release(aux); + } + + anna::Recycler a_localServersRecycler; + + anna::diameter::comm::LocalServer* allocateLocalServer() throw() { return a_localServersRecycler.create(); } + + void releaseLocalServer(anna::diameter::comm::LocalServer* localServer) throw() { + MyLocalServer* aux = static_cast (localServer); + a_localServersRecycler.release(aux); + } +}; + +#endif diff --git a/example/diameter/rxSimpleTest/MyDiameterEntity.cpp b/example/diameter/rxSimpleTest/MyDiameterEntity.cpp new file mode 100755 index 0000000..8daec6e --- /dev/null +++ b/example/diameter/rxSimpleTest/MyDiameterEntity.cpp @@ -0,0 +1,221 @@ +// 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 +#include +#include +//#include +#include + +// Process +#include +#include +#include +#include +#include + + +void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::ClientSession* clientSession, anna::diameter::comm::Message *request) throw() { + + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventRequestRetransmission", ANNA_FILE_LOCATION)); + + // Base class: + Entity::eventRequestRetransmission(clientSession, request); // warning trace + + // Performance stats: + RxSimpleTest& my_app = static_cast (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(request->getBody()); + LOGDEBUG + ( + std::string msg = "Request retransmitted: "; + msg += anna::diameter::functions::commandIdAsPairString(cid); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(clientSession->getAddress(), clientSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); +} + + +void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventRequest", ANNA_FILE_LOCATION)); + // Performance stats: + RxSimpleTest& my_app = static_cast (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 + ( + std::string msg = "Request received: "; + msg += anna::diameter::functions::commandIdAsPairString(cid); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(clientSession->getAddress(), clientSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); +} + +void MyDiameterEntity::eventResponse(const anna::diameter::comm::Response &response) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventResponse", ANNA_FILE_LOCATION)); + RxSimpleTest& my_app = static_cast (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(response.getRequest()); + const anna::DataBlock* message = response.getMessage(); + const anna::diameter::comm::ClientSession *clientSession_c = static_cast(response.getSession()); + anna::diameter::comm::ClientSession *clientSession = const_cast(clientSession_c); + bool contextExpired = (result == anna::diameter::comm::Response::ResultCode::Timeout); + bool isUnavailable = (result == anna::diameter::comm::Response::ResultCode::DiameterUnavailable); + bool isOK = (result == anna::diameter::comm::Response::ResultCode::Success); + + // CommandId: + anna::diameter::CommandId request_cid = request->getCommandId(); + LOGDEBUG + ( + std::string msg = "Response received for original diameter request: "; + msg += anna::diameter::functions::commandIdAsPairString(request_cid); + msg += " | Response: "; + msg += response.asString(); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(clientSession->getAddress(), clientSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + + if(isUnavailable) { + //if (isApplicationMessage) + LOGWARNING(anna::Logger::warning("Diameter entity unavailable for Diameter Request", ANNA_FILE_LOCATION)); + } + + if(contextExpired) { + //if (isApplicationMessage) + LOGWARNING(anna::Logger::warning("Context Expired for Diameter Request which was sent to the entity", ANNA_FILE_LOCATION)); + } + + if(isOK) { + LOGDEBUG( + std::string msg = "Received response for diameter message: "; + msg += anna::diameter::functions::commandIdAsPairString(request_cid); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + + if(request_cid == anna::diameter::helpers::base::COMMANDID__Capabilities_Exchange_Request) { + // Build AAR and send it: + anna::diameter::codec::Message aar; + + // From file would be: + //aar.loadXML("./aar.xml"); + aar.setApplicationId(anna::diameter::helpers::APPID__3GPP_Rx); // 16777236 + aar.setId("AA-Request"); + + // Session-Id + Avp *sessionId = aar.addAvp("Session-Id"); + sessionId->getUTF8String()->setValue("ocs3;1332774430;1;1332774430"); + + // Auth-Application-Id + Avp *authApplicationId = aar.addAvp("Auth-Application-Id"); + authApplicationId->getUnsigned32()->setValue(16777236); + + // Origin-Host + Avp *originHost = aar.addAvp("Origin-Host"); + originHost->getDiameterIdentity()->setValue("thehost.theOriginRealm.com"); + + // Origin-Realm + Avp *originRealm = aar.addAvp("Origin-Realm"); + originRealm->getDiameterIdentity()->setValue("theOriginRealm.com"); + + // Destination-Realm + Avp *destinationRealm = aar.addAvp("Destination-Realm"); + destinationRealm->getDiameterIdentity()->setValue("theDestinationRealm.com"); + + // Suppported features: + Avp *supportedFeatures = aar.addAvp("Supported-Features"); + supportedFeatures->addAvp("Vendor-Id")->getUnsigned32()->setValue(10415); + supportedFeatures->addAvp("Feature-List-ID")->getUnsigned32()->setValue(1); + supportedFeatures->addAvp("Feature-List")->getUnsigned32()->setValue(3); + + anna::diameter::comm::Message *msg; + + try { + msg = my_node->createCommMessage(); + msg->setBody(aar.code()); + /* response = NULL =*/clientSession->send(msg); + } catch(anna::RuntimeException &ex) { + ex.trace(); + } + + // release msg + my_node->releaseCommMessage(msg); + } + else if(request_cid == anna::diameter::helpers::nas::COMMANDID__AA_Request) { + // Decode + anna::diameter::codec::Message aaa; + try { aaa.decode(*message); } catch(anna::RuntimeException &ex) { ex.trace(); } + + Avp *resultCode = aaa.getAvp("Result-Code"); + int rc = resultCode->getUnsigned32()->getValue(); + + if (rc != 2001) exit(1); + else exit(0); + } + } +} + +void MyDiameterEntity::eventUnknownResponse(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventUnknownResponse", ANNA_FILE_LOCATION)); + // Performance stats: + RxSimpleTest& my_app = static_cast (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 + ( + std::string msg = "Out-of-context response received from entity: "; + msg += anna::diameter::functions::commandIdAsPairString(cid); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(clientSession->getAddress(), clientSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); +} + +void MyDiameterEntity::eventDPA(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyDiameterEntity", "eventDPA", ANNA_FILE_LOCATION)); + // Performance stats: + RxSimpleTest& my_app = static_cast (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 + ( + std::string msg = "Disconnect-Peer-Answer received from entity: "; + msg += anna::diameter::functions::commandIdAsPairString(cid); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(clientSession->getAddress(), clientSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); +} + diff --git a/example/diameter/rxSimpleTest/MyDiameterEntity.hpp b/example/diameter/rxSimpleTest/MyDiameterEntity.hpp new file mode 100755 index 0000000..f328d3c --- /dev/null +++ b/example/diameter/rxSimpleTest/MyDiameterEntity.hpp @@ -0,0 +1,37 @@ +// 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 example_diameter_rxSimpleTest_MyDiameterEntity_hpp +#define example_diameter_rxSimpleTest_MyDiameterEntity_hpp + +// Project +#include + +namespace anna { + namespace diameter { + namespace codec { + class Engine; + } + } +} + +class MyDiameterEntity : public anna::diameter::comm::Entity { + + void eventRequestRetransmission(const anna::diameter::comm::ClientSession *, anna::diameter::comm::Message*) throw(); + void eventResponse(const anna::diameter::comm::Response&) throw(anna::RuntimeException); + void eventRequest(anna::diameter::comm::ClientSession *, const anna::DataBlock&) throw(anna::RuntimeException); + void eventUnknownResponse(anna::diameter::comm::ClientSession *, const anna::DataBlock&) throw(anna::RuntimeException); + void eventDPA(anna::diameter::comm::ClientSession *, const anna::DataBlock&) throw(anna::RuntimeException); + +public: + + MyDiameterEntity() {;} + virtual ~MyDiameterEntity() {;} +}; + +#endif diff --git a/example/diameter/rxSimpleTest/MyLocalServer.cpp b/example/diameter/rxSimpleTest/MyLocalServer.cpp new file mode 100755 index 0000000..38a538a --- /dev/null +++ b/example/diameter/rxSimpleTest/MyLocalServer.cpp @@ -0,0 +1,151 @@ +// 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 +#include +#include +#include +#include + +// Process +#include +#include +#include +#include + + +void MyLocalServer::eventRequest(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventRequest", ANNA_FILE_LOCATION)); + // Performance stats: + RxSimpleTest& my_app = static_cast (anna::app::functions::getApp()); + anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); + anna::diameter::codec::Engine *codecEngine = my_node->getCodecEngine(); + + // CommandId: + anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message); + LOGDEBUG + ( + std::string msg = "Request received: "; + msg += anna::diameter::functions::commandIdAsPairString(cid); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(serverSession->getAddress(), serverSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + + anna::diameter::codec::Message codecMsg; + anna::diameter::codec::Message codecAnsMsg; + anna::diameter::codec::Message *answer_message = (anna::diameter::codec::Message *)&codecAnsMsg; + my_app.getCommunicator()->prepareAnswer(answer_message, message); + + anna::diameter::comm::Message *msg; + try { + msg = my_node->createCommMessage(); + msg->setBody(answer_message->code()); + /* response = NULL =*/serverSession->send(msg); + } catch(anna::RuntimeException &ex) { + ex.trace(); + } + + // release msg + my_node->releaseCommMessage(msg); +} + +void MyLocalServer::eventResponse(const anna::diameter::comm::Response &response) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventResponse", ANNA_FILE_LOCATION)); + RxSimpleTest& my_app = static_cast (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(response.getRequest()); + const anna::DataBlock* message = response.getMessage(); + const anna::diameter::comm::ServerSession *serverSession = static_cast(response.getSession()); + bool contextExpired = (result == anna::diameter::comm::Response::ResultCode::Timeout); + bool isUnavailable = (result == anna::diameter::comm::Response::ResultCode::DiameterUnavailable); + bool isOK = (result == anna::diameter::comm::Response::ResultCode::Success); + + // CommandId: + anna::diameter::CommandId request_cid = request->getCommandId(); + LOGDEBUG + ( + std::string msg = "Response received for original diameter request: "; + msg += anna::diameter::functions::commandIdAsPairString(request_cid); + msg += " | Response: "; + msg += response.asString(); + msg += " | LocalServer: "; + msg += anna::functions::socketLiteralAsString(serverSession->getAddress(), serverSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + + if(isUnavailable) { + //if (isApplicationMessage) + LOGWARNING(anna::Logger::warning("Diameter client unavailable for Diameter Request", ANNA_FILE_LOCATION)); + } + + if(contextExpired) { + //if (isApplicationMessage) + LOGWARNING(anna::Logger::warning("Context Expired for Diameter Request which was sent to the client", ANNA_FILE_LOCATION)); + } + + if(isOK) { + LOGDEBUG( + std::string msg = "Received response for diameter message: "; + msg += anna::diameter::functions::commandIdAsPairString(request_cid); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + } +} + +void MyLocalServer::eventUnknownResponse(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventUnknownResponse", ANNA_FILE_LOCATION)); + // Performance stats: + RxSimpleTest& my_app = static_cast (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 + ( + std::string msg = "Out-of-context response received from client: "; + msg += anna::diameter::functions::commandIdAsPairString(cid); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(serverSession->getAddress(), serverSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); +} + +void MyLocalServer::eventDPA(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message) +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("rxSimpleTest::MyLocalServer", "eventDPA", ANNA_FILE_LOCATION)); + // Performance stats: + RxSimpleTest& my_app = static_cast (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 + ( + std::string msg = "Disconnect-Peer-Answer response received from client: "; + msg += anna::diameter::functions::commandIdAsPairString(cid); + msg += " | DiameterServer: "; + msg += anna::functions::socketLiteralAsString(serverSession->getAddress(), serverSession->getPort()); + msg += " | EventTime: "; + msg += anna::time::functions::currentTimeAsString(); + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); +} diff --git a/example/diameter/rxSimpleTest/MyLocalServer.hpp b/example/diameter/rxSimpleTest/MyLocalServer.hpp new file mode 100755 index 0000000..c1cfd57 --- /dev/null +++ b/example/diameter/rxSimpleTest/MyLocalServer.hpp @@ -0,0 +1,36 @@ +// 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 example_diameter_rxSimpleTest_MyLocalServer_hpp +#define example_diameter_rxSimpleTest_MyLocalServer_hpp + +// Project +#include + + +namespace anna { + namespace diameter { + namespace codec { + class Engine; + } + } +} + +class MyLocalServer : public anna::diameter::comm::LocalServer { + + void eventResponse(const anna::diameter::comm::Response&) throw(anna::RuntimeException); + void eventRequest(anna::diameter::comm::ServerSession *, const anna::DataBlock&) throw(anna::RuntimeException); + void eventUnknownResponse(anna::diameter::comm::ServerSession *, const anna::DataBlock&) throw(anna::RuntimeException); + void eventDPA(anna::diameter::comm::ServerSession *, const anna::DataBlock&) throw(anna::RuntimeException); + +public: + virtual ~MyLocalServer() {;} +}; + +#endif + diff --git a/example/diameter/rxSimpleTest/includes.txt b/example/diameter/rxSimpleTest/includes.txt new file mode 100755 index 0000000..9730e33 --- /dev/null +++ b/example/diameter/rxSimpleTest/includes.txt @@ -0,0 +1 @@ +dynamic/launcher/default diff --git a/example/diameter/rxSimpleTest/libraries.txt b/example/diameter/rxSimpleTest/libraries.txt new file mode 100755 index 0000000..028b715 --- /dev/null +++ b/example/diameter/rxSimpleTest/libraries.txt @@ -0,0 +1,13 @@ +anna_diameter.comm_static +anna_diameter_static +anna_time_static +anna_statistics_static +anna_timex_static +anna_comm_static +anna_app_static +anna_xml_static +anna_io_static +anna_core_static +pthread +rt +xml2 diff --git a/example/diameter/rxSimpleTest/main.cpp b/example/diameter/rxSimpleTest/main.cpp new file mode 100755 index 0000000..0406d6a --- /dev/null +++ b/example/diameter/rxSimpleTest/main.cpp @@ -0,0 +1,43 @@ +// 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 // + + +// Standard +#include + +// Project +#include +#include + +// Process +#include + +// To calculate the current working directory and get an absolute path for traces: +#include +#include + + +int main(int argc, const char** argv) { + anna::Logger::setLevel(anna::Logger::Debug); + + // Current working directory and absolute trace path file: + std::string trace_file = "./rxSimpleTest.trace"; + + anna::Logger::initialize("rxSimpleTest", new TraceWriter(trace_file.c_str(), 2048000)); + anna::time::functions::initialize(); // before application instantiation (it have a anna::time object) + anna::time::functions::setControlPoint(); // start control point (application lifetime) + RxSimpleTest app; + + try { + app.start(); + } catch(anna::Exception& ex) { + std::cout << ex.asString() << std::endl; + } + + return 0; +} + diff --git a/example/diameter/rxSimpleTest/resources/README b/example/diameter/rxSimpleTest/resources/README new file mode 100755 index 0000000..bc76e80 --- /dev/null +++ b/example/diameter/rxSimpleTest/resources/README @@ -0,0 +1 @@ +Make release to fix executable symlink (if broken) diff --git a/example/diameter/rxSimpleTest/resources/anna_diameter_rxSimpleTest b/example/diameter/rxSimpleTest/resources/anna_diameter_rxSimpleTest new file mode 120000 index 0000000..d869d21 --- /dev/null +++ b/example/diameter/rxSimpleTest/resources/anna_diameter_rxSimpleTest @@ -0,0 +1 @@ +../../../../build/Release/bin/anna_diameter_rxSimpleTest \ No newline at end of file diff --git a/example/diameter/rxSimpleTest/resources/dictionaryRx.xml b/example/diameter/rxSimpleTest/resources/dictionaryRx.xml new file mode 100755 index 0000000..1745fba --- /dev/null +++ b/example/diameter/rxSimpleTest/resources/dictionaryRx.xml @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/diameter/rxSimpleTest/rxSimpleTest.cpp b/example/diameter/rxSimpleTest/rxSimpleTest.cpp new file mode 100755 index 0000000..95a3580 --- /dev/null +++ b/example/diameter/rxSimpleTest/rxSimpleTest.cpp @@ -0,0 +1,238 @@ +// 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 // + + +// Standard +#include // std::istringstream +#include // std::cout +#include // ceil +#include +#include // chdir +//#include TODO: use this from gcc4.9.0: http://stackoverflow.com/questions/8060025/is-this-c11-regex-error-me-or-the-compiler +#include + +// Project +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Process +#include +#include + +RxSimpleTest::RxSimpleTest() : anna::comm::Application("rxSimpleTest", "RxSimpleTest", "1.1"), a_communicator(NULL) { + a_timeEngine = NULL; + a_admlMinResolution = 2 * anna::timex::Engine::minResolution; // 2*10 = 20 ms; 1000/20 = 50 ticks per second; + //a_admlMinResolution = (anna::Millisecond)100; + a_workingNode = NULL; +} + +void RxSimpleTest::startService() throw(anna::RuntimeException) { + + // Stacks + anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate(); + anna::diameter::stack::Dictionary *d; + const anna::diameter::stack::Dictionary *bpd = NULL; // base protocol dictionary + + // Codec engine manager: + anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate(); + anna::diameter::codec::Engine *ce; + + /////////////////////////////////////////// + // APPLICATION MESSAGE OAM MODULE SCOPES // + /////////////////////////////////////////// + // We will register a scope per stack id registered. The counters will be dynamically registered at count method. + anna::diameter::comm::ApplicationMessageOamModule & appMsgOamModule = anna::diameter::comm::ApplicationMessageOamModule::instantiate(); + appMsgOamModule.enableCounters(); // this special module is disabled by default (the only) + int scope_id = 3; + unsigned int id_value = anna::diameter::helpers::APPID__3GPP_Rx; // 16777236 + + try { + d = stackEngine.createDictionary(id_value, "./dictionaryRx.xml"); + LOGDEBUG(anna::Logger::debug(anna::functions::asString("Created dictionary (%p) for stack id %llu", d, id_value), ANNA_FILE_LOCATION)); + + // OAM module for counters: + appMsgOamModule.createStackCounterScope(scope_id, id_value /* application-id */); + + } catch(anna::RuntimeException &ex) { + //_exit(ex.asString()); + throw ex; + } + + bpd = d; // base protocol dictionary in case of monostack + + // Create codec engine and register it in the codec engine manager: + std::string codecEngineName = anna::functions::asString("CodecEngineForStackId_%llu", id_value); + ce = new anna::diameter::codec::Engine(codecEngineName.c_str(), d); + em.registerCodecEngine(id_value, ce); + + // Codec engine configuration: + + // Validation mode: BeforeEncoding, AfterDecoding, Always, Never + ce->setValidationMode(anna::diameter::codec::Engine::ValidationMode::AfterDecoding); + + // Validation depth: Complete, FirstError + ce->setValidationDepth(anna::diameter::codec::Engine::ValidationDepth::FirstError); + + // Fix mode: BeforeEncoding, AfterDecoding, Always, Never + ce->setFixMode(anna::diameter::codec::Engine::FixMode::BeforeEncoding); + + // Ignore validation flags: + ce->ignoreFlagsOnValidation(true); + + // Show loaded stacks: + std::cout << "Stacks currently loaded:" << std::endl; + std::cout << anna::functions::tab(stackEngine.asString(false /* light */)) << std::endl; + + // REALMS: + unsigned int applicationId = id_value; + if (!stackEngine.getDictionary(applicationId)) { + std::string msg = anna::functions::asString("Cannot found a registered stack id with the value of applicationId provided: %u", applicationId); + throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); + } + + // Engine time measures checking & assignment: + anna::Millisecond allowedInactivityTimeMs(90000); + anna::Millisecond tcpConnectDelayMs(200); + anna::Millisecond answersTimeoutMs(10000); + anna::Millisecond ceaTimeoutMs(10000); + anna::Millisecond watchdogPeriodMs(30000); + + ///////////////////////////////////////////////////////////////////////////////////////////// + // Diameter communication engine: + std::string originHostRealm = "nodeHostRealm"; + std::string originHostName = "afNodeHostname."; originHostName += originHostRealm; originHostName += ".com"; + std::string commEngineName = originHostName + "_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. + commEngine->setMaxConnectionDelay(tcpConnectDelayMs); + commEngine->setWatchdogPeriod(watchdogPeriodMs); + commEngine->setOriginHostName(originHostName); + commEngine->setOriginRealmName(originHostRealm); + + // Origin host node: + a_workingNode = new anna::diameter::comm::OriginHost((anna::diameter::comm::Engine*)commEngine, applicationId); + // a_workingNode->setRequestRetransmissions(0); + + // Diameter entity: + commEngine->setNumberOfClientSessionsPerServer(1); + //commEngine->setClientCERandDWR("./cer.xml", "./dwr.xml"); + commEngine->setClientCERandDWR(); + + // Register one entity for this engine: + a_workingNode->createEntity("localhost:3868", ceaTimeoutMs, answersTimeoutMs); + a_workingNode->getEntity()->bind(); + + // Diameter server: + //a_workingNode->createDiameterServer("localhost:3869", 1, allowedInactivityTimeMs, answersTimeoutMs, "./cea.xml"); + + commEngine->lazyInitialize(); + + // Node and Codec Engine registration /////////////////////////////////////////////////////// + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + ohm.registerOriginHost(originHostName, a_workingNode); +} + +anna::diameter::comm::OriginHost *RxSimpleTest::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; +} + +MyDiameterEntity *RxSimpleTest::getEntity() const throw(anna::RuntimeException) { + MyDiameterEntity *result = (MyDiameterEntity *)(a_workingNode->getEntity()); + if (!result) + throw anna::RuntimeException("No entity created", ANNA_FILE_LOCATION); + return result; +} + +MyLocalServer *RxSimpleTest::getServer() const throw(anna::RuntimeException) { + MyLocalServer *result = (MyLocalServer *)(a_workingNode->getDiameterServer()); + if (!result) + throw anna::RuntimeException("No local server created", ANNA_FILE_LOCATION); + return result; +} + +void RxSimpleTest::initialize() +throw(anna::RuntimeException) { + anna::comm::Application::initialize(); + CommandLine& cl(anna::CommandLine::instantiate()); + anna::comm::Communicator::WorkMode::_v workMode(anna::comm::Communicator::WorkMode::Single); + a_communicator = new MyCommunicator(workMode); + a_timeEngine = new anna::timex::Engine((anna::Millisecond)600000, a_admlMinResolution); + + startService(); +} + +void RxSimpleTest::run() +throw(anna::RuntimeException) { + LOGMETHOD(anna::TraceMethod tm("RxSimpleTest", "run", ANNA_FILE_LOCATION)); + anna::diameter::stack::Engine::instantiate(); + + // Start time: + a_start_time.setNow(); + + // Initial working directory: + char cwd[1024]; + if (getcwd(cwd, sizeof(cwd)) == NULL) + throw anna::RuntimeException("Cannot retrieve initial working directory !!", ANNA_FILE_LOCATION); + a_initialWorkingDirectory = cwd; + + // Statistics: + anna::statistics::Engine::instantiate().enable(); + + // Start client connections ////////////////////////////////////////////////////////////////////////////////// + MyDiameterEntity *entity; + 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(); + } + + // Go into communicator poll + // Reconnection period (tcp reconnect retry time): + anna::Millisecond reconnectionPeriod = (anna::Millisecond)10000; + + a_communicator->setRecoveryTime(reconnectionPeriod); + a_communicator->accept(); +} + +anna::xml::Node* RxSimpleTest::asXML(anna::xml::Node* parent) const +throw() { + anna::xml::Node* result = parent->createChild("rxSimpleTest"); + anna::comm::Application::asXML(result); + // Timming: + result->createAttribute("StartTime", a_start_time.asString()); + result->createAttribute("InitialWorkingDirectory", a_initialWorkingDirectory); + result->createAttribute("SecondsLifeTime", anna::time::functions::lapsedMilliseconds() / 1000); + // Diameter: + 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); + } + + // Registered codec engines: + anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate(); + em.asXML(result); + + return result; +} + diff --git a/example/diameter/rxSimpleTest/rxSimpleTest.hpp b/example/diameter/rxSimpleTest/rxSimpleTest.hpp new file mode 100755 index 0000000..7e90033 --- /dev/null +++ b/example/diameter/rxSimpleTest/rxSimpleTest.hpp @@ -0,0 +1,74 @@ +// 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 example_diameter_rxSimpleTest_hpp +#define example_diameter_rxSimpleTest_hpp + +// Standard +#include +#include +#include + +// Project +#include +#include +#include +#include + +// Process +#include + + +namespace anna { + namespace timex { + class Engine; + } + namespace diameter { + namespace codec { + class Engine; + } + namespace comm { + class OriginHost; + } + } +} + +class MyDiameterEntity; +class MyLocalServer; +class MyDiameterEngine; + +class RxSimpleTest : public anna::comm::Application { + + // Start time: + anna::time::Date a_start_time; + + // Core engines: + MyCommunicator *a_communicator; + anna::timex::Engine* a_timeEngine; + anna::Millisecond a_admlMinResolution; + anna::diameter::comm::OriginHost *a_workingNode; + std::string a_initialWorkingDirectory; + + + void initialize() throw(anna::RuntimeException); // HTTP + void run() throw(anna::RuntimeException); + +public: + RxSimpleTest(); + + MyDiameterEntity *getEntity() const throw(anna::RuntimeException); + MyLocalServer *getServer() const throw(anna::RuntimeException); + MyDiameterEngine *getEngine() const throw(anna::RuntimeException); + MyCommunicator *getCommunicator() throw() { return a_communicator; } + void startService() throw(anna::RuntimeException); + anna::diameter::comm::OriginHost *getOriginHost(const std::string &name) const throw(anna::RuntimeException); + + anna::xml::Node* asXML(anna::xml::Node* parent) const throw(); +}; + +#endif -- 2.20.1