From 9d093f76a82c88647df1cd0ef08b3e8f82e26abb Mon Sep 17 00:00:00 2001
From: Alan Hicks <ahicks@p-o.co.uk>
Date: Fri, 30 Sep 2016 17:17:05 +0100
Subject: [PATCH 09/33] Rework temporary connection failures

---
 src/modules/authldap.c | 102 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 67 insertions(+), 35 deletions(-)

diff --git src/modules/authldap.c src/modules/authldap.c
index 19802c8..2073768 100644
--- src/modules/authldap.c
+++ src/modules/authldap.c
@@ -110,18 +110,48 @@ static gpointer authldap_once(gpointer UNUSED data)
 	return (gpointer)NULL;
 }
 
-/* 
- lookup thread-local ldap connection
-*/
+/*
+ * ldap_con_get()
+ *
+ * Lookup thread-local ldap connection and bind using config credentials
+ * retrying a few times if the server is temporarily unavailable
+ * 
+ * returns connection on success, NULL on failure
+ */
 static LDAP * ldap_con_get(void)
 {
-	LDAP * c = (LDAP *)g_static_private_get(&ldap_conn_key);
-	if (! c) {
-		authldap_connect();
-		c = (LDAP *)g_static_private_get(&ldap_conn_key);
+	LDAP * ld = (LDAP *)g_static_private_get(&ldap_conn_key);
+	if (ld) {
+		TRACE(TRACE_DEBUG, "connection [%p]", ld);
+		return ld;
 	}
-	TRACE(TRACE_DEBUG, "connection [%p]", c);
-	return c;
+	int c = 0;
+	int err = -1; // Start wanting success
+	while (err != 0 && c++ < 5) {
+		// Loop until success or too many retries
+		TRACE(TRACE_DEBUG, "No connection trying [%d]", c);
+
+		err = authldap_connect();
+
+		switch (err) {
+			case LDAP_SUCCESS:
+				ld = (LDAP *)g_static_private_get(&ldap_conn_key);
+				TRACE(TRACE_DEBUG, "connection [%p]", ld);
+				break;
+			case LDAP_SERVER_DOWN:
+				TRACE(TRACE_WARNING, "LDAP gone away: %s. Trying to reconnect(%d/5).", ldap_err2string(err),c);
+				sleep(2); // reconnect failed. wait before trying again
+				break;
+			default:
+				TRACE(TRACE_ERR, "LDAP error(%d): %s", err, ldap_err2string(err));
+				break;
+		}
+	}
+	if (! ld) {
+		TRACE(TRACE_ERR, "Unable to connect to LDAP giving up");
+	}
+	TRACE(TRACE_DEBUG, "connection [%p]", ld);
+	return ld;
 }
 
 /*
@@ -140,6 +170,13 @@ static void authldap_free(gpointer data)
 	sigaction(SIGPIPE, &oldact, 0);
 }
 
+/*
+ * auth_ldap_bind()
+ *
+ * Bind to server using config credentials
+ * 
+ * returns 0 on success, -1 on failure
+ */
 static int auth_ldap_bind(void)
 {
 	int err;
@@ -153,7 +190,6 @@ static int auth_ldap_bind(void)
 	}
 
 	return 0;
-
 }
 
 /*
@@ -213,44 +249,40 @@ static int authldap_connect(void)
 	return auth_ldap_bind();	
 }
 
-static int authldap_reconnect(void)
-{
-	LDAP *c;
-	if ((c = ldap_con_get())) authldap_free((gpointer)c);
-	return authldap_connect();
-}
-
+/*
+ * authldap_search()
+ *
+ * Perform an LDAP search
+ * 
+ * returns search results on success, NULL on failure
+ */
 static LDAPMessage * authldap_search(const gchar *query)
 {
 	LDAPMessage *ldap_res;
 	int _ldap_attrsonly = 0;
 	char **_ldap_attrs = NULL;
-	int c=0, err;
+	int err;
 	LDAP *_ldap_conn;
 
 	g_return_val_if_fail(query!=NULL, NULL);
 
 	_ldap_conn = ldap_con_get();
 
-	while (c++ < 5) {
-		TRACE(TRACE_DEBUG, " [%s]", query);
-		err = ldap_search_s(_ldap_conn, _ldap_cfg.base_dn, _ldap_cfg.scope_int, 
-				query, _ldap_attrs, _ldap_attrsonly, &ldap_res);
+	TRACE(TRACE_DEBUG, " [%s]", query);
+	err = ldap_search_s(_ldap_conn, _ldap_cfg.base_dn, _ldap_cfg.scope_int, 
+			query, _ldap_attrs, _ldap_attrsonly, &ldap_res);
 
-		if (! err)
-			return ldap_res;
+	if (! err)
+		return ldap_res;
 
-		switch (err) {
-			case LDAP_SERVER_DOWN:
-				TRACE(TRACE_WARNING, "LDAP gone away: %s. Try to reconnect(%d/5).", ldap_err2string(err),c);
-				if (authldap_reconnect())
-					sleep(2); // reconnect failed. wait before trying again
-				break;
-			default:
-				TRACE(TRACE_ERR, "LDAP error(%d): %s", err, ldap_err2string(err));
-				return NULL;
-				break;
-		}
+	switch (err) {
+		case LDAP_SERVER_DOWN:
+			TRACE(TRACE_WARNING, "LDAP gone away: %s).", ldap_err2string(err));
+			break;
+		default:
+			TRACE(TRACE_ERR, "LDAP error(%d): %s", err, ldap_err2string(err));
+			return NULL;
+			break;
 	}
 
 	TRACE(TRACE_EMERG,"unrecoverable error while talking to ldap server");
-- 
2.10.1 (Apple Git-78)

