]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
*-login: Change API for how login_plugins hook into client allocation.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 15 Mar 2017 16:20:31 +0000 (18:20 +0200)
committerGitLab <gitlab@git.dovecot.net>
Thu, 16 Mar 2017 06:48:33 +0000 (08:48 +0200)
The previous API worked badly when there were more than one plugin.
The current behavior works similarly to how mail_plugins work.

src/login-common/client-common.c
src/login-common/client-common.h
src/login-common/main.c

index 4a46e8d7aff98e263971802b82c26e3305cee9e8..599a0e3e1112665cb30682dfcaa72bc1940eb731 100644 (file)
@@ -8,6 +8,7 @@
 #include "ostream.h"
 #include "iostream-rawlog.h"
 #include "process-title.h"
+#include "hook-build.h"
 #include "buffer.h"
 #include "str.h"
 #include "base64.h"
@@ -29,19 +30,54 @@ struct client *clients = NULL;
 static struct client *last_client = NULL;
 static unsigned int clients_count = 0;
 
-static void empty_login_client_allocated_hook(struct client *client ATTR_UNUSED)
+struct login_client_module_hooks {
+       struct module *module;
+       const struct login_client_hooks *hooks;
+};
+
+static ARRAY(struct login_client_module_hooks) module_hooks = ARRAY_INIT;
+
+void login_client_hooks_add(struct module *module,
+                           const struct login_client_hooks *hooks)
 {
+       struct login_client_module_hooks *hook;
+
+       hook = array_append_space(&module_hooks);
+       hook->module = module;
+       hook->hooks = hooks;
 }
-static login_client_allocated_func_t *hook_client_allocated =
-       empty_login_client_allocated_hook;
 
-login_client_allocated_func_t *
-login_client_allocated_hook_set(login_client_allocated_func_t *new_hook)
+void login_client_hooks_remove(const struct login_client_hooks *hooks)
 {
-       login_client_allocated_func_t *old_hook = hook_client_allocated;
+       const struct login_client_module_hooks *module_hook;
+       unsigned int idx = UINT_MAX;
+
+       array_foreach(&module_hooks, module_hook) {
+               if (module_hook->hooks == hooks) {
+                       idx = array_foreach_idx(&module_hooks, module_hook);
+                       break;
+               }
+       }
+       i_assert(idx != UINT_MAX);
 
-       hook_client_allocated = new_hook;
-       return old_hook;
+       array_delete(&module_hooks, idx, 1);
+}
+
+static void hook_login_client_allocated(struct client *client)
+{
+       const struct login_client_module_hooks *module_hook;
+       struct hook_build_context *ctx;
+
+       ctx = hook_build_init((void *)&client->v, sizeof(client->v));
+       client->vlast = &client->v;
+       array_foreach(&module_hooks, module_hook) {
+               if (module_hook->hooks->client_allocated != NULL) T_BEGIN {
+                       module_hook->hooks->client_allocated(client);
+                       hook_build_update(ctx, client->vlast);
+               } T_END;
+       }
+       client->vlast = NULL;
+       hook_build_deinit(&ctx);
 }
 
 static void client_idle_disconnect_timeout(struct client *client)
@@ -168,7 +204,7 @@ client_create(int fd, bool ssl, pool_t pool,
                            client_idle_disconnect_timeout, client);
        client_open_streams(client);
 
-       hook_client_allocated(client);
+       hook_login_client_allocated(client);
        client->v.create(client, other_sets);
 
        if (auth_client_is_connected(auth_client))
@@ -869,3 +905,13 @@ void client_input(struct client *client)
 {
        client->v.input(client);
 }
+
+void client_common_init(void)
+{
+       i_array_init(&module_hooks, 32);
+}
+
+void client_common_deinit(void)
+{
+       array_free(&module_hooks);
+}
index c70f5b7445afb69f082760a628223f008c52c531..4dc3db76220a70db13362dddb8e9e5ff035f6435 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef CLIENT_COMMON_H
 #define CLIENT_COMMON_H
 
+struct module;
+
 #include "net.h"
 #include "login-proxy.h"
 #include "sasl-server.h"
@@ -123,6 +125,7 @@ struct client {
        struct client *prev, *next;
        pool_t pool;
        struct client_vfuncs v;
+       struct client_vfuncs *vlast;
 
        time_t created;
        int refcount;
@@ -205,14 +208,17 @@ union login_client_module_context {
        struct login_module_register *reg;
 };
 
+struct login_client_hooks {
+       void (*client_allocated)(struct client *client);
+};
+
 extern struct client *clients;
 
 typedef void login_client_allocated_func_t(struct client *client);
 
-/* Sets the client allocation hook and returns the previous hook,
-   which the new hook should call. */
-login_client_allocated_func_t *
-login_client_allocated_hook_set(login_client_allocated_func_t *new_hook);
+void login_client_hooks_add(struct module *module,
+                           const struct login_client_hooks *hooks);
+void login_client_hooks_remove(const struct login_client_hooks *hooks);
 
 struct client *
 client_create(int fd, bool ssl, pool_t pool,
@@ -273,4 +279,7 @@ void client_destroy_oldest(void);
 void clients_destroy_all(void);
 void clients_destroy_all_reason(const char *reason);
 
+void client_common_init(void);
+void client_common_deinit(void);
+
 #endif
index 0cf055f16d18102102248ba1de5f1525c240c938..a086b44ee006d85d5cc19ee768c1dc9bfebf8543 100644 (file)
@@ -336,6 +336,7 @@ static void main_preinit(void)
           key file. */
        ssl_proxy_init();
        dsasl_clients_init();
+       client_common_init();
 
        /* set the number of fds we want to use. it may get increased or
           decreased. leave a couple of extra fds for auth sockets and such.
@@ -433,6 +434,7 @@ static void main_deinit(void)
                anvil_client_deinit(&anvil);
        if (auth_client_to != NULL)
                timeout_remove(&auth_client_to);
+       client_common_deinit();
        dsasl_clients_deinit();
        login_settings_deinit();
 }