1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
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 //
9 #ifndef anna_diameter_comm_Session_hpp
10 #define anna_diameter_comm_Session_hpp
16 #include <anna/core/util/SortedVector.hpp>
17 #include <anna/core/util/Millisecond.hpp>
18 #include <anna/core/RuntimeException.hpp>
19 #include <anna/timex/Timer.hpp>
21 #include <anna/diameter/defines.hpp>
22 #include <anna/diameter.comm/ClassCode.hpp>
23 #include <anna/diameter.comm/Message.hpp>
24 #include <anna/diameter.comm/Timer.hpp>
53 Modela la conexion realizada contra un servidor diameter.
55 class Session : public anna::timex::Timer {
59 Session(const char *className, const char *timerName);
63 * Default timeout for application message requests over the session.
65 static const anna::Millisecond DefaultTimeout;
68 * Default diameter port
70 static const int DefaultPort;
77 \see diameter::comm::Session::getState
81 /* client + server */ Closed, /**< Closed */
82 /* client */ WaitingBind, /**< Connection confirmation pending*/
83 /* client + server */ Bound, /**< Connection done included level application */
84 /* client */ Failover, /**< Last DWR timed out */
85 /* server */ Suspect, /**< Inactivity detected on session */
90 // Cierre de iniciativa local:
91 // 1. Envio DPR al PCRF y me pongo en estado 'WaitingDPA'. En este estado no habr� keep-alive DWR/DWA.
92 // 2. No dejo pasar nuevas peticiones (BLOCK-SEND).
93 // 3. Cierro al recibir el DPA.
94 // 4. Si expira el DPA, tambien cierro.
95 WaitingDPA, /**< After requesting DPR to server, send is blocked over the session: when DPA arrives (or answer expires) the session is closed */
97 // Cierre de iniciativa remota:
98 // 1. Recibo DPR del PCRF y me pongo en estado 'Disconnecting'. En este estado no habr� keep-alive DWR/DWA.
99 // 2. No dejo pasar nuevas peticiones (BLOCK-SEND).
100 // 3. Espero cursar las peticiones pendientes (a m�s tardar, ser� una expiracion Tx desde la recepcion del DPR).
101 // 4. Envio DPA y activo un temporizador de cierre local (2*Tx) como proteccion (por si el servidor no cierra).
102 Disconnecting, /**< After receiving DPR from server, send is blocked over the session: when no pending requests, DPA is sent to the server who will close connection */
104 // Cierre abrupto con/sin espera de pendings:
105 Closing /** Planned local disconnection without DPR; send is blocked over the session. Immediate unbind is used when IgnorePendings behaviour is configured */
111 \return State for this session.
113 State::_v getState() const { return a_state; }
116 * Defines behaviour on 'Disconnecting' state, about #unbind action (ignore/wait pending answers)
118 struct OnDisconnect { enum _v { IgnorePendings, WaitPendings /* graceful unbind */ }; };
121 * Sets behaviour on 'Disconnecting' state, about #unbind action (ignore/wait pending answers).
122 * \param onDisconnect Behaviour on 'Disconnecting' state, about #unbind action (ignore/wait pending answers).
124 void setOnDisconnect(const OnDisconnect::_v onDisconnect) { a_onDisconnect = onDisconnect; }
127 * Returns behaviour on 'Disconnecting' state, about #unbind action (ignore/wait pending answers).
128 * \return behaviour on 'Disconnecting' state, about #unbind action (ignore/wait pending answers).
130 OnDisconnect::_v getOnDisconnect() const { return a_onDisconnect; }
135 Diameter server address, ip or hostname (remote for client-session, local for server-session).
136 \return Diameter server address (remote for client-session, local for server-session).
138 virtual const std::string& getAddress() const = 0;
141 Diameter server listen port (remote for client-session, local for server-session).
142 \return Diameter server listen port (remote for client-session, local for server-session).
144 virtual int getPort() const = 0;
150 int getSocketId() const { return a_socketId; }
153 Returns the next hop-by-hop which will be used over the diameter session to send a message
154 It is recommended to fix the message with this value (or store along with the message),
155 for application context identification purposes
157 const HopByHop & getNextHopByHop() const { return a_nextHopByHop; }
159 /** Returns the next end-to-end which will be used over the diameter session to send a message
160 It is recommended to fix the message with this value (or store along with the message),
161 for application context identification purposes
163 const EndToEnd & getNextEndToEnd() const { return a_nextEndToEnd; }
167 Set timeout to consider failed a request.
168 \param v Requests class code.
169 \param millisecond Milliseconds wait before considering the requests failed.
171 Timers are internally managed and automatically activated.
173 void setClassCodeTimeout(const ClassCode::_v v, const anna::Millisecond & millisecond) { a_timeouts [v] = millisecond; }
176 * Timeout configured for class code \em v requests.
177 * \return Timeout configured for class code \em v requests.
179 anna::Millisecond getClassCodeTimeout(const ClassCode::_v v) const { return a_timeouts [v]; }
183 Returns \em true when diameter server is connected (application level) \em false in other case.
184 \return \em true when diameter server is connected (application level) \em false in other case.
186 bool isBound() const { return a_state == State::Bound; }
189 // Envia el mensaje recibido como parametro al servidor con el que estamos conectados mediante esta
190 // sesion diameter. Dicho mensaje puede ser una peticion o una respuesta (no temporizada).
192 // En caso de enviar una peticion se activara automaticamente un temporizador. Si este llegara a caducar
193 // se cancelara la busqueda y se invocara al metodo Session::eventResponse indicado que se ha producido
194 // un error de temporizaci�n. La duracion del temporizador sera la establecida por
195 // diameter::comm::TimerManager::setTimeout o el valor defecto.
197 // \param message Mensaje a enviar al servidor diameter con el que estamos conectados.
198 // @return Diameter response reference asociated to a request. NULL if answer sent.
199 // \warning Solo se podra hacer uso de este metodo cuando el metodo #isBound devuelva \em true.
200 virtual const Response* send(const Message* message) noexcept(false) = 0;
201 const Response* send(const Message& message) noexcept(false) { return send(&message); }
203 // Desconecta del extremo remoto
204 // Se notifica la terminaci�n de cada una de las peticiones pendientes invocando al m�todo Session::eventResponse
205 // \warning Despu�s de invocar a este m�todo habr�a que volver a iniciar una sesion.
206 virtual bool unbind(bool forceDisconnect /* se usa en timer, para el actionTimer del tipo SessionUnbind, etc. */ = false) noexcept(false) = 0;
207 // returns true if done at call time (no pendings or ignore pendings, except Disconnecting state by mean DPR/DPA)
211 Gets the timestamp for last incoming activity over the session.
213 @return Last incoming activity timestamp.
215 const anna::Millisecond & getLastIncomingActivityTime() const { return a_lastIncomingActivityTime; }
218 Gets the timestamp for last outgoing activity over the session.
220 @return Last outgoing activity timestamp.
222 const anna::Millisecond & getLastOutgoingActivityTime() const { return a_lastOutgoingActivityTime; }
225 Gets the number of requests messages over-the-air.
227 @return OTA messages.
229 int getOTARequests() const { return a_responses.size(); }
233 Returns idle state (no pending answers).
237 bool idle() const { return (getOTARequests() == 0); }
241 In order to avoid message burst during failover procedures (alternate server forwardings done by application),
242 orphan request notification could be deferred to expiration event. This is the default behaviour, however if
243 need to notice quickly the transport failure for such requets, 'false' should be established. Result code of
244 'OrphanTimeout' will be configured at response instance.
246 This only applies to client-sessions because is not usual to send request from server sessions and there wont
247 be impact notifying orphan requests at the moment of the transport failure.
249 @defer Delayed notification for orphan request due to transport failures
251 void notifyOrphansOnExpiration(bool defer = true) { a_notifyOrphansOnExpiration = defer; }
254 Class string representation
255 \return String with relevant information for this instance.
257 virtual std::string asString() const ;
261 Class xml representation
262 \param parent Parent XML node on which hold this instance information.
263 \return XML document with relevant information for this instance.
265 virtual anna::xml::Node* asXML(anna::xml::Node* parent) const ;
269 // Internal, traces, etc.
270 const char *a_className;
272 // Main session attributes
273 int a_socketId; // multiple connection functionality
275 OnDisconnect::_v a_onDisconnect;
276 anna::diameter::comm::Timer *a_actionTimer;
279 HopByHop a_nextHopByHop;
280 EndToEnd a_nextEndToEnd;
281 virtual void initialize() ;
282 void initializeSequences() ; // debe invocarse despues de haber asignado el a_parent
283 void generateNextSequences() { a_nextHopByHop++; a_nextEndToEnd++; }
287 static HopByHop value(const Response*) ;
289 typedef anna::SortedVector <Response, SortById, HopByHop> response_container;
290 typedef response_container::iterator response_iterator;
291 typedef response_container::const_iterator const_response_iterator;
292 response_container a_responses;
293 bool a_notifyOrphansOnExpiration;
295 void response_add(Response* response) ;
296 void response_erase(Response* response) ;
297 Response* response_find(const HopByHop hopByHop) noexcept(false);
299 response_iterator response_begin() { return a_responses.begin(); }
300 response_iterator response_end() { return a_responses.end(); }
301 static Response* response(response_iterator ii) { return response_container::data(ii); }
303 const_response_iterator response_begin() const { return a_responses.begin(); }
304 const_response_iterator response_end() const { return a_responses.end(); }
305 static const Response* response(const_response_iterator ii) { return response_container::data(ii); }
308 anna::timex::Engine* a_timeController;
309 anna::Millisecond a_lastIncomingActivityTime; // last unix timestamp (in milliseconds) when message reception was managed over the session
310 anna::Millisecond a_lastOutgoingActivityTime; // last unix timestamp (in milliseconds) when message sending was managed over the session
311 virtual void updateIncomingActivityTime() ;
312 virtual void updateOutgoingActivityTime() ;
314 // Self-timer expiration handler
315 virtual void expire(anna::timex::Engine *timeController) noexcept(false) {;}
318 anna::Millisecond a_timeouts [ClassCode::Max];
322 Handler about event break connection over the session.
324 When notified, ANNA.diameter.comm generates an diameter::comm::ClientSession::eventResponse for every request with pending answers.
326 virtual void eventPeerShutdown() = 0;
329 Handler about a request retransmission over the session.
331 \param request Message retransmitted
333 virtual void eventRequestRetransmission(Message *request) = 0;
336 Handler for diameter session responses
338 \param response Answer data block object for corresponding diameter request
339 \param myNode Own origin host
341 virtual void eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
344 Handler for diameter session requests
346 \param request Request container object for corresponding diameter reception
347 \param myNode Own origin host
349 virtual void eventRequest(const anna::DataBlock& request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
350 //void eventRequest(const Message& request) noexcept(false);
354 Handler for diameter session responses out of context
356 \param response Answer data block object without context match
357 \param myNode Own origin host
359 virtual void eventUnknownResponse(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
362 Handler for diameter session Disconnect-Peer-Answer messages
364 \param response Answer data block object without context match
365 \param myNode Own origin host
367 virtual void eventDPA(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) = 0;
374 virtual void receive(const anna::comm::Message& message) noexcept(false) = 0;
376 //The errors at the protocol level are reported in response messages that contain the �E� bit and the error code in the AVP result-Code (various errors having been produced only the first one of them is reported). Examples of these errors are:
377 //An unrecognized AVP with the �M� bit is received.
378 //An AVP is received with an unrecognized value (in the AVP failed-AVP indicates the attribute that the error caused).
379 //An mandatory AVP is not received.
380 //Length of operation incorrect.
381 //Length of AVP incorrect.
382 //Coding of some AVP incorrect.
383 //Erroneous inclusion of parameters.
389 virtual void finalize() ; // invoked from ClientSessionReceiver::eventBreakConnection()
392 virtual void expireResponse(Response*) ;
393 void sendDPA(const Engine *commEngine, const anna::DataBlock &dprDataBlock) noexcept(false);
394 void activateActionTimer(const anna::diameter::comm::Timer::Type::_v type) ;
395 void cancelActionTimer() ;
396 void activateTimer() ; // Session timer
397 void cancelTimer() ; // Session timer
398 virtual void timerStopped() {;}
399 virtual void timerStarted() {;}
402 virtual void setState(State::_v state) ;
404 //anna::diameter::comm::Timer *getActionTimer() const { return (a_actionTimer); }
408 static const char* asText(const State::_v) ;
409 static const char* asText(const OnDisconnect::_v) ;
412 friend class anna::diameter::comm::Timer;
413 friend class Response;