Changed LICENSE. Now referenced to web site and file on project root directory
[anna.git] / include / anna / diameter.comm / Entity.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
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 //
7
8
9 #ifndef anna_diameter_comm_Entity_hpp
10 #define anna_diameter_comm_Entity_hpp
11
12
13 // STL
14 #include <string>
15 #include <vector>
16
17 #include <anna/config/defines.hpp>
18
19 #include <anna/core/RuntimeException.hpp>
20 #include <anna/core/util/Millisecond.hpp>
21
22
23 namespace anna {
24 class DataBlock;
25 namespace xml {
26 class Node;
27 }
28 }
29
30
31
32 namespace anna {
33
34 namespace diameter {
35
36 namespace comm {
37
38 class Engine;
39 class Server;
40 class Response;
41 class Message;
42
43
44 /**
45    Generic diameter server list (N-servers entity)
46 */
47 class Entity {
48
49   std::vector<Server*> a_servers;
50   int a_maxServers; // -1 means "no limit to add servers"
51   std::string a_description;
52   int a_category;
53   std::vector<Server*>::iterator a_deliveryIterator;
54   Server *a_lastUsedResource;
55
56   // Engine
57   Engine *a_engine;
58
59   // Availability
60   bool a_available; // any of the servers must be bound
61   void availabilityLost() throw();
62   void availabilityRecovered() throw();
63   bool refreshAvailability() throw(); // return true if change
64   void assertReady() throw(anna::RuntimeException);
65   void initialize() throw();
66   void childIdle() const throw();
67
68   // Selected for remove
69   bool a_deprecated; // entity has been selected as deprecated (will be removed when idle)
70
71   // internal helpers
72   std::string a_socketListLiteral; // ADDRESS:PORT space-separated list
73   std::string a_primarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities)
74   std::string a_secondarySocketLiteral; // ADDRESS:PORT for primary (used on standard entities)
75
76
77   // Activity
78   anna::Millisecond a_lastIncomingActivityTime;   // last unix timestamp (in milliseconds) when message reception was managed over this entity
79   anna::Millisecond a_lastOutgoingActivityTime;   // last unix timestamp (in milliseconds) when message sending was managed over this entity
80   void updateIncomingActivityTime() throw();
81   void updateOutgoingActivityTime() throw();
82
83   // Private close/destroy method
84   void close(bool destroy) throw(anna::RuntimeException);
85
86
87 public:
88
89
90   /**
91    * Default constructor. Entities should be create through diameter::comm::Engine
92    * @param maxServers Maximum number of servers managed by the entity. Default is 2 (standard/dual entity).
93    * The value -1, means no limit to add servers.
94    */
95   Entity(int maxServers = 2) : a_maxServers(maxServers) { initialize(); }
96
97
98   /**
99    * Sets the maximum number of servers managed by the entity.
100    *
101    * @param maxServers Maximum number of servers managed by the entity.
102    */
103   void setMaxServers(int maxServers) throw() { a_maxServers = maxServers; }
104
105   /**
106    * Gets the maximum number of servers managed by the entity.
107    *
108    * @return Maximum number of servers managed by the entity.
109    */
110   int getMaxServers() const throw() { return a_maxServers; }
111
112
113   /**
114    * Sets the entity description.
115    *
116    * @param description Entity description. Empty by default.
117    */
118   void setDescription(const std::string &description) throw() { a_description = description; }
119
120   /**
121    * Gets the entity description.
122    *
123    * @return Entity description.
124    */
125   const std::string & getDescription() const throw() { return a_description; }
126
127
128   /**
129   * Sets the diameter::comm::Engine
130   * @param e Diameter::comm::Engine
131   */
132   void setEngine(Engine *e) throw() { a_engine = e; }
133
134
135   /**
136   * Add a server to the entity and create all the servers configured at #setSocketsPerDiameterServer within that server.
137   *
138   * \param serverId Diameter server ip/port.
139   *
140   * @return Returns success on send operation over any server within the entity
141   */
142   void addServer(const socket_t & serverId) throw(anna::RuntimeException);
143
144   /**
145    * Binds entity servers.
146    *
147    * @return Returns true if all client-session were successfully bound
148    */
149   bool bind() throw(anna::RuntimeException);
150
151   /**
152    * Propagate auto recovery configuration to servers within entity
153    *
154    * @param autoRecovery Auto recovery indicator. True by default.
155    */
156   void raiseAutoRecovery(bool autoRecovery = true) throw(anna::RuntimeException);
157
158   /**
159      Sets timeout for wait responses for any class code request for all entity servers
160
161      \param v Diameter request type.
162      \param millisecond Milliseconds for timeout
163   */
164   void setClassCodeTimeout(const ClassCode::_v v, const anna::Millisecond & millisecond) throw();
165
166   /**
167      Sets entity category. Used by application in order to categorize or clasify.
168
169      @param category Entity category
170   */
171   void setCategory(int category) throw() { a_category = category; }
172
173   /**
174      Gets entity category. Used by application in order to categorize or clasify.
175
176      @return Entity category
177   */
178   int getCategory() const throw() { return a_category; }
179
180   /**
181      Gets the last used resource (server) during sending.
182      Broadcast doesn't updates this information.
183   */
184   Server *getLastUsedResource() const throw() { return (a_lastUsedResource); }
185
186
187
188 // SIMPLE BALANCE or STANDARD documentation version
189 //   /**
190 //      Sent a message to the entity. First uses primary server, secondary if fails and so on to the
191 //      last defined resource (server) within entity. Another sending algorithm (non standard) could
192 //      be enabled (balance boolean parameter): it consist in round-robin server selection without
193 //      trying any one if fails (standard behaviour tries all servers from FIRST defined).
194 //      Anyway, last used delivery resource could be known through #getLastUsedResource().
195 //
196 //      When the message is a request, a timer will be set automatically to control the response time.
197 //      If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This
198 //      timeout value will be configured at #setClassCodeTimeout.
199 //
200 //      \param message Message sent.
201 //      \param balance False by default (standard beaviour), but useful to balance over servers within entity.
202 //
203 //      @return Boolean about success in send operation. Standard behaviour (no balance) implies true result when any
204 //      of the entity servers could send the message, and false when neither of the servers was available or fail to
205 //      send the message. Broadcast try to send all over the resources in spite of any fail, and balanced sendings
206 //      fails when next selected resource fail to send the message (and no alarm or error counter is generated in
207 //      this case because it can't be understood/ensured as entity-sending fail.
208 //   */
209
210 // OJO: en el caso estandard, no se prueban todas las sessiones de un servidor si tiene mas de una, luego la alarma
211 //      generada en caso de error, presupone que las sessiones no usadas, también darían error, lo cual no tiene porque
212 //      ser cierto. En condiciones normales, los servidores tienen una session, con lo que lo anterior es cierto y el
213 //      la practica es lo mas normal.
214
215   /**
216      Sent a message to the entity. First uses primary server, secondary if fails and so on to the
217      last defined resource (server) within entity. Another sending algorithm (non standard) could
218      be enabled (balance boolean parameter): it consist in round-robin server selection to set the
219      first resource in a complete cycle (standard behaviour tries all servers from FIRST defined).
220      Anyway, last used delivery resource could be known through #getLastUsedResource().
221
222      When the message is a request, a timer will be set automatically to control the response time.
223      If expires, the ResultCode Timeout will be finally notified on #Entity::eventResponse. This
224      timeout value will be configured at #setClassCodeTimeout.
225
226      \param message Message sent.
227      \param balance False by default (standard beaviour), but useful to balance over servers within entity.
228
229      @return Boolean about success in send operation. Implies true result when any of the entity servers could
230      send the message, and false when neither of the servers was available or fail to send the message (an alarm
231      and error counter will be generated in this case). Broadcast try to send all over the resources in spite of
232      any fail.
233   */
234   bool send(const Message *message, bool balance = false) throw(anna::RuntimeException);
235   bool send(const Message &message, bool balance = false) throw(anna::RuntimeException) { return send(&message, balance); }
236
237
238   /**
239      Before sending a message over each entity server, socketId could be specified to select
240      which client session within such server will manage the message.
241
242      Default implementation has been focused on charging applications but any other kind of
243      application could re-implement this method and change the behaviour:
244
245      <pre>
246      Charging involves two peers:
247
248         Charging Trigger Function (CTF): Makes decisions on how to charge the user for specific
249                                          services, issues requests to the server (OCF).
250         Online Charging Function (OCF):  Performs actual charging based on received message type,
251                                          service logic and user profile information.
252
253      There are three main scenarios:
254
255         Immediate Event Charging (IEC): The CTF sends a one time request. This request contains
256                                         a predefined set of AVPs indicating which service has
257                                         been activated or how many units have been consumed
258                                         (this depends on application logic).
259
260         Event Charging with Unit Reservation (ECUR): The CTF issues a request which indicates the
261                                                      desired unit count for reservation. On service
262                                                      delivery, the CTF issues another request which
263                                                      indicates how many units were actually consumed.
264                                                      Units can be of any type, as they are application
265                                                      specific.
266
267         Session Charging with Unit Reservation(SCUR): As above, however reservation can happen more than once.
268
269      In order to minimize race conditions within trasactions, default implementation will select the connection
270      fixed by an stickiness value (Session-Id will be used) for ECUR and SCUR models (Data, Voice and Content
271      traffic). IEC model, represented by SMS ans MMS traffic will use round-robin between sockets. The type
272      of traffic will be analyzed by mean Service-Context-Id AVP. If traffic type is not reconized, value of
273      '-1' will be returned doing round-robin socket selection within active server.
274
275      Diameter session-oriented load balancing enables to distribute Diameter signaling traffic across
276      multiple client sessions for the selected entity server. Application could re-implement different
277      load balancing policies, including support for session stickiness and business decisions, and
278      subscriber and service aware contextual load balancing strategies. By default, Session-Id avp
279      is used to select the resource. Session-Id is split into 4 sections: diameter identity, high
280      part, low part and optional part. Default implementation analizes 'low' part, returning its
281      value as reference for socket selection.
282      </pre>
283
284      When server is configured as single client session (max client sessions equal to 1), entity will ignore
285      this method being more efficient, because former algorithms would not affect the session selection.
286
287      \param message Message which is being sent.
288      \param maxClientSessions Number of client-sessions on specific server prepared for send.
289
290      @return Socket-id used within range [0,maxClientSessions-1]. Value '-1' if round-robin is desired.
291      If socket-id is return out of range, send procedure will throw an exception.
292   */
293   virtual int readSocketId(const Message *message, int maxClientSessions) const throw();
294
295
296   /**
297      Sent a message to all the entity servers.
298      It is used, i.e., in Disconnect-Peer-Request procedure over a certain entity.
299
300      \param message Message which is being sent.
301
302      @return Returns true (success) only when broadcast is success over all the entity servers. If any server fails,
303      then false is returned.
304   */
305   bool broadcast(const Message *message) throw(anna::RuntimeException);
306   bool broadcast(const Message &message) throw(anna::RuntimeException) { return broadcast(&message); }
307
308
309   /**
310      Returns true when any of the entity servers is Bound. False when all not-bound.
311   */
312   bool isAvailable() const throw() { return a_available; }
313
314   /**
315      Returns true when the entity has been selected as deprecated
316   */
317   bool isDeprecated() const throw() { return a_deprecated; }
318
319   /**
320      Sets the entity deprecated state
321   */
322   void setDeprecated(bool deprecated = true) throw() { a_deprecated = deprecated; }
323
324
325   /**
326      Gets the number of requests messages over-the-air.
327
328      @return OTA messages.
329   */
330   int getOTARequests() const throw();
331
332   /**
333      Returns idle state (no pending answers).
334
335      @return Idle state.
336   */
337   bool idle() const throw() { return (getOTARequests() == 0); }
338
339
340   std::vector<Server*>::iterator begin() throw() { return a_servers.begin(); }
341   std::vector<Server*>::iterator end() throw() { return a_servers.end(); }
342   std::vector<Server*>::const_iterator begin() const throw() { return a_servers.begin(); }
343   std::vector<Server*>::const_iterator end() const throw() { return a_servers.end(); }
344
345   /**
346      Close all the entity servers (close client-sessions within them). Depending on client-session configuration ('OnDisconnect' behaviour),
347      pending answers will be wait (graceful) or ignored (immediate-abrupt close).
348      Resources are not destroyed.
349   */
350   void close() throw(anna::RuntimeException) { close(false /* no destroy */); }
351
352   // helpers
353
354   /**
355      Number of currently configured servers
356   */
357   int getNumberOfServers() const throw() { return a_servers.size(); }
358
359   /**
360      Number of maximum allowed servers
361   */
362   int getMaxServerss() const throw() { return a_maxServers; }
363
364   /**
365      List of (address,port) pairs defining entity servers
366   */
367   socket_v getAddressPortList() const throw();
368
369
370   /**
371      Deny resources for delivery restriction.
372      Deny all its servers
373   */
374   void hide() throw();
375
376   /**
377      Allow resource for delivery permission.
378      Allow all its servers
379   */
380   void show() throw();
381
382   /**
383      Returns true when all its servers resources are hidden for application messages delivery
384   */
385   bool hidden() const throw();
386
387   /**
388      Returns true when all its servers resources are shown for application messages delivery
389   */
390   bool shown() const throw();
391
392
393   /**
394      Class string representation
395      \return String with relevant information for this instance.
396   */
397   std::string asString() const throw();
398
399   /**
400      Class xml representation
401      \param parent Parent XML node on which hold this instance information.
402      \return XML document with relevant information for this instance.
403   */
404   anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
405
406 protected:
407
408   /**
409      Handler about event break connection from diameter server (server) over this entity.
410      When notified, ANNA.diameter.comm generates an diameter::comm::Entity::eventResponse for every request with pending answers.
411      Default implementation traces warning event
412      \param clientSession ClientSession from which shutdown has been received
413   */
414   virtual void eventPeerShutdown(const ClientSession* clientSession) throw();
415
416   /**
417      Handler for diameter server (server) responses
418
419      \param response Answer container object for corresponding diameter request
420   */
421   virtual void eventResponse(const Response& response) throw(anna::RuntimeException) = 0;
422
423   /**
424      Handler for diameter server (server) requests
425
426      \param clientSession ClientSession from which request has been received
427      \param request Diameter request message received
428   */
429   virtual void eventRequest(ClientSession* clientSession, const anna::DataBlock &request) throw(anna::RuntimeException) = 0;
430   //virtual void eventRequest(ClientSession* clientSession, const Message& request) throw(anna::RuntimeException) = 0;
431
432   /**
433      Handler for diameter session responses out of context
434
435      \param clientSession ClientSession from which request has been received
436      \param response Answer data block object without context match
437   */
438   virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response) throw(anna::RuntimeException) = 0;
439
440   /**
441      Handler for diameter session Disconnect-Peer-Answer messages
442
443      \param clientSession ClientSession from which request has been received
444      \param response Answer data block object without context match
445   */
446   virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response) throw(anna::RuntimeException) = 0;
447
448
449
450
451   friend class Engine;
452   friend class Server;
453 };
454
455 }
456 }
457 }
458
459 #endif
460