]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
fixes
authorTimo Sirainen <tss@iki.fi>
Fri, 22 Aug 2003 06:37:57 +0000 (09:37 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 22 Aug 2003 06:37:57 +0000 (09:37 +0300)
--HG--
branch : HEAD

src/lib-auth/auth-server-connection.c
src/lib-auth/auth-server-connection.h
src/lib-auth/auth-server-request.c

index 6c19df5bbdeb60d187771b44f0615389f0af1112..1fa6ea4def825345f06a5ed689622761c303779b 100644 (file)
@@ -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 @@ static void auth_client_input(void *context)
                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 @@ auth_server_connection_new(struct auth_client *client, const char *path)
 
        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 @@ void auth_server_connection_destroy(struct auth_server_connection *conn,
        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 @@ void auth_server_connection_destroy(struct auth_server_connection *conn,
                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 @@ void auth_server_connection_destroy(struct auth_server_connection *conn,
        }
 }
 
+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)
 {
index bf3dc896c5cfa3e738dd6598609f5bfd7a05211c..4e212552881b0990c8fa9fd0605ed6f479d260a5 100644 (file)
@@ -20,6 +20,8 @@ struct auth_server_connection {
        struct auth_server_connection *next;
 
        pool_t pool;
+       int refcount;
+
        struct auth_client *client;
        const char *path;
        int fd;
index ca756abe0824e5dce1b145627a94ed164151def7..cba0be7fe2e15d0156de975c26a4f9ffd43e99c0 100644 (file)
@@ -47,6 +47,26 @@ static int auth_server_send_new_request(struct auth_server_connection *conn,
        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 @@ void auth_server_request_handle_reply(struct auth_server_connection *conn,
 
        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)
-                       break;
-
-               next = get_next_plain_server(conn);
-               if (next == NULL)
+               hash_remove(conn->requests, POINTER_CAST(request->id));
+               if (!request->retrying)
                        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 @@ void auth_server_request_handle_reply(struct auth_server_connection *conn,
                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 @@ auth_client_request_new(struct auth_client *client,
 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 @@ void auth_client_request_continue(struct auth_request *request,
                                    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)