From: Timo Sirainen Date: Sun, 10 Oct 2021 00:23:13 +0000 (+0300) Subject: lib-master, ipc: Remove all code related to ipc process X-Git-Tag: 2.4.0~4477 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7e1c590d4efbacc339e399b623f4e6bf17b77ad7;p=thirdparty%2Fdovecot%2Fcore.git lib-master, ipc: Remove all code related to ipc process --- diff --git a/configure.ac b/configure.ac index a92d402784..b3616d49bf 100644 --- a/configure.ac +++ b/configure.ac @@ -888,7 +888,6 @@ src/dict/Makefile src/director/Makefile src/dns/Makefile src/indexer/Makefile -src/ipc/Makefile src/imap/Makefile src/imap-hibernate/Makefile src/imap-login/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index e8fa97059d..d8954ff22d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,7 +50,6 @@ SUBDIRS = \ dict \ dns \ indexer \ - ipc \ master \ login-common \ imap-hibernate \ diff --git a/src/ipc/Makefile.am b/src/ipc/Makefile.am deleted file mode 100644 index a12609e468..0000000000 --- a/src/ipc/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -pkglibexecdir = $(libexecdir)/dovecot - -pkglibexec_PROGRAMS = ipc - -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-settings \ - -I$(top_srcdir)/src/lib-master \ - $(BINARY_CFLAGS) - -ipc_LDADD = $(LIBDOVECOT) \ - $(BINARY_LDFLAGS) -ipc_DEPENDENCIES = $(LIBDOVECOT_DEPS) - -ipc_SOURCES = \ - client.c \ - main.c \ - ipc-connection.c \ - ipc-group.c \ - ipc-settings.c - -noinst_HEADERS = \ - client.h \ - ipc-connection.h \ - ipc-group.h diff --git a/src/ipc/client.c b/src/ipc/client.c deleted file mode 100644 index 483452e387..0000000000 --- a/src/ipc/client.c +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "llist.h" -#include "ioloop.h" -#include "istream.h" -#include "ostream.h" -#include "master-service.h" -#include "ipc-group.h" -#include "ipc-connection.h" -#include "client.h" - -#include - -struct client { - struct client *prev, *next; - - int fd; - struct io *io; - struct istream *input; - struct ostream *output; -}; - -static struct client *clients; - -static void client_input(struct client *client); - -static void -client_cmd_input(enum ipc_cmd_status status, const char *line, void *context) -{ - struct client *client = context; - char chr = '\0'; - - switch (status) { - case IPC_CMD_STATUS_REPLY: - chr = ':'; - break; - case IPC_CMD_STATUS_OK: - chr = '+'; - break; - case IPC_CMD_STATUS_ERROR: - chr = '-'; - break; - } - - T_BEGIN { - o_stream_nsend_str(client->output, - t_strdup_printf("%c%s\n", chr, line)); - } T_END; - - if (status != IPC_CMD_STATUS_REPLY && client->io == NULL) { - client->io = io_add(client->fd, IO_READ, client_input, client); - client_input(client); - } -} - -static void client_input(struct client *client) -{ - struct ipc_group *group; - struct ipc_connection *conn; - char *line, *id, *data; - unsigned int id_num; - bool ret; - - while ((line = i_stream_read_next_line(client->input)) != NULL) { - /* *| */ - id = strchr(line, '\t'); - if (id == NULL) - data = NULL; - else { - *id++ = '\0'; - data = strchr(id, '\t'); - } - if (data == NULL || data[1] == '\0') { - o_stream_nsend_str(client->output, "-Invalid input\n"); - continue; - } - *data++ = '\0'; - - group = ipc_group_lookup_name(line); - - ret = FALSE; - if (strcmp(id, "*") == 0) { - /* send to everyone */ - if (group == NULL) { - client_cmd_input(IPC_CMD_STATUS_OK, "", client); - } else { - ret = ipc_group_cmd(group, data, - client_cmd_input, client); - } - } else if (str_to_uint(id, &id_num) < 0) { - o_stream_nsend_str(client->output, - t_strdup_printf("-Invalid IPC connection id: %s\n", id)); - continue; - } else if (group == NULL) { - o_stream_nsend_str(client->output, - t_strdup_printf("-Unknown IPC group: %s\n", line)); - } else if ((conn = ipc_connection_lookup_id(group, id_num)) == NULL) { - o_stream_nsend_str(client->output, - t_strdup_printf("-Unknown IPC connection id: %u\n", id_num)); - continue; - } else { - ipc_connection_cmd(conn, data, client_cmd_input, client); - ret = TRUE; - } - - if (ret) { - /* we'll handle commands one at a time. stop reading - input until this command is finished. */ - io_remove(&client->io); - break; - } - } - if (client->input->eof || client->input->stream_errno != 0) - client_destroy(&client); -} - -struct client *client_create(int fd) -{ - struct client *client; - - client = i_new(struct client, 1); - client->fd = fd; - client->io = io_add(fd, IO_READ, client_input, client); - client->input = i_stream_create_fd(fd, SIZE_MAX); - client->output = o_stream_create_fd(fd, SIZE_MAX); - o_stream_set_no_error_handling(client->output, TRUE); - - DLLIST_PREPEND(&clients, client); - return client; -} - -void client_destroy(struct client **_client) -{ - struct client *client = *_client; - - *_client = NULL; - - DLLIST_REMOVE(&clients, client); - io_remove(&client->io); - i_stream_destroy(&client->input); - o_stream_destroy(&client->output); - if (close(client->fd) < 0) - i_error("close(client) failed: %m"); - i_free(client); - - master_service_client_connection_destroyed(master_service); -} - -void clients_destroy_all(void) -{ - while (clients != NULL) { - struct client *client = clients; - - client_destroy(&client); - } -} diff --git a/src/ipc/client.h b/src/ipc/client.h deleted file mode 100644 index a5936a69e1..0000000000 --- a/src/ipc/client.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CLIENT_H -#define CLIENT_H - -struct client *client_create(int fd); -void client_destroy(struct client **client); - -void clients_destroy_all(void); - -#endif diff --git a/src/ipc/ipc-connection.c b/src/ipc/ipc-connection.c deleted file mode 100644 index 763752ac63..0000000000 --- a/src/ipc/ipc-connection.c +++ /dev/null @@ -1,253 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "ioloop.h" -#include "istream.h" -#include "ostream.h" -#include "llist.h" -#include "strescape.h" -#include "master-service.h" -#include "ipc-group.h" -#include "ipc-connection.h" - -#include - -#define IPC_SERVER_PROTOCOL_MAJOR_VERSION 1 -#define IPC_SERVER_PROTOCOL_MINOR_VERSION 0 - -#define IPC_SERVER_HANDSHAKE "VERSION\tipc-proxy\t1\t0\n" - -static unsigned int connection_id_counter; - -static void ipc_connection_cmd_free(struct ipc_connection_cmd **_cmd, - const char *reason) -{ - struct ipc_connection_cmd *cmd = *_cmd; - struct ipc_connection_cmd **cmds; - unsigned int i, count; - - *_cmd = NULL; - - cmds = array_get_modifiable(&cmd->conn->cmds, &count); - for (i = 0; i < count; i++) { - if (cmds[i] == cmd) { - array_delete(&cmd->conn->cmds, i, 1); - break; - } - } - if (cmd->callback != NULL) { - i_assert(reason != NULL); - cmd->callback(IPC_CMD_STATUS_ERROR, reason, cmd->context); - } - i_free(cmd); -} - -static struct ipc_connection_cmd * -ipc_connection_cmd_find(struct ipc_connection *conn, unsigned int tag) -{ - struct ipc_connection_cmd *cmd; - - array_foreach_elem(&conn->cmds, cmd) { - if (cmd->tag == tag) - return cmd; - } - return NULL; -} - -static int -ipc_connection_input_line(struct ipc_connection *conn, char *line) -{ - struct ipc_connection_cmd *cmd; - unsigned int tag; - enum ipc_cmd_status status; - char *data; - - /* [:+-] */ - data = strchr(line, '\t'); - if (data == NULL) - return -1; - - *data++ = '\0'; - if (str_to_uint(line, &tag) < 0) - return -1; - - switch (data[0]) { - case ':': - status = IPC_CMD_STATUS_REPLY; - break; - case '+': - status = IPC_CMD_STATUS_OK; - break; - case '-': - status = IPC_CMD_STATUS_ERROR; - break; - default: - return -1; - } - data++; - - cmd = ipc_connection_cmd_find(conn, tag); - if (cmd == NULL) { - i_error("IPC server: Input for unexpected command tag %u", tag); - return 0; - } - cmd->callback(status, data, cmd->context); - if (status != IPC_CMD_STATUS_REPLY) { - cmd->callback = NULL; - ipc_connection_cmd_free(&cmd, NULL); - } - return 0; -} - -static void ipc_connection_input(struct ipc_connection *conn) -{ - const char *const *args; - char *line; - int ret; - - if (i_stream_read(conn->input) < 0) { - ipc_connection_destroy(&conn, FALSE, - i_stream_get_disconnect_reason(conn->input)); - return; - } - - if (!conn->version_received) { - if ((line = i_stream_next_line(conn->input)) == NULL) - return; - - if (!version_string_verify(line, "ipc-server", - IPC_SERVER_PROTOCOL_MAJOR_VERSION)) { - ipc_connection_destroy(&conn, TRUE, - "IPC server not compatible with this server " - "(mixed old and new binaries?)"); - return; - } - conn->version_received = TRUE; - } - if (!conn->handshake_received) { - if ((line = i_stream_next_line(conn->input)) == NULL) - return; - - args = t_strsplit_tabescaped(line); - if (str_array_length(args) < 3 || - strcmp(args[0], "HANDSHAKE") != 0) { - ipc_connection_destroy(&conn, TRUE, - "IPC server sent invalid handshake"); - return; - } - if (ipc_group_update_name(conn->group, args[1]) < 0) { - ipc_connection_destroy(&conn, TRUE, t_strdup_printf( - "IPC server named itself unexpectedly: %s " - "(existing ones were %s)", - args[1], conn->group->name)); - return; - } - if (str_to_pid(args[2], &conn->pid) < 0) { - ipc_connection_destroy(&conn, TRUE, t_strdup_printf( - "IPC server gave broken PID: %s", args[2])); - return; - } - conn->handshake_received = TRUE; - } - - while ((line = i_stream_next_line(conn->input)) != NULL) { - T_BEGIN { - ret = ipc_connection_input_line(conn, line); - } T_END; - if (ret < 0) { - ipc_connection_destroy(&conn, TRUE, t_strdup_printf( - "Invalid input from IPC server '%s': %s", - conn->group->name, line)); - break; - } - } -} - -struct ipc_connection *ipc_connection_create(int listen_fd, int fd) -{ - struct ipc_connection *conn; - - conn = i_new(struct ipc_connection, 1); - conn->group = ipc_group_lookup_listen_fd(listen_fd); - if (conn->group == NULL) - conn->group = ipc_group_alloc(listen_fd); - conn->id = ++connection_id_counter; - if (conn->id == 0) - conn->id = ++connection_id_counter; - conn->fd = fd; - conn->io = io_add(fd, IO_READ, ipc_connection_input, conn); - conn->input = i_stream_create_fd(fd, SIZE_MAX); - conn->output = o_stream_create_fd(fd, SIZE_MAX); - o_stream_set_no_error_handling(conn->output, TRUE); - i_array_init(&conn->cmds, 8); - o_stream_nsend_str(conn->output, IPC_SERVER_HANDSHAKE); - - DLLIST_PREPEND(&conn->group->connections, conn); - return conn; -} - -void ipc_connection_destroy(struct ipc_connection **_conn, - bool log_error, const char *error) -{ - struct ipc_connection *conn = *_conn; - struct ipc_connection_cmd *const *cmdp, *cmd; - const char *group_name = conn->group->name != NULL ? - conn->group->name : - t_strdup_printf("#%d", conn->group->listen_fd); - - *_conn = NULL; - - error = t_strdup_printf("IPC: '%s' PID %d server connection: %s", - group_name, conn->pid, error); - if (log_error) - i_error("%s", error); - DLLIST_REMOVE(&conn->group->connections, conn); - - while (array_count(&conn->cmds) > 0) { - cmdp = array_front(&conn->cmds); - cmd = *cmdp; - - ipc_connection_cmd_free(&cmd, error); - } - array_free(&conn->cmds); - - io_remove(&conn->io); - i_stream_destroy(&conn->input); - o_stream_destroy(&conn->output); - if (close(conn->fd) < 0) - i_error("close(ipc connection) failed: %m"); - i_free(conn); - - master_service_client_connection_destroyed(master_service); -} - -struct ipc_connection * -ipc_connection_lookup_id(struct ipc_group *group, unsigned int id) -{ - struct ipc_connection *conn; - - for (conn = group->connections; conn != NULL; conn = conn->next) { - if (conn->id == id) - return conn; - } - return NULL; -} - -void ipc_connection_cmd(struct ipc_connection *conn, const char *cmd, - ipc_cmd_callback_t *callback, void *context) -{ - struct ipc_connection_cmd *ipc_cmd; - - ipc_cmd = i_new(struct ipc_connection_cmd, 1); - ipc_cmd->tag = ++conn->cmd_tag_counter; - ipc_cmd->conn = conn; - ipc_cmd->callback = callback; - ipc_cmd->context = context; - array_push_back(&conn->cmds, &ipc_cmd); - - T_BEGIN { - o_stream_nsend_str(conn->output, - t_strdup_printf("%u\t%s\n", ipc_cmd->tag, cmd)); - } T_END; -} diff --git a/src/ipc/ipc-connection.h b/src/ipc/ipc-connection.h deleted file mode 100644 index d848f81aff..0000000000 --- a/src/ipc/ipc-connection.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef IPC_CONNECTION_H -#define IPC_CONNECTION_H - -#include "ipc-group.h" - -struct ipc_connection_cmd { - unsigned int tag; - struct ipc_connection *conn; - - ipc_cmd_callback_t *callback; - void *context; -}; - -struct ipc_connection { - struct ipc_group *group; - /* prev/next within group */ - struct ipc_connection *prev, *next; - - unsigned int id; - pid_t pid; - - int fd; - struct io *io; - struct istream *input; - struct ostream *output; - - unsigned int cmd_tag_counter; - - /* running commands */ - ARRAY(struct ipc_connection_cmd *) cmds; - - bool version_received:1; - bool handshake_received:1; -}; - -struct ipc_connection *ipc_connection_create(int listen_fd, int fd); -void ipc_connection_destroy(struct ipc_connection **conn, - bool log_error, const char *error); - -struct ipc_connection * -ipc_connection_lookup_id(struct ipc_group *group, unsigned int id); - -void ipc_connection_cmd(struct ipc_connection *conn, const char *cmd, - ipc_cmd_callback_t *callback, void *context); - -#endif diff --git a/src/ipc/ipc-group.c b/src/ipc/ipc-group.c deleted file mode 100644 index 945141990a..0000000000 --- a/src/ipc/ipc-group.c +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "ipc-connection.h" -#include "ipc-group.h" - -struct ipc_group_cmd { - ipc_cmd_callback_t *callback; - void *context; - - int refcount; - char *first_error; -}; - -static ARRAY(struct ipc_group *) ipc_groups; - -struct ipc_group *ipc_group_alloc(int listen_fd) -{ - struct ipc_group *group; - - i_assert(ipc_group_lookup_listen_fd(listen_fd) == NULL); - - group = i_new(struct ipc_group, 1); - group->listen_fd = listen_fd; - array_push_back(&ipc_groups, &group); - return group; -} - -void ipc_group_free(struct ipc_group **_group) -{ - struct ipc_group *const *groups, *group = *_group; - unsigned int i, count; - - i_assert(group->connections == NULL); - - *_group = NULL; - groups = array_get(&ipc_groups, &count); - for (i = 0; i < count; i++) { - if (groups[i] == group) { - array_delete(&ipc_groups, i, 1); - break; - } - } - i_free(group->name); - i_free(group); -} - -struct ipc_group *ipc_group_lookup_listen_fd(int listen_fd) -{ - struct ipc_group *group; - - array_foreach_elem(&ipc_groups, group) { - if (group->listen_fd == listen_fd) - return group; - } - return NULL; -} - -struct ipc_group *ipc_group_lookup_name(const char *name) -{ - struct ipc_group *group; - - array_foreach_elem(&ipc_groups, group) { - if (group->name != NULL && - strcmp(group->name, name) == 0) - return group; - } - return NULL; -} - -int ipc_group_update_name(struct ipc_group *group, const char *name) -{ - if (group->name == NULL) - group->name = i_strdup(name); - else if (strcmp(group->name, name) != 0) - return -1; - return 0; -} - -static void ipc_group_cmd_callback(enum ipc_cmd_status status, - const char *line, void *context) -{ - struct ipc_group_cmd *group_cmd = context; - - i_assert(group_cmd->refcount > 0); - - switch (status) { - case IPC_CMD_STATUS_REPLY: - group_cmd->callback(IPC_CMD_STATUS_REPLY, line, - group_cmd->context); - break; - case IPC_CMD_STATUS_ERROR: - if (group_cmd->first_error == NULL) - group_cmd->first_error = i_strdup(line); - /* fall through */ - case IPC_CMD_STATUS_OK: - if (--group_cmd->refcount > 0) - break; - - if (group_cmd->first_error == NULL) { - group_cmd->callback(IPC_CMD_STATUS_OK, line, - group_cmd->context); - } else { - group_cmd->callback(IPC_CMD_STATUS_ERROR, - group_cmd->first_error, - group_cmd->context); - i_free(group_cmd->first_error); - } - i_free(group_cmd); - break; - } - -} - -bool ipc_group_cmd(struct ipc_group *group, const char *cmd, - ipc_cmd_callback_t *callback, void *context) -{ - struct ipc_connection *conn, *next; - struct ipc_group_cmd *group_cmd; - - if (group->connections == NULL) { - callback(IPC_CMD_STATUS_OK, NULL, context); - return FALSE; - } - - group_cmd = i_new(struct ipc_group_cmd, 1); - group_cmd->callback = callback; - group_cmd->context = context; - - for (conn = group->connections; conn != NULL; conn = next) { - next = conn->next; - - group_cmd->refcount++; - ipc_connection_cmd(conn, cmd, - ipc_group_cmd_callback, group_cmd); - } - return TRUE; -} - -void ipc_groups_init(void) -{ - i_array_init(&ipc_groups, 16); -} - -void ipc_groups_disconnect_all(void) -{ - struct ipc_group *const *groupp, *group; - - while (array_count(&ipc_groups) > 0) { - groupp = array_front(&ipc_groups); - group = *groupp; - - while ((*groupp)->connections != NULL) { - struct ipc_connection *conn = (*groupp)->connections; - ipc_connection_destroy(&conn, FALSE, "Shutting down"); - } - ipc_group_free(&group); - } -} - -void ipc_groups_deinit(void) -{ - ipc_groups_disconnect_all(); - array_free(&ipc_groups); -} diff --git a/src/ipc/ipc-group.h b/src/ipc/ipc-group.h deleted file mode 100644 index c993f5a8c4..0000000000 --- a/src/ipc/ipc-group.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef IPC_GROUP_H -#define IPC_GROUP_H - -enum ipc_cmd_status { - /* Command received a reply line */ - IPC_CMD_STATUS_REPLY, - /* Command finished successfully */ - IPC_CMD_STATUS_OK, - /* Command finished with errors */ - IPC_CMD_STATUS_ERROR -}; - -struct ipc_group { - int listen_fd; - char *name; - - /* connections list also acts as a refcount */ - struct ipc_connection *connections; -}; - -/* line is non-NULL only with IPC_CMD_STATUS_REPLY. - Each line begins with the connection ID and TAB. */ -typedef void ipc_cmd_callback_t(enum ipc_cmd_status status, - const char *line, void *context); - -struct ipc_group *ipc_group_alloc(int listen_fd); -void ipc_group_free(struct ipc_group **group); - -struct ipc_group *ipc_group_lookup_listen_fd(int listen_fd); -struct ipc_group *ipc_group_lookup_name(const char *name); - -/* Returns 0 if name is ok, -1 if name doesn't match the existing one. */ -int ipc_group_update_name(struct ipc_group *group, const char *name); - -/* Send a command to all connections in a group. All connections are expected - to answer something. If there are no connections, callback() is called - immediately and FALSE is returned. */ -bool ipc_group_cmd(struct ipc_group *group, const char *cmd, - ipc_cmd_callback_t *callback, void *context); - -void ipc_groups_init(void); -void ipc_groups_deinit(void); -void ipc_groups_disconnect_all(void); - -#endif diff --git a/src/ipc/ipc-settings.c b/src/ipc/ipc-settings.c deleted file mode 100644 index 664565c620..0000000000 --- a/src/ipc/ipc-settings.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "buffer.h" -#include "settings-parser.h" -#include "service-settings.h" - -#include - -/* */ -static struct file_listener_settings ipc_unix_listeners_array[] = { - { "ipc", 0600, "$default_internal_user", "" }, - { "login/ipc-proxy", 0600, "$default_login_user", "" } -}; -static struct file_listener_settings *ipc_unix_listeners[] = { - &ipc_unix_listeners_array[0], - &ipc_unix_listeners_array[1] -}; -static buffer_t ipc_unix_listeners_buf = { - { { ipc_unix_listeners, sizeof(ipc_unix_listeners) } } -}; -/* */ - -struct service_settings ipc_service_settings = { - .name = "ipc", - .protocol = "", - .type = "", - .executable = "ipc", - .user = "$default_internal_user", - .group = "", - .privileged_group = "", - .extra_groups = "", - .chroot = "empty", - - .drop_priv_before_exec = FALSE, - - .process_min_avail = 0, - .process_limit = 1, - .client_limit = 0, - .service_count = 0, - .idle_kill = 0, - .vsz_limit = UOFF_T_MAX, - - .unix_listeners = { { &ipc_unix_listeners_buf, - sizeof(ipc_unix_listeners[0]) } }, - .fifo_listeners = ARRAY_INIT, - .inet_listeners = ARRAY_INIT, - - .process_limit_1 = TRUE -}; diff --git a/src/ipc/main.c b/src/ipc/main.c deleted file mode 100644 index ebd4b228b0..0000000000 --- a/src/ipc/main.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "restrict-access.h" -#include "master-service.h" -#include "master-service-settings.h" -#include "ipc-group.h" -#include "ipc-connection.h" -#include "client.h" - -static bool ipc_socket_is_client(const char *name) -{ - size_t len; - - if (strcmp(name, "ipc") == 0) - return TRUE; - - len = strlen(name); - if (len > 7 && strcmp(name + len - 7, "-client") == 0) - return TRUE; - return FALSE; -} - -static void client_connected(struct master_service_connection *conn) -{ - master_service_client_connection_accept(conn); - - if (ipc_socket_is_client(conn->name)) - (void)client_create(conn->fd); - else - (void)ipc_connection_create(conn->listen_fd, conn->fd); -} - -static void ipc_die(void) -{ - clients_destroy_all(); - ipc_groups_disconnect_all(); -} - -int main(int argc, char *argv[]) -{ - const enum master_service_flags service_flags = - /* This process likely won't need to send any stats. It's also - problematic because it's chrooted to empty directory, so it - can't reconnect to stats if it gets disconnected. So at - least for now disable connecting to stats entirely. */ - MASTER_SERVICE_FLAG_DONT_SEND_STATS | - MASTER_SERVICE_FLAG_UPDATE_PROCTITLE; - const char *error; - - master_service = master_service_init("ipc", service_flags, - &argc, &argv, ""); - if (master_getopt(master_service) > 0) - return FATAL_DEFAULT; - if (master_service_settings_read_simple(master_service, - NULL, &error) < 0) - i_fatal("Error reading configuration: %s", error); - master_service_init_log(master_service); - master_service_set_die_with_master(master_service, TRUE); - master_service_set_die_callback(master_service, ipc_die); - - restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); - restrict_access_allow_coredumps(TRUE); - ipc_groups_init(); - master_service_init_finish(master_service); - - master_service_run(master_service, client_connected); - - clients_destroy_all(); - ipc_groups_deinit(); - master_service_deinit(&master_service); - return 0; -} diff --git a/src/lib-master/Makefile.am b/src/lib-master/Makefile.am index 8893d18ddf..d0c9554fc9 100644 --- a/src/lib-master/Makefile.am +++ b/src/lib-master/Makefile.am @@ -16,8 +16,6 @@ AM_CPPFLAGS = \ libmaster_la_SOURCES = \ anvil-client.c \ - ipc-client.c \ - ipc-server.c \ master-admin-client.c \ master-auth.c \ master-instance.c \ @@ -34,8 +32,6 @@ libmaster_la_SOURCES = \ headers = \ anvil-client.h \ - ipc-client.h \ - ipc-server.h \ master-admin-client.h \ master-auth.h \ master-instance.h \ diff --git a/src/lib-master/ipc-client.c b/src/lib-master/ipc-client.c deleted file mode 100644 index b734c1bbe4..0000000000 --- a/src/lib-master/ipc-client.c +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "net.h" -#include "llist.h" -#include "istream.h" -#include "ostream.h" -#include "hostpid.h" -#include "master-service.h" -#include "ipc-client.h" - -#include - -struct ipc_client_cmd { - struct ipc_client_cmd *prev, *next; - - ipc_client_callback_t *callback; - void *context; -}; - -struct ipc_client { - char *path; - ipc_client_callback_t *callback; - - int fd; - struct io *io; - struct timeout *to_failed; - struct istream *input; - struct ostream *output; - struct ipc_client_cmd *cmds_head, *cmds_tail; - unsigned int aborted_cmds_count; -}; - -static void ipc_client_disconnect(struct ipc_client *client); - -static void ipc_client_input_line(struct ipc_client *client, const char *line) -{ - struct ipc_client_cmd *cmd = client->cmds_head; - enum ipc_client_cmd_state state; - bool disconnect = FALSE; - - if (client->aborted_cmds_count > 0) { - /* the command was already aborted */ - cmd = NULL; - } else if (cmd == NULL) { - i_error("IPC proxy sent unexpected input: %s", line); - return; - } - - switch (*line++) { - case ':': - state = IPC_CLIENT_CMD_STATE_REPLY; - break; - case '+': - state = IPC_CLIENT_CMD_STATE_OK; - break; - case '-': - state = IPC_CLIENT_CMD_STATE_ERROR; - break; - default: - i_error("IPC proxy sent invalid input: %s", line); - line = "Invalid input"; - disconnect = TRUE; - state = IPC_CLIENT_CMD_STATE_ERROR; - break; - } - - if (state != IPC_CLIENT_CMD_STATE_REPLY) { - if (cmd != NULL) - DLLIST2_REMOVE(&client->cmds_head, - &client->cmds_tail, cmd); - else - client->aborted_cmds_count--; - } - if (cmd != NULL) - cmd->callback(state, line, cmd->context); - if (state != IPC_CLIENT_CMD_STATE_REPLY) - i_free(cmd); - if (disconnect) - ipc_client_disconnect(client); -} - -static void ipc_client_input(struct ipc_client *client) -{ - const char *line; - - if (i_stream_read(client->input) < 0) { - ipc_client_disconnect(client); - return; - } - while ((line = i_stream_next_line(client->input)) != NULL) T_BEGIN { - ipc_client_input_line(client, line); - } T_END; -} - -static int ipc_client_connect(struct ipc_client *client) -{ - if (client->fd != -1) - return 0; - - client->fd = net_connect_unix(client->path); - if (client->fd == -1) { - i_error("connect(%s) failed: %m", client->path); - return -1; - } - - client->io = io_add(client->fd, IO_READ, ipc_client_input, client); - client->input = i_stream_create_fd(client->fd, SIZE_MAX); - client->output = o_stream_create_fd(client->fd, SIZE_MAX); - o_stream_set_no_error_handling(client->output, TRUE); - return 0; -} - -static void ipc_client_abort_commands(struct ipc_client *client, - const char *reason) -{ - struct ipc_client_cmd *cmd, *next; - - cmd = client->cmds_head; - client->cmds_head = client->cmds_tail = NULL; - for (; cmd != NULL; cmd = next) { - cmd->callback(IPC_CLIENT_CMD_STATE_ERROR, reason, cmd->context); - next = cmd->next; - i_free(cmd); - } -} - -static void ipc_client_disconnect(struct ipc_client *client) -{ - timeout_remove(&client->to_failed); - ipc_client_abort_commands(client, "Disconnected"); - - if (client->fd == -1) - return; - - io_remove(&client->io); - i_stream_destroy(&client->input); - o_stream_destroy(&client->output); - if (close(client->fd) < 0) - i_error("close(%s) failed: %m", client->path); - client->fd = -1; -} - -struct ipc_client * -ipc_client_init(const char *ipc_socket_path) -{ - struct ipc_client *client; - - client = i_new(struct ipc_client, 1); - client->path = i_strdup(ipc_socket_path); - client->fd = -1; - return client; -} - -void ipc_client_deinit(struct ipc_client **_client) -{ - struct ipc_client *client = *_client; - - *_client = NULL; - - ipc_client_disconnect(client); - i_free(client->path); - i_free(client); -} - -static void ipc_client_cmd_connect_failed(struct ipc_client *client) -{ - ipc_client_abort_commands(client, "ipc connect failed"); - timeout_remove(&client->to_failed); -} - -struct ipc_client_cmd * -ipc_client_cmd(struct ipc_client *client, const char *cmd, - ipc_client_callback_t *callback, void *context) -{ - struct ipc_client_cmd *ipc_cmd; - struct const_iovec iov[2]; - - ipc_cmd = i_new(struct ipc_client_cmd, 1); - ipc_cmd->callback = callback; - ipc_cmd->context = context; - DLLIST2_APPEND(&client->cmds_head, &client->cmds_tail, ipc_cmd); - - if (client->to_failed != NULL || - ipc_client_connect(client) < 0) { - /* Delay calling the failure callback. Fail all commands until - the callback is called. */ - if (client->to_failed == NULL) { - client->to_failed = timeout_add_short(0, - ipc_client_cmd_connect_failed, client); - } - } else { - iov[0].iov_base = cmd; - iov[0].iov_len = strlen(cmd); - iov[1].iov_base = "\n"; - iov[1].iov_len = 1; - o_stream_nsendv(client->output, iov, N_ELEMENTS(iov)); - } - return ipc_cmd; -} - -void ipc_client_cmd_abort(struct ipc_client *client, - struct ipc_client_cmd **_cmd) -{ - struct ipc_client_cmd *cmd = *_cmd; - - *_cmd = NULL; - cmd->callback = NULL; - /* Free the command only if it's the oldest. Free also other such - commands in case they were aborted earlier. */ - while (client->cmds_head != NULL && - client->cmds_head->callback == NULL) { - struct ipc_client_cmd *head = client->cmds_head; - - client->aborted_cmds_count++; - DLLIST2_REMOVE(&client->cmds_head, &client->cmds_tail, head); - i_free(head); - } -} diff --git a/src/lib-master/ipc-client.h b/src/lib-master/ipc-client.h deleted file mode 100644 index 99bce16027..0000000000 --- a/src/lib-master/ipc-client.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef IPC_CLIENT_H -#define IPC_CLIENT_H - -enum ipc_client_cmd_state { - IPC_CLIENT_CMD_STATE_REPLY, - IPC_CLIENT_CMD_STATE_OK, - IPC_CLIENT_CMD_STATE_ERROR -}; - -typedef void ipc_client_callback_t(enum ipc_client_cmd_state state, - const char *data, void *context); - -struct ipc_client * -ipc_client_init(const char *ipc_socket_path); -void ipc_client_deinit(struct ipc_client **client); - -struct ipc_client_cmd * -ipc_client_cmd(struct ipc_client *client, const char *cmd, - ipc_client_callback_t *callback, void *context) - ATTR_NULL(4); -void ipc_client_cmd_abort(struct ipc_client *client, - struct ipc_client_cmd **cmd); - -#endif diff --git a/src/lib-master/ipc-server.c b/src/lib-master/ipc-server.c deleted file mode 100644 index 8bd8c23c3b..0000000000 --- a/src/lib-master/ipc-server.c +++ /dev/null @@ -1,202 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "net.h" -#include "istream.h" -#include "ostream.h" -#include "hostpid.h" -#include "master-service.h" -#include "ipc-server.h" - -#include - -#define IPC_SERVER_RECONNECT_MSECS (10*1000) -#define IPC_SERVER_PROTOCOL_MAJOR_VERSION 1 -#define IPC_SERVER_PROTOCOL_MINOR_VERSION 0 -#define IPC_SERVER_HANDSHAKE "VERSION\tipc-server\t1\t0\nHANDSHAKE\t%s\t%s\n" - -struct ipc_cmd { - struct ipc_server *server; - unsigned int tag; -}; - -struct ipc_server { - char *name, *path; - ipc_command_callback_t *callback; - - int ipc_cmd_refcount; - - int fd; - struct io *io; - struct timeout *to; - struct istream *input; - struct ostream *output; - - bool version_received:1; -}; - -static void ipc_server_disconnect(struct ipc_server *server); -static void ipc_server_connect(struct ipc_server *server); - -static void ipc_server_input_line(struct ipc_server *server, char *line) -{ - struct ipc_cmd *cmd; - unsigned int tag = 0; - char *p; - - /* tag cmd */ - p = strchr(line, '\t'); - if (p != NULL) { - *p++ = '\0'; - if (str_to_uint(line, &tag) < 0) - p = NULL; - } - if (p == NULL || *p == '\0') { - i_error("IPC proxy sent invalid input: %s", line); - return; - } - - cmd = i_new(struct ipc_cmd, 1); - cmd->server = server; - cmd->tag = tag; - - server->ipc_cmd_refcount++; - T_BEGIN { - server->callback(cmd, p); - } T_END; -} - -static void ipc_server_input(struct ipc_server *server) -{ - char *line; - - if (i_stream_read(server->input) < 0) { - ipc_server_disconnect(server); - ipc_server_connect(server); - return; - } - - if (!server->version_received) { - if ((line = i_stream_next_line(server->input)) == NULL) - return; - - if (!version_string_verify(line, "ipc-proxy", - IPC_SERVER_PROTOCOL_MAJOR_VERSION)) { - i_error("IPC proxy not compatible with this server " - "(mixed old and new binaries?)"); - ipc_server_disconnect(server); - return; - } - server->version_received = TRUE; - } - - while ((line = i_stream_next_line(server->input)) != NULL) - ipc_server_input_line(server, line); -} - -static void ipc_server_connect(struct ipc_server *server) -{ - i_assert(server->fd == -1); - - timeout_remove(&server->to); - - server->fd = net_connect_unix(server->path); - if (server->fd == -1) { - i_error("connect(%s) failed: %m", server->path); - server->to = timeout_add(IPC_SERVER_RECONNECT_MSECS, - ipc_server_connect, server); - return; - } - - server->io = io_add(server->fd, IO_READ, ipc_server_input, server); - server->input = i_stream_create_fd(server->fd, SIZE_MAX); - server->output = o_stream_create_fd(server->fd, SIZE_MAX); - o_stream_set_no_error_handling(server->output, TRUE); - o_stream_nsend_str(server->output, - t_strdup_printf(IPC_SERVER_HANDSHAKE, server->name, my_pid)); - o_stream_cork(server->output); -} - -static void ipc_server_disconnect(struct ipc_server *server) -{ - if (server->fd == -1) - return; - - io_remove(&server->io); - i_stream_destroy(&server->input); - o_stream_destroy(&server->output); - if (close(server->fd) < 0) - i_error("close(%s) failed: %m", server->path); - server->fd = -1; -} - -struct ipc_server * -ipc_server_init(const char *ipc_socket_path, const char *name, - ipc_command_callback_t *callback) -{ - struct ipc_server *server; - - server = i_new(struct ipc_server, 1); - server->name = i_strdup(name); - server->path = i_strdup(ipc_socket_path); - server->callback = callback; - server->fd = -1; - ipc_server_connect(server); - return server; -} - -void ipc_server_deinit(struct ipc_server **_server) -{ - struct ipc_server *server = *_server; - - *_server = NULL; - - i_assert(server->ipc_cmd_refcount == 0); - - ipc_server_disconnect(server); - timeout_remove(&server->to); - i_free(server->name); - i_free(server->path); - i_free(server); -} - -void ipc_cmd_send(struct ipc_cmd *cmd, const char *data) -{ - o_stream_nsend_str(cmd->server->output, - t_strdup_printf("%u\t:%s\n", cmd->tag, data)); -} - -static void ipc_cmd_finish(struct ipc_cmd *cmd, const char *line) -{ - o_stream_nsend_str(cmd->server->output, - t_strdup_printf("%u\t%s\n", cmd->tag, line)); - o_stream_uncork(cmd->server->output); - - i_assert(cmd->server->ipc_cmd_refcount > 0); - cmd->server->ipc_cmd_refcount--; - i_free(cmd); -} - -void ipc_cmd_success(struct ipc_cmd **_cmd) -{ - ipc_cmd_success_reply(_cmd, ""); -} - -void ipc_cmd_success_reply(struct ipc_cmd **_cmd, const char *data) -{ - struct ipc_cmd *cmd = *_cmd; - - *_cmd = NULL; - ipc_cmd_finish(cmd, t_strconcat("+", data, NULL)); -} - -void ipc_cmd_fail(struct ipc_cmd **_cmd, const char *errormsg) -{ - struct ipc_cmd *cmd = *_cmd; - - i_assert(errormsg != NULL); - - *_cmd = NULL; - ipc_cmd_finish(cmd, t_strconcat("-", errormsg, NULL)); -} diff --git a/src/lib-master/ipc-server.h b/src/lib-master/ipc-server.h deleted file mode 100644 index e9e27369d1..0000000000 --- a/src/lib-master/ipc-server.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef IPC_SERVER_H -#define IPC_SERVER_H - -struct ipc_cmd; - -/* The callback must eventually free the cmd by calling ip_cmd_success/fail(). - line is guaranteed to be non-empty. */ -typedef void ipc_command_callback_t(struct ipc_cmd *cmd, const char *line); - -struct ipc_server * -ipc_server_init(const char *ipc_socket_path, const char *name, - ipc_command_callback_t *callback); -void ipc_server_deinit(struct ipc_server **server); - -void ipc_cmd_send(struct ipc_cmd *cmd, const char *data); -void ipc_cmd_success(struct ipc_cmd **cmd); -void ipc_cmd_success_reply(struct ipc_cmd **cmd, const char *data); -void ipc_cmd_fail(struct ipc_cmd **cmd, const char *errormsg); - -#endif