bug in RC
[anna.git] / include / anna / comm / ServerSocket.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_ServerSocket_hpp
10 #define anna_comm_ServerSocket_hpp
11
12 #include <anna/core/util/Recycler.hpp>
13 #include <anna/core/util/Millisecond.hpp>
14
15 #include <anna/comm/Socket.hpp>
16 #include <anna/comm/internal/LocalConnection.hpp>
17
18 namespace anna {
19
20 namespace comm {
21
22 class INetAddress;
23 class BinderSocket;
24
25 /**
26    Esta clase implementa el servidor de Socket. Un servidor de Socket espera las peticiones de entrada procedentes
27    de la red y realiza las operaciones necesarias para tratar la operacion y posiblemente devolver un resultado
28    al peticionario.
29
30    El 'backlog' de un servidor de socket define la longitud maxima que la cola de mensajes pendientes puede alcanzar.
31    Si cliente realiza una peticion mediante una conexion UF_UNIX cuando la cola de mensajes del servidor esta llena
32    recibira un error ECONNREFUSED, aunque normalmente el protocolo subyacente se encarga de retransmitir la peticion
33    un numero indeterminado de veces.
34
35    @see Communicator::accept
36 */
37 class ServerSocket : public Socket {
38 public:
39   /**
40      numero de milisegundos por defecto que espera antes de dar por fallida una asociacion a una
41      direccion.
42   */
43   static const Millisecond DefaultBindDelay;
44
45   typedef Recycler<LocalConnection>::iterator iterator;
46
47   /**
48      Tamao de la cola de mensajes tomado por defecto.
49   */
50   static const int defaultBacklog = 30;
51
52   /**
53      Crea un servidor de socket liberado.
54      \param transportFactory Factoria de protocolos de transporte a usar por este sockets.
55      \param domain Dominio del socket.
56      \param type Tipo de socket.
57      \warning La Factoria de protocolos debe estar disponible mientras el Socket esta activo.
58   */
59   ServerSocket(TransportFactory* transportFactory = NULL, Domain::_v domain = Socket::Domain::Inet, Type::_v type = Socket::Type::Stream) :
60     Socket(domain, type, transportFactory),
61     a_backlog(defaultBacklog),
62     a_sharedBind(false),
63     a_binderSocket(NULL),
64     a_msBindDelay(DefaultBindDelay) {}
65
66   /**
67      Crea un servidor de socket conectado a la direccion y puerto indicado y con la longitud de cola maxima indicada.
68
69      \param localAddress Direccion Local en la que atendera las peticiones.
70      \param transportFactory Factoria de protocolos de transporte a usar por este sockets.
71      \param sharedBind \em true Si puede haber mas de una aplicacion escuchando es esta misma direccion.
72      \warning La factoria de protocolos debe estar disponible mientras el Socket esta activo.
73   */
74   ServerSocket(const INetAddress& localAddress, const bool sharedBind, TransportFactory* transportFactory = NULL) :
75     Socket(localAddress, Socket::Type::Stream, transportFactory),
76     a_backlog(defaultBacklog),
77     a_sharedBind(sharedBind),
78     a_binderSocket(NULL),
79     a_msBindDelay(DefaultBindDelay) {}
80
81   /**
82      Destructor.
83   */
84   virtual ~ServerSocket();
85
86   /**
87      Devuelve el numero de milisegundos esperado al hacer el bind compartido con este sockets
88      antes de considerar que no se puede atender peticiones en esa direccion.
89      \return el numero de milisegundos esperado al hacer el bind compartido con este sockets
90      antes de considerar que no se puede atender peticiones en esa direccion.
91   */
92   const Millisecond &getBindDelay() throw() { return a_msBindDelay; }
93
94   /**
95      Devuelve el socket asociado a este socket de bind compartido.
96      \return El socket asociado a este socket de bind compartido. Puede ser NULL.
97   */
98   BinderSocket* getBinderSocket() throw() { return a_binderSocket; }
99
100   /**
101      Devuelve el modo de asociacion de este socket.
102      \return El modo de asociacion de este socket.
103      \warning El valor devuelto por este metodo solo sera valido despues de ejecutar correctamente
104      el metodo #bind
105   */
106   bool isSharedBind() const throw() { return a_sharedBind; }
107
108   /**
109      Establece el tamao de la cola de mensajes.
110      \param backlog Tamao de la cola de mensajes.
111   */
112   void setBacklog(const int backlog) throw() { a_backlog = backlog; }
113
114   /**
115      Establece el numero de milisegundos esperado al hacer el bind con este sockets antes
116      de considerar que no se puede realizar la conexion.
117
118      \param bindDelay numero de milisegundos esperado al hacer la conexion con este
119      sockets antes de considerar que no se puede realizar la conexion.
120
121      \see #DefaultBindDelay
122
123      \warning Solo tendra efecto en el caso de que el socket tenga activado el modo de 'Bind compartido'.
124   */
125   void setBindDelay(const Millisecond &bindDelay) throw() { a_msBindDelay = bindDelay; }
126
127   /**
128      Metodo que debemos invocar una vez que el ServerSocket esta establecido.
129      \warning Normalmente se invocar�desde Communicator::attach(ServerSocket&,bool)
130   */
131   virtual void prepare() throw(RuntimeException);
132
133   /**
134      Comprueba la conexion establecida y acepta las peticiones. Esta funcin puede bloquear al thread
135      que la invoca mientras no llegue una peticion de apertura de conexion si no hemos establecido el modo
136      no-bloqueante del socket. Ver Socket::setBlockingMode.
137
138      Cada uno de los socket obtenidos con este Metodo debe ser liberado con #release cuando ya no sean
139      necesarios.
140
141      @return Nueva conexion aceptada, pendiente de pasar los filtros de acceptacion.
142
143      \warning Exclusivamente uso interno.
144   */
145   LocalConnection* accept() throw(RuntimeException);
146
147   /**
148      Libera los recursos del socket recibido como parametro.
149
150      @param localConnection Socket del que vamos a liberar los recursos. Esta instancia deberia haberse obtenido
151      mediante el Metodo #accept, ya que en otro caso los resultados no estan definidos.
152
153      \warning Exclusivamente uso interno.
154   */
155   void release(LocalConnection* localConnection) throw(RuntimeException);
156
157   /**
158      Devuelve un iterador al primer LocalConnection definido.
159      \return un iterador al primer LocalConnection definido.
160   */
161   iterator begin() throw() { return a_localConnections.begin(); }
162
163   /**
164      Devuelve un iterador al ultimo LocalConnection definido.
165      \return un iterador al ultimo LocalConnection definido.
166   */
167   iterator end() throw() { return a_localConnections.end(); }
168
169   /**
170      Devuelve una cadena con la informacion referente a este socket.
171      @return Una cadena con la informacion referente a este socket.
172   */
173   virtual std::string asString() const throw();
174
175   /**
176      Devuelve un nodo XML con la informacion referente a este objeto.
177      \param parent Nodo XML a partir del cual introducir la informacion.
178      \return Un nodo XML con la informacion referente a este objeto.
179   */
180   virtual xml::Node* asXML(xml::Node* parent) const throw(RuntimeException);
181
182   /**
183      Metodo manejador de evento que permite ajustar el funcionamiento cuando el nucleo de
184      anna.comm notifica que ha detectado una peticion de conexion desde un proceso
185      remoto a un ServerSocket asociado al comunicador. Permite independencia de dicho
186      comunicador y complementa el control de aceptacion (por defecto, se devuelve true
187      para no influir en la implementacion del metodo analogo en el comunicador).
188
189      @param clientSocket Socket cliente que solicita acceso.
190
191      \return \em true si la conexion es acceptada a \em false en otro caso, en cuyo caso se liberaran
192      automaticamente todos los recursos asociados a la peticion de conexion.
193   */
194   virtual bool eventAcceptConnection(const ClientSocket &clientSocket) throw(RuntimeException) { return true; }
195
196 //   /**
197 //       Informa sobre la rotura de una conexion que se creo a partir de un ServerSocket
198 //
199 //      @param localConnection Socket que se acepto sobre el server socket y que se ha roto.
200 //   */
201 //   virtual void eventBreakLocalConnection (LocalConnection* localConnection) throw (RuntimeException) {;}
202
203
204   /**
205      Devuelve una referencia al contenido apuntado por el iterador.
206      \return una referencia al contenido apuntado por el iterador.
207   */
208   static LocalConnection* localConnection(iterator& ii) throw() { return Recycler<LocalConnection>::data(ii); }
209
210   /**
211      Devuelve el nombre logico de esta clase.
212      \return el nombre logico de esta clase.
213   */
214   static const char* className() throw() { return "anna::comm::ServerSocket"; }
215
216 protected:
217   /**
218      Crea un servidor de socket conectado a la direccion y puerto indicado y con la longitud de cola maxima indicada.
219
220      \param transportFactory Factoria de protocolos de transporte a usar por este sockets.
221      \param localAddress Puede ser usado para limitar la direccion por la que atendiende peticiones un servidor de socket
222      instalado en una maquina con mas de una direccion.
223      \param sharedBind \em true Si puede haber mas de una aplicacion escuchando es esta misma direccion.
224      \param type Tipo de socket.
225      \warning La Factoria de protocolos debe estar disponible mientras el Socket esta activo.
226   */
227   ServerSocket(const INetAddress& localAddress, const bool sharedBind, Type::_v type, TransportFactory* transportFactory = NULL) :
228     Socket(localAddress, type, transportFactory),
229     a_backlog(defaultBacklog),
230     a_sharedBind(false),
231     a_binderSocket(NULL),
232     a_msBindDelay(DefaultBindDelay) {}
233
234 private:
235   int a_backlog;
236   Recycler <LocalConnection> a_localConnections;
237   const bool a_sharedBind;
238   BinderSocket* a_binderSocket;
239   Millisecond a_msBindDelay;
240
241   virtual ClientSocket* allocateClientSocket() const throw();
242   int do_bind(const struct sockaddr *, const int len) throw(RuntimeException);
243
244   friend class BinderSocket;
245 };
246
247 }
248 }
249
250
251 #endif
252
253
254