69f5e80d95933d54a4119b782ac23b38a53f1be6
[anna.git] / include / anna / diameter.comm / Server.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_Server_hpp
10 #define anna_diameter_comm_Server_hpp
11
12
13 // STL
14 #include <string>
15 #include <vector>
16
17 #include <anna/core/util/Millisecond.hpp>
18 #include <anna/core/RuntimeException.hpp>
19
20 #include <anna/diameter/defines.hpp>
21 #include <anna/config/defines.hpp>
22 #include <anna/diameter.comm/ClassCode.hpp>
23 #include <anna/statistics/Accumulator.hpp>
24
25
26 namespace anna {
27 class DataBlock;
28 namespace timex {
29 class Engine;
30 }
31 }
32
33
34 namespace anna {
35
36 namespace diameter {
37
38 namespace comm {
39
40 class Engine;
41 class Entity;
42 class ClientSession;
43 class Response;
44 class Message;
45
46
47 /**
48    Diameter server with 1..N connections.
49 */
50 class Server {
51
52   // Parent information
53   Entity *a_parent;
54
55   // Main server attributes
56   socket_t a_socket;
57
58   // ClientSessions
59   std::vector<ClientSession*> a_clientSessions;
60   int a_maxClientSessions; // -1 means "no limit to add client-sessions" (sockets per server)
61   std::vector<ClientSession*>::iterator a_deliveryIterator;
62   ClientSession *a_lastUsedResource;
63
64   // Activity
65   anna::Millisecond a_lastIncomingActivityTime;   // last unix timestamp (in milliseconds) when message reception was managed over this server
66   anna::Millisecond a_lastOutgoingActivityTime;   // last unix timestamp (in milliseconds) when message sending was managed over this server
67   void updateIncomingActivityTime() throw();
68   void updateOutgoingActivityTime() throw();
69
70   // Engine
71   Engine *a_engine;
72
73   // Statistics
74   int a_processing_time__StatisticConceptId;
75   int a_received_message_size__StatisticConceptId;
76   anna::statistics::Accumulator *a_statisticsAccumulator;
77   void initializeStatisticResources() throw();
78   void resetStatistics() throw();
79
80   // Availability
81   bool a_available; // any of the client-sessions must be bound
82   void availabilityLost() throw();
83   void availabilityRecovered() throw();
84   bool refreshAvailability() throw(); // return true if change
85   void assertReady() throw(anna::RuntimeException);
86   void initialize() throw();
87   void childIdle() const throw();
88
89   // Private close/destroy method
90   void close(bool destroy) throw(anna::RuntimeException);
91
92
93 public:
94
95
96   /**
97    * Default constructor.
98    * @param maxClientSessions Maximum number of client-sessions managed by the server. Default is 1 (monoconnection server).
99    * The value -1, means no limit to add client-sessions.
100    */
101   Server(int maxClientSessions = 1) : a_maxClientSessions(maxClientSessions) { initialize(); }
102
103
104   /**
105   * Add a server to the entity and create all the client-sessions configured at #setSocketsPerDiameterServer within that server.
106   *
107   * \param socketId Diameter socket identifier within the server.
108   */
109   void addClientSession(int socketId) throw(anna::RuntimeException);
110
111   /**
112      Set timeout to consider failed a request.
113      \param v Requests class code.
114      \param millisecond Milliseconds wait before considering the requests failed.
115
116      Timers are internally managed and automatically activated.
117   */
118   void setClassCodeTimeout(const ClassCode::_v v, const anna::Millisecond & millisecond) throw();
119
120   /**
121    * Binds server client-sessions.
122    *
123    * @return Returns true if all client-session were successfully bound
124    */
125   bool bind() throw(anna::RuntimeException);
126
127   /**
128    * Propagate auto recovery configuration to client-sessions within server
129    *
130    * @param autoRecovery Auto recovery indicator. True by default.
131    */
132   void raiseAutoRecovery(bool autoRecovery = true) throw(anna::RuntimeException);
133
134
135 // Sent a message to the server using a certain client-session by mean round-robin between socketId's for
136 //  multiple client client-sessions functionality. If a specific socketId is provided, then uses such specific client-session.
137 // Last used delivery resource could be known through #getLastUsedResource().
138   bool send(const Message*, int socketId = -1 /* client-sessions round-robin */) throw(anna::RuntimeException);
139   bool send(const Message& message, int socketId = -1 /* client-sessions round-robin */) throw(anna::RuntimeException) { return send(&message, socketId); }
140
141   /**
142      Gets the last used resource (client session) during sending.
143      Broadcast doesn't updates this information.
144   */
145   ClientSession *getLastUsedResource() const throw() { return (a_lastUsedResource); }
146
147   /**
148      Sent a message to all the server client-sessions (socketId's) for multiple client client-sessions functionality.
149      It is used, i.e., in Disconnect-Peer-Request procedure over a certain server.
150      Returns true (success) only when broadcast is success over all the server client-sessions. If any client-session fails,
151      then false is returned. Broadcast try to send all over the resources in spite of any fail.
152   */
153   bool broadcast(const Message*) throw(anna::RuntimeException);
154   bool broadcast(const Message& message) throw(anna::RuntimeException) { return broadcast(&message); }
155
156   /**
157      Close all the server client-sessions. Depending on client-session configuration ('OnDisconnect' behaviour),
158      pending answers will be wait (graceful) or ignored (immediate-abrupt close).
159      Resources are not destroyed.
160   */
161   void close() throw(anna::RuntimeException) { close(false /* no destroy */); }
162
163
164   /**
165      Diameter parent entity.
166      \return Diameter parent entity.
167   */
168   const Entity *getParent() const throw() { return a_parent; }
169
170   /**
171      Returns true when any of the server client-sessions is Bound. False when all not-bound.
172   */
173   bool isAvailable() const throw() { return a_available; }
174
175
176   std::vector<ClientSession*>::iterator begin() throw() { return a_clientSessions.begin(); }
177   std::vector<ClientSession*>::iterator end() throw() { return a_clientSessions.end(); }
178   std::vector<ClientSession*>::const_iterator begin() const throw() { return a_clientSessions.begin(); }
179   std::vector<ClientSession*>::const_iterator end() const throw() { return a_clientSessions.end(); }
180
181   int getNumberOfClientSessions() const throw() { return a_clientSessions.size(); }
182   int getMaxClientSessions() const throw() { return a_maxClientSessions; }
183   void setMaxClientSessions(int maxClientSessions) throw() { a_maxClientSessions = maxClientSessions; }
184
185   /**
186      Diameter server  address (IP or hostname)
187      \return Diameter server address.
188   */
189   const std::string& getAddress() const throw() { return a_socket.first; }
190
191   /**
192      Diameter server port.
193      \return Diameter server port.
194   */
195   int getPort() const throw() { return a_socket.second; }
196
197
198   /** Server presentation as 'ADDRESS:PORT' */
199   std::string socketAsString() const throw();
200
201
202   /**
203      Gets the timestamp for last incoming activity over the server.
204
205      @return Last incoming activity timestamp.
206   */
207   const anna::Millisecond & getLastIncomingActivityTime() const throw() { return a_lastIncomingActivityTime; }
208
209   /**
210      Gets the timestamp for last outgoing activity over the server.
211
212      @return Last outgoing activity timestamp.
213   */
214   const anna::Millisecond & getLastOutgoingActivityTime() const throw() { return a_lastOutgoingActivityTime; }
215
216
217   /**
218      Gets the number of requests messages over-the-air.
219
220      @return OTA messages.
221   */
222   int getOTARequests() const throw();
223
224   /**
225      Returns idle state (no pending answers).
226
227      @return Idle state.
228   */
229   bool idle() const throw() { return (getOTARequests() == 0); }
230
231
232   /**
233      Deny resources for delivery restriction.
234      Deny all its client sessions
235   */
236   void hide() throw();
237
238   /**
239      Allow resource for delivery permission.
240      Allow all its client sessions
241   */
242   void show() throw();
243
244   /**
245      Returns true when all its client session resources are hidden for application messages delivery
246   */
247   bool hidden() const throw();
248
249   /**
250      Returns true when all its client session resources are shown for application messages delivery
251   */
252   bool shown() const throw();
253
254
255   /**
256      Class string representation
257      \return String with relevant information for this instance.
258   */
259   std::string asString() const throw();
260
261   /**
262      Class xml representation
263      \param parent Parent XML node on which hold this instance information.
264      \return XML document with relevant information for this instance.
265   */
266   anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
267
268
269   // Statistics
270   void updateProcessingTimeStatisticConcept(const double &value) throw();
271   void updateReceivedMessageSizeStatisticConcept(const double &value) throw();
272   int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
273   int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
274
275 protected:
276
277   /**
278      Handler about event break connection from diameter server (client-session) over this entity.
279
280      When notified, ANNA.diameter.comm generates an diameter::comm::Entity::eventResponse for every request with pending answers.
281   */
282   virtual void eventPeerShutdown(const ClientSession*) throw();
283
284   /**
285      Handler about a request retransmission over the session.
286
287      \param request Message retransmitted
288   */
289   virtual void eventRequestRetransmission(const ClientSession*, Message *request) throw();
290
291   /**
292      Handler for diameter server (client-session) responses
293
294      \param response Answer container object for corresponding diameter request
295   */
296   virtual void eventResponse(const Response & response) throw(anna::RuntimeException);
297
298   /**
299      Handler for diameter server (client-session) requests
300
301      \param clientSession ClientSession from which request has been received
302      \param request Diameter request message received
303   */
304   virtual void eventRequest(ClientSession *clientSession, const anna::DataBlock &request) throw(anna::RuntimeException);
305   //virtual void eventRequest(ClientSession *clientSession, const Message & request) throw(anna::RuntimeException);
306
307   /**
308      Handler for diameter server (client-session) responses out of context
309
310      \param clientSession ClientSession from which request has been received
311      \param response Answer data block object without context match
312   */
313   virtual void eventUnknownResponse(ClientSession *clientSession, const anna::DataBlock& response) throw(anna::RuntimeException);
314
315   /**
316      Handler for diameter server (client-session) Disconnect-Peer-Answer messages
317
318      \param clientSession ClientSession from which request has been received
319      \param response Answer data block object without context match
320   */
321   virtual void eventDPA(ClientSession *clientSession, const anna::DataBlock& response) throw(anna::RuntimeException);
322
323
324
325   friend class Engine;
326   friend class ClientSession;
327 };
328
329 }
330 }
331 }
332
333 #endif