New rxSimpleTest example
authorEduardo Ramos Testillano (eramedu) <eduardo.ramos.testillano@ericsson.com>
Sun, 9 Jun 2019 03:25:43 +0000 (05:25 +0200)
committerEduardo Ramos Testillano (eramedu) <eduardo.ramos.testillano@ericsson.com>
Sun, 9 Jun 2019 03:25:43 +0000 (05:25 +0200)
API-implemented example for RX simple test

15 files changed:
example/diameter/rxSimpleTest/MyCommunicator.cpp [new file with mode: 0755]
example/diameter/rxSimpleTest/MyCommunicator.hpp [new file with mode: 0755]
example/diameter/rxSimpleTest/MyDiameterEngine.hpp [new file with mode: 0755]
example/diameter/rxSimpleTest/MyDiameterEntity.cpp [new file with mode: 0755]
example/diameter/rxSimpleTest/MyDiameterEntity.hpp [new file with mode: 0755]
example/diameter/rxSimpleTest/MyLocalServer.cpp [new file with mode: 0755]
example/diameter/rxSimpleTest/MyLocalServer.hpp [new file with mode: 0755]
example/diameter/rxSimpleTest/includes.txt [new file with mode: 0755]
example/diameter/rxSimpleTest/libraries.txt [new file with mode: 0755]
example/diameter/rxSimpleTest/main.cpp [new file with mode: 0755]
example/diameter/rxSimpleTest/resources/README [new file with mode: 0755]
example/diameter/rxSimpleTest/resources/anna_diameter_rxSimpleTest [new symlink]
example/diameter/rxSimpleTest/resources/dictionaryRx.xml [new file with mode: 0755]
example/diameter/rxSimpleTest/rxSimpleTest.cpp [new file with mode: 0755]
example/diameter/rxSimpleTest/rxSimpleTest.hpp [new file with mode: 0755]

