changeset 4772:d36a5df3f492 HEAD

Handle LDAP requests while being disconnected more correctly.
author Timo Sirainen <tss@iki.fi>
date Tue, 07 Nov 2006 18:16:11 +0200
parents 7576055e5377
children 5cd0924c8031
files src/auth/db-ldap.c src/auth/db-ldap.h src/auth/passdb-ldap.c
diffstat 3 files changed, 71 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/db-ldap.c	Tue Nov 07 17:19:34 2006 +0200
+++ b/src/auth/db-ldap.c	Tue Nov 07 18:16:11 2006 +0200
@@ -137,6 +137,20 @@
 	return ldap_err2string(err);
 }
 
+void db_ldap_add_delayed_request(struct ldap_connection *conn,
+				 struct ldap_request *request)
+{
+	i_assert(!conn->connected);
+
+	request->next = NULL;
+
+	if (conn->delayed_requests_head == NULL)
+		conn->delayed_requests_head = request;
+	else
+		conn->delayed_requests_tail->next = request;
+	conn->delayed_requests_tail = request;
+}
+
 void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request,
 		    int scope)
 {
@@ -165,21 +179,24 @@
 			request->callback(conn, request, NULL);
 			return;
 		}
+		hash_insert(conn->requests, POINTER_CAST(msgid), request);
+	} else {
+		db_ldap_add_delayed_request(conn, request);
 	}
-
-	hash_insert(conn->requests, POINTER_CAST(msgid), request);
 }
 
 static void ldap_conn_retry_requests(struct ldap_connection *conn)
 {
 	struct hash_table *old_requests;
         struct hash_iterate_context *iter;
+	struct ldap_request *request, **p, *next;
 	void *key, *value;
-	bool have_binds = FALSE;
+	bool have_hash_binds = FALSE;
 
 	i_assert(conn->connected);
 
-	if (hash_size(conn->requests) == 0)
+	if (hash_size(conn->requests) == 0 &&
+	    conn->delayed_requests_head == NULL)
 		return;
 
 	old_requests = conn->requests;
@@ -189,11 +206,11 @@
 	/* first retry all the search requests */
 	iter = hash_iterate_init(old_requests);
 	while (hash_iterate(iter, &key, &value)) {
-		struct ldap_request *request = value;
+		request = value;
 
 		if (request->filter == NULL) {
 			/* bind request */
-			have_binds = TRUE;
+			have_hash_binds = TRUE;
 		} else {
 			i_assert(conn->connected);
 			db_ldap_search(conn, request, conn->set.ldap_scope);
@@ -201,21 +218,47 @@
 	}
 	hash_iterate_deinit(iter);
 
-	if (have_binds && conn->set.auth_bind) {
+	/* then delayed search requests */
+	p = &conn->delayed_requests_head;
+	while (*p != NULL) {
+		request = *p;
+
+		if (request->filter != NULL) {
+			*p = request->next;
+
+			i_assert(conn->connected);
+			db_ldap_search(conn, request, conn->set.ldap_scope);
+		} else {
+			p = &(*p)->next;
+		}
+	}
+
+	if (have_hash_binds && conn->set.auth_bind) {
 		/* next retry all the bind requests. without auth binds the
 		   only bind request can be the initial connection binding,
 		   which we don't care to retry. */
 		iter = hash_iterate_init(old_requests);
 		while (hash_iterate(iter, &key, &value)) {
-			struct ldap_request *request = value;
+			request = value;
 
 			if (request->filter == NULL)
 				request->callback(conn, request, NULL);
 		}
 		hash_iterate_deinit(iter);
 	}
+	if (conn->delayed_requests_head != NULL && conn->set.auth_bind) {
+		request = conn->delayed_requests_head;
+		for (; request != NULL; request = next) {
+			next = request->next;
+
+			i_assert(request->filter == NULL);
+			request->callback(conn, request, NULL);
+		}
+	}
 	hash_destroy(old_requests);
 
+	i_assert(conn->delayed_requests_head == NULL);
+	conn->delayed_requests_tail = NULL;
 	conn->retrying = FALSE;
 }
 
@@ -486,17 +529,27 @@
 static void ldap_conn_close(struct ldap_connection *conn, bool flush_requests)
 {
 	struct hash_iterate_context *iter;
+	struct ldap_request *request, *next;
 	void *key, *value;
 
 	if (flush_requests) {
 		iter = hash_iterate_init(conn->requests);
 		while (hash_iterate(iter, &key, &value)) {
-			struct ldap_request *request = value;
+			request = value;
 
 			request->callback(conn, request, NULL);
 		}
 		hash_iterate_deinit(iter);
 		hash_clear(conn->requests, FALSE);
+
+		request = conn->delayed_requests_head;
+		for (; request != NULL; request = next) {
+			next = request->next;
+
+			request->callback(conn, request, NULL);
+		}
+		conn->delayed_requests_head = NULL;
+		conn->delayed_requests_tail = NULL;
 	}
 
 	conn->connected = FALSE;
--- a/src/auth/db-ldap.h	Tue Nov 07 17:19:34 2006 +0200
+++ b/src/auth/db-ldap.h	Tue Nov 07 18:16:11 2006 +0200
@@ -57,7 +57,9 @@
 	LDAP *ld;
 	int fd; /* only set when connected/connecting */
 	struct io *io;
+
 	struct hash_table *requests;
+	struct ldap_request *delayed_requests_head, *delayed_requests_tail;
 
 	char **pass_attr_names, **user_attr_names;
 	struct hash_table *pass_attr_map, *user_attr_map;
@@ -69,6 +71,8 @@
 };
 
 struct ldap_request {
+	struct ldap_request *next; /* in conn->delayed_requests */
+
 	db_search_callback_t *callback;
 	void *context;
 
@@ -85,6 +89,8 @@
 	const char *authzid;
 };
 
+void db_ldap_add_delayed_request(struct ldap_connection *conn,
+				 struct ldap_request *request);
 void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request,
 		    int scope);
 
--- a/src/auth/passdb-ldap.c	Tue Nov 07 17:19:34 2006 +0200
+++ b/src/auth/passdb-ldap.c	Tue Nov 07 18:16:11 2006 +0200
@@ -268,14 +268,16 @@
 					     auth_request);
 			return;
 		}
+		hash_insert(conn->requests, POINTER_CAST(msgid), ldap_request);
 
 		auth_request_log_debug(auth_request, "ldap", "bind: dn=%s",
 				       ldap_request->base);
+	} else {
+		db_ldap_add_delayed_request(conn, ldap_request);
 	}
 
 	/* Bind started */
 	auth_request_ref(auth_request);
-	hash_insert(conn->requests, POINTER_CAST(msgid), ldap_request);
 }
 
 static void