1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #ifndef anna_ldap_Session_hpp
38 #define anna_ldap_Session_hpp
42 #include <anna/core/util/SortedVector.hpp>
44 #include <anna/comm/Handler.hpp>
46 #include <anna/ldap/defines.hpp>
47 #include <anna/ldap/ClassCode.hpp>
64 Modela la conexion realizada contra una servidor LDAP.
66 class Session : public comm::Handler {
69 Define los estados en los que puede estar una sesion LDAP.
70 \see ldap::Session::getState
74 Closed, /**< Cerrada */
75 WaitingBind, /**< Pendiente de confirmacion de conexion */
76 Bound /**< Conectada al servidor LDAP */
81 Opciones disponibles para ajustar el comporamiento de nuestra sesion.
86 Modos de interpretar las referencias.
91 Never, /**< Valor por defecto */
92 Searching, /**< Indica que los valores son interpretados durante la busqueda, pero no cuando localiza el objeto base de la misma */
93 Finding, /**< Indica que los valores son interpretados cuando se localiza el objeto base, pero no durante la busqueda */
98 Determina si la biblioteca LDAP realiza de forma automatica el siguimiento de las referencias retornadas
99 por los servidores LDAP.
102 struct Referral { enum _v { Off, On }; };
106 * Periodo de espera por defecto para cada una de las peticiones de esta sesión.
108 static const Millisecond DefaultTimeout;
111 Devuelve la direccion del servidor LDAP. Coincidira con la indicada en ldap::Engine::createSession.
112 \return La direccion del servidor LDAP. Coincidira con la indicada en ldap::Engine::createSession.
114 const std::string& getURL() const throw() { return a_url; }
117 Devuelve el usuario de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
118 \return El usuario de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
120 const std::string& getUser() const throw() { return a_user; }
123 Devuelve el password de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
124 \return El password de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
126 const std::string& getPassword() const throw() { return a_password; }
129 Devuelve la categoria de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
130 \return La categoria de esta sesion. Coincidira con la indicada en ldap::Engine::createSession.
132 int getCategory() const throw() { return a_category; }
135 * Devuelve la clave externa con la que fué creada esta sesión.
137 int getExternalID() const throw() { return a_externalID; }
140 Devuelve el manejador usado para conectar con el servidor LDAP.
141 \warning Exclusivamente uso interno.
143 void* getLDAP() throw() { return a_ldap; }
146 * Devuelve el fd asociado a esta sesión de LDAP.
147 * \return el fd asociado a esta sesión de LDAP.
148 * \warning Las operaciones sobre este fd podrían influir negativamente en el sistema.
150 int getDangerousFileDescriptor() const throw(RuntimeException);
153 Devuelve el modo de interpretar las referencias establecido en esta sesion.
154 \return El modo de interpretar las referencias establecido en esta sesion.
156 Option::Defer::_v getDefer() const throw() { return a_defer; }
159 Devuelve \em true si la biblioteca LDAP realiza de forma automatica el siguimiento de las referencias
160 retornadas por los servidores LDAP o \em false en otro caso.
161 \return \em true si la biblioteca LDAP realiza de forma automatica el siguimiento de las referencias
162 retornadas por los servidores LDAP o \em false en otro caso.
164 Option::Referral::_v getReferral() const throw() { return a_referral; }
167 Devuelve el estado de esta sesion.
168 \return El estado de esta sesion.
170 State::_v getState() const throw() { return a_state; }
173 * Devuelve el periodo de espera establecido para las peticiones del tipo \em v.
174 * \return el periodo de espera establecido para las peticiones del tipo \em v.
176 const Millisecond &getTimeout(const ClassCode::_v v) const throw() { return a_timeouts [v]; }
179 * Devuelve el valor establecido en #setNetworkTimeout
180 * \return Los miligundos establecidos por #setNetworkTimeout.
181 * \warning El valor retornado sólo tendrá valided si #hasNetworkTimeout devolvió \em true.
183 Millisecond getNetworkTimeout() const throw() {
184 Millisecond result(1000 * a_networkTimeout.tv_sec);
185 return Millisecond(result + a_networkTimeout.tv_usec / 1000);
189 * Devuelve \em true si se estableció el tiempo de espera de conexión o \em false en otro caso.
190 * \return \em true si se estableció el tiempo de espera de conexión o \em false en otro caso.
192 bool hasNetworkTimeout() const throw() { return a_networkTimeout.tv_sec != -1; }
195 Solicita la conexion al servidor asociado a esta sesion.
197 \warning Solo deberia invocarse directamente este metodo en caso de que el #eventResponse
198 notifique no ha sido posible contactar con el servidor indicado.
200 void bind() throw(RuntimeException);
203 Devuelve \em true si la sesion esta conectada al servidor LDAP o \em false en otro caso.
204 \return \em true si la sesion esta conectada al servidor LDAP o \em false en otro caso.
206 bool isBound() const throw() { return a_state == State::Bound; }
209 Establece el modo de interpretar las referencias.
210 \param defer Indica el modo de interpretar las referencias.
212 void setOption(const Option::Defer::_v defer) throw() { a_defer = defer; }
215 Establece el modo en que la biblioteca LDAP actua a la hora de realizar el siguimiento de las referencias.
216 \param referral Indica el modo de realizar el seguimiento de las referncias.
218 void setOption(const Option::Referral::_v referral) throw() { a_referral = referral; }
221 * Establece el periodo de tiempo máximo que esperará la conexión a un servidor LDAP antes de considerar que
222 * éste no es alcanzable.
224 * \param timeout Milisegundos que esperará la conexión a un servidor LDAP antes de considerar que no es alcanzable.
226 * \see http://manpages.courier-mta.org/htmlman3/ldap_get_option.3.html
227 * \warning Sólo tiene efecto antes de invocar al #bind, por lo que habrá que desactivar la auto conexión, para establecer el valor.
229 void setNetworkTimeout(const Millisecond &timeout) throw() { a_networkTimeout.tv_sec = timeout / 1000; a_networkTimeout.tv_usec = (timeout % 1000) * 1000; }
232 * Elimina el tiempo asignado en #setNetworkTimeout.
234 * \see http://manpages.courier-mta.org/htmlman3/ldap_get_option.3.html
235 * \warning Sólo tiene efecto antes de invocar al #bind
237 void clearNetworkTimeout() throw() { a_networkTimeout.tv_sec = -1; a_networkTimeout.tv_usec = 0; }
240 Establece el tiempo de espera maximo antes de considerar fallida una peticion LDAP.
241 \param v Tipo de peticion LDAP.
242 \param millisecond Milisegundos esperados antes de considerar fallida la peticion LDAP.
244 Los temporizadores correspondientes las peticiones LDAP se activaran automaticamente al
245 invocar a los distintos métodos de esta clase.
247 void setTimeout(const ClassCode::_v v, const Millisecond &millisecond) throw() { a_timeouts [v] = millisecond; }
250 Envia la peticion recibida como parametro al servidor con el que estamos conectados mediante esta
253 Una vez enviada la peticion se activara automaticamente un temporizador. Si este llegara a caducar
254 se cancelara la busqueda y se invocara al metodo Session::eventResponse indicado que se ha producido
255 un error de temporización. La duracion del temporizador sera la establecida por
256 ldap::TimerManager::setTimeout o el valor defecto.
258 \param request Peticion a enviar al servidor LDAP con el que estamos conectados.
259 \return La instancia de la respuesta LDAP asociada la peticion realizada.
260 \warning Solo se podra hacer uso de este metodo cuando el metodo #isBound devuelva \em true.
262 const Response* send(const Request* request) throw(RuntimeException);
265 Envia la peticion recibida como parametro al servidor con el que estamos conectados mediante esta
268 Una vez enviada la peticion se activara automaticamente un temporizador. Si este llegara a caducar
269 se cancelara la busqueda y se invocara al metodo Session::eventResponse indicado que se ha producido
270 un error de temporización. La duracion del temporizador sera la establecida por
271 ldap::TimerManager::setTimeout o el valor defecto.
273 \param request Peticion a enviar al servidor LDAP con el que estamos conectados.
274 \return La instancia de la respuesta LDAP asociada la peticion realizada.
275 \warning Solo se podra hacer uso de este metodo cuando el metodo #isBound devuelva \em true.
277 const Response* send(const Request& request) throw(RuntimeException) { return send(&request); }
280 * Desconecta este cliente LDAP del servidor LDAP.
281 * Se notifica la terminación de cada una de las peticiones pendientes invocando al método Session::eventResponse
282 * indicando un error y se cancelan en el servidor LDAP.
283 * \warning Después de invocar a este método habría que volver a invocar a ldap::Session::bind y esperar la conexión
284 * antes de volver a usar esta sessión.
286 void unbind() throw(RuntimeException);
289 Devuelve una cadena con la informacion relevante sobre esta instancia.
290 \return Una cadena con la informacion relevante sobre esta instancia.
292 std::string asString() const throw();
295 Devuelve un documento XML con la informacion relevante sobre esta instancia.
296 \param parent Nodo XML del que colgar la informacion referente a esta instancia.
297 \return Un documento XML con la informacion relevante sobre esta instancia.
299 xml::Node* asXML(xml::Node* parent) const throw();
304 \see ldap::Engine::createSession
309 Metodo-manejador que informa de que el servidor LDAP con el que estaba conectado esta sesion
310 ha dejado de dar servicio.
312 Una vez que se ha notificado la caida de la sesion, el nucleo de ANNA.ldap genera un
313 ldap::Session::eventResponse para cada una de las peticiones que hay pendientes de contestar.
315 virtual void eventServerShutdown() throw() {;}
318 Metodo-manejador de las respuestas provenientes del servidor LDAP.
320 \param response Objeto que contiene la respuesta correspondiente a la peticion LDAP realizada.
322 virtual void eventResponse(const Response& response) throw(RuntimeException) = 0;
325 Metodo-manejador de los errores provenientes del servidor LDAP.
326 \param resultCode Instancia que contiene la información sobre el error recibido.
327 \param disconnect Incicador que informa al nivel de aplicación sobre cómo actuará la ANNA.ldap
328 para recuperar este error, si vale \em true la conexión se cerrará o \em false en otro caso.
330 virtual void eventResponseError(const ResultCode& resultCode, const bool disconnect) throw() {;}
333 * Método-manejador que se invoca cuando alguno de los mensajes intermedios requeridos para formar
334 * la contestación completa no se puede interpretar correctamente.
336 \param response Objeto que contiene la respuesta correspondiente a la peticion LDAP realizada.
338 virtual void eventIntermediateResponseError(const Response& response) throw() {;}
342 static IdMessage value(const Response*) throw();
344 typedef SortedVector <Response, SortById, IdMessage> response_container;
345 typedef response_container::iterator response_iterator;
346 typedef response_container::const_iterator const_response_iterator;
348 typedef void* HandleLDAP;
349 typedef void* HandleMessage;
356 std::string a_password;
357 Option::Defer::_v a_defer;
358 Option::Referral::_v a_referral;
359 response_container a_responses;
361 Millisecond a_timeouts [ClassCode::Max];
362 struct timeval a_networkTimeout;
364 /* Dependiendo de cómo se cree la sesión este miembro puede ser una copia de a_user
365 * o el identificador numérico que pasaron como parámetro al crear la sesión
367 std::string a_keymap;
369 void apply() throw(RuntimeException);
370 void receiveBind(const IdMessage, HandleMessage) throw(RuntimeException);
371 void receiveEntry(const IdMessage, HandleMessage) throw(RuntimeException);
372 void receiveReference(const IdMessage, HandleMessage) throw(RuntimeException);
373 void receiveResult(const IdMessage, HandleMessage) throw(RuntimeException);
374 void expireResponse(Response*) throw();
376 void finalize() throw();
378 response_iterator response_begin() throw() { return a_responses.begin(); }
379 response_iterator response_end() throw() { return a_responses.end(); }
380 void response_add(Response* response) throw();
381 void response_erase(Response* response) throw();
382 Response* response_find(const IdMessage idMessage) throw(RuntimeException);
384 static Response* response(response_iterator ii) throw() { return response_container::data(ii); }
386 const_response_iterator response_begin() const throw() { return a_responses.begin(); }
387 const_response_iterator response_end() const throw() { return a_responses.end(); }
388 static const Response* response(const_response_iterator ii) throw() { return response_container::data(ii); }
390 static const char* asText(const State::_v) throw();