changeset 21741:ad2aa897a8d7

*-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.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 15 Mar 2017 18:20:31 +0200
parents 3ce8158b7fd5
children 0347ed67254e
files src/login-common/client-common.c src/login-common/client-common.h src/login-common/main.c
diffstat 3 files changed, 70 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/login-common/client-common.c	Mon Mar 13 22:52:41 2017 +0200
+++ b/src/login-common/client-common.c	Wed Mar 15 18:20:31 2017 +0200
@@ -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 @@
 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;
+
+void login_client_hooks_remove(const struct login_client_hooks *hooks)
+{
+	const struct login_client_module_hooks *module_hook;
+	unsigned int idx = UINT_MAX;
 
-login_client_allocated_func_t *
-login_client_allocated_hook_set(login_client_allocated_func_t *new_hook)
+	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);
+
+	array_delete(&module_hooks, idx, 1);
+}
+
+static void hook_login_client_allocated(struct client *client)
 {
-	login_client_allocated_func_t *old_hook = hook_client_allocated;
+	const struct login_client_module_hooks *module_hook;
+	struct hook_build_context *ctx;
 
-	hook_client_allocated = new_hook;
-	return old_hook;
+	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)
@@ -170,7 +206,7 @@
 			    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))
@@ -842,3 +878,13 @@
 {
 	client->v.input(client);
 }
+
+void client_common_init(void)
+{
+	i_array_init(&module_hooks, 32);
+}
+
+void client_common_deinit(void)
+{
+	array_free(&module_hooks);
+}
--- a/src/login-common/client-common.h	Mon Mar 13 22:52:41 2017 +0200
+++ b/src/login-common/client-common.h	Wed Mar 15 18:20:31 2017 +0200
@@ -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"
@@ -106,6 +108,7 @@
 	struct client *prev, *next;
 	pool_t pool;
 	struct client_vfuncs v;
+	struct client_vfuncs *vlast;
 
 	time_t created;
 	int refcount;
@@ -191,14 +194,17 @@
 	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,
@@ -259,4 +265,7 @@
 void clients_destroy_all(void);
 void clients_destroy_all_reason(const char *reason);
 
+void client_common_init(void);
+void client_common_deinit(void);
+
 #endif
--- a/src/login-common/main.c	Mon Mar 13 22:52:41 2017 +0200
+++ b/src/login-common/main.c	Wed Mar 15 18:20:31 2017 +0200
@@ -336,6 +336,7 @@
 	   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 @@
 		anvil_client_deinit(&anvil);
 	if (auth_client_to != NULL)
 		timeout_remove(&auth_client_to);
+	client_common_deinit();
 	dsasl_clients_deinit();
 	login_settings_deinit();
 }