-// 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 <string>
-#include <vector>
-
-#include <anna/config/defines.hpp>
-
-#include <anna/core/RuntimeException.hpp>
-#include <anna/core/util/Millisecond.hpp>
-
-
-namespace anna {
-class DataBlock;
-namespace xml {
-class Node;
-}
-}
-
-
-
-namespace anna {
-
-namespace diameter {
-
-namespace comm {
-
-class Engine;
-class Server;
-class Response;
-class Message;
-
-
-/**
- Generic diameter server list (N-servers entity)
-*/
-class Entity {
-
- std::vector<Server*> a_servers;
- int a_maxServers; // -1 means "no limit to add servers"
- std::string a_description;
- int a_category;
- std::vector<Server*>::iterator a_deliveryIterator;
- Server *a_lastUsedResource;
-
- // Engine
- Engine *a_engine;
-
- // Availability
- bool a_available; // any of the servers must be bound
- void availabilityLost() throw();
- void availabilityRecovered() throw();
- bool refreshAvailability() throw(); // return true if change
- void assertReady() throw(anna::RuntimeException);
- void initialize() throw();
- void childIdle() const throw();
-
- // 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() throw();
- void updateOutgoingActivityTime() throw();
-
- // Private close/destroy method
- void close(bool destroy) throw(anna::RuntimeException);
-
-
-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) throw() { 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 throw() { return a_maxServers; }
-
-
- /**
- * Sets the entity description.
- *
- * @param description Entity description. Empty by default.
- */
- void setDescription(const std::string &description) throw() { a_description = description; }
-
- /**
- * Gets the entity description.
- *
- * @return Entity description.
- */
- const std::string & getDescription() const throw() { return a_description; }
-
-
- /**
- * Sets the diameter::comm::Engine
- * @param e Diameter::comm::Engine
- */
- void setEngine(Engine *e) throw() { a_engine = e; }
-
-
- /**
- * 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) throw(anna::RuntimeException);
-
- /**
- * Binds entity servers.
- *
- * @return Returns true if all client-session were successfully bound
- */
- bool bind() throw(anna::RuntimeException);
-
- /**
- * Propagate auto recovery configuration to servers within entity
- *
- * @param autoRecovery Auto recovery indicator. True by default.
- */
- void raiseAutoRecovery(bool autoRecovery = true) throw(anna::RuntimeException);
-
- /**
- 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) throw();
-
- /**
- Sets entity category. Used by application in order to categorize or clasify.
-
- @param category Entity category
- */
- void setCategory(int category) throw() { a_category = category; }
-
- /**
- Gets entity category. Used by application in order to categorize or clasify.
-
- @return Entity category
- */
- int getCategory() const throw() { return a_category; }
-
- /**
- Gets the last used resource (server) during sending.
- Broadcast doesn't updates this information.
- */
- Server *getLastUsedResource() const throw() { return (a_lastUsedResource); }
-
-
-
-// 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 (balance boolean parameter): 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.
- \param balance False by default (standard beaviour), but useful to balance over servers within entity.
-
- @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, bool balance = false) throw(anna::RuntimeException);
- bool send(const Message &message, bool balance = false) throw(anna::RuntimeException) { return send(&message, balance); }
-
-
- /**
- 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:
-
- <pre>
- 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.
- </pre>
-
- 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 throw();
-
-
- /**
- 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) throw(anna::RuntimeException);
- bool broadcast(const Message &message) throw(anna::RuntimeException) { return broadcast(&message); }
-
-
- /**
- Returns true when any of the entity servers is Bound. False when all not-bound.
- */
- bool isAvailable() const throw() { return a_available; }
-
- /**
- Returns true when the entity has been selected as deprecated
- */
- bool isDeprecated() const throw() { return a_deprecated; }
-
- /**
- Sets the entity deprecated state
- */
- void setDeprecated(bool deprecated = true) throw() { a_deprecated = deprecated; }
-
-
- /**
- Gets the number of requests messages over-the-air.
-
- @return OTA messages.
- */
- int getOTARequests() const throw();
-
- /**
- Returns idle state (no pending answers).
-
- @return Idle state.
- */
- bool idle() const throw() { return (getOTARequests() == 0); }
-
-
- std::vector<Server*>::iterator begin() throw() { return a_servers.begin(); }
- std::vector<Server*>::iterator end() throw() { return a_servers.end(); }
- std::vector<Server*>::const_iterator begin() const throw() { return a_servers.begin(); }
- std::vector<Server*>::const_iterator end() const throw() { 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() throw(anna::RuntimeException) { close(false /* no destroy */); }
-
- // helpers
-
- /**
- Number of currently configured servers
- */
- int getNumberOfServers() const throw() { return a_servers.size(); }
-
- /**
- Number of maximum allowed servers
- */
- int getMaxServerss() const throw() { return a_maxServers; }
-
- /**
- List of (address,port) pairs defining entity servers
- */
- socket_v getAddressPortList() const throw();
-
-
- /**
- Deny resources for delivery restriction.
- Deny all its servers
- */
- void hide() throw();
-
- /**
- Allow resource for delivery permission.
- Allow all its servers
- */
- void show() throw();
-
- /**
- Returns true when all its servers resources are hidden for application messages delivery
- */
- bool hidden() const throw();
-
- /**
- Returns true when all its servers resources are shown for application messages delivery
- */
- bool shown() const throw();
-
-
- /**
- Class string representation
- \return String with relevant information for this instance.
- */
- std::string asString() const throw();
-
- /**
- 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 throw();
-
-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) throw();
-
- /**
- Handler for diameter server (server) responses
-
- \param response Answer container object for corresponding diameter request
- */
- virtual void eventResponse(const Response& response) throw(anna::RuntimeException) = 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) throw(anna::RuntimeException) = 0;
- //virtual void eventRequest(ClientSession* clientSession, const Message& request) throw(anna::RuntimeException) = 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) throw(anna::RuntimeException) = 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) throw(anna::RuntimeException) = 0;
-
-
-
-
- friend class Engine;
- friend class Server;
-};
-
-}
-}
-}
-
-#endif
-