X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=include%2Fanna%2Fdiameter.comm%2FEntity.hpp;h=b8ade9be4792bccadcc0e545f3f804bafa7c4f21;hb=5a6cba5fde2b2f538a7515f8293cc0a8d9589dfa;hp=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391;hpb=705d780f70b3596a222479ec7ad0dc3b3ab192cf;p=anna.git diff --git a/include/anna/diameter.comm/Entity.hpp b/include/anna/diameter.comm/Entity.hpp index e69de29..b8ade9b 100644 --- a/include/anna/diameter.comm/Entity.hpp +++ b/include/anna/diameter.comm/Entity.hpp @@ -0,0 +1,518 @@ +// 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_Entity_hpp +#define anna_diameter_comm_Entity_hpp + + +// STL +#include +#include + +#include + +#include +#include + +#include + + +namespace anna { +class DataBlock; +namespace xml { +class Node; +} +} + + + +namespace anna { + +namespace diameter { + +namespace comm { + +class Engine; +class Server; +class Response; +class Message; +class ClientSession; + + +/** + Generic diameter server list (N-servers entity) +*/ +class Entity { + +public: + + /** + * Sessions based models type + */ + struct SessionBasedModelsType { enum _v { RoundRobin, SessionIdOptionalPart, SessionIdHighPart, SessionIdLowPart /* default */ }; }; + +private: + + + std::vector a_servers; + int a_maxServers; // -1 means "no limit to add servers" + std::string a_description; + int a_category; + std::vector::iterator a_deliveryIterator; + Server *a_lastUsedResource; + + // Engine + Engine *a_engine; + + // Balance and socket selection: + bool a_balance; + SessionBasedModelsType::_v a_sessionBasedModelsType; + + // Availability + bool a_available; // any of the servers must be bound + void availabilityLost() ; + void availabilityRecovered() ; + bool refreshAvailability() ; // return true if change + void assertReady() noexcept(false); + void initialize() ; + void childIdle() const ; + + // Selected for remove + bool a_deprecated; // entity has been selected as deprecated (will be removed when idle) + + // internal helpers + std::string a_socketListLiteral; // ADDRESS:PORT space-separated list + std::string a_primarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities) + std::string a_secondarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities) + + + // Activity + anna::Millisecond a_lastIncomingActivityTime; // last unix timestamp (in milliseconds) when message reception was managed over this entity + anna::Millisecond a_lastOutgoingActivityTime; // last unix timestamp (in milliseconds) when message sending was managed over this entity + void updateIncomingActivityTime() ; + void updateOutgoingActivityTime() ; + + // Private close/destroy method + void close(bool destroy) noexcept(false); + + // helpers + static const char* asText(const SessionBasedModelsType::_v) ; + +public: + + + /** + * Default constructor. Entities should be create through diameter::comm::Engine + * @param maxServers Maximum number of servers managed by the entity. Default is 2 (standard/dual entity). + * The value -1, means no limit to add servers. + */ + Entity(int maxServers = 2) : a_maxServers(maxServers) { initialize(); } + + + /** + * Sets the maximum number of servers managed by the entity. + * + * @param maxServers Maximum number of servers managed by the entity. + */ + void setMaxServers(int maxServers) { a_maxServers = maxServers; } + + /** + * Gets the maximum number of servers managed by the entity. + * + * @return Maximum number of servers managed by the entity. + */ + int getMaxServers() const { return a_maxServers; } + + + /** + * Sets the entity description. + * + * @param description Entity description. Empty by default. + */ + void setDescription(const std::string &description) { a_description = description; } + + /** + * Gets the entity description. + * + * @return Entity description. + */ + const std::string & getDescription() const { return a_description; } + + + /** + * Sets the diameter::comm::Engine + * @param e Diameter::comm::Engine + */ + void setEngine(Engine *e) { a_engine = e; } + + /** + * Gets the diameter::comm::Engine + * @return Diameter::comm::Engine + */ + Engine *getEngine() const { return a_engine; } + + /** + * Add a server to the entity and create all the servers configured at #setSocketsPerDiameterServer within that server. + * + * \param serverId Diameter server ip/port. + * + * @return Returns success on send operation over any server within the entity + */ + void addServer(const socket_t & serverId) noexcept(false); + + /** + * Binds entity servers. + * + * @return Returns true if all client-session were successfully bound + */ + bool bind() noexcept(false); + + /** + * Propagate auto recovery configuration to servers within entity + * + * @param autoRecovery Auto recovery indicator. True by default. + */ + void raiseAutoRecovery(bool autoRecovery = true) noexcept(false); + + /** + Sets timeout for wait responses for any class code request for all entity servers + + \param v Diameter request type. + \param millisecond Milliseconds for timeout + */ + void setClassCodeTimeout(const ClassCode::_v v, const anna::Millisecond & millisecond) ; + + /** + Sets entity category. Used by application in order to categorize or clasify. + + @param category Entity category + */ + void setCategory(int category) { a_category = category; } + + /** + Gets entity category. Used by application in order to categorize or clasify. + + @return Entity category + */ + int getCategory() const { return a_category; } + + /** + Gets the last used resource (server) during sending. + Broadcast doesn't updates this information. + */ + Server *getLastUsedResource() const { return (a_lastUsedResource); } + + + /** + * Balance over entity servers or use standard behaviour (first primary, secondary if fails, etc.). + * New created entities have balance disabled. + * + * @param balance True or false to enable or disable. + */ + void setBalance (bool balance) { a_balance = balance; } + + /** + * Gets the balance mode + * + * @return True if balance over entity servers is enabled, false if standard behaviour is configured (default). + */ + bool getBalance() const { return a_balance; } + + +// SIMPLE BALANCE or STANDARD documentation version +// /** +// Sent a message to the entity. First uses primary server, secondary if fails and so on to the +// last defined resource (server) within entity. Another sending algorithm (non standard) could +// be enabled (balance boolean parameter): it consist in round-robin server selection without +// trying any one if fails (standard behaviour tries all servers from FIRST defined). +// Anyway, last used delivery resource could be known through #getLastUsedResource(). +// +// When the message is a request, a timer will be set automatically to control the response time. +// If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This +// timeout value will be configured at #setClassCodeTimeout. +// +// \param message Message sent. +// \param balance False by default (standard beaviour), but useful to balance over servers within entity. +// +// @return Boolean about success in send operation. Standard behaviour (no balance) implies true result when any +// of the entity servers could send the message, and false when neither of the servers was available or fail to +// send the message. Broadcast try to send all over the resources in spite of any fail, and balanced sendings +// fails when next selected resource fail to send the message (and no alarm or error counter is generated in +// this case because it can't be understood/ensured as entity-sending fail. +// */ + +// OJO: en el caso estandard, no se prueban todas las sessiones de un servidor si tiene mas de una, luego la alarma +// generada en caso de error, presupone que las sessiones no usadas, tambi�n dar�an error, lo cual no tiene porque +// ser cierto. En condiciones normales, los servidores tienen una session, con lo que lo anterior es cierto y el +// la practica es lo mas normal. + + /** + Sent a message to the entity. First uses primary server, secondary if fails and so on to the + last defined resource (server) within entity. Another sending algorithm (non standard) could + be enabled (@setBalance): it consist in round-robin server selection to set the first resource + in a complete cycle (standard behaviour tries all servers from FIRST defined). + Anyway, last used delivery resource could be known through #getLastUsedResource(). + + When the message is a request, a timer will be set automatically to control the response time. + If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This + timeout value will be configured at #setClassCodeTimeout. + + \param message Message sent. + + @return Boolean about success in send operation. Implies true result when any of the entity servers could + send the message, and false when neither of the servers was available or fail to send the message (an alarm + and error counter will be generated in this case). Broadcast try to send all over the resources in spite of + any fail. + */ + bool send(const Message *message) noexcept(false); + bool send(const Message &message) noexcept(false) { return send(&message); } + + /** + * Sets sessions based models type. + * \param sessionBasedModelsType Session based models type: RoundRobin, SessionIdLowPart (default), SessionIdHighPart or SessionIdOptionalPart. + */ + void setSessionBasedModelsType(const SessionBasedModelsType::_v sessionBasedModelsType) { a_sessionBasedModelsType = sessionBasedModelsType; } + + /** + * Returns sessions based models type. + * \return Session based models type: RoundRobin, SessionIdLowPart, SessionIdHighPart or SessionIdOptionalPart. + */ + SessionBasedModelsType::_v getSessionBasedModelsType() const { return a_sessionBasedModelsType; } + + + /** + Before sending a message over each entity server, socketId could be specified to select + which client session within such server will manage the message. + + Default implementation has been focused on charging applications but any other kind of + application could re-implement this method and change the behaviour: + +
+     Charging involves two peers:
+
+        Charging Trigger Function (CTF): Makes decisions on how to charge the user for specific
+                                         services, issues requests to the server (OCF).
+        Online Charging Function (OCF):  Performs actual charging based on received message type,
+                                         service logic and user profile information.
+
+     There are three main scenarios:
+
+        Immediate Event Charging (IEC): The CTF sends a one time request. This request contains
+                                        a predefined set of AVPs indicating which service has
+                                        been activated or how many units have been consumed
+                                        (this depends on application logic).
+
+        Event Charging with Unit Reservation (ECUR): The CTF issues a request which indicates the
+                                                     desired unit count for reservation. On service
+                                                     delivery, the CTF issues another request which
+                                                     indicates how many units were actually consumed.
+                                                     Units can be of any type, as they are application
+                                                     specific.
+
+        Session Charging with Unit Reservation(SCUR): As above, however reservation can happen more than once.
+
+     In order to minimize race conditions within trasactions, default implementation will select the connection
+     fixed by an stickiness value (Session-Id will be used) for ECUR and SCUR models (Data, Voice and Content
+     traffic). IEC model, represented by SMS ans MMS traffic will use round-robin between sockets. The type
+     of traffic will be analyzed by mean Service-Context-Id AVP. If traffic type is not reconized, value of
+     '-1' will be returned doing round-robin socket selection within active server.
+
+     Diameter session-oriented load balancing enables to distribute Diameter signaling traffic across
+     multiple client sessions for the selected entity server. Application could re-implement different
+     load balancing policies, including support for session stickiness and business decisions, and
+     subscriber and service aware contextual load balancing strategies. By default, Session-Id avp
+     is used to select the resource. Session-Id is split into 4 sections: diameter identity, high
+     part, low part and optional part. Default implementation analizes 'low' part, returning its
+     value as reference for socket selection. Use @setSessionBasedModelsType to change this behaviour.
+     
+ + When server is configured as single client session (max client sessions equal to 1), entity will ignore + this method being more efficient, because former algorithms would not affect the session selection. + + \param message Message which is being sent. + \param maxClientSessions Number of client-sessions on specific server prepared for send. + + @return Socket-id used within range [0,maxClientSessions-1]. Value '-1' if round-robin is desired. + If socket-id is return out of range, send procedure will throw an exception. + */ + virtual int readSocketId(const Message *message, int maxClientSessions) const ; + + + /** + Sent a message to all the entity servers. + It is used, i.e., in Disconnect-Peer-Request procedure over a certain entity. + + \param message Message which is being sent. + + @return Returns true (success) only when broadcast is success over all the entity servers. If any server fails, + then false is returned. + */ + bool broadcast(const Message *message) noexcept(false); + bool broadcast(const Message &message) noexcept(false) { return broadcast(&message); } + + + /** + Returns true when any of the entity servers is Bound. False when all not-bound. + */ + bool isAvailable() const { return a_available; } + + /** + Returns true when the entity has been selected as deprecated + */ + bool isDeprecated() const { return a_deprecated; } + + /** + Sets the entity deprecated state + */ + void setDeprecated(bool deprecated = true) { a_deprecated = deprecated; } + + + /** + Gets the number of requests messages over-the-air. + + @return OTA messages. + */ + int getOTARequests() const ; + + /** + Returns idle state (no pending answers). + + @return Idle state. + */ + bool idle() const { return (getOTARequests() == 0); } + + + std::vector::iterator begin() { return a_servers.begin(); } + std::vector::iterator end() { return a_servers.end(); } + std::vector::const_iterator begin() const { return a_servers.begin(); } + std::vector::const_iterator end() const { return a_servers.end(); } + + /** + Close all the entity servers (close client-sessions within them). Depending on client-session configuration ('OnDisconnect' behaviour), + pending answers will be wait (graceful) or ignored (immediate-abrupt close). + Resources are not destroyed. + */ + void close() noexcept(false) { close(false /* no destroy */); } + + // helpers + + /** + Number of currently configured servers + */ + int getNumberOfServers() const { return a_servers.size(); } + + /** + Number of maximum allowed servers + */ + int getMaxServerss() const { return a_maxServers; } + + /** + List of (address,port) pairs defining entity servers + */ + socket_v getAddressPortList() const ; + + + /** + Deny resources for delivery restriction. + Deny all its servers + */ + void hide() ; + + /** + Allow resource for delivery permission. + Allow all its servers + */ + void show() ; + + /** + Returns true when all its servers resources are hidden for application messages delivery + */ + bool hidden() const ; + + /** + Returns true when all its servers resources are shown for application messages delivery + */ + bool shown() const ; + + + /** + Class string representation + \return String with relevant information for this instance. + */ + std::string asString() const ; + + /** + Class xml representation + \param parent Parent XML node on which hold this instance information. + \return XML document with relevant information for this instance. + */ + anna::xml::Node* asXML(anna::xml::Node* parent) const ; + +protected: + + /** + Handler about event break connection from diameter server (server) over this entity. + When notified, ANNA.diameter.comm generates an diameter::comm::Entity::eventResponse for every request with pending answers. + Default implementation traces warning event + \param clientSession ClientSession from which shutdown has been received + */ + virtual void eventPeerShutdown(const ClientSession* clientSession) ; + + /** + Handler about a request retransmission over the session. + Default implementation traces warning event + \param clientSession ClientSession from which retransmission happened + \param request Retransmitted request message + */ + virtual void eventRequestRetransmission(const ClientSession* clientSession, Message *request) ; + + /** + Handler for diameter server (server) responses + + \param response Answer container object for corresponding diameter request + */ + virtual void eventResponse(const Response& response) noexcept(false) = 0; + + /** + Handler for diameter server (server) requests + + \param clientSession ClientSession from which request has been received + \param request Diameter request message received + */ + virtual void eventRequest(ClientSession* clientSession, const anna::DataBlock &request) noexcept(false) = 0; + //virtual void eventRequest(ClientSession* clientSession, const Message& request) noexcept(false) = 0; + + /** + Handler for diameter session responses out of context + + \param clientSession ClientSession from which request has been received + \param response Answer data block object without context match + */ + virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response) noexcept(false) = 0; + + /** + Handler for diameter session Disconnect-Peer-Answer messages + + \param clientSession ClientSession from which request has been received + \param response Answer data block object without context match + */ + virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response) noexcept(false) = 0; + + + + + friend class Engine; + friend class Server; +}; + +} +} +} + +#endif +