1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
9 #ifndef anna_diameter_comm_Entity_hpp
10 #define anna_diameter_comm_Entity_hpp
17 #include <anna/config/defines.hpp>
19 #include <anna/core/RuntimeException.hpp>
20 #include <anna/core/util/Millisecond.hpp>
22 #include <anna/diameter.comm/ClassCode.hpp>
48 Generic diameter server list (N-servers entity)
52 std::vector<Server*> a_servers;
53 int a_maxServers; // -1 means "no limit to add servers"
54 std::string a_description;
56 std::vector<Server*>::iterator a_deliveryIterator;
57 Server *a_lastUsedResource;
63 bool a_available; // any of the servers must be bound
64 void availabilityLost() throw();
65 void availabilityRecovered() throw();
66 bool refreshAvailability() throw(); // return true if change
67 void assertReady() throw(anna::RuntimeException);
68 void initialize() throw();
69 void childIdle() const throw();
71 // Selected for remove
72 bool a_deprecated; // entity has been selected as deprecated (will be removed when idle)
75 std::string a_socketListLiteral; // ADDRESS:PORT space-separated list
76 std::string a_primarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities)
77 std::string a_secondarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities)
81 anna::Millisecond a_lastIncomingActivityTime; // last unix timestamp (in milliseconds) when message reception was managed over this entity
82 anna::Millisecond a_lastOutgoingActivityTime; // last unix timestamp (in milliseconds) when message sending was managed over this entity
83 void updateIncomingActivityTime() throw();
84 void updateOutgoingActivityTime() throw();
86 // Private close/destroy method
87 void close(bool destroy) throw(anna::RuntimeException);
94 * Default constructor. Entities should be create through diameter::comm::Engine
95 * @param maxServers Maximum number of servers managed by the entity. Default is 2 (standard/dual entity).
96 * The value -1, means no limit to add servers.
98 Entity(int maxServers = 2) : a_maxServers(maxServers) { initialize(); }
102 * Sets the maximum number of servers managed by the entity.
104 * @param maxServers Maximum number of servers managed by the entity.
106 void setMaxServers(int maxServers) throw() { a_maxServers = maxServers; }
109 * Gets the maximum number of servers managed by the entity.
111 * @return Maximum number of servers managed by the entity.
113 int getMaxServers() const throw() { return a_maxServers; }
117 * Sets the entity description.
119 * @param description Entity description. Empty by default.
121 void setDescription(const std::string &description) throw() { a_description = description; }
124 * Gets the entity description.
126 * @return Entity description.
128 const std::string & getDescription() const throw() { return a_description; }
132 * Sets the diameter::comm::Engine
133 * @param e Diameter::comm::Engine
135 void setEngine(Engine *e) throw() { a_engine = e; }
138 // * Gets the diameter::comm::Engine
139 // * @return Diameter::comm::Engine
141 // Engine *getEngine() const throw() { return a_engine; }
144 * Add a server to the entity and create all the servers configured at #setSocketsPerDiameterServer within that server.
146 * \param serverId Diameter server ip/port.
148 * @return Returns success on send operation over any server within the entity
150 void addServer(const socket_t & serverId) throw(anna::RuntimeException);
153 * Binds entity servers.
155 * @return Returns true if all client-session were successfully bound
157 bool bind() throw(anna::RuntimeException);
160 * Propagate auto recovery configuration to servers within entity
162 * @param autoRecovery Auto recovery indicator. True by default.
164 void raiseAutoRecovery(bool autoRecovery = true) throw(anna::RuntimeException);
167 Sets timeout for wait responses for any class code request for all entity servers
169 \param v Diameter request type.
170 \param millisecond Milliseconds for timeout
172 void setClassCodeTimeout(const ClassCode::_v v, const anna::Millisecond & millisecond) throw();
175 Sets entity category. Used by application in order to categorize or clasify.
177 @param category Entity category
179 void setCategory(int category) throw() { a_category = category; }
182 Gets entity category. Used by application in order to categorize or clasify.
184 @return Entity category
186 int getCategory() const throw() { return a_category; }
189 Gets the last used resource (server) during sending.
190 Broadcast doesn't updates this information.
192 Server *getLastUsedResource() const throw() { return (a_lastUsedResource); }
196 // SIMPLE BALANCE or STANDARD documentation version
198 // Sent a message to the entity. First uses primary server, secondary if fails and so on to the
199 // last defined resource (server) within entity. Another sending algorithm (non standard) could
200 // be enabled (balance boolean parameter): it consist in round-robin server selection without
201 // trying any one if fails (standard behaviour tries all servers from FIRST defined).
202 // Anyway, last used delivery resource could be known through #getLastUsedResource().
204 // When the message is a request, a timer will be set automatically to control the response time.
205 // If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This
206 // timeout value will be configured at #setClassCodeTimeout.
208 // \param message Message sent.
209 // \param balance False by default (standard beaviour), but useful to balance over servers within entity.
211 // @return Boolean about success in send operation. Standard behaviour (no balance) implies true result when any
212 // of the entity servers could send the message, and false when neither of the servers was available or fail to
213 // send the message. Broadcast try to send all over the resources in spite of any fail, and balanced sendings
214 // fails when next selected resource fail to send the message (and no alarm or error counter is generated in
215 // this case because it can't be understood/ensured as entity-sending fail.
218 // OJO: en el caso estandard, no se prueban todas las sessiones de un servidor si tiene mas de una, luego la alarma
219 // generada en caso de error, presupone que las sessiones no usadas, también darían error, lo cual no tiene porque
220 // ser cierto. En condiciones normales, los servidores tienen una session, con lo que lo anterior es cierto y el
221 // la practica es lo mas normal.
224 Sent a message to the entity. First uses primary server, secondary if fails and so on to the
225 last defined resource (server) within entity. Another sending algorithm (non standard) could
226 be enabled (balance boolean parameter): it consist in round-robin server selection to set the
227 first resource in a complete cycle (standard behaviour tries all servers from FIRST defined).
228 Anyway, last used delivery resource could be known through #getLastUsedResource().
230 When the message is a request, a timer will be set automatically to control the response time.
231 If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This
232 timeout value will be configured at #setClassCodeTimeout.
234 \param message Message sent.
235 \param balance False by default (standard beaviour), but useful to balance over servers within entity.
237 @return Boolean about success in send operation. Implies true result when any of the entity servers could
238 send the message, and false when neither of the servers was available or fail to send the message (an alarm
239 and error counter will be generated in this case). Broadcast try to send all over the resources in spite of
242 bool send(const Message *message, bool balance = false) throw(anna::RuntimeException);
243 bool send(const Message &message, bool balance = false) throw(anna::RuntimeException) { return send(&message, balance); }
247 Before sending a message over each entity server, socketId could be specified to select
248 which client session within such server will manage the message.
250 Default implementation has been focused on charging applications but any other kind of
251 application could re-implement this method and change the behaviour:
254 Charging involves two peers:
256 Charging Trigger Function (CTF): Makes decisions on how to charge the user for specific
257 services, issues requests to the server (OCF).
258 Online Charging Function (OCF): Performs actual charging based on received message type,
259 service logic and user profile information.
261 There are three main scenarios:
263 Immediate Event Charging (IEC): The CTF sends a one time request. This request contains
264 a predefined set of AVPs indicating which service has
265 been activated or how many units have been consumed
266 (this depends on application logic).
268 Event Charging with Unit Reservation (ECUR): The CTF issues a request which indicates the
269 desired unit count for reservation. On service
270 delivery, the CTF issues another request which
271 indicates how many units were actually consumed.
272 Units can be of any type, as they are application
275 Session Charging with Unit Reservation(SCUR): As above, however reservation can happen more than once.
277 In order to minimize race conditions within trasactions, default implementation will select the connection
278 fixed by an stickiness value (Session-Id will be used) for ECUR and SCUR models (Data, Voice and Content
279 traffic). IEC model, represented by SMS ans MMS traffic will use round-robin between sockets. The type
280 of traffic will be analyzed by mean Service-Context-Id AVP. If traffic type is not reconized, value of
281 '-1' will be returned doing round-robin socket selection within active server.
283 Diameter session-oriented load balancing enables to distribute Diameter signaling traffic across
284 multiple client sessions for the selected entity server. Application could re-implement different
285 load balancing policies, including support for session stickiness and business decisions, and
286 subscriber and service aware contextual load balancing strategies. By default, Session-Id avp
287 is used to select the resource. Session-Id is split into 4 sections: diameter identity, high
288 part, low part and optional part. Default implementation analizes 'low' part, returning its
289 value as reference for socket selection.
292 When server is configured as single client session (max client sessions equal to 1), entity will ignore
293 this method being more efficient, because former algorithms would not affect the session selection.
295 \param message Message which is being sent.
296 \param maxClientSessions Number of client-sessions on specific server prepared for send.
298 @return Socket-id used within range [0,maxClientSessions-1]. Value '-1' if round-robin is desired.
299 If socket-id is return out of range, send procedure will throw an exception.
301 virtual int readSocketId(const Message *message, int maxClientSessions) const throw();
305 Sent a message to all the entity servers.
306 It is used, i.e., in Disconnect-Peer-Request procedure over a certain entity.
308 \param message Message which is being sent.
310 @return Returns true (success) only when broadcast is success over all the entity servers. If any server fails,
311 then false is returned.
313 bool broadcast(const Message *message) throw(anna::RuntimeException);
314 bool broadcast(const Message &message) throw(anna::RuntimeException) { return broadcast(&message); }
318 Returns true when any of the entity servers is Bound. False when all not-bound.
320 bool isAvailable() const throw() { return a_available; }
323 Returns true when the entity has been selected as deprecated
325 bool isDeprecated() const throw() { return a_deprecated; }
328 Sets the entity deprecated state
330 void setDeprecated(bool deprecated = true) throw() { a_deprecated = deprecated; }
334 Gets the number of requests messages over-the-air.
336 @return OTA messages.
338 int getOTARequests() const throw();
341 Returns idle state (no pending answers).
345 bool idle() const throw() { return (getOTARequests() == 0); }
348 std::vector<Server*>::iterator begin() throw() { return a_servers.begin(); }
349 std::vector<Server*>::iterator end() throw() { return a_servers.end(); }
350 std::vector<Server*>::const_iterator begin() const throw() { return a_servers.begin(); }
351 std::vector<Server*>::const_iterator end() const throw() { return a_servers.end(); }
354 Close all the entity servers (close client-sessions within them). Depending on client-session configuration ('OnDisconnect' behaviour),
355 pending answers will be wait (graceful) or ignored (immediate-abrupt close).
356 Resources are not destroyed.
358 void close() throw(anna::RuntimeException) { close(false /* no destroy */); }
363 Number of currently configured servers
365 int getNumberOfServers() const throw() { return a_servers.size(); }
368 Number of maximum allowed servers
370 int getMaxServerss() const throw() { return a_maxServers; }
373 List of (address,port) pairs defining entity servers
375 socket_v getAddressPortList() const throw();
379 Deny resources for delivery restriction.
385 Allow resource for delivery permission.
386 Allow all its servers
391 Returns true when all its servers resources are hidden for application messages delivery
393 bool hidden() const throw();
396 Returns true when all its servers resources are shown for application messages delivery
398 bool shown() const throw();
402 Class string representation
403 \return String with relevant information for this instance.
405 std::string asString() const throw();
408 Class xml representation
409 \param parent Parent XML node on which hold this instance information.
410 \return XML document with relevant information for this instance.
412 anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
417 Handler about event break connection from diameter server (server) over this entity.
418 When notified, ANNA.diameter.comm generates an diameter::comm::Entity::eventResponse for every request with pending answers.
419 Default implementation traces warning event
420 \param clientSession ClientSession from which shutdown has been received
422 virtual void eventPeerShutdown(const ClientSession* clientSession) throw();
425 Handler for diameter server (server) responses
427 \param response Answer container object for corresponding diameter request
429 virtual void eventResponse(const Response& response) throw(anna::RuntimeException) = 0;
432 Handler for diameter server (server) requests
434 \param clientSession ClientSession from which request has been received
435 \param request Diameter request message received
437 virtual void eventRequest(ClientSession* clientSession, const anna::DataBlock &request) throw(anna::RuntimeException) = 0;
438 //virtual void eventRequest(ClientSession* clientSession, const Message& request) throw(anna::RuntimeException) = 0;
441 Handler for diameter session responses out of context
443 \param clientSession ClientSession from which request has been received
444 \param response Answer data block object without context match
446 virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response) throw(anna::RuntimeException) = 0;
449 Handler for diameter session Disconnect-Peer-Answer messages
451 \param clientSession ClientSession from which request has been received
452 \param response Answer data block object without context match
454 virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response) throw(anna::RuntimeException) = 0;