Remove dynamic exceptions
[anna.git] / include / anna / comm / Handler.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_comm_Handler_hpp
10 #define anna_comm_Handler_hpp
11
12 #include <netinet/in.h>
13
14 #include <anna/core/mt/Runnable.hpp>
15 #include <anna/core/util/Millisecond.hpp>
16 #include <anna/core/util/Microsecond.hpp>
17
18 namespace anna {
19
20 namespace xml {
21 class Node;
22 }
23
24 namespace comm {
25
26 class Communicator;
27 class Transport;
28 class ClientSocket;
29
30 /**
31    Controlador de comunicaciones generico.
32 */
33 class Handler : public Runnable {
34 public:
35   using Runnable::initialize;
36   using Runnable::run;
37   using Runnable::setIsRunning;
38
39   /**
40      Mascara que define el funcionamiento de los manejadores de mensajes.
41   */
42   struct Support { enum _v { None = 0, CongestionControl = 1 }; };
43
44   /**
45      Tipo de controladores predefinidos.
46   */
47   struct Type {
48     enum _v {
49       ServerSocket,  /**< Controlador para ServerSocket */
50       LocalConnection,  /**< Controlador para LocalConnection */
51       RemoteConnection,  /**< Controlador para RemoteConnection */
52       DatagramSocket,  /**< Controlador para DatagramSocket */
53       BinderSocket,  /**< Controlador para comm::BinderSocket usado para compartir direcciones IPs. */
54       Custom,  /**< Controlador definido por el usuario */
55       ClientSocket /**< Controlador para un ClientSocket directo (sin uso intermedio de Server */
56     };
57   };
58
59   /**
60      Devuelve el tipo de controlador.
61      \return el tipo de controlador.
62   */
63   Type::_v getType() const { return a_type; }
64
65   /**
66      Devuelve el descriptor de fichero asociado a este controlador.
67      \return el descriptor de fichero asociado a este controlador.
68   */
69   int getfd() const { return a_fd; }
70
71   /**
72      Devuelve \em true si el descriptor de fichero asociado a este controlador soporta
73      control de congestion o \em false en otro caso.
74      \return \em true si el descriptor de fichero asociado a este controlador soporta
75      control de congestion o \em false en otro caso.
76   */
77   bool supportCongestionControl() const { return (a_support & Support::CongestionControl) != 0; }
78
79   /**
80      Devuelve \em true si este manejador soporta control de temporizacion o \em false en otro
81      caso.
82      \return \em true si este manejador soporta control de temporizacion o \em false en otro
83      caso.
84   */
85   bool supportTimeout() const { return a_timeout > 0; }
86
87   /**
88      Operador de comparacion.
89      \param fd Descriptor de fichero con el que comparar.
90      \return \em true si el fd recibido es igual al establecido con #setfd o \em false en caso contrario.
91   */
92   bool operator == (const int fd) const { return a_fd == fd; }
93
94   /**
95     Metodo invocado por el comunicador cuando detectado actividad en el descriptor de
96     fichero asociado a este controlador.
97   */
98   virtual void apply() noexcept(false) = 0;
99
100   /**
101      Devuelve el ClientSocket asociado a este manejador de conexiones.
102      \return El ClientSocket asociado a este manejador de conexiones. Puede ser NULL.
103      \warning Uso interno. Se necesita para poder cooperar con el anna::comm::CongestionController.
104   */
105   virtual ClientSocket* getClientSocket() { return NULL; }
106
107   /**
108      Devuelve una cadena con la informacion referente a esta instancia.
109      \return una cadena con la informacion referente a esta instancia.
110   */
111   virtual std::string asString() const ;
112
113   /**
114      Devuelve un documento XML con la informacion referente a esta instancia.
115      \return un documento XML con la informacion referente a esta instancia.
116   */
117   virtual xml::Node* asXML(xml::Node* parent) const noexcept(false);
118
119   /**
120      Amplia la informacion XML del nodo recibido como parametro.
121      \param node Nodo XML en el que incorporar los atributos.
122   */
123   void asAttribute(xml::Node* node) const noexcept(false);
124
125 protected:
126   /**
127      Instancia del comunicador puede ser NULL.
128   */
129   Communicator* a_communicator;
130
131   /**
132      Constructor.
133      \param communicator Comunicador asociado a este controlador.
134      \param type Tipo de Comunicador.
135      \param support Una combinacion de los valores de Handler::Support.
136   */
137   Handler(Communicator* communicator, const Type::_v type, const int support = Support::CongestionControl) :
138     a_communicator(communicator),
139     a_type(type),
140     a_support(support),
141     a_fd(-1),
142     a_timeout(0),
143     a_maxTime(0),
144     a_loop(0)
145   {;}
146
147   /**
148      Constructor.
149      \param type Tipo de Comunicador.
150      \param support Una combinacion de los valores de Handler::Support.
151   */
152   Handler(const Type::_v type, const int support = Support::CongestionControl) :
153     a_communicator(NULL),
154     a_type(type),
155     a_support(support),
156     a_fd(-1),
157     a_timeout(0),
158     a_maxTime(0),
159     a_loop(0)
160   {;}
161
162   /**
163      Establecer el descriptor de fichero asociado a este controlador.
164      \param fd Descriptor de fichero asociado a este controlador.
165      \warning La implementacion del metodo initialize debe invocar a este metodo
166      con descriptor de fichero valido.
167   */
168   void setfd(const int fd) { setId(anna::functions::asText("Handler", a_fd = fd)); }
169
170   /**
171      Establece el numero de milisegundos maximo que puede estar este manejador sin
172      recibir mensajes antes de ser cerrado por el nucleo.
173      \param timeout Numero de milisegundos maximo sin recibir mensajes.
174   */
175   void setTimeout(const Millisecond &timeout) {
176     a_timeout = timeout;
177     a_maxTime = functions::hardwareClock() + a_timeout;
178   }
179
180   /**
181      En los manejadores que pueden recibir mas de una peticion en cada llamada a apply este
182      metodo debe ser invocado para saber si debe dejar de procesar mensajes.
183   */
184   bool canContinue() const { return hasRequestedStop() == false; }
185
186   /**
187      Metodo con el que podemos redefinir el comportamiento cuando recibe la notificacion de
188      que una IP ha dejado de estar disponible.
189      \param address Direccion IP que ha dejado de estar disponible.
190      \warning Se invoca automaticamente desde el comunicador.
191   */
192   virtual void breakAddress(const in_addr_t& address) {;}
193
194   /**
195      Metodo con el que podemos redefinir el comportamiento cuando recibe la notificacion de
196      que una IP esta disponible.
197      \param address Direccion IP que ha pasado a estar disponible.
198      \warning Se invoca automaticamente desde el comunicador.
199   */
200   virtual void recoverAddress(const in_addr_t& address) {;}
201
202   /**
203    * Método que se invoca periódicamente para comprobar si tenemos pendiente el cierre de la conexión
204    * con el canal asociado a este manejador, cuando el fd asociado al manejador de recibe actividad.
205    *
206    * \return \em true Si termina la conexión o \em false en otro caso.
207    */
208   virtual bool testClose() noexcept(false) { return false;}
209
210   /**
211      Metodo con el que podemos redefinir el comportamiento cuando recibe la notificacion de
212      que el componente asociado a este controlador ha dejado de estar operativo.
213      \warning Se invoca automaticamente desde el comunicador al invocar al metodo
214      \em detach correspondiente.
215   */
216   virtual void finalize() {;}
217
218   /**
219    * Metodo con el que podemos redefinir el comportamiento cuando recibe la notificacion de
220    * que el componente asociado a este controlador ha sido duplicado en un proceso hijo.
221    * \warning Exclusivamente uso interno.
222   */
223   virtual void clone() noexcept(false) {;}
224
225 private:
226   const Type::_v a_type;
227   const int a_support;
228   int a_fd;
229   Microsecond a_timeout;
230   Microsecond a_maxTime;
231   int a_loop;
232
233   Handler(const Handler&);
234   void do_action() noexcept(false);
235   void beat(const Microsecond& now) { a_maxTime = now + a_timeout; }
236   bool isTimeout(const Microsecond& now) { return a_maxTime > 0 && a_maxTime <= now; }
237
238   friend class Communicator;
239 };
240
241 }
242 }
243
244 #endif
245