From: Stephan Bosch Date: Sun, 7 Oct 2018 18:42:20 +0000 (+0200) Subject: lib-smtp: server: Add hooks API for recipient. X-Git-Tag: 2.3.9~1217 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ba3af55e4facf2c63497b38db1c488cd94c16d8;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: server: Add hooks API for recipient. --- diff --git a/src/lib-smtp/smtp-server-private.h b/src/lib-smtp/smtp-server-private.h index 3d78040e33..f537a9bbea 100644 --- a/src/lib-smtp/smtp-server-private.h +++ b/src/lib-smtp/smtp-server-private.h @@ -54,6 +54,14 @@ struct smtp_server_command_hook { void *context; }; +struct smtp_server_recipient_hook { + enum smtp_server_recipient_hook_type type; + struct smtp_server_recipient_hook *prev, *next; + + smtp_server_rcpt_func_t *func; + void *context; +}; + struct smtp_server_reply_content { unsigned int status; const char *status_prefix; @@ -102,6 +110,12 @@ struct smtp_server_command { bool reply_early:1; }; +struct smtp_server_recipient_private { + struct smtp_server_recipient rcpt; + + struct smtp_server_recipient_hook *hooks_head, *hooks_tail; +}; + struct smtp_server_state_data { enum smtp_server_state state; time_t timestamp; diff --git a/src/lib-smtp/smtp-server-recipient.c b/src/lib-smtp/smtp-server-recipient.c index 9589b71de6..8e384c4cec 100644 --- a/src/lib-smtp/smtp-server-recipient.c +++ b/src/lib-smtp/smtp-server-recipient.c @@ -1,24 +1,29 @@ /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "llist.h" #include "smtp-address.h" #include "smtp-server-private.h" +static void +smtp_server_recipient_call_hooks(struct smtp_server_recipient *rcpt, + enum smtp_server_recipient_hook_type type); + struct smtp_server_recipient * smtp_server_recipient_create(struct smtp_server_connection *conn, const struct smtp_address *rcpt_to) { - struct smtp_server_recipient *rcpt; + struct smtp_server_recipient_private *prcpt; pool_t pool; pool = pool_alloconly_create("smtp server recipient", 512); - rcpt = p_new(pool, struct smtp_server_recipient, 1); - rcpt->pool = pool; - rcpt->conn = conn; - rcpt->path = smtp_address_clone(pool, rcpt_to); + prcpt = p_new(pool, struct smtp_server_recipient_private, 1); + prcpt->rcpt.pool = pool; + prcpt->rcpt.conn = conn; + prcpt->rcpt.path = smtp_address_clone(pool, rcpt_to); - return rcpt; + return &prcpt->rcpt; } void smtp_server_recipient_destroy(struct smtp_server_recipient **_rcpt) @@ -30,6 +35,9 @@ void smtp_server_recipient_destroy(struct smtp_server_recipient **_rcpt) if (rcpt == NULL) return; + smtp_server_recipient_call_hooks( + rcpt, SMTP_SERVER_RECIPIENT_HOOK_DESTROY); + pool_unref(&rcpt->pool); } @@ -40,4 +48,83 @@ void smtp_server_recipient_approved(struct smtp_server_recipient *rcpt) i_assert(trans != NULL); smtp_server_transaction_add_rcpt(trans, rcpt); + + smtp_server_recipient_call_hooks( + rcpt, SMTP_SERVER_RECIPIENT_HOOK_APPROVED); +} + +#undef smtp_server_recipient_add_hook +void smtp_server_recipient_add_hook(struct smtp_server_recipient *rcpt, + enum smtp_server_recipient_hook_type type, + smtp_server_rcpt_func_t func, void *context) +{ + struct smtp_server_recipient_private *prcpt = + (struct smtp_server_recipient_private *)rcpt; + struct smtp_server_recipient_hook *hook; + + i_assert(func != NULL); + + hook = prcpt->hooks_head; + while (hook != NULL) { + /* no double registrations */ + i_assert(hook->type != type || hook->func != func); + + hook = hook->next; + } + + hook = p_new(rcpt->pool, struct smtp_server_recipient_hook, 1); + hook->type = type; + hook->func = func; + hook->context = context; + + DLLIST2_APPEND(&prcpt->hooks_head, &prcpt->hooks_tail, hook); +} + +#undef smtp_server_recipient_remove_hook +void smtp_server_recipient_remove_hook( + struct smtp_server_recipient *rcpt, + enum smtp_server_recipient_hook_type type, + smtp_server_rcpt_func_t *func) +{ + struct smtp_server_recipient_private *prcpt = + (struct smtp_server_recipient_private *)rcpt; + struct smtp_server_recipient_hook *hook; + bool found = FALSE; + + hook = prcpt->hooks_head; + while (hook != NULL) { + struct smtp_server_recipient_hook *hook_next = hook->next; + + if (hook->type == type && hook->func == func) { + DLLIST2_REMOVE(&prcpt->hooks_head, &prcpt->hooks_tail, + hook); + found = TRUE; + break; + } + + hook = hook_next; + } + i_assert(found); +} + +static void +smtp_server_recipient_call_hooks(struct smtp_server_recipient *rcpt, + enum smtp_server_recipient_hook_type type) +{ + struct smtp_server_recipient_private *prcpt = + (struct smtp_server_recipient_private *)rcpt; + struct smtp_server_recipient_hook *hook; + + hook = prcpt->hooks_head; + while (hook != NULL) { + struct smtp_server_recipient_hook *hook_next = hook->next; + + if (hook->type == type) { + DLLIST2_REMOVE(&prcpt->hooks_head, &prcpt->hooks_tail, + hook); + hook->func(rcpt, hook->context); + } + + hook = hook_next; + } } diff --git a/src/lib-smtp/smtp-server.h b/src/lib-smtp/smtp-server.h index ff4c61b56d..5e85786b94 100644 --- a/src/lib-smtp/smtp-server.h +++ b/src/lib-smtp/smtp-server.h @@ -17,6 +17,8 @@ struct smtp_server_cmd_mail; struct smtp_server_cmd_ctx; struct smtp_server_command; struct smtp_server_reply; +struct smtp_server_recipient; +struct smtp_server_transaction; struct smtp_server; @@ -48,6 +50,17 @@ struct smtp_server_helo_data { * Recipient */ +enum smtp_server_recipient_hook_type { + /* approved: the server is about to approve this recipient by sending + a success reply to the RCPT command. */ + SMTP_SERVER_RECIPIENT_HOOK_APPROVED, + /* destroy: recipient is about to be destroyed. */ + SMTP_SERVER_RECIPIENT_HOOK_DESTROY +}; + +typedef void smtp_server_rcpt_func_t(struct smtp_server_recipient *rcpt, + void *context); + struct smtp_server_recipient { pool_t pool; struct smtp_server_connection *conn; @@ -60,6 +73,25 @@ struct smtp_server_recipient { }; ARRAY_DEFINE_TYPE(smtp_server_recipient, struct smtp_server_recipient *); +/* Hooks */ + +void smtp_server_recipient_add_hook(struct smtp_server_recipient *rcpt, + enum smtp_server_recipient_hook_type type, + smtp_server_rcpt_func_t func, + void *context); +#define smtp_server_recipient_add_hook(_rcpt, _type, _func, _context) \ + smtp_server_recipient_add_hook((_rcpt), (_type) + \ + CALLBACK_TYPECHECK(_func, void (*)( \ + struct smtp_server_recipient *, typeof(_context))), \ + (smtp_server_rcpt_func_t *)(_func), (_context)) +void smtp_server_recipient_remove_hook( + struct smtp_server_recipient *rcpt, + enum smtp_server_recipient_hook_type type, + smtp_server_rcpt_func_t *func); +#define smtp_server_recipient_remove_hook(_rcpt, _type, _func) \ + smtp_server_recipient_remove_hook((_rcpt), (_type), \ + (smtp_server_rcpt_func_t *)(_func)); + /* * Transaction */