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