doveadm-mail-server.c revision 06c303e21a11e11209f40a2658f2864819d59f70
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "array.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "hash.h"
3343a61404603b21c246783a7963b77833095f31Timo Sirainen#include "str.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "strescape.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ioloop.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "master-service.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "auth-master.h"
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen#include "mail-storage.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mail-storage-service.h"
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainen#include "server-connection.h"
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include "doveadm-settings.h"
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen#include "doveadm-print.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "doveadm-server.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "doveadm-mail.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define DOVEADM_SERVER_CONNECTIONS_MAX 4
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen#define DOVEADM_SERVER_QUEUE_MAX 16
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen#define DOVEADM_MAIL_SERVER_FAILED() \
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen (internal_failure || master_service_is_killed(master_service))
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainenstruct doveadm_mail_server_cmd {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen struct server_connection *conn;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen char *username;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen};
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainenstatic HASH_TABLE(char *, struct doveadm_server *) servers;
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainenstatic pool_t server_pool;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainenstatic struct doveadm_mail_cmd_context *cmd_ctx;
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainenstatic bool internal_failure = FALSE;
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen const char *username);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic struct doveadm_server *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainendoveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct doveadm_server *server;
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen char *dup_name;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (!hash_table_is_created(servers)) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen server_pool = pool_alloconly_create("doveadm servers", 1024*16);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen hash_table_create(&servers, server_pool, 0, str_hash, strcmp);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen server = hash_table_lookup(servers, name);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (server == NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen server = p_new(server_pool, struct doveadm_server, 1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen server->name = dup_name = p_strdup(server_pool, name);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen p_array_init(&server->connections, server_pool,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ctx->set->doveadm_worker_count);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen p_array_init(&server->queue, server_pool,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen DOVEADM_SERVER_QUEUE_MAX);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen hash_table_insert(servers, dup_name, server);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return server;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen}
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic struct server_connection *
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainendoveadm_server_find_unused_conn(struct doveadm_server *server)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct server_connection *const *connp;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen array_foreach(&server->connections, connp) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (server_connection_is_idle(*connp))
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return *connp;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen return NULL;
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen}
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainenstatic bool doveadm_server_have_used_connections(struct doveadm_server *server)
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen{
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen struct server_connection *const *connp;
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen array_foreach(&server->connections, connp) {
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen if (!server_connection_is_idle(*connp))
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen return TRUE;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen }
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen return FALSE;
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen}
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvistatic void doveadm_cmd_callback(int exit_code, const char *error,
d42eb03b3a4e79a2da22a1be2de59b95660af2beTimo Sirainen void *context)
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen{
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen struct doveadm_mail_server_cmd *servercmd = context;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen struct doveadm_server *server =
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen server_connection_get_server(servercmd->conn);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *username = t_strdup(servercmd->username);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen i_free(servercmd->username);
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen i_free(servercmd);
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen switch (exit_code) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen case 0:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen case SERVER_EXIT_CODE_DISCONNECTED:
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen i_error("%s: Command %s failed for %s: %s",
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen server->name, cmd_ctx->cmd->name, username, error);
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen internal_failure = TRUE;
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen master_service_stop(master_service);
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen return;
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen case EX_NOUSER:
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen i_error("%s: No such user: %s", server->name, username);
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen if (cmd_ctx->exit_code == 0)
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen cmd_ctx->exit_code = EX_NOUSER;
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen break;
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen default:
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen if (cmd_ctx->exit_code == 0 || exit_code == EX_TEMPFAIL)
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen cmd_ctx->exit_code = exit_code;
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen break;
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen }
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen if (array_count(&server->queue) > 0) {
3d4c24127f4f83259c0f81851184abc34793dbe0Timo Sirainen struct server_connection *conn;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen char *const *usernamep = array_idx(&server->queue, 0);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen char *username = *usernamep;
3d4c24127f4f83259c0f81851184abc34793dbe0Timo Sirainen
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen conn = doveadm_server_find_unused_conn(server);
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen if (conn != NULL) {
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen array_delete(&server->queue, 0, 1);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen doveadm_mail_server_handle(conn, username);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_free(username);
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen }
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen }
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen master_service_stop(master_service);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen}
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic void doveadm_mail_server_handle(struct server_connection *conn,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen const char *username)
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen{
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen struct doveadm_mail_server_cmd *servercmd;
424236b2b88a5a7bbde5cf6a6b32189ca3437629Timo Sirainen string_t *cmd;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen unsigned int i;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen /* <flags> <username> <command> [<args>] */
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen cmd = t_str_new(256);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (doveadm_debug)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen str_append_c(cmd, 'D');
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen else if (doveadm_verbose)
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen str_append_c(cmd, 'v');
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen str_append_c(cmd, '\t');
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen str_append_tabescaped(cmd, username);
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen str_append_c(cmd, '\t');
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->cmd->name);
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen for (i = 0; cmd_ctx->full_args[i] != NULL; i++) {
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen str_append_c(cmd, '\t');
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen str_append_tabescaped(cmd, cmd_ctx->full_args[i]);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen str_append_c(cmd, '\n');
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen servercmd = i_new(struct doveadm_mail_server_cmd, 1);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen servercmd->conn = conn;
761c441db58493fcf10d3418b0cabadc3028cfb6Timo Sirainen servercmd->username = i_strdup(username);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen server_connection_cmd(conn, str_c(cmd),
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen doveadm_cmd_callback, servercmd);
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen}
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen
1b5366b2234892f8930a29351da06b193e385150Timo Sirainenstatic void doveadm_server_flush_one(struct doveadm_server *server)
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen{
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen unsigned int count = array_count(&server->queue);
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen do {
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen io_loop_run(current_ioloop);
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen } while (array_count(&server->queue) == count &&
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen doveadm_server_have_used_connections(server) &&
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen !DOVEADM_MAIL_SERVER_FAILED());
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen}
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen
1b5366b2234892f8930a29351da06b193e385150Timo Sirainenstatic int
1b5366b2234892f8930a29351da06b193e385150Timo Sirainendoveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx,
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen const struct mail_storage_service_input *input,
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen const char **host_r, const char **error_r)
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen{
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen struct auth_master_connection *auth_conn;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct auth_user_info info;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen pool_t pool;
e5afebd2df1d4990f7bec2a839260ff2e6d78168Timo Sirainen const char *auth_socket_path, *proxy_host, *const *fields;
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen unsigned int i;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen bool proxying;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen int ret;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen *host_r = ctx->set->doveadm_socket_path;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if (ctx->set->doveadm_port == 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen /* make sure we have an auth connection */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_storage_service_init_settings(ctx->storage_service, input);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
761c441db58493fcf10d3418b0cabadc3028cfb6Timo Sirainen memset(&info, 0, sizeof(info));
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen info.service = master_service_get_name(master_service);
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen info.local_ip = input->local_ip;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen info.remote_ip = input->remote_ip;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen info.local_port = input->local_port;
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen info.remote_port = input->remote_port;
3343a61404603b21c246783a7963b77833095f31Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen pool = pool_alloconly_create("auth lookup", 1024);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen auth_conn = mail_storage_service_get_auth_conn(ctx->storage_service);
3343a61404603b21c246783a7963b77833095f31Timo Sirainen auth_socket_path = auth_master_get_socket_path(auth_conn);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ret = auth_master_pass_lookup(auth_conn, input->username, &info,
3343a61404603b21c246783a7963b77833095f31Timo Sirainen pool, &fields);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (ret < 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen *error_r = fields[0] != NULL ?
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen t_strdup(fields[0]) : "passdb lookup failed";
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen *error_r = t_strdup_printf("%s: %s (to see if user is proxied, "
"because doveadm_port is set)",
auth_socket_path, *error_r);
} else if (ret == 0) {
/* user not found from passdb. it could be in userdb though,
so just continue with the default host */
} else {
proxy_host = NULL; proxying = FALSE;
for (i = 0; fields[i] != NULL; i++) {
if (strncmp(fields[i], "proxy", 5) == 0 &&
(fields[i][5] == '\0' || fields[i][5] == '='))
proxying = TRUE;
else if (strncmp(fields[i], "host=", 5) == 0)
proxy_host = fields[i]+5;
}
if (!proxying)
ret = 0;
else if (proxy_host == NULL) {
*error_r = t_strdup_printf("%s: Proxy is missing destination host",
auth_socket_path);
if (strstr(auth_socket_path, "/auth-userdb") != NULL) {
*error_r = t_strdup_printf(
"%s (maybe set auth_socket_path=director-userdb)",
*error_r);
}
ret = -1;
} else {
*host_r = t_strdup_printf("%s:%u", proxy_host,
ctx->set->doveadm_port);
}
}
pool_unref(&pool);
return ret;
}
int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx,
const struct mail_storage_service_input *input,
const char **error_r)
{
struct doveadm_server *server;
struct server_connection *conn;
const char *host;
char *username_dup;
int ret;
i_assert(cmd_ctx == ctx || cmd_ctx == NULL);
cmd_ctx = ctx;
ret = doveadm_mail_server_user_get_host(ctx, input, &host, error_r);
if (ret < 0)
return -1;
if (ret == 0 &&
(ctx->set->doveadm_worker_count == 0 || doveadm_server)) {
/* run it ourself */
return 0;
}
/* server sends the sticky headers for each row as well,
so undo any sticks we might have added already */
doveadm_print_unstick_headers();
server = doveadm_server_get(ctx, host);
conn = doveadm_server_find_unused_conn(server);
if (conn != NULL)
doveadm_mail_server_handle(conn, input->username);
else if (array_count(&server->connections) <
I_MAX(ctx->set->doveadm_worker_count, 1)) {
if (server_connection_create(server, &conn) < 0)
internal_failure = TRUE;
else
doveadm_mail_server_handle(conn, input->username);
} else {
if (array_count(&server->queue) >= DOVEADM_SERVER_QUEUE_MAX)
doveadm_server_flush_one(server);
username_dup = i_strdup(input->username);
array_append(&server->queue, &username_dup, 1);
}
*error_r = "doveadm server failure";
return DOVEADM_MAIL_SERVER_FAILED() ? -1 : 1;
}
static struct doveadm_server *doveadm_server_find_used(void)
{
struct hash_iterate_context *iter;
struct doveadm_server *ret = NULL;
char *key;
struct doveadm_server *server;
iter = hash_table_iterate_init(servers);
while (hash_table_iterate(iter, servers, &key, &server)) {
if (doveadm_server_have_used_connections(server)) {
ret = server;
break;
}
}
hash_table_iterate_deinit(&iter);
return ret;
}
static void doveadm_servers_destroy_all_connections(void)
{
struct hash_iterate_context *iter;
char *key;
struct doveadm_server *server;
iter = hash_table_iterate_init(servers);
while (hash_table_iterate(iter, servers, &key, &server)) {
while (array_count(&server->connections) > 0) {
struct server_connection *const *connp, *conn;
connp = array_idx(&server->connections, 0);
conn = *connp;
server_connection_destroy(&conn);
}
}
hash_table_iterate_deinit(&iter);
}
void doveadm_mail_server_flush(void)
{
struct doveadm_server *server;
if (!hash_table_is_created(servers)) {
cmd_ctx = NULL;
return;
}
while ((server = doveadm_server_find_used()) != NULL &&
!DOVEADM_MAIL_SERVER_FAILED())
doveadm_server_flush_one(server);
doveadm_servers_destroy_all_connections();
if (master_service_is_killed(master_service))
i_error("Aborted");
if (DOVEADM_MAIL_SERVER_FAILED())
doveadm_mail_failed_error(cmd_ctx, MAIL_ERROR_TEMP);
hash_table_destroy(&servers);
pool_unref(&server_pool);
cmd_ctx = NULL;
}