Remove dynamic exceptions
[anna.git] / include / anna / ldap / Session.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_ldap_Session_hpp
10 #define anna_ldap_Session_hpp
11
12 #include <string>
13
14 #include <anna/core/util/SortedVector.hpp>
15
16 #include <anna/comm/Handler.hpp>
17
18 #include <anna/ldap/defines.hpp>
19 #include <anna/ldap/ClassCode.hpp>
20
21 namespace anna {
22
23 namespace xml {
24 class Node;
25 }
26
27 namespace ldap {
28
29 class Request;
30 class Response;
31 class Timer;
32 class Engine;
33 class ResultCode;
34
35 /**
36    Modela la conexion realizada contra una servidor LDAP.
37 */
38 class Session : public comm::Handler {
39 public:
40   /**
41      Define los estados en los que puede estar una sesion LDAP.
42      \see ldap::Session::getState
43   */
44   struct State {
45     enum _v {
46       Closed, /**< Cerrada */
47       WaitingBind, /**< Pendiente de confirmacion de conexion */
48       Bound /**< Conectada al servidor LDAP */
49     };
50   };
51
52   /**
53      Opciones disponibles para ajustar el comporamiento de nuestra sesion.
54      \see ldap::Session
55   */
56   struct Option {
57     /**
58        Modos de interpretar las referencias.
59        \see ldap::Session
60     */
61     struct Defer {
62       enum _v {
63         Never, /**< Valor por defecto */
64         Searching, /**< Indica que los valores son interpretados durante la busqueda, pero no cuando localiza el objeto base de la misma */
65         Finding, /**< Indica que los valores son interpretados cuando se localiza el objeto base, pero no durante la busqueda */
66         Always
67       };
68     };
69     /**
70        Determina si la biblioteca LDAP realiza de forma automatica el siguimiento de las referencias retornadas
71        por los servidores LDAP.
72        \see ldap::Session
73     */
74     struct Referral { enum _v { Off, On }; };
75   };
76
77   /**
78    * Periodo de espera por defecto para cada una de las peticiones de esta sesión.
79    */
80   static const Millisecond DefaultTimeout;
81
82   /**
83      Devuelve la direccion del servidor LDAP. Coincidira con la indicada en ldap::Engine::createSession.
84      \return La direccion del servidor LDAP. Coincidira con la indicada en ldap::Engine::createSession.
85   */
86   const std::string& getURL() const { return a_url; }
87
88   /**
89      Devuelve el usuario de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
90      \return El usuario de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
91   */
92   const std::string& getUser() const { return a_user; }
93
94   /**
95      Devuelve el password de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
96      \return El password de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
97   */
98   const std::string& getPassword() const { return a_password; }
99
100   /**
101      Devuelve la categoria de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
102      \return La categoria de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
103   */
104   int getCategory() const { return a_category; }
105
106   /**
107    * Devuelve la clave externa con la que fué creada esta sesión.
108    */
109   int getExternalID() const { return a_externalID; }
110
111   /**
112      Devuelve el manejador usado para conectar con el servidor LDAP.
113      \warning Exclusivamente uso interno.
114   */
115   void* getLDAP() { return a_ldap; }
116
117   /**
118    * Devuelve el fd asociado a esta sesión de LDAP.
119    * \return el fd asociado a esta sesión de LDAP.
120    * \warning Las operaciones sobre este fd podrían influir negativamente en el sistema.
121    */
122   int getDangerousFileDescriptor() const noexcept(false);
123
124   /**
125      Devuelve el modo de interpretar las referencias establecido en esta sesion.
126      \return El modo de interpretar las referencias establecido en esta sesion.
127   */
128   Option::Defer::_v getDefer() const { return a_defer; }
129
130   /**
131      Devuelve \em true si la biblioteca LDAP realiza de forma automatica el siguimiento de las referencias
132      retornadas por los servidores LDAP o \em false en otro caso.
133      \return \em true si la biblioteca LDAP realiza de forma automatica el siguimiento de las referencias
134      retornadas por los servidores LDAP o \em false en otro caso.
135   */
136   Option::Referral::_v getReferral() const { return a_referral; }
137
138   /**
139      Devuelve el estado de esta sesion.
140      \return El estado de esta sesion.
141   */
142   State::_v getState() const { return a_state; }
143
144   /**
145    * Devuelve el periodo de espera establecido para las peticiones del tipo \em v.
146    * \return el periodo de espera establecido para las peticiones del tipo \em v.
147    */
148   const Millisecond &getTimeout(const ClassCode::_v v) const { return a_timeouts [v]; }
149
150   /**
151    * Devuelve el valor establecido en #setNetworkTimeout
152    * \return Los miligundos establecidos por #setNetworkTimeout.
153    * \warning El valor retornado sólo tendrá valided si #hasNetworkTimeout devolvió \em true.
154    */
155   Millisecond getNetworkTimeout() const {
156     Millisecond result(1000 * a_networkTimeout.tv_sec);
157     return Millisecond(result + a_networkTimeout.tv_usec / 1000);
158   }
159
160   /**
161    * Devuelve \em true si se estableció el tiempo de espera de conexión o \em false en otro caso.
162    * \return \em true si se estableció el tiempo de espera de conexión o \em false en otro caso.
163    */
164   bool hasNetworkTimeout() const { return a_networkTimeout.tv_sec != -1; }
165
166   /**
167      Solicita la conexion al servidor asociado a esta sesion.
168
169      \warning Solo deberia invocarse directamente este metodo en caso de que el #eventResponse
170      notifique no ha sido posible contactar con el servidor indicado.
171   */
172   void bind() noexcept(false);
173
174   /**
175      Devuelve \em true si la sesion esta conectada al servidor LDAP o \em false en otro caso.
176      \return \em true si la sesion esta conectada al servidor LDAP o \em false en otro caso.
177   */
178   bool isBound() const { return a_state == State::Bound; }
179
180   /**
181      Establece el modo de interpretar las referencias.
182      \param defer Indica el modo de interpretar las referencias.
183   */
184   void setOption(const Option::Defer::_v defer) { a_defer = defer; }
185
186   /**
187      Establece el modo en que la biblioteca LDAP actua a la hora de realizar el siguimiento de las referencias.
188      \param referral Indica el modo de realizar el seguimiento de las referncias.
189   */
190   void setOption(const Option::Referral::_v referral) { a_referral = referral; }
191
192   /**
193    * Establece el periodo de tiempo máximo que esperará la conexión a un servidor LDAP antes de considerar que
194    * éste no es alcanzable.
195    *
196    * \param timeout Milisegundos que esperará la conexión a un servidor LDAP antes de considerar que no es alcanzable.
197    *
198    * \see http://manpages.courier-mta.org/htmlman3/ldap_get_option.3.html
199    * \warning Sólo tiene efecto antes de invocar al #bind, por lo que habrá que desactivar la auto conexión, para establecer el valor.
200    */
201   void setNetworkTimeout(const Millisecond &timeout) { a_networkTimeout.tv_sec = timeout / 1000; a_networkTimeout.tv_usec = (timeout % 1000) * 1000; }
202
203   /**
204    * Elimina el tiempo asignado en #setNetworkTimeout.
205    *
206    * \see http://manpages.courier-mta.org/htmlman3/ldap_get_option.3.html
207    * \warning Sólo tiene efecto antes de invocar al #bind
208    */
209   void clearNetworkTimeout() { a_networkTimeout.tv_sec = -1; a_networkTimeout.tv_usec = 0; }
210
211   /**
212      Establece el tiempo de espera maximo antes de considerar fallida una peticion LDAP.
213      \param v Tipo de peticion LDAP.
214      \param millisecond Milisegundos esperados antes de considerar fallida la peticion LDAP.
215
216      Los temporizadores correspondientes las peticiones LDAP se activaran automaticamente al
217      invocar a los distintos métodos de esta clase.
218   */
219   void setTimeout(const ClassCode::_v v, const Millisecond &millisecond) { a_timeouts [v] = millisecond;  }
220
221   /**
222      Envia la peticion recibida como parametro al servidor con el que estamos conectados mediante esta
223      sesion LDAP.
224
225      Una vez enviada la peticion se activara automaticamente un temporizador. Si este llegara a caducar
226      se cancelara la busqueda y se invocara al metodo Session::eventResponse indicado que se ha producido
227      un error de temporización. La duracion del temporizador sera la establecida por
228      ldap::TimerManager::setTimeout o el valor defecto.
229
230      \param request Peticion a enviar al servidor LDAP con el que estamos conectados.
231      \return La instancia de la respuesta LDAP asociada la peticion realizada.
232      \warning Solo se podra hacer uso de este metodo cuando el metodo #isBound devuelva \em true.
233   */
234   const Response* send(const Request* request) noexcept(false);
235
236   /**
237      Envia la peticion recibida como parametro al servidor con el que estamos conectados mediante esta
238      sesion LDAP.
239
240      Una vez enviada la peticion se activara automaticamente un temporizador. Si este llegara a caducar
241      se cancelara la busqueda y se invocara al metodo Session::eventResponse indicado que se ha producido
242      un error de temporización. La duracion del temporizador sera la establecida por
243      ldap::TimerManager::setTimeout o el valor defecto.
244
245      \param request Peticion a enviar al servidor LDAP con el que estamos conectados.
246      \return La instancia de la respuesta LDAP asociada la peticion realizada.
247      \warning Solo se podra hacer uso de este metodo cuando el metodo #isBound devuelva \em true.
248   */
249   const Response* send(const Request& request) noexcept(false) { return send(&request); }
250
251   /**
252    * Desconecta este cliente LDAP del servidor LDAP.
253    * Se notifica la terminación de cada una de las peticiones pendientes invocando al método Session::eventResponse
254    * indicando un error y se cancelan en el servidor LDAP.
255    * \warning Después de invocar a este método habría que volver a invocar a ldap::Session::bind y esperar la conexión
256    * antes de volver a usar esta sessión.
257    */
258   void unbind() noexcept(false);
259
260   /**
261      Devuelve una cadena con la informacion relevante sobre esta instancia.
262      \return Una cadena con la informacion relevante sobre esta instancia.
263   */
264   std::string asString() const ;
265
266   /**
267      Devuelve un documento XML con la informacion relevante sobre esta instancia.
268      \param parent Nodo XML del que colgar la informacion referente a esta instancia.
269      \return Un documento XML con la informacion relevante sobre esta instancia.
270   */
271   xml::Node* asXML(xml::Node* parent) const ;
272
273 protected:
274   /**
275      Constructor.
276      \see ldap::Engine::createSession
277   */
278   Session();
279
280   /**
281      Metodo-manejador que informa de que el servidor LDAP con el que estaba conectado esta sesion
282      ha dejado de dar servicio.
283
284      Una vez que se ha notificado la caida de la sesion, el nucleo de ANNA.ldap genera un
285      ldap::Session::eventResponse para cada una de las peticiones que hay pendientes de contestar.
286   */
287   virtual void eventServerShutdown() {;}
288
289   /**
290      Metodo-manejador de las respuestas provenientes del servidor LDAP.
291
292      \param response Objeto que contiene la respuesta correspondiente a la peticion LDAP realizada.
293   */
294   virtual void eventResponse(const Response& response) noexcept(false) = 0;
295
296   /**
297      Metodo-manejador de los errores provenientes del servidor LDAP.
298      \param resultCode Instancia que contiene la información sobre el error recibido.
299      \param disconnect Incicador que informa al nivel de aplicación sobre cómo actuará la ANNA.ldap
300      para recuperar este error, si vale \em true la conexión se cerrará o \em false en otro caso.
301   */
302   virtual void eventResponseError(const ResultCode& resultCode, const bool disconnect) {;}
303
304   /**
305    * Método-manejador que se invoca cuando alguno de los mensajes intermedios requeridos para formar
306    * la contestación completa no se puede interpretar correctamente.
307    *
308      \param response Objeto que contiene la respuesta correspondiente a la peticion LDAP realizada.
309    */
310   virtual void eventIntermediateResponseError(const Response& response) {;}
311
312 private:
313   struct SortById {
314     static IdMessage value(const Response*) ;
315   };
316   typedef SortedVector <Response, SortById, IdMessage> response_container;
317   typedef response_container::iterator response_iterator;
318   typedef response_container::const_iterator const_response_iterator;
319
320   typedef void* HandleLDAP;
321   typedef void* HandleMessage;
322
323   int a_category;
324   HandleLDAP a_ldap;
325   State::_v a_state;
326   std::string a_url;
327   std::string a_user;
328   std::string a_password;
329   Option::Defer::_v a_defer;
330   Option::Referral::_v a_referral;
331   response_container a_responses;
332   int a_externalID;
333   Millisecond a_timeouts [ClassCode::Max];
334   struct timeval a_networkTimeout;
335
336   /* Dependiendo de cómo se cree la sesión este miembro puede ser una copia de a_user
337    * o el identificador numérico que pasaron como parámetro al crear la sesión
338    */
339   std::string a_keymap;
340
341   void apply() noexcept(false);
342   void receiveBind(const IdMessage, HandleMessage) noexcept(false);
343   void receiveEntry(const IdMessage, HandleMessage) noexcept(false);
344   void receiveReference(const IdMessage, HandleMessage) noexcept(false);
345   void receiveResult(const IdMessage, HandleMessage) noexcept(false);
346   void expireResponse(Response*) ;
347
348   void finalize() ;
349
350   response_iterator response_begin() { return a_responses.begin(); }
351   response_iterator response_end() { return a_responses.end(); }
352   void response_add(Response* response) ;
353   void response_erase(Response* response) ;
354   Response* response_find(const IdMessage idMessage) noexcept(false);
355
356   static Response* response(response_iterator ii) { return response_container::data(ii); }
357
358   const_response_iterator response_begin() const { return a_responses.begin(); }
359   const_response_iterator response_end() const { return a_responses.end(); }
360   static const Response* response(const_response_iterator ii) { return response_container::data(ii); }
361
362   static const char* asText(const State::_v) ;
363
364   friend class Timer;
365   friend class Engine;
366 };
367
368 }
369 }
370
371 #endif
372