From: Timo Sirainen Date: Wed, 15 Mar 2017 16:20:31 +0000 (+0200) Subject: *-login: Change API for how login_plugins hook into client allocation. X-Git-Tag: 2.3.0.rc1~1942 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5e62353a11087958ea4e619660e084a613e1a37;p=thirdparty%2Fdovecot%2Fcore.git *-login: Change API for how login_plugins hook into client allocation. The previous API worked badly when there were more than one plugin. The current behavior works similarly to how mail_plugins work. --- diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index 4a46e8d7af..599a0e3e11 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -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); +} diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index c70f5b7445..4dc3db7622 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -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 diff --git a/src/login-common/main.c b/src/login-common/main.c index 0cf055f16d..a086b44ee0 100644 --- a/src/login-common/main.c +++ b/src/login-common/main.c @@ -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(); }