summaryrefslogtreecommitdiffstats
path: root/src/imap-hibernate/imap-master-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/imap-hibernate/imap-master-connection.c')
-rw-r--r--src/imap-hibernate/imap-master-connection.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/imap-hibernate/imap-master-connection.c b/src/imap-hibernate/imap-master-connection.c
new file mode 100644
index 0000000..71fa4dd
--- /dev/null
+++ b/src/imap-hibernate/imap-master-connection.c
@@ -0,0 +1,140 @@
+/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "connection.h"
+#include "imap-master-connection.h"
+
+#define IMAP_MASTER_CONNECTION_TIMEOUT_MSECS 30000
+
+struct imap_master_connection {
+ struct connection conn;
+ struct timeout *to;
+
+ imap_master_connection_send_callback_t *send_callback;
+ imap_master_connection_read_callback_t *read_callback;
+ void *context;
+};
+
+static struct connection_list *master_clients;
+
+static void imap_master_connection_timeout(struct imap_master_connection *conn)
+{
+ e_error(conn->conn.event,
+ "Timeout communicating with %s (version %sreceived)",
+ conn->conn.name, conn->conn.version_received ? "" : "not ");
+ imap_master_connection_deinit(&conn);
+}
+
+int imap_master_connection_init(const char *path,
+ imap_master_connection_send_callback_t *send_callback,
+ imap_master_connection_read_callback_t *read_callback,
+ void *context,
+ struct imap_master_connection **conn_r,
+ const char **error_r)
+{
+ struct imap_master_connection *conn;
+
+ conn = i_new(struct imap_master_connection, 1);
+ conn->send_callback = send_callback;
+ conn->read_callback = read_callback;
+ conn->context = context;
+ connection_init_client_unix(master_clients, &conn->conn, path);
+ if (connection_client_connect(&conn->conn) < 0) {
+ int ret = errno == EAGAIN ? 0 : -1;
+
+ *error_r = t_strdup_printf(
+ "net_connect_unix(%s) failed: %m", path);
+ connection_deinit(&conn->conn);
+ i_free(conn);
+ return ret;
+ }
+ conn->to = timeout_add(IMAP_MASTER_CONNECTION_TIMEOUT_MSECS,
+ imap_master_connection_timeout, conn);
+ *conn_r = conn;
+ return 1;
+}
+
+static void
+imap_master_read_callback(struct imap_master_connection **_conn,
+ const char *line)
+{
+ struct imap_master_connection *conn = *_conn;
+ imap_master_connection_read_callback_t *read_callback =
+ conn->read_callback;
+
+ *_conn = NULL;
+ conn->read_callback = NULL;
+ read_callback(conn->context, line);
+ /* connection is destroyed now */
+}
+
+void imap_master_connection_deinit(struct imap_master_connection **_conn)
+{
+ imap_master_read_callback(_conn, t_strdup_printf(
+ "-%s", connection_disconnect_reason(&(*_conn)->conn)));
+}
+
+void imap_master_connection_free(struct imap_master_connection **_conn)
+{
+ struct imap_master_connection *conn = *_conn;
+
+ *_conn = NULL;
+
+ timeout_remove(&conn->to);
+ connection_deinit(&conn->conn);
+ i_free(conn);
+}
+
+static void imap_master_client_destroy(struct connection *_conn)
+{
+ struct imap_master_connection *conn =
+ (struct imap_master_connection *)_conn;
+
+ imap_master_connection_deinit(&conn);
+}
+
+static int
+imap_master_client_input_line(struct connection *_conn, const char *line)
+{
+ struct imap_master_connection *conn =
+ (struct imap_master_connection *)_conn;
+
+ if (!_conn->version_received) {
+ if (connection_input_line_default(_conn, line) < 0)
+ return -1;
+
+ conn->send_callback(conn->context, _conn->output);
+ return 1;
+ } else {
+ imap_master_read_callback(&conn, line);
+ /* we're finished now with this connection - disconnect it */
+ return -1;
+ }
+}
+
+static struct connection_settings client_set = {
+ .service_name_in = "imap-master",
+ .service_name_out = "imap-master",
+ .major_version = 1,
+ .minor_version = 0,
+
+ .input_max_size = SIZE_MAX,
+ .output_max_size = SIZE_MAX,
+ .client = TRUE
+};
+
+static const struct connection_vfuncs client_vfuncs = {
+ .destroy = imap_master_client_destroy,
+ .input_line = imap_master_client_input_line
+};
+
+void imap_master_connections_init(void)
+{
+ master_clients = connection_list_init(&client_set, &client_vfuncs);
+}
+
+void imap_master_connections_deinit(void)
+{
+ connection_list_deinit(&master_clients);
+}