]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: Fixes to handling master-login services.
authorTimo Sirainen <tss@iki.fi>
Tue, 27 Oct 2009 03:41:54 +0000 (23:41 -0400)
committerTimo Sirainen <tss@iki.fi>
Tue, 27 Oct 2009 03:41:54 +0000 (23:41 -0400)
--HG--
branch : HEAD

src/lib-master/master-login-auth.c
src/lib-master/master-login-auth.h
src/lib-master/master-login.c
src/lib-master/master-service-private.h
src/lib-master/master-service.c

index 4ed0be373b92cd0e0a0ab690fffda17b11838562..8d15a9f9ec3117e63cd1aa0bdbe030b2bea4f735 100644 (file)
@@ -288,3 +288,8 @@ void master_login_auth_request(struct master_login_auth *auth,
        login_req->context = context;
        hash_table_insert(auth->requests, POINTER_CAST(id), login_req);
 }
+
+unsigned int master_login_auth_request_count(struct master_login_auth *auth)
+{
+       return hash_table_count(auth->requests);
+}
index 3db896d6bd1111ebb0f90a8730857060f0d68b76..7dd485ae0a26e3b5ff34659207444b2766234218 100644 (file)
@@ -14,5 +14,6 @@ void master_login_auth_request(struct master_login_auth *auth,
                               const struct master_auth_request *req,
                               master_login_auth_request_callback_t *callback,
                               void *context);
+unsigned int master_login_auth_request_count(struct master_login_auth *auth);
 
 #endif
index 56138524fba1e7ebdd985336a02f5a58a962d786..50629e7b85b7fc4656372ad74ad4d334f1757209 100644 (file)
@@ -131,7 +131,8 @@ master_login_auth_callback(const char *const *auth_args, void *context)
 {
        struct master_login_client *client = context;
        struct master_auth_reply reply;
-       struct master_service *service = client->conn->login->service;
+       struct master_login_connection *conn = client->conn;
+       struct master_service *service = conn->login->service;
        bool close_config;
 
        memset(&reply, 0, sizeof(reply));
@@ -139,7 +140,7 @@ master_login_auth_callback(const char *const *auth_args, void *context)
        reply.status = auth_args != NULL ? MASTER_AUTH_STATUS_OK :
                MASTER_AUTH_STATUS_INTERNAL_ERROR;
        reply.mail_pid = getpid();
-       o_stream_send(client->conn->output, &reply, sizeof(reply));
+       o_stream_send(conn->output, &reply, sizeof(reply));
 
        if (auth_args == NULL) {
                if (close(client->fd) < 0)
@@ -148,17 +149,19 @@ master_login_auth_callback(const char *const *auth_args, void *context)
                return;
        }
 
+       i_assert(service->master_status.available_count > 0);
        service->master_status.available_count--;
        master_status_update(service);
        close_config = service->master_status.available_count == 0 &&
                service->service_count_left == 1;
 
-       client->conn->login->callback(client, auth_args[0], auth_args+1);
+       conn->login->callback(client, auth_args[0], auth_args+1);
        i_free(client);
 
        if (close_config) {
                /* we're dying as soon as this connection closes. */
                master_service_close_config_fd(service);
+               master_login_conn_deinit(&conn);
        }
 }
 
@@ -166,7 +169,9 @@ static void master_login_conn_input(struct master_login_connection *conn)
 {
        struct master_auth_request req;
        struct master_login_client *client;
+       struct master_login *login = conn->login;
        unsigned char data[MASTER_AUTH_MAX_DATA_SIZE];
+       unsigned int request_count;
        int ret, client_fd;
 
        ret = master_login_conn_read_request(conn, &req, data, &client_fd);
@@ -188,8 +193,11 @@ static void master_login_conn_input(struct master_login_connection *conn)
        client->auth_req = req;
        memcpy(client->data, data, req.data_size);
 
-       master_login_auth_request(conn->login->auth, &req,
+       master_login_auth_request(login->auth, &req,
                                  master_login_auth_callback, client);
+       request_count = master_login_auth_request_count(login->auth);
+       if (login->service->master_status.available_count <= request_count)
+               io_remove(&conn->io);
 }
 
 void master_login_add(struct master_login *login, int fd)
@@ -203,6 +211,10 @@ void master_login_add(struct master_login *login, int fd)
        conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
 
        DLLIST_PREPEND(&login->conns, conn);
+
+       /* don't accept more connections. this is mainly a temporary
+          workaround.. */
+       master_service_io_listeners_remove(login->service);
 }
 
 static void master_login_conn_deinit(struct master_login_connection **_conn)
@@ -213,9 +225,11 @@ static void master_login_conn_deinit(struct master_login_connection **_conn)
 
        DLLIST_REMOVE(&conn->login->conns, conn);
 
-       io_remove(&conn->io);
+       if (conn->io != NULL)
+               io_remove(&conn->io);
        o_stream_unref(&conn->output);
        if (close(conn->fd) < 0)
                i_error("close(master login) failed: %m");
+       master_service_io_listeners_add(conn->login->service);
        i_free(conn);
 }
index ff64a00d468fffe76d5f8fa34f17cd5efb2bba99..2ba018fb2f6f859f46c106bf3e77c1660d4e3851 100644 (file)
@@ -62,4 +62,6 @@ void master_service_io_listeners_add(struct master_service *service);
 void master_status_update(struct master_service *service);
 void master_service_close_config_fd(struct master_service *service);
 
+void master_service_io_listeners_remove(struct master_service *service);
+
 #endif
index a64e4e978a61acc3d7ff902db3a2a26ec7d2e85d..cc3e36310adc38ce53f46472bd492540fcbf6518 100644 (file)
@@ -39,7 +39,6 @@
 struct master_service *master_service;
 
 static void master_service_refresh_login_state(struct master_service *service);
-static void io_listeners_remove(struct master_service *service);
 
 const char *master_service_getopt_string(void)
 {
@@ -265,7 +264,7 @@ bool master_service_parse_option(struct master_service *service,
 
 static void master_service_error(struct master_service *service)
 {
-       io_listeners_remove(service);
+       master_service_io_listeners_remove(service);
        if (service->master_status.available_count ==
            service->total_available_count || service->die_with_master) {
                if (service->die_callback == NULL)
@@ -585,7 +584,7 @@ void master_service_deinit(struct master_service **_service)
 
        *_service = NULL;
 
-       io_listeners_remove(service);
+       master_service_io_listeners_remove(service);
 
        master_service_close_config_fd(service);
        if (service->to_die != NULL)
@@ -631,7 +630,7 @@ static void master_service_listen(struct master_service_listener *l)
                }
 
                if (service->master_status.available_count == 0) {
-                       io_listeners_remove(service);
+                       master_service_io_listeners_remove(service);
                        return;
                }
        }
@@ -663,6 +662,7 @@ static void master_service_listen(struct master_service_listener *l)
        if (service->login_connections)
                close_config = FALSE;
        else {
+               i_assert(service->master_status.available_count > 0);
                service->master_status.available_count--;
                master_status_update(service);
                close_config = service->master_status.available_count == 0 &&
@@ -715,7 +715,7 @@ void master_service_io_listeners_add(struct master_service *service)
        }
 }
 
-static void io_listeners_remove(struct master_service *service)
+void master_service_io_listeners_remove(struct master_service *service)
 {
        unsigned int i;