bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "lib.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "ioloop.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "connection.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "imap-master-connection.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
4b9355028a364c6e901ce2d8a7d91180d3e55399Timo Sirainen#define IMAP_MASTER_CONNECTION_TIMEOUT_MSECS 30000
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstruct imap_master_connection {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct connection conn;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct timeout *to;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_send_callback_t *send_callback;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_read_callback_t *read_callback;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen void *context;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen};
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic struct connection_list *master_clients;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void imap_master_connection_timeout(struct imap_master_connection *conn)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
c7a9a1fdd4373558aed893635b7493f6acbb60a9Timo Sirainen i_error("Timeout communicating with %s (version %sreceived)",
c7a9a1fdd4373558aed893635b7493f6acbb60a9Timo Sirainen conn->conn.name, conn->conn.version_received ? "" : "not ");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_deinit(&conn);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenint imap_master_connection_init(const char *path,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_send_callback_t *send_callback,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_read_callback_t *read_callback,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen void *context,
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen struct imap_master_connection **conn_r,
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen const char **error_r)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct imap_master_connection *conn;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn = i_new(struct imap_master_connection, 1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->send_callback = send_callback;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->read_callback = read_callback;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->context = context;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen connection_init_client_unix(master_clients, &conn->conn, path);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (connection_client_connect(&conn->conn) < 0) {
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen int ret = errno == EAGAIN ? 0 : -1;
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen *error_r = t_strdup_printf(
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen "net_connect_unix(%s) failed: %m", path);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen connection_deinit(&conn->conn);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_free(conn);
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen return ret;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->to = timeout_add(IMAP_MASTER_CONNECTION_TIMEOUT_MSECS,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_timeout, conn);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen *conn_r = conn;
17062405030a3fa095e43d5b8b71afc5536f0a22Timo Sirainen return 1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid imap_master_connection_deinit(struct imap_master_connection **_conn)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct imap_master_connection *conn = *_conn;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen *_conn = NULL;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (conn->read_callback != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->read_callback(conn->context, "-");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timeout_remove(&conn->to);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen connection_deinit(&conn->conn);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_free(conn);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void imap_master_client_destroy(struct connection *_conn)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct imap_master_connection *conn =
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen (struct imap_master_connection *)_conn;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_deinit(&conn);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic int
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenimap_master_client_input_line(struct connection *_conn, const char *line)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct imap_master_connection *conn =
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen (struct imap_master_connection *)_conn;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!_conn->version_received) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (connection_input_line_default(_conn, line) < 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->send_callback(conn->context, _conn->output);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return 1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_master_connection_read_callback_t *read_callback =
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->read_callback;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen conn->read_callback = NULL;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen read_callback(conn->context, line);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* we're finished now with this connection - disconnect it */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic struct connection_settings client_set = {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .service_name_in = "imap-master",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .service_name_out = "imap-master",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .major_version = 1,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .minor_version = 0,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .input_max_size = (size_t)-1,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .output_max_size = (size_t)-1,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .client = TRUE
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen};
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic const struct connection_vfuncs client_vfuncs = {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .destroy = imap_master_client_destroy,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen .input_line = imap_master_client_input_line
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen};
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid imap_master_connections_init(void)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen master_clients = connection_list_init(&client_set, &client_vfuncs);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid imap_master_connections_deinit(void)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen connection_list_deinit(&master_clients);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}