Fixes and improvs. Basic DRA feature.
[anna.git] / include / anna / diameter.comm / Engine.hpp
index 8ec2757..742c0fc 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>
@@ -47,9 +49,13 @@ namespace codec {
 class Engine;
 }
 
-namespace comm {
+namespace stack {
+class Dictionary;
+}
 
+namespace comm {
 
+class Response;
 class Entity;
 class Server;
 class LocalServer;
@@ -94,27 +100,6 @@ class LocalServer;
 class Engine : public anna::app::Component {
 public:
 
-  /**
-   * Sets the base protocol codec engine used internally
-   *
-   * @param baseProtocolCodecEngine This will be used internally during invokation of @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. It is recommended to register
-   * a codec engine pointed to a base protocol stack (you can use the files 'avps_ietf.xml' and 'commands_baseProtocol.xml'
-   * located on ANNA suite project under 'source/diameter/stack/setups', or perhaps you can create your own dictionary from
-   * file or directly with the dictionay creation API. Even you can use a greater dictionary (application dictionary), the
-   * only condition is that must contain the resources to build base protocol messages. You could provide this in engine constructor,
-   * but don't forget it.
-  */
-  void setBaseProtocolCodecEngine(codec::Engine *baseProtocolCodecEngine) throw() { a_baseProtocolCodecEngine = baseProtocolCodecEngine; }
-
-  /**
-   * Gets the base protocol codec engine used internally
-   *
-   * @see setBaseProtocolCodecEngine
-   */
-  codec::Engine * getBaseProtocolCodecEngine() const throw() { return a_baseProtocolCodecEngine; }
-
   /**
      Diameter application node realm name (used to be the site domain name).
 
@@ -632,6 +617,19 @@ public:
   */
   virtual void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) throw();
 
+  /**
+   * 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 = "") throw(anna::RuntimeException);
+
   /**
      Reset engine statistics.
      At the moment, only diameter servers processing time is observed.
@@ -653,17 +651,15 @@ protected:
      Constructor.
 
      @param className Component class name
-     @param baseProtocolCodecEngine This will be used internally during invokation of @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. It is recommended to register
-     a codec engine pointed to a base protocol stack (you can use the files 'avps_ietf.xml' and 'commands_baseProtocol.xml'
-     located on ANNA suite project under 'source/diameter/stack/setups', or perhaps you can create your own dictionary from
-     file or directly with the dictionay creation API. Even you can use a greater dictionary (application dictionary), the
-     only condition is that must contain the resources to build base protocol messages. You could use @setBaseProtocolCodecEngine
-     to set this reference later; don't forget it.
+     @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 setClientCERandDWR 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, codec::Engine *baseProtocolCodecEngine);
-
+  Engine(const char *className, const stack::Dictionary *baseProtocolDictionary);
 
   // INTERNAL CREATORS AND CLOSE METHODS
   Server *createServer(Entity*, const socket_t&) throw(anna::RuntimeException);
@@ -712,11 +708,10 @@ protected:
   virtual void releaseLocalServer(LocalServer*) throw() {;}
 
 
-
 private:
 
   // Internal use: tracing and readCEA/DPA/DWA
-  codec::Engine *a_baseProtocolCodecEngine;
+  codec::Engine a_baseProtocolCodecEngine;
 
   std::string a_realm;
   std::string a_host;
@@ -756,8 +751,17 @@ private:
 
   // Integrity:
   void checkEntityCollision(const socket_v &) throw(anna::RuntimeException);
+  void assertBaseProtocolHealth() throw(anna::RuntimeException); // checks the dictionary
 
 
+  //  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 throw() { return const_cast<codec::Engine *>(&a_baseProtocolCodecEngine); }
+
   //////////////////////////
   // CLIENT FUNCTIONALITY //
   //////////////////////////
@@ -830,10 +834,22 @@ private:
   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
-
+  // 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) throw();
 
   friend class Session;
+  friend class ClientSession;
   friend class ServerSession;
   friend class ServerSocket;
   friend class Server;