Remove dynamic exceptions
[anna.git] / include / anna / comm / Communicator.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_Communicator_hpp
10 #define anna_comm_Communicator_hpp
11
12 #include <vector>
13
14 #include <anna/config/defines.hpp>
15 #include <anna/core/DataBlock.hpp>
16 #include <anna/core/util/Recycler.hpp>
17 #include <anna/core/util/SortedVector.hpp>
18
19 #include <anna/app/Component.hpp>
20
21 #include <anna/comm/INetAddress.hpp>
22 #include <anna/comm/Socket.hpp>
23 #include <anna/comm/Status.hpp>
24
25 #include <anna/comm/internal/ConnectionRecover.hpp>
26
27 #include <anna/core/util/Millisecond.hpp>
28
29 namespace anna {
30
31 // MT
32 class ThreadManager;
33
34 namespace xml {
35 class Node;
36 }
37
38 namespace comm {
39
40 class Application;
41 class Transport;
42 class Message;
43 class ServerSocket;
44 class ClientSocket;
45 class LocalConnection;
46 class RemoteConnection;
47 class DatagramSocket;
48 class INetAddress;
49 class Handler;
50 class Server;
51 class Service;
52 class BinderSocket;
53 class ConnectionRecover;
54
55 namespace handler {
56 class LocalConnection;
57 class RemoteConnection;
58 class ClientSocket;
59 }
60
61 // ST
62 class Poll;
63
64 /**
65    Clase que integra todos los elementos implicados en la recepcin y/o envio y tratamiento de mensajes
66    de red.
67
68    Los mensajes recibidos y/o enviados a la capa de transporte seran tratados por el protocolo asociado
69    al socket cliente. Normalmente todos los socket clientes asociados a un comunicador tendran asociado
70    un mismo tipo de protocolo. Ver Transport.
71
72    Normalmente, y una vez que recibimos un mensaje (ver #eventReceiveMessage) aplicaremos algun codec (ver @ref Codec)
73    para interpretar el contenido del mensaje, de forma analoga, para enviar un mensaje a la capa de transporte
74    usando cualquier protocolo lo normal sera haber codificado cierta informacion usando algun codec.
75
76    \warning Siempre que usemos un Communicator debemos establecer una clase Application heredada
77    de comm::Application.
78 */
79 class Communicator : public app::Component {
80   struct SortByFileDescriptor {
81     static int value(const Handler*) ;
82   };
83
84   /**
85    * Tamaño del búfer usado para leer los mensajes de la red.
86    * Se puede establecer desde comm::Communicator::setReceivingChunkSize.
87    */
88   static Millisecond st_ReceivingChunkSize;
89
90 public:
91   /**
92    * Modo de aceptar peticiones en el caso de una arquitectura ST.
93    * \warning Solo tiene efecto en caso de generar la libreria en modo ST.
94    * \see Communicator
95    */
96   struct WorkMode {
97     enum _v {
98       /**
99        * Un único proceso atiende todas las peticiones, el reparto de atención implementado asegura que todos
100        * los clientes tendrán un tiempo de respuesta similar, el tratamiento de N peticiones que llegan simultáneamente
101        * se realiza de forma secuencial. Es el modo usado hasta ahora en modo ST. Tiene la ventaja de ser el método que
102        * origina código más simple y fácil de mantener.
103        */
104       Single,
105       /**
106        *  Cada cliente tiene su propia copia del servidor original que trata sus peticiones de forma particular.
107        * De esta forma se podrían llegar a servir simultáneamente cada una de las peticiones de cada uno de los
108        * clientes conectados al servidor. Puede ser una buena opción si tenemos en cuenta la relación entre el
109        * rendimiento y la complejidad de desarrollo.
110        *
111        * Podria ser la mejor opcion para implementar un servidor de base de datos.
112        *
113        * \warning Solo puede usarse para implementar servidores finales, es decir, procesos que no requieran de la
114        * respuesta de ningun otro proceso remoto para realizar su operacion.
115        */
116       Clone
117     };
118   };
119
120   /**
121    * Numero de mínimo milisegundos esperados para intentar la recuperacion de la conexion con los
122    * servidores en caso de detectar algun error.
123    */
124   static const Millisecond MinRecoveryTime;
125
126   /**
127      Numero de milisegundos esperados para intentar la recuperacion de la conexion con los
128      servidores en caso de detectar algun error.
129   */
130   static const Millisecond DefaultRecoveryTime;
131
132   /**
133    * Numero de mínimo milisegundos esperados para intentar la recuperacion de la conexion con los
134    * servidores en caso de detectar algun error.
135    */
136   static const Millisecond MaxRecoveryTime;
137
138   /**
139    * Periodo de tiempo mínimo que estará intentando conectar con servidores cada vez que se cumpla el periodo de
140    * comprobación de conexiones.
141    */
142   static const Millisecond MinTryingConnectionTime;
143
144   /**
145    * Periodo de tiempo usado por defectoque estará intentando conectar con servidores cada vez que se cumpla el
146    * periodo de comprobación de conexiones.
147    */
148   static const Millisecond DefaultTryingConnectionTime;
149
150   /**
151    * Periodo de tiempo máximo que estará intentando conectar con servidores cada vez que se cumpla el periodo de
152    * comprobación de conexiones.
153    */
154   static const Millisecond MaxTryingConnectionTime;
155
156   /**
157    * Tamaño mínimo de la cola de entrada de mensajes que se puede establecer.
158    */
159   static const int MinReceivingChunkSize = 2 * 1024;
160
161   /**
162    * Tamaño máximo de la cola de entrada de mensajes que se puede establecer.
163    */
164   static const int MaxReceivingChunkSize = 64 * 1024;
165
166   /**
167      Numero de milisegundos esperados para considerar que un cliente remoto ha abandonado
168      la conexion.
169   */
170   static const Millisecond DefaultTimeout;
171
172   /**
173    * Tamaño máximo del búfer a tratar de forma ininterrumpida.
174    */
175   static const int DefaultChunkSize = 16 * 1024;
176
177   typedef SortedVector <Handler, SortByFileDescriptor> Handlers; /**< Definicion para gestionar los controladores asociados a este comunicador */
178   typedef Handlers::const_iterator const_handler_iterator; /**< Definicion para el iterador de controladores */
179   typedef Handlers::iterator handler_iterator; /**< Definicion para el iterador de controladores */
180
181   typedef std::vector <const Service*> Services; /**< Definicion para gestionar los servicios asociados a este comunicador */
182   typedef Services::const_iterator const_service_iterator; /**< Definicion para el iterador de servicios */
183
184   /**
185      Constructor.
186      \param acceptMode Modo en que se trata las peticiones.
187   */
188   Communicator(const WorkMode::_v acceptMode = WorkMode::Single);
189
190   /**
191    * Destructor
192    */
193   virtual ~Communicator();
194
195   /**
196      Devuelve el numero de segundos esperado para intentar recuperar las conexiones de los servidores
197      con los que se han detectado errores de conexion.
198      @return El numero de segundos esperado para intentar recuperar las conexiones de los servidores
199      con los que se han detectado errores de conexion.
200   */
201   const Millisecond &getRecoveryTime() const { return a_recoveryTime; }
202
203   /**
204      Devuelve el estado de este proceso con respecto al sistema de comunicaciones.
205      \return El estado de este proceso con respecto al sistema de comunicaciones.
206   */
207   const Status& getStatus() const { return a_status; }
208
209   /**
210      Devuelve el numero de milisegundos maximo que puede estar un manejador de conexion local
211      sin recibir mensajes antes de ser cerrado por el nucleo.
212      \return el numero de milisegundos maximo que puede estar un manejador de conexion local
213      sin recibir mensajes antes de ser cerrado por el nucleo.
214   */
215   const Millisecond &getTimeout() const { return a_timeout; }
216
217   /**
218    * Devuelve el modo de tratamiento de conexiones establecido en el constructor.
219    */
220   WorkMode::_v getWorkMode() const { return a_workMode; }
221
222   /**
223      Devuelve \em true si este comunicador esta atendiendo peticiones como servidor o \em false en otro
224      caso.
225      @return \em true si este comunicador esta atendiendo peticiones como servidor o \em false en otro
226      caso.
227   */
228   bool isServing() const { return a_isServing; }
229
230   /**
231      Devuelve el estado del indicador de peticion de parada.
232      \return el estado del indicador de peticion de parada.
233   */
234   bool hasRequestedStop() const { return a_requestedStop; }
235
236   /**
237    * Informa al comunicador de que hay algún socket que ha solicitado el cierre de la conexión.
238    */
239   void notifyPendingClose() { a_pendingClose = true; }
240
241   /**
242      Establece el numero de milisegundos esperado para intentar recuperar las conexiones de los servidores
243      con los que se han detectado errores de conexion.
244
245      @param recoveryTime numero de milisegundos esperado para intentar recuperar las conexiones de los
246      servidores con los que se han detectado errores de conexion.
247
248      \warning el valor indicado deberá estar entre #MinRecoveryTime y #MaxRecoveryTime
249   */
250   void setRecoveryTime(const Millisecond &recoveryTime) noexcept(false);
251
252   /**
253      Establece el numero de milisegundos empleados en intentar conectar con los servidores caídos cada
254      vez que se cumple el periodo de recuperación y hay servidores caídos.
255
256      @param tryingConnectionTime numero de milisegundos empleados en intentar recuperar las conexiones
257      de los servidores con los que se han detectado errores de conexion.
258
259      \warning el valor indicado deberá estar entre #MinTryingConnectionTime y #MaxTryingConnectionTime
260   */
261   void setTryingConnectionTime(const Millisecond &tryingConnectionTime) noexcept(false);
262
263   /**
264    * Devuelve el numero de milisegundos empleados en intentar conectar con los servidores caídos.
265    */
266   const Millisecond &getTryingConnectionTime() const { return a_tryingConnectionTime; }
267
268   /**
269    * Establece el tamaño del bloque de memoria usado para procesar los mensajes entrantes. Todos
270    * los mensajes completos contenidos en el chunk se procesarán de forma ininterrumpida.
271    * \param receivingChunkSize Número de bytes a leer/procesar de forma ininterrumpida.
272    *
273    * \warning el valor indicado deberá estar entre #MinReceivingChunkSize y #MaxReceivingChunkSize
274    * \warning Experimentalmente se ha comprobado que los mejores rendimientos se obtiene cuando
275    * este valor y el MaxPendingBytes del control de congestión tiene valores cercanos, así que
276    * cuando se cambia este valor también se invocará a CongestionController::setMaxPendingBytes para
277    * establecer este mismo valor.
278    */
279   static void setReceivingChunkSize(const int receivingChunkSize) noexcept(false);
280
281   /**
282    * Obtiene el tamaño máximo del bloque de memoria a procesar de forma ininterrumpida.
283    * \return el tamaño máximo del bloque de memoria a procesar de forma ininterrumpida.
284    */
285   static int getReceivingChunkSize() { return st_ReceivingChunkSize; }
286
287   /**
288      Establece el numero de milisegundos maximo que puede estar un manejador de conexion local
289      sin recibir mensajes antes de ser cerrado por el nucleo.
290      \param timeout Numero de milisegundos maximo sin recibir mensajes.
291   */
292   void setTimeout(const Millisecond & timeout) { a_timeout = timeout; }
293
294   /**
295    * Establece el nivel de congestión global a partir del cual un servidor no aceptará nuevas conexiones. Su valor
296    * por defecto será comm::CongestionController::MaxLevel.
297    *
298    * \param levelOfDenialService Nivel de congestión global a partir del cual no se permitirán nuevas conexiones.
299    *
300    * \warning Debe estar entre [comm::CongestionController::MaxLevel - 2, comm::CongestionController::MaxLevel].
301    */
302   void setLevelOfDenialService(const int levelOfDenialService) noexcept(false);
303
304   /**
305    * Devuelve el nivel de congestión a partir del cual un servidor no aceptará nuevas conexiones.
306    * \return el nivel de congestión a partir del cual un servidor no aceptará nuevas conexiones.
307    */
308   int getLevelOfDenialService() const { return a_levelOfDenialService; }
309
310   /**
311      Registra un servidor de socket a la lista de peticiones por las que atiende peticiones este
312      Communicator. Un Communicator puede atender peticiones por un numero indeterminado de direcciones
313      lo que nos permite disear facilmente sistemas tolerantes a fallos.
314
315      \param serverSocket Servidor de socket por el que vamos a atender el establecimiento de conexiones
316      una vez que invoquemos al Metodo #accept.
317   */
318   void attach(ServerSocket* serverSocket) noexcept(false);
319
320   /**
321      Registra una conexion Local entre alguno de los ServerSocket definidos en nuestra aplicacion
322      y algun cliente remoto que solicita la conexion.
323
324      Antes de pasar a gestionar esta conexion debera de haber sido acceptada en el metodo
325      #eventAcceptConnection (a no ser que re-escribamos su comportamiento aceptara conexiones
326      de cualquier cliente).
327
328      \param localConnection Instancia de la conexion local que vamos a controlar.
329
330      \warning Exclusivamente uso interno
331   */
332   void attach(LocalConnection* localConnection) noexcept(false);
333
334   /**
335      Establece la conexion entre el comunicador y un ClientSocket recibido como parametro.
336      El socket recibido se inicializa se fuera necesario.
337
338      \param clientSocket Instancia del socket que vamos a controlar.
339   */
340   void attach(ClientSocket* clientSocket) noexcept(false);
341
342   /**
343      Establece la conexion entre el comunicador y un DatagramSocket recibido como parametro.
344      El socket recibido se inicializa se fuera necesario.
345
346      \param datagramSocket Instancia del socket que vamos a controlar.
347   */
348   void attach(DatagramSocket* datagramSocket) noexcept(false);
349
350   /**
351      Conecta un conector externo a este comunicador.
352      \param handler Controlador de comunicaciones externas.
353      \warning Debe de haber sido creado como de tipo Handler::Type::Custom.
354   */
355   void attach(Handler* handler) noexcept(false);
356
357   /**
358      Conecta un servicio de reparto de comunicaciones con este comunicador. El estado de
359      disponibilidad/indisponibilidad de este comunicador estara definido en base a la
360      disponibilidad de todos los servicios definidos como criticos.
361      \param service Instancia del servicio.
362      \warning Todos los servicios registrados como criticos deberian estar asociados al comunicador.
363   */
364   void attach(Service* service) noexcept(false);
365
366   /**
367      Desconecta el ServerSocket que fue previamente conectado con #attach
368      \param serverSocket Instancia del socket que vamos a desconectar.
369      \warning Este metodo es invocado automaticamente desde el nucleo de anna.comm y no deberia
370      ser usado por el programador final.
371   */
372   void detach(ServerSocket* serverSocket) ;
373
374   /**
375      Desconecta el ClientSocket que fue previamente conectado con #attach
376      \param clientSocket Instancia del socket que vamos a desconectar.
377      \warning Este metodo es invocado automaticamente desde el nucleo de ANNA.comm y no deberia
378      ser usado por el programador final.
379   */
380   void detach(ClientSocket* clientSocket) ;
381
382   /**
383      Desconecta el conector externo de este comunicador. Supone que todas las operaciones
384      adicionales necesarias para liberar los recursos de este fichero seran realizadas
385      externamente.
386
387      \param handler Controlador de comunicaciones externas.
388
389      \warning Exclusivamente uso interno
390   */
391   void detach(Handler* handler) ;
392
393   /**
394      Devuelve el manejador asociado al ClientSocket recibido como parametro.
395      \param clientSocket Socket cliente del que queremos obtener en handler.
396      \return El manejador asociado al socket recibido como parametro. Puede ser NULL.
397   */
398   const Handler* getHandler(const ClientSocket& clientSocket) noexcept(false);
399
400   /**
401       El thread que invoca a este Metodo entra en un proceso continuo de comprobacin/recepcin
402       de mensajes, todos los eventos que pueden afectar al comportamiento de nuestro comunicador como son
403       aceptacin y cierre de conexiones, caidas, recepcin de mensajes, etc, etc se notifican a
404       traves de los Metodos manejadores de eventos de esta misma clase.
405       El thread saldra de este bucle tras la invocacion del Metodo #requestStop.
406    */
407   void accept() noexcept(false);
408
409   /**
410      Solicita la parada de este comunicador.
411   */
412   void requestStop() ;
413
414   /**
415      Devuelve \em true si el ClientSocket recibido como parametro sigue siendo valido o \em false
416      en caso de que haya dejado de ser valido debido al cierre del extremo remoto, por ejemplo.
417
418      Si el ClientSocket recibido es NULL siempre devolvera \em false.
419
420      \return \em true si el ClientSocket recibido como parametro sigue siendo valido o \em false
421      en caso de que haya dejado de ser valido debido al cierre del extremo remoto, por ejemplo.
422   */
423   bool isUsable(const ClientSocket* clientSocket) ;
424
425   /**
426      Devuelve el numero handlers activos.
427      \return el numero handlers activos.
428   */
429   int handler_size() const { return a_handlers.size(); }
430
431   /**
432      Devuelve un iterador que apunta el primer controlador.
433      \return un iterador que apunta el primer controlador.
434   */
435   handler_iterator handler_begin() { return a_handlers.begin(); }
436
437   /**
438      Devuelve un iterador que apunta al final de la lista de controladores.
439      \return un iterador que apunta al final de la lista de controladores.
440   */
441   handler_iterator handler_end() { return a_handlers.end(); }
442
443   /**
444      Devuelve un iterador que apunta el primer controlador.
445      \return un iterador que apunta el primer controlador.
446   */
447   const_handler_iterator handler_begin() const { return a_handlers.begin(); }
448
449   /**
450      Devuelve un iterador que apunta al final de la lista de controladores.
451      \return un iterador que apunta al final de la lista de controladores.
452   */
453   const_handler_iterator handler_end() const { return a_handlers.end(); }
454
455   /**
456      Devuelve un iterador que apunta el primer servicio.
457      \return un iterador que apunta el primer service.
458   */
459   const_service_iterator service_begin() const { return a_services.begin(); }
460
461   /**
462      Devuelve un iterador que apunta al final de la lista de servicios.
463      \return un iterador que apunta al final de la lista de servicios.
464   */
465   const_service_iterator service_end() const { return a_services.end(); }
466
467   /**
468      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador ante
469      un evento generado por el propio programador.
470
471      Sera invocado por algun Metodo del programador con el objetivo de actuar sobre su comunicador
472      en una situacin indeterminada.
473
474      La interpretacin del identificador y el contenido de este contexto sera problema exclusivo
475      del programador ya que ANNA.comm no impone ninguna regla ni realiza ningn tipo de proceso
476      adicional con estos datos.
477
478      @param id Identifica el evento generado.
479      @param context Contexto asociado al evento que ha generado el usuario.
480
481      \warning Este Metodo no debera generar ningn tipo de excepcin.
482   */
483   virtual void eventUser(const char* id, const void* context) {;}
484
485   /**
486      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
487      el nucleo de ANNA.comm notifica la perdida de conexion con la direccion IP indicada.
488
489      \param address Interfaz de red que ha dejado de estar disponible.
490
491      \warning
492      \li La forma en que detectara la caida del interfaz de red no esta dentro del ambito
493      del problema de ANNA.comm debera haber una capa superior que se encargue de comprobar las
494      interfaces.
495      \li El nucleo de ANNA.comm necesita conocer este evento por lo que cualquier implementacin
496      debera invocar al Metodo eventBreakAddress de su clase base.
497   */
498   virtual void eventBreakAddress(const in_addr_t& address) ;
499
500   /**
501      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
502      el nucleo de ANNA.comm notifica la recuperacin de conexion con la direccion IP indicada.
503
504      \param address Interfaz de red que ha vuelto a estar disponible.
505
506      \warning
507      \li La forma en que detectara la recuperacin del interfaz de red no esta dentro del ambito
508      del problema de ANNA.comm debera haber una capa superior que se encargue de comprobar las
509      interfaces.
510      \li El nucleo de ANNA.comm necesita conocer este evento por lo que cualquier implementacin
511      debera invocar al Metodo eventRecoverAddress de su clase base.
512   */
513   virtual void eventRecoverAddress(const in_addr_t& address) ;
514
515   /**
516      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
517      el nucleo de ANNA.comm notifica que ha detectado una peticion de conexion desde un
518      proceso remoto a un ServerSocket asociado a este comunicador.
519      Cualquier re-implementacion de este metodo debe invocar al metodo de la clase base y
520      devolver \em false en caso de que este lo devuelva.
521
522      @param clientSocket Socket cliente que solicita acceso.
523
524      \return \em true si la conexion es acceptada a \em false en otro caso, en cuyo caso se liberaran
525      automaticamente todos los recursos asociados a la peticion de conexion.
526
527      \warning Desde ANNA.comm 1.11.18 se mide el nivel de carga del proceso y si se evalúa como
528      congestionado no permitirá aceptar la nueva conexión.
529   */
530   virtual bool eventAcceptConnection(const ClientSocket& clientSocket) noexcept(false);
531
532   /**
533       Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
534       el nucleo de ANNA.comm notifica la creacion de una nueva conexion con el proceso servidor
535       recibido como parametro.
536
537       En la mayoria de los casos no sera necesario indicar ninguna accion ya que ANNA.comm realiza
538       todas las operaciones necesarias.
539
540       \warning Cualquier reimplementacion de este metodo debe comenzar invocando al metodo original de la
541       clase Communicator de la que herede nuestra clase.
542
543       @param server Proceso servidor con el que hemos establecido la conexion.
544
545       \see Host::createServer
546    */
547   virtual void eventCreateConnection(const Server* server) ;
548
549   /**
550       Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
551       el nucleo de ANNA.comm notifica la creacion de una nueva conexion con el servicio de reparto
552       recibido como parametro.
553
554       En la mayoria de los casos no sera necesario indicar ninguna accion ya que ANNA.comm realiza
555       todas las operaciones necesarias.
556
557       \warning  Cualquier reimplementacion de este metodo debe comenzar invocando al metodo original de la
558       clase Communicator de la que herede nuestra clase.
559
560       @param service Servicio con el que hemos establecido la conexion.
561
562       \see Host::createServer
563    */
564   virtual void eventCreateConnection(const Service* service) ;
565
566   /**
567      Establece las acciones a realizar cuando la clase Communicator detecta la llegada de un
568      mensaje completo analizado con el protocolo indicado.
569
570      Se invocara desde el Metodo #accept cuando se detecta la llegada de un mensaje.
571
572      En entorno MT todos los threads actuaran sobre la unica instancia del comm::Communicator
573      lo que restara eficacia debido al bajo nivel de paralelismo.
574
575      @param clientSocket Socket cliente por el que ha llegado el mensaje.
576      @param message Ultimo mensaje recibido. El bloque de datos recibido ya ha sido
577      decodificado aplicando las reglas establecidas por la capa de transporte asociado
578      al ClientSocket por el que llega el mensaje.
579
580      \warning Para ANNA.comm version 1.5.2 y posteriores se deberian usar el sistema de
581      receiveres (anna::comm::Receiver) que ofrece mayor rendimiento y facilita la programacion
582      en entorno MT.
583   */
584   virtual void eventReceiveMessage(ClientSocket& clientSocket, const Message& message)
585   noexcept(false) { ; }
586
587   /**
588      Establece las acciones a realizar cuando el nucleo de ANNA.comm notifica que ha
589      cerrado un anna::comm::ClientSocket debido a un consumo excesivo de memoria.
590      \param clientSocket Socket cliente que va a ser cerrado por el nucleo de ANNA.comm.
591   */
592   virtual void eventOverQuota(const ClientSocket& clientSocket) {;}
593
594   /**
595      Establece las acciones a realizar cuando el núcleo de ANNA.comm notifica que ha
596      cerrado un anna::comm::ClientSocket debido a que ha recibido un mensaje que no
597      ha sido analizado correctamente.
598      \param clientSocket Socket cliente que va a ser cerrado por el nucleo de ANNA.comm.
599   */
600   virtual void eventDiscardConnection(const ClientSocket& clientSocket) {;}
601
602   /**
603    * Método manejador invocado cuando un client socket que tiene activado el indicador de ignorar los
604    * mensajes entrantes recibe un mensaje.
605    * \param clientSocket ClientSocket por el que se recibe el mensaje.
606    * \param burst Bloque de datos que contiene la trama recibida.
607    */
608   virtual void eventIgnoreBurst(const ClientSocket& clientSocket, const DataBlock& burst) {;}
609
610   /**
611      Devuelve una cadena con la informacion mas relevante de esta instancia.
612      \return Una cadena con la informacion mas relevante de esta instancia.
613   */
614   std::string asString() const ;
615
616   /**
617      Devuelve un documento XML con la informacion mas relevante de esta instancia.
618      \param parent Nodo XML del que colgar la informacion referente a esta instancia.
619      \return Un documento XML con la informacion mas relevante de esta instancia.
620   */
621   virtual xml::Node* asXML(xml::Node* parent) const ;
622
623   /**
624      Devuelve el controlador apuntado por el iterador recibido.
625      \param ii Iterador con el que estamos recorriendo los controladores.
626      \return el controlador apuntado por el iterador recibido.
627   */
628   static Handler* handler(handler_iterator& ii) { return Handlers::data(ii); }
629
630   /**
631      Devuelve el controlador apuntado por el iterador recibido.
632      \param ii Iterador con el que estamos recorriendo los controladores.
633      \return el controlador apuntado por el iterador recibido.
634   */
635   static const Handler* handler(const_handler_iterator& ii) { return Handlers::data(ii); }
636
637   /**
638      Devuelve el servicio apuntado por el iterador recibido.
639      \param ii Iterador con el que estamos recorriendo los servicios.
640      \return el servicio apuntado por el iterador recibido.
641   */
642   static const Service* service(const_service_iterator& ii) { return *ii; }
643
644   /**
645      Devuelve la cadena por la que podemos buscar el componente.
646      \return La cadena por la que podemos buscar el componente.
647      \see Application::find
648   */
649   static const char* getClassName() { return "anna::comm::Communicator"; }
650
651 protected:
652   /**
653      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
654      el nucleo de ANNA.comm notifica la perdida de conexion con un servidor remoto.
655
656      En la mayoria de los casos no sera necesario indicar ninguna accion ya que ANNA.comm realiza
657      todas las operaciones necesarias.
658
659      @param clientSocket Socket cliente asociado a esta rotura de conexion.
660
661      \warning despues de llamar a este Metodo el clientSocket pasado como parametro se liberara por lo
662      que despues de este Metodo esta instancia no debera utilizarse.
663      \warning Estado MT: \code [Tx] -> Communicator \endcode
664   */
665   virtual void eventBreakConnection(const ClientSocket& clientSocket) {;}
666
667   /**
668      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
669      el nucleo de ANNA.comm notifica la perdida de conexion de una conexion generada por un server socket.
670
671      En la mayoria de los casos no sera necesario indicar ninguna accion ya que ANNA.comm realiza
672      todas las operaciones necesarias.
673
674      @param clientSocket Socket cliente asociado a esta rotura de conexion.
675   */
676   virtual void eventBreakLocalConnection(const ClientSocket& clientSocket) {;}
677
678
679   /**
680      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
681      el nucleo de ANNA.comm notifica la perdida de conexion con el proceso servidor recibido como
682      parametro.
683
684      Se invocara desde #accept(ServerSocket&) cuando no se detecta la rotura de conexion con un
685      socket asociado a uno de nuestros servidores.
686
687      En la mayoria de los casos no sera necesario indicar ninguna accion ya que ANNA.comm realiza
688      todas las operaciones necesarias.
689
690      Las acciones realizadas por este metodo incluyen:
691      \li Cierre del socket asociado al proceso servidor cuya conexion ha caido.
692      \li Reorganizacion del sistema de reparto de carga para que marque el proceso servidor como no disponible.
693      \li Activar los sistemas de recuperacion de conexion en el caso de que el servidor que ha caido
694      vuelva a estar disponible.
695
696      \warning Cualquier reimplementacion de este metodo debe comenzar invocando al metodo original de la
697      clase Communicator de la que herede nuestra clase.
698      \warning Estado MT: \code [Tx] -> Communicator \endcode
699
700      @param server Proceso servidor con el que hemos perdido la conexion.
701   */
702   virtual void eventBreakConnection(const Server* server) ;
703
704   /**
705      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador
706      cuando el nucleo de anna.comm notifica la perdida de conexion con todos los procesos
707      asociados al servicio recibido como parametro.
708
709      \param service Servicio que ha dejado de estar disponible.
710      \warning Estado MT: \code [Tx] -> Communicator \endcode
711   */
712   virtual void eventBreakConnection(const Service* service) ;
713
714   /**
715      Establecer la configuracin de este comunicador. El cargador de configuracin se encarga de establecer
716      los ServerSocket por los que este comunicador va a atender peticiones y/o los procesos servidores
717      remotos con los que tenemos que establecer el canal de comunicaciones.
718
719      \warning Este Metodo debe invocarse desde las clases heredadas.
720   */
721   virtual void do_initialize() noexcept(false) {;}
722
723   /**
724      Solicita la parada de este comunicador. Se reimplementa para mantener el interfaz de la clase
725      Component de la que hereda este Communicator.
726   */
727   void do_stop() { requestStop(); }
728
729   /**
730      Establece el estado de este proceso con respecto al sistema de comunicaciones
731      @param status Estado del sistema de comunicaciones que deseamos establecer.
732   */
733   virtual void setStatus(const Status& status) ;
734
735   /**
736      Establece la conexion entre el comunicador y un socket dedicado a la comparticion de una
737      determinada direccion IP:puerto.
738
739      \param binderSocket Define un socket por el que tratar las peticiones de comparticion
740      de una determinada direccion IP:puerto.
741
742      \internal
743   */
744   void attach(BinderSocket* binderSocket) noexcept(false);
745
746   /**
747      Desconecta el BinderSocket que fue previamente conectado con attach(BinderSocket*).
748      \param binderSocket Instancia del BinderSocket a desconectar.
749      \warning Exclusivamente uso interno
750   */
751   void detach(BinderSocket* binderSocket) ;
752
753   /**
754      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
755      el nucleo de ANNA.comm notifica que este comunicador esta preparado para comenzar a
756      aceptar y/o enviar mensajes.
757
758      Se invocara desde el metodo #accept inmediatamente antes de comenzar a
759      comprobar la llegada de mensajes.
760
761      En la mayoria de los casos no sera necesario indicar ninguna accion ya que ANNA.comm realiza
762      todas las operaciones necesarias.
763   */
764   virtual void eventStartup() noexcept(false) {;}
765
766   /**
767      Metodo manejador de evento que permite ajustar el funcionamiento de nuestro comunicador cuando
768      el nucleo de ANNA.comm notifica que este va a dejar de atender peticiones.
769
770      En la mayoria de los casos no sera necesario indicar ninguna accion ya que ANNA.comm realiza
771      todas las operaciones necesarias.
772   */
773   virtual void eventShutdown() ;
774
775 private:
776   const WorkMode::_v a_workMode;
777   bool a_isServing;
778   bool a_requestedStop;
779   Handlers a_handlers;
780   Millisecond a_recoveryTime;
781   Status a_status;
782   Services a_services;
783   Millisecond a_timeout;
784   comm::Handler* a_mainHandler;
785   ConnectionRecover* a_connectionRecover;
786   bool a_pendingClose;
787   Millisecond a_tryingConnectionTime;
788   int a_levelOfDenialService;
789
790   // ST
791   Poll* a_poll;
792   Handlers a_timedouts;
793   void singlethreadedAccept() noexcept(false);
794
795   // MT
796   ThreadManager* a_threadManager;
797   void multithreadedAccept() noexcept(false);
798
799   ConnectionRecover* getConnectionRecover() { return a_connectionRecover; }
800
801   void attach(RemoteConnection* remoteConnection) noexcept(false);
802
803   void insert(Handler*) noexcept(false);
804   Handler* find(const int fd) { return a_handlers.find(fd); }
805
806   // Reimplementado de app::Component
807   void do_cloneParent() noexcept(false);
808   void do_cloneChild() ;
809
810   friend class Handler;
811
812   friend class Server;
813   // attach (RemoteConnection)
814
815   friend class handler::RemoteConnection;
816   // getConnectionRecover, eventBreakConnection
817
818   friend class handler::ClientSocket;
819   // eventBreakConnection
820
821   // EDU
822   friend class handler::LocalConnection;
823   // eventBreakLocalConnection
824 };
825
826 }
827 }
828
829 #endif
830