First commit
[anna.git] / include / anna / diameter.comm / ClientSession.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_ClientSession_hpp
38 #define anna_diameter_comm_ClientSession_hpp
39
40
41 // STL
42 #include <string>
43
44 #include <anna/core/util/SortedVector.hpp>
45 #include <anna/core/util/Millisecond.hpp>
46 #include <anna/core/RuntimeException.hpp>
47
48 #include <anna/diameter.comm/Session.hpp>
49 #include <anna/diameter/defines.hpp>
50 #include <anna/diameter.comm/Message.hpp>
51 #include <anna/diameter.comm/ClientSessionReceiver.hpp>
52 #include <anna/diameter.comm/ReceiverFactoryImpl.hpp>
53
54
55 namespace anna {
56 class DataBlock;
57 namespace timex {
58 class Engine;
59 }
60
61 namespace comm {
62 class Server;
63 }
64 }
65
66
67 namespace anna {
68
69 namespace diameter {
70
71 namespace comm {
72
73 class Server;
74
75
76 /**
77    Modela la conexion realizada contra un servidor diameter.
78 */
79 class ClientSession : public Session {
80
81   // Helper:
82   static std::string getKey(const std::string & addr, int port, int socketId) throw() {
83     return (anna::functions::asString("%s:%d|%d", addr.c_str(), port, socketId));
84   }
85
86   bool a_hidden; // hide resource for restricted delivery over servers/entities
87
88
89 public:
90
91   ClientSession();
92
93
94   /* virtual */void initialize() throw();
95
96   /**
97    * Default watchdog period for the diameter client-session health.
98    */
99   static const anna::Millisecond DefaultWatchdogPeriod;
100
101   /**
102      Client session key: <address ip or hostname>:<remote port>|<socket id: 0..N-1>
103   */
104   std::string getKey() const throw() { return ClientSession::getKey(getAddress(), getPort(), getSocketId()); }
105
106   /**
107      Diameter server address (IPv4 or hostname)
108      \return Diameter server address
109   */
110   /* virtual */const std::string& getAddress() const throw();
111
112   /**
113      Diameter server listen port
114      \return Diameter server listen port
115   */
116   /* virtual */int getPort() const throw();
117
118   /**
119      Diameter parent server.
120      \return Diameter parent server.
121   */
122   const Server *getParent() const throw() { return a_parent; }
123
124   /**
125      Diameter server created at diameter::comm::Engine::createClientSession.
126      \return Diameter server
127   */
128   anna::comm::Server * getServer() throw() { return a_server; }
129
130   /**
131      Disables server resource (avoid the use of the server)
132   */
133   void disable() throw() { a_server->disable(); }
134
135   /**
136      Sets auto recovery indicator. When a connection is lost, by default it will be recovered automatically.
137      \param autoRecovery Auto recovery indicator. TRue by default.
138   */
139   void setAutoRecovery(bool autoRecovery = true) throw() { a_autoRecovery = autoRecovery; a_server->setAutoRecovery(autoRecovery); }
140
141   /**
142      Gets the auto recovery indicator for the client connection (client-session).
143
144      @return Auto recovery indicator.
145   */
146   bool getAutoRecovery() const throw() { return a_autoRecovery; }
147
148   /**
149      Sets the milliseconds wait to achieve a client connection to server by mean connect primitive.
150      This allow to perform specific configurations (some servers could be slower than others).
151      Changes will be taken into account on the next connect operation.
152
153      \param maxConnectionDelay Milliseconds wait to get connection
154   */
155   void setMaxConnectionDelay(const anna::Millisecond & maxConnectionDelay) throw() { a_server->setMaxConnectionDelay(maxConnectionDelay); }
156
157   /**
158      Gets the milliseconds wait to achieve a client connection to server by mean connect primitive.
159
160      \return Milliseconds wait to get connection
161   */
162   const anna::Millisecond & getMaxConnectionDelay() throw() { return a_server->getMaxConnectionDelay(); }
163
164   /**
165    * Sets CER and DWR diameter messages to be used over created client-sessions
166    *
167    * @param cer Capabilities-Exchange-Request message (encoded) for the client-sessions bind.
168    * @param dwr Device-Watchdog-Request message (encoded) for the client-sessions keep-alive.
169    */
170   void setCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) throw(anna::RuntimeException);
171
172   // Internal
173   void bind() throw(anna::RuntimeException);
174
175   /* virtual */const Response* send(const Message* message) throw(anna::RuntimeException);
176   /* virtual */bool unbind(bool forceDisconnect /* se usa en timer, para el actionTimer del tipo SessionUnbind, etc. */ = false) throw(anna::RuntimeException); // returns true if done at call time (no pendings or ignore pendings, except Disconnecting state by mean DPR/DPA)
177
178   /**
179      Deny resource for delivery restriction
180   */
181   void hide() throw() { a_hidden = true; }
182
183   /**
184      Allow resource for delivery permission
185   */
186   void show() throw() { a_hidden = false; }
187
188   /**
189      Returns true when client session resource is hidden for application messages delivery
190   */
191   bool hidden() const throw() { return a_hidden; }
192
193   /**
194      Returns true when client session resource is shown for application messages delivery
195   */
196   bool shown() const throw() { return !a_hidden; }
197
198
199   /**
200      Class string representation
201      \return String with relevant information for this instance.
202   */
203   /* virtual */std::string asString() const throw();
204
205
206   /**
207      Class xml representation
208      \param parent Parent XML node on which hold this instance information.
209      \return XML document with relevant information for this instance.
210   */
211   /* virtual */anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
212
213
214 private:
215
216   // Receiver factory
217   ReceiverFactoryImpl<ClientSession, ClientSessionReceiver> a_receiverFactory;
218
219   // Parent information
220   Server *a_parent;
221
222   // ClientSession messages:
223   Message a_cer;
224   Message a_dwr;
225
226   // Connectivity
227   bool a_autoRecovery;
228
229   // Server
230   anna::comm::Server *a_server;
231
232   // Watchdog control:
233   struct WatchdogState {
234     enum _v {
235       TimerStopped,           // Until CEA (bound state), timer is stopped
236       WaitingTimerExpiration, // DWA has been received and we wait for next expiration to send DWR
237       WaitingDWA              // DWR has been sent, but DWA hasn't been received yet
238     };
239   };
240   WatchdogState::_v a_watchdogState;
241   void setWatchdogState(WatchdogState::_v wState) throw();
242
243   /* virtual */void expire(anna::timex::Engine *timeController) throw(anna::RuntimeException);
244   void setWatchdogPeriod(const anna::Millisecond & watchdogPeriod) throw();
245
246   /*virtual*/ void timerStopped() throw();
247   /*virtual*/ void timerStarted() throw();
248
249
250   // Activity:
251   /* virtual */void updateIncomingActivityTime() throw();
252   /* virtual */void updateOutgoingActivityTime() throw();
253   void countSendings(const diameter::CommandId & cid, bool ok) throw();
254
255   // Handlers:
256   /**
257      Handler about event break connection from diameter server over this client-session.
258
259      When notified, ANNA.diameter.comm generates an diameter::comm::ClientSession::eventResponse for every request with pending answers.
260   */
261   void eventPeerShutdown() throw();
262
263   /**
264      Handler for diameter server (client-session) responses
265
266      \param response Answer container object for corresponding diameter request
267   */
268   void eventResponse(const Response& response) throw(anna::RuntimeException);
269
270   /**
271      Handler for diameter server (client-session) requests
272
273      \param request Request data block object for corresponding diameter reception
274   */
275   void eventRequest(const anna::DataBlock& request) throw(anna::RuntimeException);
276   //void eventRequest(const Message& request) throw(anna::RuntimeException);
277
278   /**
279      Handler for diameter server (client-session) responses out of context
280
281      \param response Answer data block object without context match
282   */
283   void eventUnknownResponse(const anna::DataBlock& response) throw(anna::RuntimeException);
284
285
286   /**
287   * Handlers for receptions
288   */
289   /* virtual */void receive(const anna::comm::Message& message) throw(anna::RuntimeException);
290   /* virtual */void finalize() throw();
291   void recover() throw();
292
293   /* virtual */void expireResponse(Response*) throw();
294   /* virtual */void setState(State::_v state) throw();
295
296   void sendDWAToServer(const anna::DataBlock& dwrDB) throw(anna::RuntimeException); // non-usual behaviour, but DWR could be received from server
297
298   // helpers
299   static const char* asText(const WatchdogState::_v) throw();
300
301
302   friend class Server;
303   friend class Engine;
304   friend class ClientSessionReceiver;
305 };
306
307 }
308 }
309 }
310
311 #endif
312