]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-auth-client: auth-master - Add internal support for initiating invalid requests
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 11 Mar 2018 23:44:39 +0000 (00:44 +0100)
committerStephan Bosch <stephan.bosch@open-xchange.com>
Wed, 27 Aug 2025 14:17:02 +0000 (16:17 +0200)
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.

src/lib-auth-client/auth-master-private.h
src/lib-auth-client/auth-master-request.c
src/lib-auth-client/auth-master.c

index 9098b20eb4a689317b0c07149e7c6ce00d55656b..770195c2dc1d8ed179ad0e7c7f2c4350d75a03ac 100644 (file)
@@ -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
index 5e4e5a169ce6d21faa6bbfc8ced9481987bcdb0d..81e0b9713f62677476e1ade5974fe87014a2eab0 100644 (file)
@@ -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;
 }
 
index d095214583750945327f7775b45d052a52cfa24e..9f4f1a36135de7f37a366701b9e06909520986a1 100644 (file)
@@ -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);
 }