2416e8ce70e47737f7cba9c40c3fe9bdd5ad05e8
[anna.git] / include / anna / diameter.comm / LocalServer.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_LocalServer_hpp
10 #define anna_diameter_comm_LocalServer_hpp
11
12
13 #include <anna/core/RuntimeException.hpp>
14 #include <anna/core/util/Millisecond.hpp>
15 #include <anna/core/util/Recycler.hpp>
16
17 // STL
18 #include <string>
19 #include <vector>
20
21 #include <anna/config/defines.hpp>
22 #include <anna/statistics/Accumulator.hpp>
23 #include <anna/diameter.comm/ServerSession.hpp>
24
25
26 namespace anna {
27 namespace xml {
28 class Node;
29 }
30 namespace comm {
31 class ClientSocket;
32 //class LocalConnection;
33 }
34 class DataBlock;
35 }
36
37 namespace anna {
38
39 namespace diameter {
40
41 namespace comm {
42
43 class Engine;
44 class Response;
45 class ServerSocket;
46 class Message;
47
48
49 /**
50    Diameter server socket
51 */
52 class LocalServer {
53
54   // main
55   socket_t a_key;
56   std::string a_description;
57   int a_maxConnections;
58   int a_currentConnections; // deberia coincidir en todo momento con el numero de local connections del server socket
59   anna::Millisecond a_allowedInactivityTime;
60   ServerSocket *a_serverSocket;
61   int a_category;
62   bool a_lock;
63
64   // Engine
65   Engine *a_engine;
66
67   // Statistics
68   int a_processing_time__StatisticConceptId; // request from local server (dpr's, etc.)
69   int a_received_message_size__StatisticConceptId;
70   anna::statistics::Accumulator *a_statisticsAccumulator;
71   void initializeStatisticResources() throw();
72   void resetStatistics() throw();
73
74 //   void eraseServerSession(const anna::comm::ClientSocket& clientSocket) throw();
75 //   void eraseServerSession(const serverSession_iterator &it) throw();
76   void lostConnection() throw();
77   void newConnection() throw(anna::RuntimeException);
78
79   // Activity
80   anna::Millisecond a_lastIncomingActivityTime;   // last unix timestamp (in milliseconds) when message reception was managed over this entity
81   anna::Millisecond a_lastOutgoingActivityTime;   // last unix timestamp (in milliseconds) when message sending was managed over this entity
82   void updateIncomingActivityTime() throw();
83   void updateOutgoingActivityTime() throw();
84
85   // Availability
86   bool a_available; // any of the server-sessions must be bound
87   void availabilityLost() throw();
88   void availabilityRecovered() throw();
89   bool refreshAvailability() throw(); // return true if change
90
91   void attach() throw(); // attach server socket to the communicator
92   void attachPlanning() throw(); // used when attach fails (socket already in use, etc.)
93
94   typedef int serverSession_key;
95   serverSession_key getServerSessionKey(const anna::comm::ClientSocket&) const throw(); // hash for Client Socket INetAddress serialization
96   typedef std::map <serverSession_key, ServerSession*> serverSession_container;
97   typedef serverSession_container::value_type serverSession_value_type;
98   typedef serverSession_container::iterator serverSession_iterator;
99   typedef serverSession_container::const_iterator const_serverSession_iterator;
100   serverSession_container a_serverSessions;
101   anna::Recycler<ServerSession> a_serverSessionsRecycler;
102   serverSession_iterator serverSession_find(const serverSession_key&) throw();
103   serverSession_iterator serverSession_begin() throw() { return a_serverSessions.begin(); }
104   serverSession_iterator serverSession_end() throw() { return a_serverSessions.end(); }
105   static ServerSession* serverSession(serverSession_iterator ii) throw() { return ii->second; }
106   const_serverSession_iterator serverSession_begin() const throw() { return a_serverSessions.begin(); }
107   const_serverSession_iterator serverSession_end() const throw() { return a_serverSessions.end(); }
108   static const ServerSession* serverSession(const_serverSession_iterator ii) throw() { return ii->second; }
109
110   // INTERNAL CREATORS AND CLOSE METHODS
111   ServerSession *createServerSession(const anna::comm::ClientSocket&) throw(anna::RuntimeException);
112   void closeServerSession(ServerSession*) throw(anna::RuntimeException);
113
114   // INTERNAL ALLOCATORS
115   ServerSession* allocateServerSession() throw();
116   void releaseServerSession(ServerSession*) throw();
117
118   // Auxiliary
119   serverSession_iterator a_deliveryIterator;
120   ServerSession *a_lastUsedResource;
121
122 public:
123
124   /** Constructor */
125   LocalServer();
126
127   /** Destructor */
128   ~LocalServer() { close(); }
129
130
131   // setters
132
133   /**
134   * Sets the local server key
135   * @param LocalServer key
136   */
137   void setKey(const socket_t &key) throw() { a_key = key; }
138
139   /**
140      Sets the server socket optional description
141
142      @param description Server socket description
143   */
144   void setDescription(const std::string description) throw() { a_description = description; }
145
146   /**
147      Set timeout to consider failed a request.
148      \param v Requests class code.
149      \param millisecond Milliseconds wait before considering the requests failed.
150
151      Timers are internally managed and automatically activated.
152   */
153   void setClassCodeTimeout(const ClassCode::_v v, const anna::Millisecond & millisecond) throw();
154
155   /**
156      Sets the server socket optional category
157
158      @param description Server socket category
159   */
160   void setCategory(int category) throw() { a_category = category; }
161
162   /**
163      Sets the maximum supported connections.
164      If provided value is negative or lesser than the number of current connections, an exception will be launched.
165      If all the connections was established, a new maximum will open the listen port.
166      when margin is zeroed (maximum configured is equal to current connections), listen port will be closed.
167
168      @param maxConnections Number of maximum connections allowed
169   */
170   void setMaxConnections(int maxConnections) throw(anna::RuntimeException);
171
172   /**
173      Sets the maximum allowed inactivity time on server sessions born over the local server before being reset.
174      Communication engine assign a default value of 90000 msecs.
175
176      @param allowedInactivityTime Inactivity time allowed
177   */
178   void setAllowedInactivityTime(const anna::Millisecond & allowedInactivityTime) throw() { a_allowedInactivityTime = allowedInactivityTime; }
179
180   /**
181   * Sets the diameter::comm::Engine
182   * @param e Diameter::comm::Engine
183   */
184   void setEngine(Engine *e) throw() { a_engine = e; }
185
186   // getters
187
188   /**
189   * Gets the diameter::comm::Engine
190   * @return Diameter::comm::Engine
191   */
192   Engine *getEngine() const throw() { return a_engine; }
193
194   /**
195   * Gets the local server key
196   * @return LocalServer key
197   */
198   const socket_t & getKey() const throw() { return a_key; }
199
200   /**
201      Gets the number of maximum accepted connections that server socket is configured to handle
202   */
203   int getMaxConnections() const throw() { return a_maxConnections; }
204
205   /**
206      Gets the number of current connections being established through server socket
207   */
208   int getCurrentConnections() const throw() { return a_currentConnections; }
209
210   /**
211      Gets the maximum allowed inactivity time on server sessions born over the local server before being reset
212
213      @return Inactivity time allowed
214   */
215   const anna::Millisecond & getAllowedInactivityTime() const throw() { return a_allowedInactivityTime; }
216
217   /**
218      Returns true when any of the server-sessions is Bound. False when all not-bound.
219   */
220   bool isAvailable() const throw() { return a_available; }
221
222   // helpers
223
224   /**
225      Disables local server socket (listener) keeping current server sessions alive.
226      Note that applications should not close the listen port directly to keep coherence (see #resetConnectionsMargin)
227
228      @param lock Locks disabled state (make it permanent even if new connections margin is reached).
229      Used during diameter agent isolation (lost of service, maintenance, etc.)
230   */
231   void disable(bool lock = false) throw(anna::RuntimeException);
232
233   /** Enables local server socket (listener)
234
235      @param unlock Unlocks permanent disabled states
236   */
237   void enable(bool unlock = false) throw(anna::RuntimeException);
238
239   /**
240      Gets the number of requests messages over-the-air.
241
242      @return OTA messages.
243   */
244   int getOTARequests() const throw();
245
246   /**
247      Returns idle state (no pending answers).
248
249      @return Idle state.
250   */
251   bool idle() const throw() { return (getOTARequests() == 0); }
252
253   /**
254      Close the local server means two things: close the server socket and close all the server sessions born
255      from this local server freeing such server sessions resources.
256   */
257   void close() throw(anna::RuntimeException);
258
259   /**
260      Performs coherent server socket close procedure zeroing margin between current established connections and maximum allowed.
261   */
262   void resetConnectionsMargin() throw(anna::RuntimeException) { setMaxConnections(a_currentConnections); }
263
264
265   /**
266    * Returns server-session instance identified by client socket provided.
267    *
268    * \param clientSocket Client socket associated to the server session
269    * \param emode Action when no client-session is found with provided parameters (Throw/Ignore).
270    *
271    * \return The server-session instance identified by client socket provided.
272    *
273    * \warning If no server-session found, an exception is launched by default.
274    */
275   ServerSession* findServerSession(const anna::comm::ClientSocket &clientSocket, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
276
277   /**
278    * Returns server-session instance identified by socket id provided (hash over serialized client socket information).
279    *
280    * \param socketId Socket id which is key for the server session
281    * \param emode Action when no client-session is found with provided parameters (Throw/Ignore).
282    *
283    * \return The server-session instance identified by client socket provided.
284    *
285    * \warning If no server-session found, an exception is launched by default.
286    */
287   ServerSession* findServerSession(int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
288
289
290   /**
291      Sent a message to the client using a certain server-session provided or defined by #readSocketId if not.
292      When the message is a request, a timer will be set automatically to control the response time.
293      If expires, the ResultCode Timeout will be finally notified on #LocalServer::eventResponse. This
294      timeout value will be configured at #setClassCodeTimeout.
295
296      \param message Message sent.
297      \param socketId Server session socket id INetAddress serialization. By default, #readSocketId is invoked to get the socket id used (which uses round-robin if not re-implemented)
298
299      @return Boolean about success in send operation. True when any of the server sessions could send the message.
300      False, when neither of the server sessions was available or fail to send the message. Broadcast try to send all over
301      the resources in spite of any fail. If a specific socket id is provided, only this socket is used without trying any other
302      and returning false if fails.
303   */
304   bool send(const Message*, int socketId = -1 /* default uses readSocketId() */) throw(anna::RuntimeException);
305   bool send(const Message& message, int socketId = -1 /* default uses readSocketId() */) throw(anna::RuntimeException) { return send(&message, socketId); }
306
307   /**
308      Gets the last used resource (server session) during sending.
309      Broadcast doesn't updates this information.
310   */
311   ServerSession *getLastUsedResource() const throw() { return (a_lastUsedResource); }
312
313   /**
314      Before sending a message over each local server, socketId could be specified to select
315      which session within such server will manage the message.
316
317      Default implementation performs round-robin (value '-1' for socketId) but any other kind of
318      application could re-implement this method and change the behaviour.
319
320      \param message Message which is being sent.
321
322      @return Socket-id (hash over serialized client socket information). Value '-1' if round-robin is desired.
323      If socket-id is unkonwn, send procedure will throw an exception.
324   */
325   virtual int readSocketId(const Message *message) const throw() { return -1; }
326
327   /**
328      Sent a message to all the server sessions.
329      It is used, i.e., in Disconnect-Peer-Request procedure over a certain entity.
330
331      \param message Message which is being sent.
332
333      @return Returns true (success) only when broadcast is success over all the entity servers. If any server fails,
334      then false is returned.
335   */
336   bool broadcast(const Message *message) throw(anna::RuntimeException);
337   bool broadcast(const Message &message) throw(anna::RuntimeException) { return broadcast(&message); }
338
339
340   /**
341      Class string representation
342      \return String with relevant information for this instance.
343   */
344   std::string asString() const throw();
345
346   /**
347      Class xml representation
348      \param parent Parent XML node on which hold this instance information.
349      \return XML document with relevant information for this instance.
350   */
351   anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
352
353   // Statistics
354   void updateProcessingTimeStatisticConcept(const double &value) throw();
355   void updateReceivedMessageSizeStatisticConcept(const double &value) throw();
356   int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
357   int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
358
359 protected:
360
361   // Handlers:
362   /**
363      Handler about event break connection from diameter client over this server-session.
364      When notified, ANNA.diameter.comm generates an diameter::comm::ServerSession::eventResponse for every request with pending answers.
365      Default implementation traces warning event
366      \param serverSession ServerSession from which shutdown has been received
367   */
368   virtual void eventPeerShutdown(const ServerSession* serverSession) throw();
369
370   /**
371      Handler about a request retransmission over the server-session.
372      Default implementation traces warning event
373      \param serverSession ServerSession from which retransmission happened
374      \param request Retransmitted request message
375   */
376   virtual void eventRequestRetransmission(const ServerSession* serverSession, Message *request) throw();
377
378   /**
379      Handler for diameter client responses
380
381      \param response Answer container object for corresponding diameter request
382   */
383   virtual void eventResponse(const Response& response) throw(anna::RuntimeException) = 0;
384
385   /**
386      Handler for diameter client requests
387
388      \param serverSession ServerSession from which request has been received
389      \param request Request data block object for corresponding diameter reception
390   */
391   virtual void eventRequest(ServerSession* serverSession, const anna::DataBlock& request) throw(anna::RuntimeException) = 0;
392   //void eventRequest(ServerSession* serverSession, const Message& request) throw(anna::RuntimeException);
393
394   /**
395      Handler for diameter client responses out of context
396
397      \param serverSession ServerSession from which request has been received
398      \param response Answer data block object without context match
399   */
400   virtual void eventUnknownResponse(ServerSession* serverSession, const anna::DataBlock& response) throw(anna::RuntimeException) = 0;
401
402   /**
403      Handler for diameter client Disconnect-Peer-Answer messages
404
405      \param serverSession ServerSession from which request has been received
406      \param response Answer data block object without context match
407   */
408   virtual void eventDPA(ServerSession* serverSession, const anna::DataBlock& response) throw(anna::RuntimeException) = 0;
409
410
411   friend class anna::diameter::comm::Timer;
412   friend class Engine;
413   friend class ServerSocket;
414   friend class ServerSession;
415   friend class ServerSessionReceiver;
416 };
417
418 }
419 }
420 }
421
422 #endif