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