From: Stephan Bosch Date: Sun, 11 Mar 2018 23:44:39 +0000 (+0100) Subject: lib-auth-client: auth-master - Add internal support for initiating invalid requests X-Git-Tag: 2.4.2~487 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9c5a816fc8fb77f5e5b118cb064f2f77722e1855;p=thirdparty%2Fdovecot%2Fcore.git lib-auth-client: auth-master - Add internal support for initiating invalid requests This avoids the need to return a NOTFOUND code at request creation when the request is already known to fail. This is a means to handle this asynchronously. --- diff --git a/src/lib-auth-client/auth-master-private.h b/src/lib-auth-client/auth-master-private.h index 9098b20eb4..770195c2dc 100644 --- a/src/lib-auth-client/auth-master-private.h +++ b/src/lib-auth-client/auth-master-private.h @@ -49,6 +49,7 @@ struct auth_master_request { ARRAY(struct auth_master_request_destroy_callback) destroy_callbacks; bool sent:1; + bool invalid:1; bool aborted:1; bool removed:1; bool in_callback:1; @@ -63,7 +64,7 @@ struct auth_master_connection { const char *auth_socket_path; enum auth_master_flags flags; - struct timeout *to_connect, *to_idle, *to_request; + struct timeout *to_connect, *to_idle, *to_request, *to_invalid; struct ioloop *ioloop, *prev_ioloop; unsigned int id_counter; @@ -95,6 +96,15 @@ int auth_master_request_got_reply(struct auth_master_request **_req, void auth_master_request_fail(struct auth_master_request **_req, const char *reason); +void auth_master_request_abort_invalid(struct auth_master_request **_req); + +struct auth_master_request * +auth_master_request_invalid(struct auth_master_connection *conn, + auth_master_request_callback_t *callback, + void *context); +#define auth_master_request_invalid(conn, callback, context) \ + auth_master_request_invalid(conn, \ + (auth_master_request_callback_t *)callback, context) /* * Connection @@ -107,5 +117,6 @@ void auth_master_connection_update_timeout(struct auth_master_connection *conn); void auth_master_connection_start_timeout(struct auth_master_connection *conn); void auth_master_handle_requests(struct auth_master_connection *conn); +void auth_master_handle_invalid_requests(struct auth_master_connection *conn); #endif diff --git a/src/lib-auth-client/auth-master-request.c b/src/lib-auth-client/auth-master-request.c index 5e4e5a169c..81e0b9713f 100644 --- a/src/lib-auth-client/auth-master-request.c +++ b/src/lib-auth-client/auth-master-request.c @@ -226,12 +226,32 @@ void auth_master_request_fail(struct auth_master_request **_req, auth_master_request_abort(_req); } +void auth_master_request_abort_invalid(struct auth_master_request **_req) +{ + struct auth_master_request *req = *_req; + + if (req->in_callback) + return; + + e_debug(req->event, "Aborted as invalid"); + + const struct auth_master_reply mreply = { + .reply = "NOTFOUND", + }; + + i_assert(req->callback != NULL); + (void)auth_master_request_callback(req, &mreply); + + auth_master_request_abort(_req); +} + void auth_master_request_send(struct auth_master_request *req) { struct auth_master_connection *conn = req->conn; const char *id_str = dec2str(req->id); i_assert(req->state == AUTH_MASTER_REQUEST_STATE_SUBMITTED); + i_assert(!req->invalid); const struct const_iovec iov[] = { { req->cmd, strlen(req->cmd), }, @@ -253,16 +273,14 @@ void auth_master_request_send(struct auth_master_request *req) e_debug(req->event, "Sent"); } -#undef auth_master_request -struct auth_master_request * -auth_master_request(struct auth_master_connection *conn, const char *cmd, - const unsigned char *args, size_t args_size, - auth_master_request_callback_t *callback, void *context) +static struct auth_master_request * +auth_master_request_new(struct auth_master_connection *conn, + auth_master_request_callback_t *callback, void *context) { pool_t pool; struct auth_master_request *req; - pool = pool_alloconly_create("auth_master_request", 256 + args_size); + pool = pool_alloconly_create("auth_master_request", 1024); req = p_new(pool, struct auth_master_request, 1); req->pool = pool; req->refcount = 1; @@ -287,17 +305,43 @@ auth_master_request(struct auth_master_connection *conn, const char *cmd, if (conn->requests_unsent == NULL) conn->requests_unsent = conn->requests_tail; - auth_master_connection_start_timeout(conn); - auth_master_stop_idle(conn); + e_debug(req->event, "Created"); + return req; +} + +#undef auth_master_request +struct auth_master_request * +auth_master_request(struct auth_master_connection *conn, const char *cmd, + const unsigned char *args, size_t args_size, + auth_master_request_callback_t *callback, void *context) +{ + struct auth_master_request *req; + + req = auth_master_request_new(conn, callback, context); req->cmd = p_strdup(req->pool, cmd); if (args_size > 0) req->args = p_memdup(req->pool, args, args_size); req->args_size = args_size; - e_debug(req->event, "Created"); - auth_master_handle_requests(conn); + auth_master_connection_start_timeout(conn); + auth_master_stop_idle(conn); + return req; +} + +#undef auth_master_request_invalid +struct auth_master_request * +auth_master_request_invalid(struct auth_master_connection *conn, + auth_master_request_callback_t *callback, + void *context) +{ + struct auth_master_request *req; + + req = auth_master_request_new(conn, callback, context); + req->invalid = TRUE; + + auth_master_handle_invalid_requests(conn); return req; } diff --git a/src/lib-auth-client/auth-master.c b/src/lib-auth-client/auth-master.c index d095214583..9f4f1a3613 100644 --- a/src/lib-auth-client/auth-master.c +++ b/src/lib-auth-client/auth-master.c @@ -111,6 +111,7 @@ auth_master_connection_failure(struct auth_master_connection *conn, timeout_remove(&conn->to_connect); timeout_remove(&conn->to_request); timeout_remove(&conn->to_idle); + timeout_remove(&conn->to_invalid); while (conn->requests_head != NULL) { req = conn->requests_head; @@ -524,6 +525,32 @@ void auth_master_handle_requests(struct auth_master_connection *conn) o_stream_set_flush_pending(conn->conn.output, TRUE); } +static void +auth_master_abort_invalid_requests(struct auth_master_connection *conn) +{ + struct auth_master_request *req, *req_next; + + timeout_remove(&conn->to_invalid); + + req = conn->requests_unsent; + while (req != NULL) { + req_next = req->next; + if (req->invalid) + auth_master_request_abort_invalid(&req); + req = req_next; + } +} + +void auth_master_handle_invalid_requests(struct auth_master_connection *conn) +{ + if (conn->to_invalid != NULL) + return; + + conn->to_invalid = timeout_add_to( + conn->ioloop, 0, + auth_master_abort_invalid_requests, conn); +} + void auth_master_switch_ioloop_to(struct auth_master_connection *conn, struct ioloop *ioloop) { @@ -539,6 +566,10 @@ void auth_master_switch_ioloop_to(struct auth_master_connection *conn, } if (conn->to_idle != NULL) conn->to_idle = io_loop_move_timeout_to(ioloop, &conn->to_idle); + if (conn->to_invalid != NULL) { + conn->to_idle = + io_loop_move_timeout_to(ioloop, &conn->to_invalid); + } connection_switch_ioloop_to(&conn->conn, conn->ioloop); }