summaryrefslogtreecommitdiff
path: root/mail/dbmail/files/patch-0009-Rework-temporary-connection-failures
blob: 8d5486fdfd8b805bbd668f4f839def9b3804f9e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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)