doveadm-mail-server.c revision db4cad7df8f3a1a584b1f72a06995b188871dc5a
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
65cca8364f483126b396aeb2036dc879ad45ab8dTimo Sirainen#include "hash.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "str.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "strescape.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "ioloop.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "master-service.h"
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#include "auth-master.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include "mail-storage.h"
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen#include "mail-storage-service.h"
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#include "server-connection.h"
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen#include "doveadm-settings.h"
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen#include "doveadm-print.h"
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen#include "doveadm-server.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "doveadm-mail.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#define DOVEADM_SERVER_CONNECTIONS_MAX 4
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen#define DOVEADM_SERVER_QUEUE_MAX 16
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define DOVEADM_MAIL_SERVER_FAILED() \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (internal_failure || master_service_is_killed(master_service))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic struct hash_table *servers;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainenstatic pool_t server_pool;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_ctx;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainenstatic bool internal_failure = FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *username);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic struct doveadm_server *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainendoveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct doveadm_server *server;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen char *dup_name;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen if (servers == NULL) {
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen server_pool = pool_alloconly_create("doveadm servers", 1024*16);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen servers = hash_table_create(default_pool, server_pool, 0,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen str_hash,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen (hash_cmp_callback_t *)strcmp);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen server = hash_table_lookup(servers, name);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (server == NULL) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen server = p_new(server_pool, struct doveadm_server, 1);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen server->name = dup_name = p_strdup(server_pool, name);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen p_array_init(&server->connections, server_pool,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen ctx->set->doveadm_worker_count);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen p_array_init(&server->queue, server_pool,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen DOVEADM_SERVER_QUEUE_MAX);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen hash_table_insert(servers, dup_name, server);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return server;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic struct server_connection *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainendoveadm_server_find_unused_conn(struct doveadm_server *server)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct server_connection *const *connp;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_foreach(&server->connections, connp) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (server_connection_is_idle(*connp))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return *connp;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic bool doveadm_server_have_used_connections(struct doveadm_server *server)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct server_connection *const *connp;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_foreach(&server->connections, connp) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!server_connection_is_idle(*connp))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void doveadm_cmd_callback(enum server_cmd_reply reply, void *context)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct server_connection *conn = context;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct doveadm_server *server;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (reply == SERVER_CMD_REPLY_INTERNAL_FAILURE) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen internal_failure = TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen master_service_stop(master_service);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (reply != SERVER_CMD_REPLY_OK)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen cmd_ctx->failed = TRUE;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen server = server_connection_get_server(conn);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (array_count(&server->queue) > 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen char *const *usernamep = array_idx(&server->queue, 0);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen char *username = *usernamep;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen conn = doveadm_server_find_unused_conn(server);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (conn != NULL) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen array_delete(&server->queue, 0, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen doveadm_mail_server_handle(conn, username);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_free(username);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen master_service_stop(master_service);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen const char *username)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen string_t *cmd;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int i;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* <flags> <username> <command> [<args>] */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen cmd = t_str_new(256);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (doveadm_debug)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen str_append_c(cmd, 'D');
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen else if (doveadm_verbose)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen str_append_c(cmd, 'v');
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen str_append_c(cmd, '\t');
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen str_tabescape_write(cmd, username);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen str_append_c(cmd, '\t');
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen str_tabescape_write(cmd, cmd_ctx->cmd->name);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen for (i = 0; cmd_ctx->args[i] != NULL; i++) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen str_append_c(cmd, '\t');
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen str_tabescape_write(cmd, cmd_ctx->args[i]);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen str_append_c(cmd, '\n');
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen server_connection_cmd(conn, str_c(cmd), doveadm_cmd_callback, conn);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstatic void doveadm_server_flush_one(struct doveadm_server *server)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int count = array_count(&server->queue);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen do {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen master_service_run(master_service, NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } while (array_count(&server->queue) == count &&
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen doveadm_server_have_used_connections(server) &&
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen !DOVEADM_MAIL_SERVER_FAILED());
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen}
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainenstatic int
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainendoveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct mail_storage_service_input *input,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen const char **host_r, const char **error_r)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen{
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen struct auth_master_connection *auth_conn;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen struct auth_user_info info;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen pool_t pool;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const char *proxy_host, *const *fields;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen unsigned int i;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen bool proxying;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen int ret;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen *host_r = ctx->set->doveadm_socket_path;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ctx->set->doveadm_proxy_port == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* make sure we have an auth connection */
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen mail_storage_service_init_settings(ctx->storage_service, input);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen memset(&info, 0, sizeof(info));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen info.service = master_service_get_name(master_service);
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen pool = pool_alloconly_create("auth lookup", 1024);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen auth_conn = mail_storage_service_get_auth_conn(ctx->storage_service);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen ret = auth_master_pass_lookup(auth_conn, input->username, &info,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen pool, &fields);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen if (ret < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *error_r = fields[0] != NULL ?
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen t_strdup(fields[0]) : "passdb lookup failed";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else if (ret == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* user not found from passdb. it could be in userdb though,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen so just continue with the default host */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen proxy_host = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (i = 0; fields[i] != NULL; i++) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (strncmp(fields[i], "proxy", 5) == 0 &&
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen (fields[i][5] == '\0' || fields[i][5] == '='))
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen proxying = TRUE;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen else if (strncmp(fields[i], "host=", 5) == 0)
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen proxy_host = fields[i]+5;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (!proxying)
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen ret = 0;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen else if (proxy_host == NULL) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *error_r = "Proxy is missing destination host";
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen ret = -1;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk } else {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk *host_r = t_strdup_printf("%s:%u", proxy_host,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk ctx->set->doveadm_proxy_port);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen }
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk }
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk pool_unref(&pool);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk return ret;
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen}
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen const struct mail_storage_service_input *input,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen const char **error_r)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen{
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen struct doveadm_server *server;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct server_connection *conn;
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen const char *host;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen char *username_dup;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen int ret;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen i_assert(cmd_ctx == ctx || cmd_ctx == NULL);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen cmd_ctx = ctx;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen ret = doveadm_mail_server_user_get_host(ctx, input, &host, error_r);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (ret < 0)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (ret == 0 &&
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen (ctx->set->doveadm_worker_count == 0 || doveadm_server)) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* run it ourself */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return 0;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* server sends the sticky headers for each row as well,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen so undo any sticks we might have added already */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen doveadm_print_unstick_headers();
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen server = doveadm_server_get(ctx, host);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen conn = doveadm_server_find_unused_conn(server);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (conn != NULL)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen doveadm_mail_server_handle(conn, input->username);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen else if (array_count(&server->connections) <
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen I_MAX(ctx->set->doveadm_worker_count, 1)) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen conn = server_connection_create(server);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen doveadm_mail_server_handle(conn, input->username);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen } else {
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (array_count(&server->queue) >= DOVEADM_SERVER_QUEUE_MAX)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen doveadm_server_flush_one(server);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen username_dup = i_strdup(input->username);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen array_append(&server->queue, &username_dup, 1);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *error_r = "doveadm server failure";
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return DOVEADM_MAIL_SERVER_FAILED() ? -1 : 1;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic struct doveadm_server *doveadm_server_find_used(void)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen struct hash_iterate_context *iter;
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen struct doveadm_server *ret = NULL;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen void *key, *value;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen iter = hash_table_iterate_init(servers);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen while (hash_table_iterate(iter, &key, &value)) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen struct doveadm_server *server = value;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (doveadm_server_have_used_connections(server)) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen ret = server;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen break;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen hash_table_iterate_deinit(&iter);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return ret;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenstatic void doveadm_servers_destroy_all_connections(void)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct hash_iterate_context *iter;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen void *key, *value;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen iter = hash_table_iterate_init(servers);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen while (hash_table_iterate(iter, &key, &value)) {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct doveadm_server *server = value;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while (array_count(&server->connections) > 0) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct server_connection *const *connp, *conn;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen connp = array_idx(&server->connections, 0);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen conn = *connp;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen server_connection_destroy(&conn);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen hash_table_iterate_deinit(&iter);
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen}
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainenvoid doveadm_mail_server_flush(void)
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen{
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen struct doveadm_server *server;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (servers == NULL) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen cmd_ctx = NULL;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen while ((server = doveadm_server_find_used()) != NULL &&
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen !DOVEADM_MAIL_SERVER_FAILED())
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen doveadm_server_flush_one(server);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen doveadm_servers_destroy_all_connections();
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (master_service_is_killed(master_service))
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_error("Aborted");
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (DOVEADM_MAIL_SERVER_FAILED())
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen cmd_ctx->failed = TRUE;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen hash_table_destroy(&servers);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen pool_unref(&server_pool);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen cmd_ctx = NULL;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen