// 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>
class Engine;
}
-namespace comm {
+namespace stack {
+class Dictionary;
+}
+namespace comm {
+class Response;
class Entity;
class Server;
class LocalServer;
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 originRealm 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 setOriginRealm(const std::string & originRealm) throw();
/**
- Gets the configured diameter application node realm name.
+ Diameter application origin host
- @return Diameter application node realm name.
+ @param originHost 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 setOriginHost(const std::string & originHost) throw();
/**
- 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 & getOriginRealm() const throw() { 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 & getOriginHost() const throw() { return a_originHost; }
/**
* @param cer Capabilities-Exchange-Request message (encoded) for the client-sessions bind.
* @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 setClientCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) throw(anna::RuntimeException);
+ /**
+ * Sets CER and DWR diameter messages to be used over created client-sessions. If empty string is provided for CER and/or DWR, default version will be configured.
+ * Its recommended to set this global configuration although it is possible to configure each client-session separately.
+ *
+ * @param cer Capabilities-Exchange-Request xml message path file for the client-sessions bind. If empty string is provided (default), a default version for CER will be encoded.
+ * @param dwr Device-Watchdog-Request xml message path file for the client-sessions keep-alive. If empty string is provided (default), a default version for DWR will be encoded.
+ */
+ void setClientCERandDWR(const std::string & cer = "", const std::string & dwr = "") throw(anna::RuntimeException);
/**
* Sets the watchdog period (DWR) for client-sessions.
*/
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.
void resetStatistics() throw();
+ /**
+ * 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() throw(RuntimeException);
+
+
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 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, const stack::Dictionary *baseProtocolDictionary);
// INTERNAL CREATORS AND CLOSE METHODS
Server *createServer(Entity*, const socket_t&) throw(anna::RuntimeException);
*/
virtual void releaseLocalServer(LocalServer*) throw() {;}
-
+ // 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); }
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;
void eraseDeprecatedIdleEntities() throw();
// Component:
- void do_initialize() throw() {;}
+ void do_initialize() throw(anna::RuntimeException);
void do_stop() throw();
// Integrity:
void checkEntityCollision(const socket_v &) throw(anna::RuntimeException);
+ void assertBaseProtocolHealth() throw(anna::RuntimeException); // checks the dictionary
//////////////////////////
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;