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)
55 * Sessions based models type
57 struct SessionBasedModelsType { enum _v { RoundRobin, SessionIdOptionalPart, SessionIdHighPart, SessionIdLowPart /* default */ }; };
62 std::vector<Server*> a_servers;
63 int a_maxServers; // -1 means "no limit to add servers"
64 std::string a_description;
66 std::vector<Server*>::iterator a_deliveryIterator;
67 Server *a_lastUsedResource;
72 // Balance and socket selection:
74 SessionBasedModelsType::_v a_sessionBasedModelsType;
77 bool a_available; // any of the servers must be bound
78 void availabilityLost() ;
79 void availabilityRecovered() ;
80 bool refreshAvailability() ; // return true if change
81 void assertReady() noexcept(false);
83 void childIdle() const ;
85 // Selected for remove
86 bool a_deprecated; // entity has been selected as deprecated (will be removed when idle)
89 std::string a_socketListLiteral; // ADDRESS:PORT space-separated list
90 std::string a_primarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities)
91 std::string a_secondarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities)
95 anna::Millisecond a_lastIncomingActivityTime; // last unix timestamp (in milliseconds) when message reception was managed over this entity
96 anna::Millisecond a_lastOutgoingActivityTime; // last unix timestamp (in milliseconds) when message sending was managed over this entity
97 void updateIncomingActivityTime() ;
98 void updateOutgoingActivityTime() ;
100 // Private close/destroy method
101 void close(bool destroy) noexcept(false);
104 static const char* asText(const SessionBasedModelsType::_v) ;
110 * Default constructor. Entities should be create through diameter::comm::Engine
111 * @param maxServers Maximum number of servers managed by the entity. Default is 2 (standard/dual entity).
112 * The value -1, means no limit to add servers.
114 Entity(int maxServers = 2) : a_maxServers(maxServers) { initialize(); }
118 * Sets the maximum number of servers managed by the entity.
120 * @param maxServers Maximum number of servers managed by the entity.
122 void setMaxServers(int maxServers) { a_maxServers = maxServers; }
125 * Gets the maximum number of servers managed by the entity.
127 * @return Maximum number of servers managed by the entity.
129 int getMaxServers() const { return a_maxServers; }
133 * Sets the entity description.
135 * @param description Entity description. Empty by default.
137 void setDescription(const std::string &description) { a_description = description; }
140 * Gets the entity description.
142 * @return Entity description.
144 const std::string & getDescription() const { return a_description; }
148 * Sets the diameter::comm::Engine
149 * @param e Diameter::comm::Engine
151 void setEngine(Engine *e) { a_engine = e; }
154 * Gets the diameter::comm::Engine
155 * @return Diameter::comm::Engine
157 Engine *getEngine() const { return a_engine; }
160 * Add a server to the entity and create all the servers configured at #setSocketsPerDiameterServer within that server.
162 * \param serverId Diameter server ip/port.
164 * @return Returns success on send operation over any server within the entity
166 void addServer(const socket_t & serverId) noexcept(false);
169 * Binds entity servers.
171 * @return Returns true if all client-session were successfully bound
173 bool bind() noexcept(false);
176 * Propagate auto recovery configuration to servers within entity
178 * @param autoRecovery Auto recovery indicator. True by default.
180 void raiseAutoRecovery(bool autoRecovery = true) noexcept(false);
183 Sets timeout for wait responses for any class code request for all entity servers
185 \param v Diameter request type.
186 \param millisecond Milliseconds for timeout
188 void setClassCodeTimeout(const ClassCode::_v v, const anna::Millisecond & millisecond) ;
191 Sets entity category. Used by application in order to categorize or clasify.
193 @param category Entity category
195 void setCategory(int category) { a_category = category; }
198 Gets entity category. Used by application in order to categorize or clasify.
200 @return Entity category
202 int getCategory() const { return a_category; }
205 Gets the last used resource (server) during sending.
206 Broadcast doesn't updates this information.
208 Server *getLastUsedResource() const { return (a_lastUsedResource); }
212 * Balance over entity servers or use standard behaviour (first primary, secondary if fails, etc.).
213 * New created entities have balance disabled.
215 * @param balance True or false to enable or disable.
217 void setBalance (bool balance) { a_balance = balance; }
220 * Gets the balance mode
222 * @return True if balance over entity servers is enabled, false if standard behaviour is configured (default).
224 bool getBalance() const { return a_balance; }
227 // SIMPLE BALANCE or STANDARD documentation version
229 // Sent a message to the entity. First uses primary server, secondary if fails and so on to the
230 // last defined resource (server) within entity. Another sending algorithm (non standard) could
231 // be enabled (balance boolean parameter): it consist in round-robin server selection without
232 // trying any one if fails (standard behaviour tries all servers from FIRST defined).
233 // Anyway, last used delivery resource could be known through #getLastUsedResource().
235 // When the message is a request, a timer will be set automatically to control the response time.
236 // If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This
237 // timeout value will be configured at #setClassCodeTimeout.
239 // \param message Message sent.
240 // \param balance False by default (standard beaviour), but useful to balance over servers within entity.
242 // @return Boolean about success in send operation. Standard behaviour (no balance) implies true result when any
243 // of the entity servers could send the message, and false when neither of the servers was available or fail to
244 // send the message. Broadcast try to send all over the resources in spite of any fail, and balanced sendings
245 // fails when next selected resource fail to send the message (and no alarm or error counter is generated in
246 // this case because it can't be understood/ensured as entity-sending fail.
249 // OJO: en el caso estandard, no se prueban todas las sessiones de un servidor si tiene mas de una, luego la alarma
250 // generada en caso de error, presupone que las sessiones no usadas, tambi�n dar�an error, lo cual no tiene porque
251 // ser cierto. En condiciones normales, los servidores tienen una session, con lo que lo anterior es cierto y el
252 // la practica es lo mas normal.
255 Sent a message to the entity. First uses primary server, secondary if fails and so on to the
256 last defined resource (server) within entity. Another sending algorithm (non standard) could
257 be enabled (@setBalance): it consist in round-robin server selection to set the first resource
258 in a complete cycle (standard behaviour tries all servers from FIRST defined).
259 Anyway, last used delivery resource could be known through #getLastUsedResource().
261 When the message is a request, a timer will be set automatically to control the response time.
262 If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This
263 timeout value will be configured at #setClassCodeTimeout.
265 \param message Message sent.
267 @return Boolean about success in send operation. Implies true result when any of the entity servers could
268 send the message, and false when neither of the servers was available or fail to send the message (an alarm
269 and error counter will be generated in this case). Broadcast try to send all over the resources in spite of
272 bool send(const Message *message) noexcept(false);
273 bool send(const Message &message) noexcept(false) { return send(&message); }
276 * Sets sessions based models type.
277 * \param sessionBasedModelsType Session based models type: RoundRobin, SessionIdLowPart (default), SessionIdHighPart or SessionIdOptionalPart.
279 void setSessionBasedModelsType(const SessionBasedModelsType::_v sessionBasedModelsType) { a_sessionBasedModelsType = sessionBasedModelsType; }
282 * Returns sessions based models type.
283 * \return Session based models type: RoundRobin, SessionIdLowPart, SessionIdHighPart or SessionIdOptionalPart.
285 SessionBasedModelsType::_v getSessionBasedModelsType() const { return a_sessionBasedModelsType; }
289 Before sending a message over each entity server, socketId could be specified to select
290 which client session within such server will manage the message.
292 Default implementation has been focused on charging applications but any other kind of
293 application could re-implement this method and change the behaviour:
296 Charging involves two peers:
298 Charging Trigger Function (CTF): Makes decisions on how to charge the user for specific
299 services, issues requests to the server (OCF).
300 Online Charging Function (OCF): Performs actual charging based on received message type,
301 service logic and user profile information.
303 There are three main scenarios:
305 Immediate Event Charging (IEC): The CTF sends a one time request. This request contains
306 a predefined set of AVPs indicating which service has
307 been activated or how many units have been consumed
308 (this depends on application logic).
310 Event Charging with Unit Reservation (ECUR): The CTF issues a request which indicates the
311 desired unit count for reservation. On service
312 delivery, the CTF issues another request which
313 indicates how many units were actually consumed.
314 Units can be of any type, as they are application
317 Session Charging with Unit Reservation(SCUR): As above, however reservation can happen more than once.
319 In order to minimize race conditions within trasactions, default implementation will select the connection
320 fixed by an stickiness value (Session-Id will be used) for ECUR and SCUR models (Data, Voice and Content
321 traffic). IEC model, represented by SMS ans MMS traffic will use round-robin between sockets. The type
322 of traffic will be analyzed by mean Service-Context-Id AVP. If traffic type is not reconized, value of
323 '-1' will be returned doing round-robin socket selection within active server.
325 Diameter session-oriented load balancing enables to distribute Diameter signaling traffic across
326 multiple client sessions for the selected entity server. Application could re-implement different
327 load balancing policies, including support for session stickiness and business decisions, and
328 subscriber and service aware contextual load balancing strategies. By default, Session-Id avp
329 is used to select the resource. Session-Id is split into 4 sections: diameter identity, high
330 part, low part and optional part. Default implementation analizes 'low' part, returning its
331 value as reference for socket selection. Use @setSessionBasedModelsType to change this behaviour.
334 When server is configured as single client session (max client sessions equal to 1), entity will ignore
335 this method being more efficient, because former algorithms would not affect the session selection.
337 \param message Message which is being sent.
338 \param maxClientSessions Number of client-sessions on specific server prepared for send.
340 @return Socket-id used within range [0,maxClientSessions-1]. Value '-1' if round-robin is desired.
341 If socket-id is return out of range, send procedure will throw an exception.
343 virtual int readSocketId(const Message *message, int maxClientSessions) const ;
347 Sent a message to all the entity servers.
348 It is used, i.e., in Disconnect-Peer-Request procedure over a certain entity.
350 \param message Message which is being sent.
352 @return Returns true (success) only when broadcast is success over all the entity servers. If any server fails,
353 then false is returned.
355 bool broadcast(const Message *message) noexcept(false);
356 bool broadcast(const Message &message) noexcept(false) { return broadcast(&message); }
360 Returns true when any of the entity servers is Bound. False when all not-bound.
362 bool isAvailable() const { return a_available; }
365 Returns true when the entity has been selected as deprecated
367 bool isDeprecated() const { return a_deprecated; }
370 Sets the entity deprecated state
372 void setDeprecated(bool deprecated = true) { a_deprecated = deprecated; }
376 Gets the number of requests messages over-the-air.
378 @return OTA messages.
380 int getOTARequests() const ;
383 Returns idle state (no pending answers).
387 bool idle() const { return (getOTARequests() == 0); }
390 std::vector<Server*>::iterator begin() { return a_servers.begin(); }
391 std::vector<Server*>::iterator end() { return a_servers.end(); }
392 std::vector<Server*>::const_iterator begin() const { return a_servers.begin(); }
393 std::vector<Server*>::const_iterator end() const { return a_servers.end(); }
396 Close all the entity servers (close client-sessions within them). Depending on client-session configuration ('OnDisconnect' behaviour),
397 pending answers will be wait (graceful) or ignored (immediate-abrupt close).
398 Resources are not destroyed.
400 void close() noexcept(false) { close(false /* no destroy */); }
405 Number of currently configured servers
407 int getNumberOfServers() const { return a_servers.size(); }
410 Number of maximum allowed servers
412 int getMaxServerss() const { return a_maxServers; }
415 List of (address,port) pairs defining entity servers
417 socket_v getAddressPortList() const ;
421 Deny resources for delivery restriction.
427 Allow resource for delivery permission.
428 Allow all its servers
433 Returns true when all its servers resources are hidden for application messages delivery
435 bool hidden() const ;
438 Returns true when all its servers resources are shown for application messages delivery
444 Class string representation
445 \return String with relevant information for this instance.
447 std::string asString() const ;
450 Class xml representation
451 \param parent Parent XML node on which hold this instance information.
452 \return XML document with relevant information for this instance.
454 anna::xml::Node* asXML(anna::xml::Node* parent) const ;
459 Handler about event break connection from diameter server (server) over this entity.
460 When notified, ANNA.diameter.comm generates an diameter::comm::Entity::eventResponse for every request with pending answers.
461 Default implementation traces warning event
462 \param clientSession ClientSession from which shutdown has been received
464 virtual void eventPeerShutdown(const ClientSession* clientSession) ;
467 Handler about a request retransmission over the session.
468 Default implementation traces warning event
469 \param clientSession ClientSession from which retransmission happened
470 \param request Retransmitted request message
472 virtual void eventRequestRetransmission(const ClientSession* clientSession, Message *request) ;
475 Handler for diameter server (server) responses
477 \param response Answer container object for corresponding diameter request
478 \param myNode Own origin host
480 virtual void eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
483 Handler for diameter server (server) requests
485 \param clientSession ClientSession from which request has been received
486 \param request Diameter request message received
487 \param myNode Own origin host
489 virtual void eventRequest(ClientSession* clientSession, const anna::DataBlock &request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
490 //virtual void eventRequest(ClientSession* clientSession, const Message& request) noexcept(false) = 0;
493 Handler for diameter session responses out of context
495 \param clientSession ClientSession from which request has been received
496 \param response Answer data block object without context match
497 \param myNode Own origin host
499 virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
502 Handler for diameter session Disconnect-Peer-Answer messages
504 \param clientSession ClientSession from which request has been received
505 \param response Answer data block object without context match
506 \param myNode Own origin host
508 virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;