diff --git a/example/diameter/rxSimpleTest/MyCommunicator.cpp b/example/diameter/rxSimpleTest/MyCommunicator.cpp
new file mode 100755 (executable)
index 0000000..777ac2f
--- /dev/null
@@ -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 <anna/diameter/helpers/base/functions.hpp>
+#include <anna/diameter/helpers/dcca/functions.hpp>
+#include <anna/http/Transport.hpp>
+
+// Process
+#include <MyCommunicator.hpp>
+
+
+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 (executable)
index 0000000..0d2efe5
--- /dev/null
@@ -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 <anna/core/core.hpp>
+#include <anna/comm/comm.hpp>
+#include <anna/diameter/codec/Message.hpp>
+
+
+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 (executable)
index 0000000..93f26e4
--- /dev/null
@@ -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 <anna/diameter.comm/Engine.hpp>
+
+// Process
+#include <MyDiameterEntity.hpp>
+#include <MyLocalServer.hpp>
+
+// Standard
+#include <string>
+
+
+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<MyDiameterEntity> a_entitiesRecycler;
+
+  anna::diameter::comm::Entity* allocateEntity() throw() { return a_entitiesRecycler.create(); }
+
+  void releaseEntity(anna::diameter::comm::Entity* entity) throw() {
+    MyDiameterEntity* aux = static_cast <MyDiameterEntity*>(entity);
+    a_entitiesRecycler.release(aux);
+  }
+
+  anna::Recycler<MyLocalServer> a_localServersRecycler;
+
+  anna::diameter::comm::LocalServer* allocateLocalServer() throw() { return a_localServersRecycler.create(); }
+
+  void releaseLocalServer(anna::diameter::comm::LocalServer* localServer) throw() {
+    MyLocalServer* aux = static_cast <MyLocalServer*>(localServer);
+    a_localServersRecycler.release(aux);
+  }
+};
+
+#endif
diff --git a/example/diameter/rxSimpleTest/MyDiameterEntity.cpp b/example/diameter/rxSimpleTest/MyDiameterEntity.cpp
new file mode 100755 (executable)
index 0000000..8daec6e
--- /dev/null
@@ -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 <anna/core/core.hpp>
+#include <anna/diameter/functions.hpp>
+#include <anna/time/functions.hpp>
+#include <anna/diameter.comm/Response.hpp>
+#include <anna/diameter.comm/ClientSession.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
+//#include <anna/diameter/helpers/base/functions.hpp>
+#include <anna/diameter/helpers/nas/defines.hpp>
+
+// Process
+#include <MyDiameterEngine.hpp>
+#include <MyDiameterEntity.hpp>
+#include <MyLocalServer.hpp>
+#include <rxSimpleTest.hpp>
+#include <anna/testing/TestManager.hpp>
+
+
+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 <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(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 <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
+  (
+    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 <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());
+  const anna::DataBlock* message = response.getMessage();
+  const anna::diameter::comm::ClientSession *clientSession_c = static_cast<const anna::diameter::comm::ClientSession *>(response.getSession());
+  anna::diameter::comm::ClientSession *clientSession = const_cast<anna::diameter::comm::ClientSession *>(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 <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
+  (
+    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 <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
+  (
+    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 (executable)
index 0000000..f328d3c
--- /dev/null
@@ -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 <anna/diameter.comm/Entity.hpp>
+
+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 (executable)
index 0000000..38a538a
--- /dev/null
@@ -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 <anna/core/core.hpp>
+#include <anna/diameter/functions.hpp>
+#include <anna/time/functions.hpp>
+#include <anna/diameter/codec/Engine.hpp>
+#include <anna/diameter.comm/Response.hpp>
+#include <anna/diameter.comm/ClientSession.hpp>
+#include <anna/diameter.comm/Server.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
+
+// Process
+#include <MyLocalServer.hpp>
+#include <MyDiameterEngine.hpp>
+#include <MyDiameterEntity.hpp>
+#include <rxSimpleTest.hpp>
+
+
+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 <RxSimpleTest&>(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 <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());
+  const anna::DataBlock* message = response.getMessage();
+  const anna::diameter::comm::ServerSession *serverSession = static_cast<const anna::diameter::comm::ServerSession *>(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 <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
+  (
+    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 <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
+  (
+    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 (executable)
index 0000000..c1cfd57
--- /dev/null
@@ -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 <anna/diameter.comm/LocalServer.hpp>
+
+
+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 (executable)
index 0000000..9730e33
--- /dev/null
@@ -0,0 +1 @@
+dynamic/launcher/default
diff --git a/example/diameter/rxSimpleTest/libraries.txt b/example/diameter/rxSimpleTest/libraries.txt
new file mode 100755 (executable)
index 0000000..028b715
--- /dev/null
@@ -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 (executable)
index 0000000..0406d6a
--- /dev/null
@@ -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 <string>
+
+// Project
+#include <anna/core/core.hpp>
+#include <anna/time/functions.hpp>
+
+// Process
+#include <rxSimpleTest.hpp>
+
+// To calculate the current working directory and get an absolute path for traces:
+#include <limits.h>
+#include <unistd.h>
+
+
+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 (executable)
index 0000000..bc76e80
--- /dev/null
@@ -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 (symlink)
index 0000000..d869d21
--- /dev/null
@@ -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 (executable)
index 0000000..1745fba
--- /dev/null
@@ -0,0 +1,722 @@
+<dictionary name="DictionaryRx | Application-Id: 16777236">
+   <vendor name="IETF" code="0"/>
+   <vendor name="3GPP" code="10415"/>
+   <vendor name="ETSI" code="13019"/>
+   <avp name="User-Name" code="1" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="UTF8String"/>
+   </avp>
+   <avp name="Framed-IP-Address" code="8" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Class" code="25" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Session-Timeout" code="27" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Called-Station-Id" code="30" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Proxy-State" code="33" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Acct-Session-Id" code="44" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Acct-Multi-Session-Id" code="50" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="UTF8String"/>
+   </avp>
+   <avp name="Event-Timestamp" code="55" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Time"/>
+   </avp>
+   <avp name="Acct-Interim-Interval" code="85" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Framed-IPv6-Prefix" code="97" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Host-IP-Address" code="257" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Address"/>
+   </avp>
+   <avp name="Auth-Application-Id" code="258" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Acct-Application-Id" code="259" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Vendor-Specific-Application-Id" code="260" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="Vendor-Id" type="Mandatory" qual="1*"/>
+         <avprule id="Auth-Application-Id" type="Optional"/>
+         <avprule id="Acct-Application-Id" type="Optional"/>
+      </grouped>
+   </avp>
+   <avp name="Redirect-Host-Usage" code="261" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-6">
+         <label data="0" alias="DONT_CACHE"/>
+         <label data="1" alias="ALL_SESSION"/>
+         <label data="2" alias="ALL_REALM"/>
+         <label data="3" alias="REALM_AND_APPLICATION"/>
+         <label data="4" alias="ALL_APPLICATION"/>
+         <label data="5" alias="ALL_HOST"/>
+         <label data="6" alias="ALL_USER"/>
+      </single>
+   </avp>
+   <avp name="Redirect-Max-Cache-Time" code="262" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Session-Id" code="263" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="UTF8String"/>
+   </avp>
+   <avp name="Origin-Host" code="264" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="DiameterIdentity"/>
+   </avp>
+   <avp name="Supported-Vendor-Id" code="265" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Vendor-Id" code="266" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Firmware-Revision" code="267" may-encrypt="yes" v-bit="mustnot" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Result-Code" code="268" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32">
+         <label data="1001" alias="DIAMETER_MULTI_ROUND_AUTH"/>
+         <label data="2001" alias="DIAMETER_SUCCESS"/>
+         <label data="2002" alias="DIAMETER_LIMITED_SUCCESS"/>
+         <label data="3001" alias="DIAMETER_COMMAND_UNSUPPORTED"/>
+         <label data="3002" alias="DIAMETER_UNABLE_TO_DELIVER"/>
+         <label data="3003" alias="DIAMETER_REALM_NOT_SERVED"/>
+         <label data="3004" alias="DIAMETER_TOO_BUSY"/>
+         <label data="3005" alias="DIAMETER_LOOP_DETECTED"/>
+         <label data="3006" alias="DIAMETER_REDIRECT_INDICATION"/>
+         <label data="3007" alias="DIAMETER_APPLICATION_UNSUPPORTED"/>
+         <label data="3008" alias="DIAMETER_INVALID_HDR_BITS"/>
+         <label data="3009" alias="DIAMETER_INVALID_AVP_BITS"/>
+         <label data="3010" alias="DIAMETER_UNKNOWN_PEER"/>
+         <label data="4001" alias="DIAMETER_AUTHENTICATION_REJECTED"/>
+         <label data="4002" alias="DIAMETER_OUT_OF_SPACE"/>
+         <label data="4003" alias="DIAMETER_ELECTION_LOST"/>
+         <label data="4241" alias="DIAMETER_NO_AVAILABLE_POLICY_COUNTERS"/>
+         <label data="5001" alias="DIAMETER_AVP_UNSUPPORTED"/>
+         <label data="5002" alias="DIAMETER_UNKNOWN_SESSION_ID"/>
+         <label data="5003" alias="DIAMETER_AUTHORIZATION_REJECTED"/>
+         <label data="5004" alias="DIAMETER_INVALID_AVP_VALUE"/>
+         <label data="5005" alias="DIAMETER_MISSING_AVP"/>
+         <label data="5006" alias="DIAMETER_RESOURCES_EXCEEDED"/>
+         <label data="5007" alias="DIAMETER_CONTRADICTING_AVPS"/>
+         <label data="5008" alias="DIAMETER_AVP_NOT_ALLOWED"/>
+         <label data="5009" alias="DIAMETER_AVP_OCCURS_TOO_MANY_TIMES"/>
+         <label data="5010" alias="DIAMETER_NO_COMMON_APPLICATION"/>
+         <label data="5011" alias="DIAMETER_UNSUPPORTED_VERSION"/>
+         <label data="5012" alias="DIAMETER_UNABLE_TO_COMPLY"/>
+         <label data="5013" alias="DIAMETER_INVALID_BIT_IN_HEADER"/>
+         <label data="5014" alias="DIAMETER_INVALID_AVP_LENGTH"/>
+         <label data="5015" alias="DIAMETER_INVALID_MESSAGE_LENGTH"/>
+         <label data="5016" alias="DIAMETER_INVALID_AVP_BIT_COMBO"/>
+         <label data="5017" alias="DIAMETER_NO_COMMON_SECURITY"/>
+         <label data="5030" alias="DIAMETER_USER_UNKNOWN"/>
+         <label data="5063" alias="REQUESTED_SERVICE_NOT_AUTHORIZED"/>
+         <label data="5065" alias="IP_CAN_SESSION_NOT_AVAILABLE"/>
+      </single>
+   </avp>
+   <avp name="Product-Name" code="269" may-encrypt="yes" v-bit="mustnot" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="UTF8String"/>
+   </avp>
+   <avp name="Session-Binding" code="270" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Session-Server-Failover" code="271" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-3">
+         <label data="0" alias="REFUSE_SERVICE"/>
+         <label data="1" alias="TRY_AGAIN"/>
+         <label data="2" alias="ALLOW_SERVICE"/>
+         <label data="3" alias="TRY_AGAIN_ALLOW_SERVICE"/>
+      </single>
+   </avp>
+   <avp name="Multi-Round-Time-Out" code="272" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Disconnect-Cause" code="273" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-2">
+         <label data="0" alias="REBOOTING"/>
+         <label data="1" alias="BUSY"/>
+         <label data="2" alias="DO_NOT_WANT_TO_TALK_TO_YOU"/>
+      </single>
+   </avp>
+   <avp name="Auth-Request-Type" code="274" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="1-3">
+         <label data="1" alias="AUTHENTICATE_ONLY"/>
+         <label data="2" alias="AUTHORIZE_ONLY"/>
+         <label data="3" alias="AUTHORIZE_AUTHENTICATE"/>
+      </single>
+   </avp>
+   <avp name="Auth-Grace-Period" code="276" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Auth-Session-State" code="277" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-1">
+         <label data="0" alias="STATE_MAINTAINED"/>
+         <label data="1" alias="NO_STATE_MAINTAINED"/>
+      </single>
+   </avp>
+   <avp name="Origin-State-Id" code="278" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Failed-AVP" code="279" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="AVP" type="Mandatory" qual="1*"/>
+      </grouped>
+   </avp>
+   <avp name="Proxy-Host" code="280" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="DiameterIdentity"/>
+   </avp>
+   <avp name="Error-Message" code="281" may-encrypt="yes" v-bit="mustnot" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="UTF8String"/>
+   </avp>
+   <avp name="Route-Record" code="282" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="DiameterIdentity"/>
+   </avp>
+   <avp name="Destination-Realm" code="283" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="DiameterIdentity"/>
+   </avp>
+   <avp name="Proxy-Info" code="284" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="Proxy-Host" type="Mandatory"/>
+         <avprule id="Proxy-State" type="Mandatory"/>
+         <avprule id="AVP" type="Optional" qual="*"/>
+      </grouped>
+   </avp>
+   <avp name="Re-Auth-Request-Type" code="285" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-1">
+         <label data="0" alias="AUTHORIZE_ONLY"/>
+         <label data="1" alias="AUTHORIZE_AUTHENTICATE"/>
+      </single>
+   </avp>
+   <avp name="Accounting-Sub-Session-Id" code="287" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned64"/>
+   </avp>
+   <avp name="Redirect-Host" code="292" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="DiameterURI"/>
+   </avp>
+   <avp name="Destination-Host" code="293" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="DiameterIdentity"/>
+   </avp>
+   <avp name="Error-Reporting-Host" code="294" may-encrypt="yes" v-bit="mustnot" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="DiameterIdentity"/>
+   </avp>
+   <avp name="Termination-Cause" code="295" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="1-8">
+         <label data="1" alias="LOGOUT"/>
+         <label data="2" alias="SERVICE_NOT_PROVIDED"/>
+         <label data="3" alias="BAD_ANSWER"/>
+         <label data="4" alias="ADMINISTRATIVE"/>
+         <label data="5" alias="LINK_BROKEN"/>
+         <label data="6" alias="AUTH_EXPIRED"/>
+         <label data="7" alias="USER_MOVED"/>
+         <label data="8" alias="SESSION_TIMEOUT"/>
+      </single>
+   </avp>
+   <avp name="Origin-Realm" code="296" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="DiameterIdentity"/>
+   </avp>
+   <avp name="Experimental-Result" code="297" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="Vendor-Id" type="Mandatory"/>
+         <avprule id="Experimental-Result-Code" type="Mandatory"/>
+      </grouped>
+   </avp>
+   <avp name="Experimental-Result-Code" code="298" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Inband-Security-Id" code="299" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="E2E-Sequence" code="300" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="AVP" type="Mandatory" qual="2*"/>
+      </grouped>
+   </avp>
+   <avp name="Subscription-Id" code="443" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="Subscription-Id-Type" type="Mandatory"/>
+         <avprule id="Subscription-Id-Data" type="Mandatory"/>
+      </grouped>
+   </avp>
+   <avp name="Subscription-Id-Data" code="444" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="UTF8String"/>
+   </avp>
+   <avp name="Subscription-Id-Type" code="450" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-4">
+         <label data="0" alias="END_USER_E164"/>
+         <label data="1" alias="END_USER_IMSI"/>
+         <label data="2" alias="END_USER_SIP_URI"/>
+         <label data="3" alias="END_USER_NAI"/>
+         <label data="4" alias="END_USER_PRIVATE"/>
+      </single>
+   </avp>
+   <avp name="Accounting-Record-Type" code="480" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="1-4">
+         <label data="1" alias="EVENT_RECORD"/>
+         <label data="2" alias="START_RECORD"/>
+         <label data="3" alias="INTERIM_RECORD"/>
+         <label data="4" alias="STOP_RECORD"/>
+      </single>
+   </avp>
+   <avp name="Accounting-Realtime-Required" code="483" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="1-3">
+         <label data="1" alias="DELIVER_AND_GRANT"/>
+         <label data="2" alias="GRANT_AND_STORE"/>
+         <label data="3" alias="GRANT_AND_LOSE"/>
+      </single>
+   </avp>
+   <avp name="Accounting-Record-Number" code="485" may-encrypt="yes" v-bit="mustnot" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="3GPP-SGSN-MCC-MNC" code="18" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="UTF8String"/>
+   </avp>
+   <avp name="3GPP-User-Location-Info" code="22" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="3GPP-MS-TimeZone" code="23" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Abort-Cause" code="500" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-4">
+         <label data="0" alias="BEARER_RELEASED"/>
+         <label data="1" alias="INSUFFICIENT_SERVER_RESOURCES"/>
+         <label data="2" alias="INSUFFICIENT_BEARER_RESOURCES"/>
+         <label data="3" alias="PS_TO_CS_HANDOVER"/>
+         <label data="4" alias="SPONSORED_DATA_CONNECTIVITY_DISALLOWED"/>
+      </single>
+   </avp>
+   <avp name="AF-Application-Identifier" code="504" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="AF-Charging-Identifier" code="505" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Flow-Description" code="507" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="IPFilterRule"/>
+   </avp>
+   <avp name="Flow-Number" code="509" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Flows" code="510" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="Media-Component-Number" type="Mandatory"/>
+         <avprule id="Flow-Number" type="Optional" qual="*"/>
+      </grouped>
+   </avp>
+   <avp name="Flow-Status" code="511" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-4">
+         <label data="0" alias="ENABLED-UPLINK"/>
+         <label data="1" alias="ENABLED-DOWNLINK"/>
+         <label data="2" alias="ENABLED"/>
+         <label data="3" alias="DISABLED"/>
+         <label data="4" alias="REMOVED"/>
+      </single>
+   </avp>
+   <avp name="Flow-Usage" code="512" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-2">
+         <label data="0" alias="NO_INFORMATION"/>
+         <label data="1" alias="RTCP"/>
+         <label data="2" alias="AF_SIGNALLING"/>
+      </single>
+   </avp>
+   <avp name="Specific-Action" code="513" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="1-4,6-14">
+         <label data="1" alias="CHARGING_CORRELATION_EXCHANGE"/>
+         <label data="2" alias="INDICATION_OF_LOSS_OF_BEARER"/>
+         <label data="3" alias="INDICATION_OF_RECOVERY_OF_BEARER"/>
+         <label data="4" alias="INDICATION_OF_RELEASE_OF_BEARER"/>
+         <label data="6" alias="IP-CAN_CHANGE"/>
+         <label data="7" alias="INDICATION_OF_OUT_OF_CREDIT"/>
+         <label data="8" alias="INDICATION_OF_SUCCESSFUL_RESOURCES_ALLOCATION"/>
+         <label data="9" alias="INDICATION_OF_FAILED_RESOURCES_ALLOCATION"/>
+         <label data="10" alias="INDICATION_OF_LIMITED_PCC_DEPLOYMENT"/>
+         <label data="11" alias="USAGE_REPORT"/>
+         <label data="12" alias="ACCESS_NETWORK_INFO_REPORT"/>
+         <label data="13" alias="INDICATION_OF_RECOVERY_FROM_LIMITED_PCC_DEPLOYMENT"/>
+         <label data="14" alias="INDICATION_OF_ACCESS_NETWORK_INFO_REPORTING_FAILURE"/>
+      </single>
+   </avp>
+   <avp name="Max-Requested-Bandwidth-DL" code="515" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Max-Requested-Bandwidth-UL" code="516" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Media-Component-Description" code="517" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="Media-Component-Number" type="Mandatory"/>
+         <avprule id="Media-Sub-Component" type="Optional" qual="*"/>
+         <avprule id="AF-Application-Identifier" type="Optional"/>
+         <avprule id="Media-Type" type="Optional"/>
+         <avprule id="Max-Requested-Bandwidth-UL" type="Optional"/>
+         <avprule id="Max-Requested-Bandwidth-DL" type="Optional"/>
+         <avprule id="Min-Requested-Bandwidth-UL" type="Optional"/>
+         <avprule id="Min-Requested-Bandwidth-DL" type="Optional"/>
+         <avprule id="Flow-Status" type="Optional"/>
+         <avprule id="Reservation-Priority" type="Optional"/>
+         <avprule id="RS-Bandwidth" type="Optional"/>
+         <avprule id="RR-Bandwidth" type="Optional"/>
+         <avprule id="Codec-Data" type="Optional" qual="*"/>
+      </grouped>
+   </avp>
+   <avp name="Media-Component-Number" code="518" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Media-Sub-Component" code="519" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <grouped>
+         <avprule id="Flow-Number" type="Mandatory"/>
+         <avprule id="Flow-Description" type="Optional" qual="0*2"/>
+         <avprule id="Flow-Status" type="Optional"/>
+         <avprule id="Flow-Usage" type="Optional"/>
+         <avprule id="Max-Requested-Bandwidth-UL" type="Optional"/>
+         <avprule id="Max-Requested-Bandwidth-DL" type="Optional"/>
+      </grouped>
+   </avp>
+   <avp name="Media-Type" code="520" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-6">
+         <label data="0" alias="OTHER"/>
+         <label data="1" alias="VIDEO"/>
+         <label data="2" alias="DATA"/>
+         <label data="3" alias="APPLICATION"/>
+         <label data="4" alias="CONTROL"/>
+         <label data="5" alias="TEXT"/>
+         <label data="6" alias="MESSAGE"/>
+      </single>
+   </avp>
+   <avp name="RR-Bandwidth" code="521" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="RS-Bandwidth" code="522" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="SIP-Forking-Indication" code="523" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-1">
+         <label data="0" alias="SINGLE_DIALOGUE"/>
+         <label data="1" alias="SEVERAL_DIALOGUES"/>
+      </single>
+   </avp>
+   <avp name="Codec-Data" code="524" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Service-URN" code="525" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Service-Info-Status" code="527" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="must" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-1">
+         <label data="0" alias="FINAL_SERVICE_INFORMATION"/>
+         <label data="1" alias="PRELIMINARY_SERVICE_INFORMATION"/>
+      </single>
+   </avp>
+   <avp name="MPS-Identifier" code="528" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="AF-Signalling-Protocol" code="529" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-1">
+         <label data="0" alias="NO_INFORMATION"/>
+         <label data="1" alias="SIP"/>
+      </single>
+   </avp>
+   <avp name="Rx-Request-Type" code="533" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-1">
+         <label data="0" alias="INITIAL_REQUEST"/>
+         <label data="1" alias="UPDATE_REQUEST"/>
+      </single>
+   </avp>
+   <avp name="Min-Requested-Bandwidth-DL" code="534" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Min-Requested-Bandwidth-UL" code="535" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Required-Access-Info" code="536" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-1">
+         <label data="0" alias="USER_LOCATION"/>
+         <label data="1" alias="MS_TIME_ZONE"/>
+      </single>
+   </avp>
+   <avp name="IP-Domain-Id" code="537" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="OctetString"/>
+   </avp>
+   <avp name="Supported-Features" code="628" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="may" p-bit="mustnot">
+      <grouped>
+         <avprule id="Vendor-Id" type="Mandatory"/>
+         <avprule id="Feature-List-ID" type="Mandatory"/>
+         <avprule id="Feature-List" type="Mandatory"/>
+         <avprule id="AVP" type="Optional" qual="*"/>
+      </grouped>
+   </avp>
+   <avp name="Feature-List-ID" code="629" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Feature-List" code="630" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="User-Location-Info-Time" code="2812" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Time"/>
+   </avp>
+   <avp name="NetLoc-Access-Support" code="2824" vendor-name="3GPP" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Unsigned32"/>
+   </avp>
+   <avp name="Reservation-Priority" code="458" vendor-name="ETSI" may-encrypt="yes" v-bit="must" m-bit="mustnot" p-bit="mustnot">
+      <single format-name="Enumerated" enum="0-15">
+         <label data="0" alias="DEFAULT"/>
+         <label data="1" alias="PRIORITY-ONE"/>
+         <label data="2" alias="PRIORITY-TWO"/>
+         <label data="3" alias="PRIORITY-THREE"/>
+         <label data="4" alias="PRIORITY-FOUR"/>
+         <label data="5" alias="PRIORITY-FIVE"/>
+         <label data="6" alias="PRIORITY-SIX"/>
+         <label data="7" alias="PRIORITY-SEVEN"/>
+         <label data="8" alias="PRIORITY-EIGHT"/>
+         <label data="9" alias="PRIORITY-NINE"/>
+         <label data="10" alias="PRIORITY-TEN"/>
+         <label data="11" alias="PRIORITY-ELEVEN"/>
+         <label data="12" alias="PRIORITY-TWELVE"/>
+         <label data="13" alias="PRIORITY-THIRTEEN"/>
+         <label data="14" alias="PRIORITY-FOURTEEN"/>
+         <label data="15" alias="PRIORITY-FIFTEEN"/>
+      </single>
+   </avp>
+   <command name="CER" code="257" type="Request">
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Host-IP-Address" type="Mandatory" qual="1*"/>
+      <avprule id="Vendor-Id" type="Mandatory"/>
+      <avprule id="Product-Name" type="Mandatory"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Supported-Vendor-Id" type="Optional" qual="*"/>
+      <avprule id="Auth-Application-Id" type="Optional" qual="*"/>
+      <avprule id="Inband-Security-Id" type="Optional" qual="*"/>
+      <avprule id="Acct-Application-Id" type="Optional" qual="*"/>
+      <avprule id="Vendor-Specific-Application-Id" type="Optional" qual="*"/>
+      <avprule id="Firmware-Revision" type="Optional"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="CEA" code="257" type="Answer">
+      <avprule id="Result-Code" type="Mandatory"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Host-IP-Address" type="Mandatory" qual="1*"/>
+      <avprule id="Vendor-Id" type="Mandatory"/>
+      <avprule id="Product-Name" type="Mandatory"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Error-Message" type="Optional"/>
+      <avprule id="Failed-AVP" type="Optional" qual="*"/>
+      <avprule id="Supported-Vendor-Id" type="Optional" qual="*"/>
+      <avprule id="Auth-Application-Id" type="Optional" qual="*"/>
+      <avprule id="Inband-Security-Id" type="Optional" qual="*"/>
+      <avprule id="Acct-Application-Id" type="Optional" qual="*"/>
+      <avprule id="Vendor-Specific-Application-Id" type="Optional" qual="*"/>
+      <avprule id="Firmware-Revision" type="Optional"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="RA-Request" code="258" type="Request">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Destination-Realm" type="Mandatory"/>
+      <avprule id="Destination-Host" type="Mandatory"/>
+      <avprule id="Auth-Application-Id" type="Mandatory"/>
+      <avprule id="Specific-Action" type="Mandatory" qual="*"/>
+      <avprule id="Flows" type="Optional" qual="*"/>
+      <avprule id="Abort-Cause" type="Optional"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="Route-Record" type="Optional" qual="*"/>
+      <avprule id="3GPP-MS-TimeZone" type="Optional"/>
+      <avprule id="3GPP-User-Location-Info" type="Optional"/>
+      <avprule id="3GPP-SGSN-MCC-MNC" type="Optional"/>
+      <avprule id="NetLoc-Access-Support" type="Optional"/>
+      <avprule id="User-Location-Info-Time" type="Optional"/>
+   </command>
+   <command name="RA-Answer" code="258" type="Answer">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Result-Code" type="Optional"/>
+      <avprule id="Experimental-Result" type="Optional"/>
+      <avprule id="Media-Component-Description" type="Optional" qual="*"/>
+      <avprule id="Service-URN" type="Optional"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Class" type="Optional" qual="*"/>
+      <avprule id="Error-Message" type="Optional"/>
+      <avprule id="Error-Reporting-Host" type="Optional"/>
+      <avprule id="Redirect-Host" type="Optional" qual="*"/>
+      <avprule id="Redirect-Host-Usage" type="Optional"/>
+      <avprule id="Redirect-Max-Cache-Time" type="Optional"/>
+      <avprule id="Failed-AVP" type="Optional" qual="*"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="AA-Request" code="265" type="Request">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Auth-Application-Id" type="Mandatory"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Destination-Realm" type="Mandatory"/>
+      <avprule id="Destination-Host" type="Optional"/>
+      <avprule id="IP-Domain-Id" type="Optional"/>
+      <avprule id="AF-Application-Identifier" type="Optional"/>
+      <avprule id="Media-Component-Description" type="Optional" qual="*"/>
+      <avprule id="Service-Info-Status" type="Optional"/>
+      <avprule id="AF-Charging-Identifier" type="Optional"/>
+      <avprule id="SIP-Forking-Indication" type="Optional"/>
+      <avprule id="Specific-Action" type="Optional" qual="*"/>
+      <avprule id="Subscription-Id" type="Optional" qual="*"/>
+      <avprule id="Supported-Features" type="Optional" qual="*"/>
+      <avprule id="Reservation-Priority" type="Optional"/>
+      <avprule id="Framed-IP-Address" type="Optional"/>
+      <avprule id="Framed-IPv6-Prefix" type="Optional"/>
+      <avprule id="Called-Station-Id" type="Optional"/>
+      <avprule id="Service-URN" type="Optional"/>
+      <avprule id="MPS-Identifier" type="Optional"/>
+      <avprule id="Rx-Request-Type" type="Optional"/>
+      <avprule id="Required-Access-Info" type="Optional" qual="*"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="Route-Record" type="Optional" qual="*"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="AA-Answer" code="265" type="Answer">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Auth-Application-Id" type="Mandatory"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Result-Code" type="Optional"/>
+      <avprule id="Experimental-Result" type="Optional"/>
+      <avprule id="Failed-AVP" type="Optional" qual="*"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Supported-Features" type="Optional" qual="*"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+   </command>
+   <command name="ACR" code="271" type="Request">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Destination-Realm" type="Mandatory"/>
+      <avprule id="Accounting-Record-Type" type="Mandatory"/>
+      <avprule id="Accounting-Record-Number" type="Mandatory"/>
+      <avprule id="Acct-Application-Id" type="Optional"/>
+      <avprule id="Vendor-Specific-Application-Id" type="Optional"/>
+      <avprule id="User-Name" type="Optional"/>
+      <avprule id="Accounting-Sub-Session-Id" type="Optional"/>
+      <avprule id="Acct-Session-Id" type="Optional"/>
+      <avprule id="Acct-Multi-Session-Id" type="Optional"/>
+      <avprule id="Acct-Interim-Interval" type="Optional"/>
+      <avprule id="Accounting-Realtime-Required" type="Optional"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Event-Timestamp" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="Route-Record" type="Optional" qual="*"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="ACA" code="271" type="Answer">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Result-Code" type="Mandatory"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Accounting-Record-Type" type="Mandatory"/>
+      <avprule id="Accounting-Record-Number" type="Mandatory"/>
+      <avprule id="Acct-Application-Id" type="Optional"/>
+      <avprule id="Vendor-Specific-Application-Id" type="Optional"/>
+      <avprule id="User-Name" type="Optional"/>
+      <avprule id="Accounting-Sub-Session-Id" type="Optional"/>
+      <avprule id="Acct-Session-Id" type="Optional"/>
+      <avprule id="Acct-Multi-Session-Id" type="Optional"/>
+      <avprule id="Error-Reporting-Host" type="Optional"/>
+      <avprule id="Acct-Interim-Interval" type="Optional"/>
+      <avprule id="Accounting-Realtime-Required" type="Optional"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Event-Timestamp" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="AS-Request" code="274" type="Request">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Destination-Realm" type="Mandatory"/>
+      <avprule id="Destination-Host" type="Mandatory"/>
+      <avprule id="Auth-Application-Id" type="Mandatory"/>
+      <avprule id="Abort-Cause" type="Mandatory"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="Route-Record" type="Optional" qual="*"/>
+   </command>
+   <command name="AS-Answer" code="274" type="Answer">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Result-Code" type="Optional"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Error-Message" type="Optional"/>
+      <avprule id="Error-Reporting-Host" type="Optional"/>
+      <avprule id="Failed-AVP" type="Optional" qual="*"/>
+      <avprule id="Redirect-Host" type="Optional" qual="*"/>
+      <avprule id="Redirect-Host-Usage" type="Optional"/>
+      <avprule id="Redirect-Max-Cache-Time" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="ST-Request" code="275" type="Request">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Destination-Realm" type="Mandatory"/>
+      <avprule id="Auth-Application-Id" type="Mandatory"/>
+      <avprule id="Termination-Cause" type="Mandatory"/>
+      <avprule id="Destination-Host" type="Optional"/>
+      <avprule id="Required-Access-Info" type="Optional" qual="*"/>
+      <avprule id="Class" type="Optional" qual="*"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="Route-Record" type="Optional" qual="*"/>
+      <avprule id="AVP" type="Optional" qual="*"/>
+   </command>
+   <command name="ST-Answer" code="275" type="Answer">
+      <avprule id="Session-Id" type="Fixed"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Result-Code" type="Optional"/>
+      <avprule id="Failed-AVP" type="Optional" qual="*"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+      <avprule id="Proxy-Info" type="Optional" qual="*"/>
+      <avprule id="3GPP-MS-TimeZone" type="Optional"/>
+      <avprule id="3GPP-User-Location-Info" type="Optional"/>
+      <avprule id="3GPP-SGSN-MCC-MNC" type="Optional"/>
+      <avprule id="NetLoc-Access-Support" type="Optional"/>
+      <avprule id="User-Location-Info-Time" type="Optional"/>
+   </command>
+   <command name="DWR" code="280" type="Request">
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+   </command>
+   <command name="DWA" code="280" type="Answer">
+      <avprule id="Result-Code" type="Mandatory"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Error-Message" type="Optional"/>
+      <avprule id="Failed-AVP" type="Optional" qual="*"/>
+      <avprule id="Origin-State-Id" type="Optional"/>
+   </command>
+   <command name="DPR" code="282" type="Request">
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Disconnect-Cause" type="Mandatory"/>
+   </command>
+   <command name="DPA" code="282" type="Answer">
+      <avprule id="Result-Code" type="Mandatory"/>
+      <avprule id="Origin-Host" type="Mandatory"/>
+      <avprule id="Origin-Realm" type="Mandatory"/>
+      <avprule id="Error-Message" type="Optional"/>
+      <avprule id="Failed-AVP" type="Optional" qual="*"/>
+   </command>
+</dictionary>
diff --git a/example/diameter/rxSimpleTest/rxSimpleTest.cpp b/example/diameter/rxSimpleTest/rxSimpleTest.cpp
new file mode 100755 (executable)
index 0000000..95a3580
--- /dev/null
@@ -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 <sstream>      // std::istringstream
+#include <iostream>     // std::cout
+#include <math.h> // ceil
+#include <climits>
+#include <unistd.h> // chdir
+//#include <regex> TODO: use this from gcc4.9.0: http://stackoverflow.com/questions/8060025/is-this-c11-regex-error-me-or-the-compiler
+#include <stdio.h>
+
+// Project
+#include <anna/timex/Engine.hpp>
+#include <anna/statistics/Engine.hpp>
+#include <anna/diameter/codec/functions.hpp>
+#include <anna/diameter/codec/Engine.hpp>
+#include <anna/diameter/codec/EngineManager.hpp>
+#include <anna/diameter/stack/Engine.hpp>
+#include <anna/diameter/helpers/base/functions.hpp>
+#include <anna/time/functions.hpp>
+#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
+#include <anna/testing/defines.hpp>
+#include <anna/xml/xml.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
+#include <anna/diameter.comm/OriginHostManager.hpp>
+
+// Process
+#include <rxSimpleTest.hpp>
+#include <MyDiameterEngine.hpp>
+
+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 (executable)
index 0000000..7e90033
--- /dev/null
@@ -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 <fstream>
+#include <string>
+#include <map>
+
+// Project
+#include <anna/core/core.hpp>
+#include <anna/comm/comm.hpp>
+#include <anna/time/Date.hpp>
+#include <anna/diameter/codec/Message.hpp>
+
+// Process
+#include <MyCommunicator.hpp>
+
+
+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