From: Timo Sirainen Date: Fri, 22 Aug 2003 06:37:57 +0000 (+0300) Subject: fixes X-Git-Tag: 1.1.alpha1~4396 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a272994d43de80a306a8ed1f2983960d1f3102d0;p=thirdparty%2Fdovecot%2Fcore.git fixes --HG-- branch : HEAD --- diff --git a/src/lib-auth/auth-server-connection.c b/src/lib-auth/auth-server-connection.c index 6c19df5bbd..1fa6ea4def 100644 --- a/src/lib-auth/auth-server-connection.c +++ b/src/lib-auth/auth-server-connection.c @@ -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) { diff --git a/src/lib-auth/auth-server-connection.h b/src/lib-auth/auth-server-connection.h index bf3dc896c5..4e21255288 100644 --- a/src/lib-auth/auth-server-connection.h +++ b/src/lib-auth/auth-server-connection.h @@ -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; diff --git a/src/lib-auth/auth-server-request.c b/src/lib-auth/auth-server-request.c index ca756abe08..cba0be7fe2 100644 --- a/src/lib-auth/auth-server-request.c +++ b/src/lib-auth/auth-server-request.c @@ -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)