-// ANNA - Anna is Not 'N' Anymore
-//
-// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
-//
-// https://bitbucket.org/testillano/anna
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Authors: eduardo.ramos.testillano@gmail.com
-// cisco.tierra@gmail.com
+// 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 anna_diameter_comm_Engine_hpp
// 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;
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).
* @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.
*/
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; }
-
- /**
- * 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.
*/
virtual void availabilityRecovered(Server *) const throw() {;}
+ /**
+ 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() {;}
+
/**
* Class user should implement this method in order to define Disconnect-Peer-Answer for last received DPR.
* Origin-Host and Origin-Realm are configured at comm::Engine with hostname and FQDN (Fully Qualified Domain Name).
*/
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() {;}
-
private:
+ // Internal use: tracing and readCEA/DPA/DWA
+ codec::Engine a_baseProtocolCodecEngine;
+
std::string a_realm;
std::string a_host;
bool a_autoBind;
int a_numberOfClientSessionsPerServer;
- bool a_freezeEndToEndOnSending;
// ClientSessions messages:
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
+ // 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 //
//////////////////////////
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;