Fix local server for multiple applications
[anna.git] / include / anna / diameter.comm / Engine.hpp
index 0a65b24..8da4a6b 100644 (file)
 
 // STL
 #include <map>
+#include <vector>
 #include <string>
 #include <algorithm>
 
 #include <anna/app/Component.hpp>
 #include <anna/core/util/Recycler.hpp>
 
+#include <anna/diameter/codec/Engine.hpp>
 #include <anna/diameter.comm/Server.hpp>
 #include <anna/diameter.comm/ServerSession.hpp>
 #include <anna/config/defines.hpp>
 #include <anna/diameter.comm/ClientSession.hpp>
 #include <anna/diameter.comm/ServerSession.hpp>
+#include <anna/core/util/defines.hpp> // U32
+
 
 // Standard
 #include <time.h>
@@ -47,9 +51,13 @@ namespace codec {
 class Engine;
 }
 
-namespace comm {
+namespace stack {
+class Dictionary;
+}
 
+namespace comm {
 
+class Response;
 class Entity;
 class Server;
 class LocalServer;
@@ -73,17 +81,17 @@ class LocalServer;
  *     private:
  *        anna::Recycler<MyEntity> a_entities;
  *
- *        anna::diameter::comm::Entity* allocateEntity () throw () { return a_entities.create (); }
+ *        anna::diameter::comm::Entity* allocateEntity () { return a_entities.create (); }
  *
- *        void releaseEntity (anna::diameter::comm::Entity* entity) throw () {
+ *        void releaseEntity (anna::diameter::comm::Entity* entity) {
  *           MyEntity* aux = static_cast <MyEntity*> (entity);
  *           a_entities.release (aux);
  *        }
  *
  *
- *        anna::diameter::comm::LocalServer* allocateLocalServer () throw () { return a_localServers.create (); }
+ *        anna::diameter::comm::LocalServer* allocateLocalServer () { return a_localServers.create (); }
  *
- *        void releaseLocalServer (anna::diameter::comm::LocalServer* localServer) throw () {
+ *        void releaseLocalServer (anna::diameter::comm::LocalServer* localServer) {
  *           MyLocalServer* aux = static_cast <MyLocalServer*> (localServer);
  *           a_localServers.release (aux);
  *        }
@@ -95,60 +103,53 @@ class Engine : public anna::app::Component {
 public:
 
   /**
-     Logical name for this anna::app::Component.
-     \return Logical name for this anna::app::Component.
-  */
-  static const char* getClassName() throw() { return "anna::diameter::comm::Engine"; }
-
-  /**
-     Diameter application node realm name (used to be the site domain name).
+     Diameter application node origin realm
 
-     @param name Diameter application node realm name. Used in order to configure the Origin-Realm for outgoing messages.
+     @param originRealmName Used to configure the Origin-Realm for outgoing messages.
      If not configured or empty string provided, host domainname will be set.
   */
-  void setRealm(const std::string & name) throw();
-
+  void setOriginRealmName(const std::string & originRealmName) ;
 
   /**
-     Gets the configured diameter application node realm name.
+     Diameter application origin host
 
-     @return Diameter application node realm name.
+     @param originHostName Used to configure the Origin-Host for outgoing messages.
+     If not configured or empty string provided, hostname (system name) will be set.
   */
-  const std::string & getRealm() const throw() { return a_realm; }
-
+  void setOriginHostName(const std::string & originHostName) ;
 
   /**
-     Diameter application host name as solved by #anna::functions::getHostname()
+     Gets the configured diameter application node origin realm
 
-     @param name Host name. Used in order to configure the Origin-Host for outgoing messages.
-     If not configured or empty string provided, hostname (system name) will be set.
+     @return Diameter application node origin realm
   */
-  void setHost(const std::string & name) throw();
-
+  const std::string & getOriginRealmName() const { return a_originRealm; }
 
   /**
-     Gets the configured diameter application host name.
+     Gets the configured diameter application origin host
 
-     @return Diameter application host name.
+     @return Diameter application node origin host
   */
-  const std::string & getHost() const throw() { return a_host; }
+  const std::string & getOriginHostName() const { return a_originHost; }
 
 
   /**
    * Propagate auto recovery configuration to entities within engine. Recovery period is configured at
-   * #anna::comm::Communicator::setRecoveryTime. All the client client-sessions created throught #createEntity,
-   * will be created based on the engine auto-recovery value (enable by default). But you could access entities,
-   * servers or client-sessions independently to change this behaviour.
+   * #anna::comm::Communicator::setRecoveryTime (5 seconds by default). All the client client-sessions
+   * created throught #createEntity, will be created based on the engine auto-recovery value (enabled
+   * by default).
+   * You could access entities, servers or client-sessions independently to use this method, but recovery
+   * time should be updated through communicator and will apply for new created connections.
    *
    * @param autoRecovery Auto recovery indicator. True by default.
    */
-  void raiseAutoRecovery(bool autoRecovery = true) throw(anna::RuntimeException);
+  void raiseAutoRecovery(bool autoRecovery = true) noexcept(false);
 
   /**
    * Returns automatic bind indicator for client-sessions. By default \em true will be used.
    * \return Value for automatic connection bind.
    */
-  bool getAutoBind() const throw() { return a_autoBind; }
+  bool getAutoBind() const { return a_autoBind; }
 
   /**
    * Sets automatic connection bind indicator for client-sessions. If not asigned, it will be \em true.
@@ -157,7 +158,7 @@ public:
    * In order to change bind timer, first client-session must be created without autobind, modify time
    * parameter and then invoking bind.
    */
-  void setAutoBind(const bool autoBind) throw() { a_autoBind = autoBind; }
+  void setAutoBind(const bool autoBind) { a_autoBind = autoBind; }
 
   /**
      Sets the milliseconds wait to achieve a client connection to server by mean connect primitive.
@@ -166,7 +167,7 @@ public:
 
      \param maxConnectionDelay Milliseconds wait to get connection
   */
-  void setMaxConnectionDelay(const anna::Millisecond & maxConnectionDelay) throw() { a_maxConnectionDelay = maxConnectionDelay; }
+  void setMaxConnectionDelay(const anna::Millisecond & maxConnectionDelay) { a_maxConnectionDelay = maxConnectionDelay; }
 
   /**
      Gets the milliseconds wait to achieve a client connection to server by mean connect primitive.
@@ -175,24 +176,50 @@ public:
 
      \return Milliseconds wait to get connection
   */
-  const anna::Millisecond & getMaxConnectionDelay() throw() { return a_maxConnectionDelay; }
+  const anna::Millisecond & getMaxConnectionDelay() { return a_maxConnectionDelay; }
 
   /**
    * Binds engine entities.
    *
    * @return Returns true if all client-session were successfully bound
    */
-  bool bind() throw(anna::RuntimeException);
+  bool bind() noexcept(false);
 
   /**
-   * Sets CER and DWR diameter messages to be used over created client-sessions.
-   * Its recommended to set this global configuration although it is possible to configure each client-session separately.
+   * Sets CER diameter messages to be used over created client-sessions.
    *
    * @param cer Capabilities-Exchange-Request message (encoded) for the client-sessions bind.
+   */
+  void setClientCER(const anna::DataBlock & cer) noexcept(false);
+
+  /**
+   * Sets CER diameter messages to be used over created client-sessions.
+   *
+   * @param cerPathFile Capabilities-Exchange-Request xml message path file for the client-sessions bind.
+   */
+  void setClientCER(const std::string & cerPathFile) noexcept(false);
+
+  /**
+   * Sets DEFAULT CER diameter messages to be used over created client-sessions.
+   *
+   * @param applicationId Application-Id for the Auth-Application-Id AVP.
+   */
+  void setClientCER(const anna::U32 &applicationId) noexcept(false);
+
+  /**
+   * Sets DWR for diameter keep-alive over client-sessions
+   *
    * @param dwr Device-Watchdog-Request message (encoded) for the client-sessions keep-alive.
    */
-  void setCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) throw(anna::RuntimeException);
+  void setClientDWR(const anna::DataBlock & dwr) noexcept(false);
 
+  /**
+   * Sets DWR for diameter keep-alive over client-sessions
+   *
+   * @param cerPathFile Device-Watchdog-Request xml message path file for the client-sessions keep-alive.
+   * If empty provided, a DEFAULT DWR will be built.
+   */
+  void setClientDWR(const std::string & dwrPathFile = "") noexcept(false);
 
   /**
    * Sets the watchdog period (DWR) for client-sessions.
@@ -200,33 +227,21 @@ public:
    *
    * @param wp Watchdog period.
    */
-  void setWatchdogPeriod(const anna::Millisecond & wp) throw(anna::RuntimeException);
+  void setWatchdogPeriod(const anna::Millisecond & wp) noexcept(false);
 
   /**
    * Gets the number of client-sessions per server.
    * \return numberOfClientSessionsPerServer Number of client-sessions per server.
    */
-  int getNumberOfClientSessionsPerServer() const throw() { return a_numberOfClientSessionsPerServer; }
+  int getNumberOfClientSessionsPerServer() const { return a_numberOfClientSessionsPerServer; }
 
   /**
    * Sets the number of client-sessions per server.
    * Its recommended to set this global configuration although it is possible to configure each client-session separately.
    * \param numberOfClientSessionsPerServer Number of client-sessions per server.
    */
-  void setNumberOfClientSessionsPerServer(int numberOfClientSessionsPerServer) throw() { a_numberOfClientSessionsPerServer = numberOfClientSessionsPerServer; }
-
-  /**
-   * Gets true when end-to-end sequence is freezed on requests sendings.
-   * Engine starts with false value, sequencing end-to-end as hop-by-hop does.
-   * \return Freeze end-to-end indicator.
-   */
-  bool getFreezeEndToEndOnSending() const throw() { return a_freezeEndToEndOnSending; }
+  void setNumberOfClientSessionsPerServer(int numberOfClientSessionsPerServer) { a_numberOfClientSessionsPerServer = numberOfClientSessionsPerServer; }
 
-  /**
-   * Freeze end-to-end indicator on requests sendings.
-   * \param freezeEndToEndOnSending Freeze end-to-end indicator.
-   */
-  void setFreezeEndToEndOnSending(bool freezeEndToEndOnSending = true) throw() { a_freezeEndToEndOnSending = freezeEndToEndOnSending; }
 
   /**
    * Returns client-session instance identified by (address, port, socketId) provided.
@@ -240,13 +255,13 @@ public:
    *
    * \warning If no client-session found, an exception is launched by default.
    */
-  ClientSession* findClientSession(const std::string & addr, int port, int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
+  ClientSession* findClientSession(const std::string & addr, int port, int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) noexcept(false);
 
 
   /**
    * Same as #findClientSession, but providing client session key (<address>:<port>|<socket id>)
    */
-  ClientSession* findClientSession(const std::string & key, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
+  ClientSession* findClientSession(const std::string & key, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) noexcept(false);
 
 
   /**
@@ -260,7 +275,7 @@ public:
    *
    * \warning If no server found, an exception is launched by default.
    */
-  Server* findServer(const std::string & addr, int port, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
+  Server* findServer(const std::string & addr, int port, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) noexcept(false);
 
   /**
    * Returns entity instance identified by internal index.
@@ -272,7 +287,7 @@ public:
    *
    * \warning If no entity found, an exception is launched by default.
    */
-  Entity* findEntity(const socket_v & socketList, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
+  Entity* findEntity(const socket_v & socketList, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) noexcept(false);
 
   /**
    * Returns entity instance identified by internal index.
@@ -287,7 +302,7 @@ public:
    *
    * \warning If no entity found, an exception is launched by default.
    */
-  Entity* findEntity(const std::string & addr1, int port1, const std::string & addr2, int port2, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
+  Entity* findEntity(const std::string & addr1, int port1, const std::string & addr2, int port2, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) noexcept(false);
 
   /**
    * Creates a diameter entity with provided parameters.
@@ -303,7 +318,7 @@ public:
    * indicates that 'ClassCode::Bind' has been correctly performed for any included client-session.
    */
   Entity* createEntity(const socket_v & socketList, const std::string & description = "")
-  throw(anna::RuntimeException);
+  noexcept(false);
 
   /**
    * Creates a standard (dual) diameter entity with provided parameters.
@@ -322,7 +337,7 @@ public:
    * indicates that 'ClassCode::Bind' has been correctly performed for any included client-session.
    */
   Entity* createEntity(const std::string & addr1, int port1, const std::string & addr2, int port2, const std::string & description = "")
-  throw(anna::RuntimeException);
+  noexcept(false);
 
 
   /**
@@ -336,7 +351,7 @@ public:
    *
    * \warning If no local server found, an exception is launched by default.
    */
-  LocalServer* findLocalServer(const std::string & addr, int port, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
+  LocalServer* findLocalServer(const std::string & addr, int port, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) noexcept(false);
 
   /**
    * Returns server-session instance identified by INetAddress serialization provided.
@@ -348,7 +363,7 @@ public:
    *
    * \warning If no server-session found, an exception is launched by default.
    */
-  ServerSession* findServerSession(int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
+  ServerSession* findServerSession(int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) noexcept(false);
 
   /**
    * Creates a diameter local server with provided parameters.
@@ -367,7 +382,7 @@ public:
    * \return The local server created or exception when is already created.
    */
   LocalServer *createLocalServer(const std::string & addr, int port = Session::DefaultPort, int maxConnections = -1, const anna::Millisecond & allowedInactivityTime = ServerSession::DefaultAllowedInactivityTime, int category = 1, const std::string & description = "")
-  throw(anna::RuntimeException);
+  noexcept(false);
 
 
   /**
@@ -376,7 +391,7 @@ public:
 
      @param destroy Free all engine entity resources
   */
-  void close(bool destroy = false) throw(anna::RuntimeException) { closeEntities(destroy); closeLocalServers(destroy); }
+  void close(bool destroy = false) noexcept(false) { closeEntities(destroy); closeLocalServers(destroy); }
 
 
   /**
@@ -385,7 +400,7 @@ public:
      Optionally all entities resources may be freed passing true; in this case, close is immediately performed:
      @param destroy Free all engine entity resources
   */
-  void closeEntities(bool destroy = false) throw(anna::RuntimeException);
+  void closeEntities(bool destroy = false) noexcept(false);
 
 
   /**
@@ -395,7 +410,7 @@ public:
    * \param entity Diameter entity to be closed.
    * \param destroy Deletes entity over the engine and all its resources.
    */
-  void closeEntity(Entity* entity, bool destroy = false) throw(anna::RuntimeException);
+  void closeEntity(Entity* entity, bool destroy = false) noexcept(false);
 
 
   /**
@@ -404,7 +419,7 @@ public:
 
      @param destroy Free all engine local servers resources and server sessions within them.
   */
-  void closeLocalServers(bool destroy = false) throw(anna::RuntimeException);
+  void closeLocalServers(bool destroy = false) noexcept(false);
 
   /**
    * Close local server socket and its children server sessions.
@@ -415,49 +430,49 @@ public:
    * \param localServer Local server to be closed.
    * \param destroy Deletes local server over engine and all its resources (server sessions within it).
    */
-  void closeLocalServer(LocalServer * localServer, bool destroy = false) throw(anna::RuntimeException);
+  void closeLocalServer(LocalServer * localServer, bool destroy = false) noexcept(false);
 
   /**
      Gets the number of requests messages over-the-air for entities.
 
      @return OTA messages.
   */
-  int getOTARequestsForEntities() const throw();
+  int getOTARequestsForEntities() const ;
 
   /**
      Gets the number of requests messages over-the-air for local servers.
 
      @return OTA messages.
   */
-  int getOTARequestsForLocalServers() const throw();
+  int getOTARequestsForLocalServers() const ;
 
   /**
      Gets the number of requests messages over-the-air for entities plus local servers.
 
      @return OTA messages.
   */
-  int getOTARequests() const throw() { return (getOTARequestsForEntities() + getOTARequestsForLocalServers()); }
+  int getOTARequests() const { return (getOTARequestsForEntities() + getOTARequestsForLocalServers()); }
 
   /**
      Returns idle state (no pending answers) for entities.
 
      @return Idle state.
   */
-  bool idleForEntities() const throw() { return (getOTARequestsForEntities() == 0); }
+  bool idleForEntities() const { return (getOTARequestsForEntities() == 0); }
 
   /**
      Returns idle state (no pending answers).
 
      @return Idle state.
   */
-  bool idleForLocalServers() const throw() { return (getOTARequestsForLocalServers() == 0); }
+  bool idleForLocalServers() const { return (getOTARequestsForLocalServers() == 0); }
 
   /**
      Returns idle state (no pending answers for entities or local servers).
 
      @return Idle state.
   */
-  bool idle() const throw() { return (getOTARequests() == 0); }
+  bool idle() const { return (getOTARequests() == 0); }
 
   /**
      Sent a message to all the engine entities.
@@ -468,8 +483,8 @@ public:
      @return Returns true (success) only when broadcast is success over all the engine entities. If any entity fails,
      then false is returned. Broadcast try to send all over the resources in spite of any fail.
   */
-  bool broadcastEntities(const Message*message) throw(anna::RuntimeException);
-  bool broadcastEntities(const Message& message) throw(anna::RuntimeException) { return broadcastEntities(&message); }
+  bool broadcastEntities(const Message*message) noexcept(false);
+  bool broadcastEntities(const Message& message) noexcept(false) { return broadcastEntities(&message); }
 
   /**
      Sent a message through all the engine local servers.
@@ -480,93 +495,28 @@ public:
      @return Returns true (success) only when broadcast is success over all the engine local servers. If any local server fails,
      then false is returned. Broadcast try to send all over the resources in spite of any fail.
   */
-  bool broadcastLocalServers(const Message*message) throw(anna::RuntimeException);
-  bool broadcastLocalServers(const Message& message) throw(anna::RuntimeException) { return broadcastLocalServers(&message); }
+  bool broadcastLocalServers(const Message*message) noexcept(false);
+  bool broadcastLocalServers(const Message& message) noexcept(false) { return broadcastLocalServers(&message); }
 
   /**
   * Class string representation
   *
   * @return String with class content
   */
-  virtual std::string asString(void) const throw();
+  virtual std::string asString(void) const ;
 
   /**
      Class XML representation.
      \param parent XML node over which we will put instance information.
      \return XML documentcon with class content.
   */
-  virtual anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
-
-
-  /**
-     When there is not bound server session over the engine, this virtual method will be invoked.
-     Applications must decide to do any other tasks at this idle/isolated situation.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLostForLocalServers(Engine *) const throw() {;}
-
-  /**
-     When there is any bound server session over the engine, this virtual method will be invoked.
-     Applications must decide to do be ready for incoming traffic.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecoveredForLocalServers(Engine *) const throw() {;}
-
-  /**
-     When there is not bound entity over the engine, this virtual method will be invoked.
-     Many applications must change communicator status to Unavailable when no engines are available.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLostForEntities(Engine *) const throw() {;}
-
-  /**
-     When there is any bound entity over the engine, this virtual method will be invoked.
-     Many applications must recover communicator status to Available when any engine are available.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecoveredForEntities(Engine *) const throw() {;}
-
-  /**
-     When there is not bound server-session over the local server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLost(LocalServer *) const throw() {;}
-
-  /**
-     When there is any bound server-session over the local server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecovered(LocalServer *) const throw() {;}
-
-  /**
-     When there is not bound server over the entity, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLost(Entity *) const throw() {;}
-
-  /**
-     When there is any bound server over the entity, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecovered(Entity *) const throw() {;}
-
-  /**
-     When there is not bound client-session over the server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityLost(Server *) const throw() {;}
-
-  /**
-     When there is any bound client-session over the server, this virtual method will be invoked.
-     Default implementation do nothing.
-  */
-  virtual void availabilityRecovered(Server *) const throw() {;}
+  virtual anna::xml::Node* asXML(anna::xml::Node* parent) const ;
 
   /**
      When a subyacent client session is going to be bound, this method is invoked before.
      Default implementation do nothing.
   */
-  virtual void bindingClientSession(const ClientSession *) const throw() {;}
+  virtual void bindingClientSession(const ClientSession *) const {;}
 
   /**
    * Class user should implement this method in order to define Disconnect-Peer-Answer for last received DPR.
@@ -578,14 +528,29 @@ public:
    * @param dpa DPA datablock passed as reference
    * @param dpr Corresponding DPR received (sequence values must be taken into account in order to build DPA)
   */
-  virtual void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) throw();
+  virtual void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) const;
+
+  /**
+   * Sets optional CEA from file, when default is not enough
+   *
+   * @param &ceaPathfile Path file for the CEA xml message provided
+   */
+  void setCEA(const std::string &ceaPathfile) { a_ceaPathfile = ceaPathfile; }
+
+  /**
+   * Gets optional CEA from file, when default is not enough
+   *
+   * @return Path file for the CEA xml message provided
+   */
+  const std::string & getCEA() const { return a_ceaPathfile; }
 
   /**
    * Class user should implement this method in order to define Capabilities-Exchange-Answer for received CER over server socket.
    * Origin-Host and Origin-Realm are configured at comm::Engine with hostname and FQDN (Fully Qualified Domain Name).
    * Default implementation imply CEA with DIAMETER_SUCCESS Result-Code, and own domain node parameters, but application should
    * analyze the CER message in order to accept it or not (with apropiate non-success Result-Code).
-   * Any other implementation is responsible to build a valid CEA diameter message:
+   * If @setCEA was invoked, a message from file is used instead of default implementation.
+   * Any other implementation is responsible to build a valid CEA diameter message, even ignoring a possible cea from file when @setCEA is used:
    *
    * If one peer sends a CER message to another Peer and receiver does not have support for
    *
@@ -608,7 +573,7 @@ public:
    * @param cea CEA datablock passed as reference. Empty cea implies to discard CER received.
    * @param cer Corresponding CER received (sequence values must be taken into account in order to build CEA)
   */
-  virtual void readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) throw();
+  virtual void readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) const;
 
   /**
    * Class user should implement this method in order to define Device-Watchdog-Answer for received DWR over server socket.
@@ -619,33 +584,63 @@ public:
    * @param dwa DWA datablock passed as reference
    * @param dwr Corresponding DWR received (sequence values must be taken into account in order to build DWA)
   */
-  virtual void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) throw();
+  virtual void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) const;
+
+  /**
+   * DRA basics: CER information is gathered on every server session managed by the diameter comm engine. You could send the message to a
+   * specific realm, and optionally you could restrict a host inside it. This is common for requests (answers are normally sent through
+   * the same source server session where the request was received). Exception will be thrown if not found an available server session
+   * for the Destination-Realm and/or Destination-Host provided
+   *
+   * @param destinationRealm If empty, NULL is returned, because is nonsense to specify a host out of realm context
+   * @param destinationHost If empty, no restriction is applied within the target realm node. Random delivery is applied for the available server sessions
+   *
+   * @return transactional response reference, or NULL if answer is sent
+   */
+  const Response* sendRealmHost(const Message* message, const std::string &destinationRealm, const std::string &destinationHost = "") noexcept(false);
 
   /**
      Reset engine statistics.
      At the moment, only diameter servers processing time is observed.
   */
-  void resetStatistics() throw();
+  void resetStatistics() ;
+
+
+  /**
+   * Engine lazy initialization. Used if the engine is created when application is already running; for example
+   * on dynamic realms registration. At the moment is not actually needed (nothing is done at initialization),
+   * but it is recommended to start the component and set its state as 'running' from the point of view of the
+   * application.
+   */
+  void lazyInitialize() noexcept(false);
 
 
 protected:
   /**
      Constructor.
-  */
-  Engine();
 
+     @param className Component class name
+     @param baseProtocolDictionary This will be used internally when calling \@readCEA, \@readDPA and \@readDWA on
+     servers, and also used during base protocol messages tracing (if debug traces are enabled). You could provide
+     NULL, but you must be sure that neither of the former situations are going to happen or an exception will be
+     thrown (using setClientCER and setClientDWR with DataBlock arguments, expects externally encoded messages and could help).
+     It is recommended to set a base protocol dictionary loading 'source/diameter/stack/setups' dictionaries (for
+     example 'avps_ietf.xml' plus 'commands_baseProtocol.xml'), or using the dictionary creation API. The dictionary
+     could also be an application stack, the only condition is containing the resources to build base protocol messages.
+  */
+  Engine(const char *className, const stack::Dictionary *baseProtocolDictionary);
 
   // INTERNAL CREATORS AND CLOSE METHODS
-  Server *createServer(Entity*, const socket_t&) throw(anna::RuntimeException);
-  void closeServer(Server*, bool) throw(anna::RuntimeException);
-  ClientSession *createClientSession(Server*, int) throw(anna::RuntimeException);
-  void closeClientSession(ClientSession*, bool) throw(anna::RuntimeException);
+  Server *createServer(Entity*, const socket_t&) noexcept(false);
+  void closeServer(Server*, bool) noexcept(false);
+  ClientSession *createClientSession(Server*, int) noexcept(false);
+  void closeClientSession(ClientSession*, bool) noexcept(false);
 
   // INTERNAL ALLOCATORS
-  Server* allocateServer() throw();
-  void releaseServer(Server*) throw();
-  ClientSession* allocateClientSession() throw();
-  void releaseClientSession(ClientSession*) throw();
+  Server* allocateServer() ;
+  void releaseServer(Server*) ;
+  ClientSession* allocateClientSession() ;
+  void releaseClientSession(ClientSession*) ;
 
 
   /**
@@ -655,14 +650,14 @@ protected:
 
      \see anna::Recycler
   */
-  virtual Entity* allocateEntity() throw() { return NULL; }
+  virtual Entity* allocateEntity() { return NULL; }
 
 
   /**
      Invoked to free entities.
      \see anna::Recycler
   */
-  virtual void releaseEntity(Entity*) throw() {;}
+  virtual void releaseEntity(Entity*) {;}
 
 
   /**
@@ -672,34 +667,41 @@ protected:
 
      \see anna::Recycler
   */
-  virtual LocalServer* allocateLocalServer() throw() { return NULL; }
+  virtual LocalServer* allocateLocalServer() { return NULL; }
 
 
   /**
      Invoked to free local servers.
      \see anna::Recycler
   */
-  virtual void releaseLocalServer(LocalServer*) throw() {;}
-
+  virtual void releaseLocalServer(LocalServer*) {;}
 
+  //  Gets the base protocol codec engine used internally.
+  //  This engine is initializaed on constructor with the base protocol dictionary.
+  //  The reason to not reuse any other codec engine from the application is to have this one isolated with no interference
+  //  regarding configuration changes (validation depth/mode, fix mode, etc.).
+  //
+  //  @return Pointer to the internal base protocol codec engine
+  codec::Engine *getBaseProtocolCodecEngine() const { return const_cast<codec::Engine *>(&a_baseProtocolCodecEngine); }
 
 private:
 
-  std::string a_realm;
-  std::string a_host;
+  // Internal use: tracing and readCEA/DPA/DWA
+  codec::Engine a_baseProtocolCodecEngine;
+
+  std::string a_originRealm;
+  std::string a_originHost;
   bool a_autoBind;
   int a_numberOfClientSessionsPerServer;
-  bool a_freezeEndToEndOnSending;
 
 
   // ClientSessions messages:
-  anna::DataBlock a_cer;
-  anna::DataBlock a_dwr;
+  anna::DataBlock a_client_cer;
+  anna::DataBlock a_client_dwr;
   anna::Millisecond a_watchdogPeriod;
 
-//   // ServerSessions messages:
-//   anna::DataBlock a_cea;
-//   anna::DataBlock a_dwa;
+  // ServerSessions messages: no need for DWA and DPA templates, they are built on the fly (enough information).
+  std::string a_ceaPathfile; // path file to optional CEA (diameter local server configuration)
 
   // Client connectivity
   anna::Millisecond a_maxConnectionDelay;
@@ -707,30 +709,30 @@ private:
 
   // Availability
   bool a_availableForEntities; // any of the entities must be bound
-  void availabilityLostForEntities() throw();
-  void availabilityRecoveredForEntities() throw();
-  bool refreshAvailabilityForEntities() throw(); // return true if change
+  void availabilityLostForEntities() ;
+  void availabilityRecoveredForEntities() ;
+  bool refreshAvailabilityForEntities() ; // return true if change
 
   bool a_availableForLocalServers; // any of the local servers must be bound
-  void availabilityLostForLocalServers() throw();
-  void availabilityRecoveredForLocalServers() throw();
-  bool refreshAvailabilityForLocalServers() throw(); // return true if change
+  void availabilityLostForLocalServers() ;
+  void availabilityRecoveredForLocalServers() ;
+  bool refreshAvailabilityForLocalServers() ; // return true if change
 
-  void eraseDeprecatedIdleEntities() throw();
+  void eraseDeprecatedIdleEntities() ;
 
   // Component:
-  void do_initialize() throw() {;}
-  void do_stop() throw();
+  void do_initialize() noexcept(false);
+  void do_stop() ;
 
   // Integrity:
-  void checkEntityCollision(const socket_v &) throw(anna::RuntimeException);
+  void checkEntityCollision(const socket_v &) noexcept(false);
+  void assertBaseProtocolHealth() const noexcept(false); // checks the dictionary
 
 
   //////////////////////////
   // CLIENT FUNCTIONALITY //
   //////////////////////////
 
-  //typedef int clientSession_key; // exclusiveHash('ADDR:PORT|id')
   typedef std::string clientSession_key; // 'ADDR:PORT|id'
   typedef std::map <clientSession_key, ClientSession*> clientSession_container;
   typedef clientSession_container::value_type clientSession_value_type;
@@ -738,46 +740,45 @@ private:
   typedef clientSession_container::const_iterator const_clientSession_iterator;
   clientSession_container a_clientSessions;
   anna::Recycler<ClientSession> a_clientSessionsRecycler;
-  clientSession_iterator clientSession_find(const clientSession_key&) throw();
-  clientSession_iterator clientSession_begin() throw() { return a_clientSessions.begin(); }
-  clientSession_iterator clientSession_end() throw() { return a_clientSessions.end(); }
-  static ClientSession* clientSession(clientSession_iterator ii) throw() { return ii->second; }
-  const_clientSession_iterator clientSession_begin() const throw() { return a_clientSessions.begin(); }
-  const_clientSession_iterator clientSession_end() const throw() { return a_clientSessions.end(); }
-  static const ClientSession* clientSession(const_clientSession_iterator ii) throw() { return ii->second; }
+  clientSession_iterator clientSession_find(const clientSession_key&) ;
+  clientSession_iterator clientSession_begin() { return a_clientSessions.begin(); }
+  clientSession_iterator clientSession_end() { return a_clientSessions.end(); }
+  static ClientSession* clientSession(clientSession_iterator ii) { return ii->second; }
+  const_clientSession_iterator clientSession_begin() const { return a_clientSessions.begin(); }
+  const_clientSession_iterator clientSession_end() const { return a_clientSessions.end(); }
+  static const ClientSession* clientSession(const_clientSession_iterator ii) { return ii->second; }
 
   typedef socket_t server_key;
-  server_key getServerKey(const std::string & addr, int port) const throw();
+  server_key getServerKey(const std::string & addr, int port) const ;
   typedef std::map <server_key, Server*> server_container;
   typedef server_container::value_type server_value_type;
   typedef server_container::iterator server_iterator;
   typedef server_container::const_iterator const_server_iterator;
   server_container a_servers;
   anna::Recycler<Server> a_serversRecycler;
-  server_iterator server_find(const server_key&) throw();
-  server_iterator server_begin() throw() { return a_servers.begin(); }
-  server_iterator server_end() throw() { return a_servers.end(); }
-  static Server* server(server_iterator ii) throw() { return ii->second; }
-  const_server_iterator server_begin() const throw() { return a_servers.begin(); }
-  const_server_iterator server_end() const throw() { return a_servers.end(); }
-  static const Server* server(const_server_iterator ii) throw() { return ii->second; }
-
-  //typedef int entity_key; // exclusiveHash('IP1:PORT1 IP2:PORT2 IP3:PORT3 ...')
+  server_iterator server_find(const server_key&) ;
+  server_iterator server_begin() { return a_servers.begin(); }
+  server_iterator server_end() { return a_servers.end(); }
+  static Server* server(server_iterator ii) { return ii->second; }
+  const_server_iterator server_begin() const { return a_servers.begin(); }
+  const_server_iterator server_end() const { return a_servers.end(); }
+  static const Server* server(const_server_iterator ii) { return ii->second; }
+
   typedef std::string entity_key; // 'ADDR1:PORT1 ADDR2:PORT2 ADDR3:PORT3 ...'
-  entity_key getEntityKey(const socket_v &) const throw();
-  entity_key getEntityKey(const std::string & addr1, int port1, const std::string & addr2, int port2) const throw();
+  entity_key getEntityKey(const socket_v &) const ;
+  entity_key getEntityKey(const std::string & addr1, int port1, const std::string & addr2, int port2) const ;
   typedef std::map <entity_key, Entity*> entity_container;
   typedef entity_container::value_type entity_value_type;
   typedef entity_container::iterator entity_iterator;
   typedef entity_container::const_iterator const_entity_iterator;
   entity_container a_entities;
-  entity_iterator entity_find(const entity_key&) throw();
-  entity_iterator entity_begin() throw() { return a_entities.begin(); }
-  entity_iterator entity_end() throw() { return a_entities.end(); }
-  static Entity* entity(entity_iterator ii) throw() { return ii->second; }
-  const_entity_iterator entity_begin() const throw() { return a_entities.begin(); }
-  const_entity_iterator entity_end() const throw() { return a_entities.end(); }
-  static const Entity* entity(const_entity_iterator ii) throw() { return ii->second; }
+  entity_iterator entity_find(const entity_key&) ;
+  entity_iterator entity_begin() { return a_entities.begin(); }
+  entity_iterator entity_end() { return a_entities.end(); }
+  static Entity* entity(entity_iterator ii) { return ii->second; }
+  const_entity_iterator entity_begin() const { return a_entities.begin(); }
+  const_entity_iterator entity_end() const { return a_entities.end(); }
+  static const Entity* entity(const_entity_iterator ii) { return ii->second; }
 
 
   //////////////////////////
@@ -790,18 +791,30 @@ private:
   typedef localServer_container::iterator localServer_iterator;
   typedef localServer_container::const_iterator const_localServer_iterator;
   localServer_container a_localServers;
-  localServer_iterator localServer_find(const socket_t&) throw();
-  localServer_iterator localServer_begin() throw() { return a_localServers.begin(); }
-  localServer_iterator localServer_end() throw() { return a_localServers.end(); }
-  static LocalServer* localServer(localServer_iterator ii) throw() { return ii->second; }
-  const_localServer_iterator localServer_begin() const throw() { return a_localServers.begin(); }
-  const_localServer_iterator localServer_end() const throw() { return a_localServers.end(); }
-  static const LocalServer* localServer(const_localServer_iterator ii) throw() { return ii->second; }
-
-  // Server sessions are managed within LocalServer (not at engine) due to dynamic cration nature
-
+  localServer_iterator localServer_find(const socket_t&) ;
+  localServer_iterator localServer_begin() { return a_localServers.begin(); }
+  localServer_iterator localServer_end() { return a_localServers.end(); }
+  static LocalServer* localServer(localServer_iterator ii) { return ii->second; }
+  const_localServer_iterator localServer_begin() const { return a_localServers.begin(); }
+  const_localServer_iterator localServer_end() const { return a_localServers.end(); }
+  static const LocalServer* localServer(const_localServer_iterator ii) { return ii->second; }
+
+  // Server sessions are managed within LocalServer (not at engine) due to dynamic creation nature
+  // Here we maintain the Destination-Realm / Destination-Host maps for DRA basics:
+  typedef std::vector<ServerSession*> server_sessions_vector_t;
+  typedef server_sessions_vector_t::const_iterator server_sessions_it_t;
+  typedef server_sessions_vector_t::iterator server_sessions_nc_it_t;
+  typedef std::map <std::string /* Destination-Host */, server_sessions_vector_t> dh_server_sessions_map_t;
+  typedef dh_server_sessions_map_t::const_iterator dh_server_sessions_it_t;
+  typedef dh_server_sessions_map_t::iterator dh_server_sessions_nc_it_t;
+  typedef std::map <std::string /* Destination-Realm */, dh_server_sessions_map_t> dr_dh_server_sessions_map_t;
+  typedef dr_dh_server_sessions_map_t::const_iterator dr_dh_server_sessions_it_t;
+  typedef dr_dh_server_sessions_map_t::iterator dr_dh_server_sessions_nc_it_t;
+  dr_dh_server_sessions_map_t a_dr_dh_server_sessions;
+  void manageDrDhServerSession(ServerSession *ss, bool register_or_desregister) ;
 
   friend class Session;
+  friend class ClientSession;
   friend class ServerSession;
   friend class ServerSocket;
   friend class Server;