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