1 // ANNA - Anna is Not 'N' Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // https://bitbucket.org/testillano/anna
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
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
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.
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.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #ifndef anna_diameter_comm_LocalServer_hpp
38 #define anna_diameter_comm_LocalServer_hpp
41 #include <anna/core/RuntimeException.hpp>
42 #include <anna/core/util/Millisecond.hpp>
43 #include <anna/core/util/Recycler.hpp>
49 #include <anna/config/defines.hpp>
50 #include <anna/statistics/Accumulator.hpp>
51 #include <anna/diameter.comm/ServerSession.hpp>
60 //class LocalConnection;
78 Diameter server socket
84 std::string a_description;
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;
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();
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);
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();
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
119 void attach() throw(); // attach server socket to the communicator
120 void attachPlanning() throw(); // used when attach fails (socket already in use, etc.)
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; }
138 // INTERNAL CREATORS AND CLOSE METHODS
139 ServerSession *createServerSession(const anna::comm::ClientSocket&) throw(anna::RuntimeException);
140 void closeServerSession(ServerSession*) throw(anna::RuntimeException);
142 // INTERNAL ALLOCATORS
143 ServerSession* allocateServerSession() throw();
144 void releaseServerSession(ServerSession*) throw();
147 serverSession_iterator a_deliveryIterator;
148 ServerSession *a_lastUsedResource;
156 ~LocalServer() { close(); }
162 * Sets the local server key
163 * @param LocalServer key
165 void setKey(const socket_t &key) throw() { a_key = key; }
168 Sets the server socket optional description
170 @param description Server socket description
172 void setDescription(const std::string description) throw() { a_description = description; }
176 Sets the server socket optional category
178 @param description Server socket category
180 void setCategory(int category) throw() { a_category = category; }
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.
188 @param maxConnections Number of maximum connections allowed
190 void setMaxConnections(int maxConnections) throw(anna::RuntimeException);
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.
196 @param allowedInactivityTime Inactivity time allowed
198 void setAllowedInactivityTime(const anna::Millisecond & allowedInactivityTime) throw() { a_allowedInactivityTime = allowedInactivityTime; }
201 * Sets the diameter::comm::Engine
202 * @param e Diameter::comm::Engine
204 void setEngine(Engine *e) throw() { a_engine = e; }
210 * Gets the local server key
211 * @return LocalServer key
213 const socket_t & getKey() const throw() { return a_key; }
216 Gets the number of maximum accepted connections that server socket is configured to handle
218 int getMaxConnections() const throw() { return a_maxConnections; }
221 Gets the number of current connections being established through server socket
223 int getCurrentConnections() const throw() { return a_currentConnections; }
226 Gets the maximum allowed inactivity time on server sessions born over the local server before being reset
228 @return Inactivity time allowed
230 const anna::Millisecond & getAllowedInactivityTime() const throw() { return a_allowedInactivityTime; }
233 Returns true when any of the server-sessions is Bound. False when all not-bound.
235 bool isAvailable() const throw() { return a_available; }
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)
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.)
246 void disable(bool lock = false) throw(anna::RuntimeException);
248 /** Enables local server socket (listener)
250 @param unlock Unlocks permanent disabled states
252 void enable(bool unlock = false) throw(anna::RuntimeException);
255 Gets the number of requests messages over-the-air.
257 @return OTA messages.
259 int getOTARequests() const throw();
262 Returns idle state (no pending answers).
266 bool idle() const throw() { return (getOTARequests() == 0); }
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.
272 void close() throw(anna::RuntimeException);
275 Performs coherent server socket close procedure zeroing margin between current established connections and maximum allowed.
277 void resetConnectionsMargin() throw(anna::RuntimeException) { setMaxConnections(a_currentConnections); }
281 * Returns server-session instance identified by client socket provided.
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).
286 * \return The server-session instance identified by client socket provided.
288 * \warning If no server-session found, an exception is launched by default.
290 ServerSession* findServerSession(const anna::comm::ClientSocket &clientSocket, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
293 * Returns server-session instance identified by socket id provided (hash over serialized client socket information).
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).
298 * \return The server-session instance identified by client socket provided.
300 * \warning If no server-session found, an exception is launched by default.
302 ServerSession* findServerSession(int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
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.
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)
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.
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); }
323 Gets the last used resource (server session) during sending.
324 Broadcast doesn't updates this information.
326 ServerSession *getLastUsedResource() const throw() { return (a_lastUsedResource); }
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.
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.
335 \param message Message which is being sent.
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.
340 virtual int readSocketId(const Message *message) const throw() { return -1; }
343 Sent a message to all the server sessions.
344 It is used, i.e., in Disconnect-Peer-Request procedure over a certain entity.
346 \param message Message which is being sent.
348 @return Returns true (success) only when broadcast is success over all the entity servers. If any server fails,
349 then false is returned.
351 bool broadcast(const Message *message) throw(anna::RuntimeException);
352 bool broadcast(const Message &message) throw(anna::RuntimeException) { return broadcast(&message); }
356 Class string representation
357 \return String with relevant information for this instance.
359 std::string asString() const throw();
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.
366 anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
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; }
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
383 virtual void eventPeerShutdown(const ServerSession* serverSession) throw();
386 Handler for diameter client responses
388 \param response Answer container object for corresponding diameter request
390 virtual void eventResponse(const Response& response) throw(anna::RuntimeException) = 0;
393 Handler for diameter client requests
395 \param serverSession ServerSession from which request has been received
396 \param request Request data block object for corresponding diameter reception
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);
402 Handler for diameter client responses out of context
404 \param serverSession ServerSession from which request has been received
405 \param response Answer data block object without context match
407 virtual void eventUnknownResponse(ServerSession* serverSession, const anna::DataBlock& response) throw(anna::RuntimeException) = 0;
410 friend class anna::diameter::comm::Timer;
412 friend class ServerSocket;
413 friend class ServerSession;
414 friend class ServerSessionReceiver;