changeset 1710:f1377239867e HEAD

fixes
author Timo Sirainen <tss@iki.fi>
date Fri, 22 Aug 2003 09:37:57 +0300
parents 044fdf70f11a
children 293ec0d24009
files src/lib-auth/auth-server-connection.c src/lib-auth/auth-server-connection.h src/lib-auth/auth-server-request.c
diffstat 3 files changed, 77 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-auth/auth-server-connection.c	Fri Aug 22 08:06:53 2003 +0300
+++ b/src/lib-auth/auth-server-connection.c	Fri Aug 22 09:37:57 2003 +0300
@@ -19,6 +19,8 @@
 	(sizeof(struct auth_client_request_continue) + \
 	 AUTH_CLIENT_MAX_REQUEST_DATA_SIZE)
 
+static void auth_server_connection_unref(struct auth_server_connection *conn);
+
 static void update_available_auth_mechs(struct auth_client *client)
 {
 	struct auth_server_connection *conn;
@@ -104,9 +106,13 @@
 		return;
 
 	/* we've got a full reply */
+	conn->refcount++;
 	conn->reply_received = FALSE;
+
 	auth_server_request_handle_reply(conn, &conn->reply, data);
 	i_stream_skip(conn->input, conn->reply.data_size);
+
+	auth_server_connection_unref(conn);
 }
 
 struct auth_server_connection *
@@ -128,6 +134,7 @@
 
 	pool = pool_alloconly_create("Auth connection", 1024);
 	conn = p_new(pool, struct auth_server_connection, 1);
+	conn->refcount = 1;
 	conn->pool = pool;
 
 	conn->client = client;
@@ -163,6 +170,9 @@
 	struct auth_client *client = conn->client;
 	struct auth_server_connection **pos;
 
+	if (conn->fd == -1)
+		return;
+
         pos = &conn->client->connections;
 	for (; *pos != NULL; pos = &(*pos)->next) {
 		if (*pos == conn) {
@@ -175,16 +185,17 @@
 		client->conn_waiting_handshake_count--;
 
 	io_remove(conn->io);
+	conn->io = NULL;
+
+	i_stream_close(conn->input);
+	o_stream_close(conn->output);
+
 	if (close(conn->fd) < 0)
 		i_error("close(auth) failed: %m");
 	conn->fd = -1;
 
 	auth_server_requests_remove_all(conn);
-	hash_destroy(conn->requests);
-
-	i_stream_unref(conn->input);
-	o_stream_unref(conn->output);
-	pool_unref(conn->pool);
+        auth_server_connection_unref(conn);
 
 	if (reconnect)
 		auth_client_connect_missing_servers(client);
@@ -195,6 +206,18 @@
 	}
 }
 
+static void auth_server_connection_unref(struct auth_server_connection *conn)
+{
+	if (--conn->refcount > 0)
+		return;
+
+	hash_destroy(conn->requests);
+
+	i_stream_unref(conn->input);
+	o_stream_unref(conn->output);
+	pool_unref(conn->pool);
+}
+
 struct auth_server_connection *
 auth_server_connection_find_path(struct auth_client *client, const char *path)
 {
--- a/src/lib-auth/auth-server-connection.h	Fri Aug 22 08:06:53 2003 +0300
+++ b/src/lib-auth/auth-server-connection.h	Fri Aug 22 09:37:57 2003 +0300
@@ -20,6 +20,8 @@
 	struct auth_server_connection *next;
 
 	pool_t pool;
+	int refcount;
+
 	struct auth_client *client;
 	const char *path;
 	int fd;
--- a/src/lib-auth/auth-server-request.c	Fri Aug 22 08:06:53 2003 +0300
+++ b/src/lib-auth/auth-server-request.c	Fri Aug 22 09:37:57 2003 +0300
@@ -47,6 +47,26 @@
 	return TRUE;
 }
 
