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