+static void auth_server_send_continue(struct auth_server_connection *conn,
+				      struct auth_request *request,
+				      const unsigned char *data, size_t size)
+{
+	struct auth_client_request_continue auth_request;
+
+	/* send continued request to auth */
+	auth_request.type = AUTH_CLIENT_REQUEST_CONTINUE;
+	auth_request.id = request->id;
+	auth_request.data_size = size;
+
+	if (o_stream_send(conn->output, &auth_request,
+			  sizeof(auth_request)) < 0 ||
+	    o_stream_send(conn->output, data, size) < 0) {
+		errno = conn->output->stream_errno;
+		i_warning("Error sending continue request to auth server: %m");
+		auth_server_connection_destroy(conn, TRUE);
+	}
+}
+
 static struct auth_server_connection *
 get_next_plain_server(struct auth_server_connection *conn)
 {
@@ -68,37 +88,43 @@
 
 	request = hash_lookup(conn->requests, POINTER_CAST(reply->id));
 	if (request == NULL) {
-		i_error("BUG: Auth server sent us reply with unknown ID %u",
-			reply->id);
+		/* We've already destroyed the request */
 		return;
 	}
 
 	switch (reply->result) {
 	case AUTH_CLIENT_RESULT_SUCCESS:
-		if (conn == request->conn)
-			request->next_conn = NULL;
-		else {
-			i_assert(request->next_conn == conn);
-			request->conn = request->next_conn;
-			request->next_conn = NULL;
+		hash_remove(request->conn->requests, POINTER_CAST(request->id));
+		if (request->next_conn != NULL) {
+			hash_remove(request->next_conn->requests,
+				    POINTER_CAST(request->id));
 		}
+		request->conn = conn;
+		request->next_conn = NULL;
 		break;
 	case AUTH_CLIENT_RESULT_FAILURE:
-		if (request->plaintext_data == NULL)
+		hash_remove(conn->requests, POINTER_CAST(request->id));
+		if (!request->retrying)
 			break;
 
-		next = get_next_plain_server(conn);
-		if (next == NULL)
-			break;
-
-		hash_remove(conn->requests, POINTER_CAST(request->id));
-		hash_insert(next->requests, POINTER_CAST(request->id), request);
+		next = request->next_conn == NULL ? NULL :
+			get_next_plain_server(request->next_conn);
 
 		if (conn == request->conn)
 			request->conn = request->next_conn;
+		request->next_conn = NULL;
 
+		if (next == NULL) {
+			if (request->conn != NULL) {
+				/* the other one hasn't replied yet */
+				return;
+			}
+			request->conn = conn;
+			break;
+		}
+
+		hash_insert(next->requests, POINTER_CAST(request->id), request);
 		request->next_conn = next;
-		request->retrying = TRUE;
 
 		auth_server_send_new_request(next, request);
 		return;
@@ -106,15 +132,15 @@
 		if (!request->retrying)
 			break;
 
-		auth_client_request_continue(request, request->plaintext_data,
-					     request->plaintext_data_size);
+		auth_server_send_continue(conn, request,
+					  request->plaintext_data,
+					  request->plaintext_data_size);
 		return;
 	}
 
 	request->callback(request, reply, data, request->context);
 
 	if (reply->result != AUTH_CLIENT_RESULT_CONTINUE) {
-		hash_remove(conn->requests, POINTER_CAST(request->id));
 		i_free(request->plaintext_data);
 		i_free(request);
 	}
@@ -169,7 +195,7 @@
 void auth_client_request_continue(struct auth_request *request,
 				  const unsigned char *data, size_t data_size)
 {
-	struct auth_client_request_continue auth_request;
+	auth_server_send_continue(request->conn, request, data, data_size);
 
 	if (request->mech == AUTH_MECH_PLAIN &&
 	    request->plaintext_data == NULL) {
@@ -185,21 +211,9 @@
 				    POINTER_CAST(request->id), request);
 			auth_server_send_new_request(request->next_conn,
 						     request);
+			request->retrying = TRUE;
 		}
 	}
-
-	/* send continued request to auth */
-	auth_request.type = AUTH_CLIENT_REQUEST_CONTINUE;
-	auth_request.id = request->id;
-	auth_request.data_size = data_size;
-
-	if (o_stream_send(request->conn->output, &auth_request,
-			  sizeof(auth_request)) < 0 ||
-	    o_stream_send(request->conn->output, data, data_size) < 0) {
-		errno = request->conn->output->stream_errno;
-		i_warning("Error sending continue request to auth server: %m");
-		auth_server_connection_destroy(request->conn, TRUE);
-	}
 }
 
 void auth_client_request_abort(struct auth_request *request)