9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "lib.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "array.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "ioloop.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "istream.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "ostream.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "llist.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "strescape.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "master-service.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "ipc-group.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include "ipc-connection.h"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#include <unistd.h>
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#define IPC_SERVER_PROTOCOL_MAJOR_VERSION 1
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#define IPC_SERVER_PROTOCOL_MINOR_VERSION 0
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#define IPC_SERVER_HANDSHAKE "VERSION\tipc-proxy\t1\t0\n"
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic unsigned int connection_id_counter;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic void ipc_connection_cmd_free(struct ipc_connection_cmd **_cmd,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *reason)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek{
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek struct ipc_connection_cmd *cmd = *_cmd;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek struct ipc_connection_cmd **cmds;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek unsigned int i, count;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek *_cmd = NULL;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek cmds = array_get_modifiable(&cmd->conn->cmds, &count);
0429e21a45aa26c133cb4d8285a60446a0611e44Pavel Březina for (i = 0; i < count; i++) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (cmds[i] == cmd) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek array_delete(&cmd->conn->cmds, i, 1);
d43c9d18fb263b1ea4071b20e93ce4994583f62fJakub Hrozek break;
892ddeb5190dd5c1ffa26a95142a10a0034fc5e3Pavel Březina }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
50c9d542e8bf641412debaa82a4dcf67ddb72258Lukas Slebodnik if (cmd->callback != NULL) {
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek i_assert(reason != NULL);
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek cmd->callback(IPC_CMD_STATUS_ERROR, reason, cmd->context);
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek }
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek i_free(cmd);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek}
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic struct ipc_connection_cmd *
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekipc_connection_cmd_find(struct ipc_connection *conn, unsigned int tag)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek{
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek struct ipc_connection_cmd *const *cmdp;
12e7e87ccbae0d5c2f338cd019ca51556cbcd3aeLukas Slebodnik
12e7e87ccbae0d5c2f338cd019ca51556cbcd3aeLukas Slebodnik array_foreach(&conn->cmds, cmdp) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if ((*cmdp)->tag == tag)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return *cmdp;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek return NULL;
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek}
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic int
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekipc_connection_input_line(struct ipc_connection *conn, char *line)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek{
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek struct ipc_connection_cmd *cmd;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek unsigned int tag;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek enum ipc_cmd_status status;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek char *data;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek /* <tag> [:+-]<data> */
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek data = strchr(line, '\t');
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (data == NULL)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return -1;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov *data++ = '\0';
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (str_to_uint(line, &tag) < 0)
57c5ea8825c7179fd93382dbcbb07e828e5aec19René Genz return -1;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek switch (data[0]) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov case ':':
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek status = IPC_CMD_STATUS_REPLY;
57c5ea8825c7179fd93382dbcbb07e828e5aec19René Genz break;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek case '+':
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek status = IPC_CMD_STATUS_OK;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov break;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek case '-':
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek status = IPC_CMD_STATUS_ERROR;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek break;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek default:
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return -1;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek data++;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek cmd = ipc_connection_cmd_find(conn, tag);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (cmd == NULL) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("IPC server: Input for unexpected command tag %u", tag);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return 0;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek cmd->callback(status, data, cmd->context);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (status != IPC_CMD_STATUS_REPLY) {
04868f1573f4b26ef34610b6d7069172f93bd8abJakub Hrozek cmd->callback = NULL;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_connection_cmd_free(&cmd, NULL);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return 0;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek}
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidekstatic void ipc_connection_input(struct ipc_connection *conn)
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl{
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek char *line;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek int ret;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (i_stream_read(conn->input) < 0) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_connection_destroy(&conn, FALSE,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_stream_get_disconnect_reason(conn->input));
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl return;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
12e7e87ccbae0d5c2f338cd019ca51556cbcd3aeLukas Slebodnik
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (!conn->version_received) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if ((line = i_stream_next_line(conn->input)) == NULL)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (!version_string_verify(line, "ipc-server",
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek IPC_SERVER_PROTOCOL_MAJOR_VERSION)) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_connection_destroy(&conn, TRUE,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek "IPC server not compatible with this server "
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek "(mixed old and new binaries?)");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->version_received = TRUE;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
828cc04cd1ed9076faa6e1545055ae69a04f0f0fLukas Slebodnik if (!conn->handshake_received) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if ((line = i_stream_next_line(conn->input)) == NULL)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek args = t_strsplit_tabescaped(line);
57c5ea8825c7179fd93382dbcbb07e828e5aec19René Genz if (str_array_length(args) < 3 ||
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidek strcmp(args[0], "HANDSHAKE") != 0) {
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl ipc_connection_destroy(&conn, TRUE,
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl "IPC server sent invalid handshake");
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl return;
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl }
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl if (ipc_group_update_name(conn->group, args[1]) < 0) {
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl ipc_connection_destroy(&conn, TRUE, t_strdup_printf(
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl "IPC server named itself unexpectedly: %s "
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl "(existing ones were %s)",
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl args[1], conn->group->name));
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidek return;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (str_to_pid(args[2], &conn->pid) < 0) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_connection_destroy(&conn, TRUE, t_strdup_printf(
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl "IPC server gave broken PID: %s", args[2]));
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl return;
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl }
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl conn->handshake_received = TRUE;
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl }
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl while ((line = i_stream_next_line(conn->input)) != NULL) {
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl T_BEGIN {
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl ret = ipc_connection_input_line(conn, line);
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl } T_END;
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl if (ret < 0) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_connection_destroy(&conn, TRUE, t_strdup_printf(
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek "Invalid input from IPC server '%s': %s",
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl conn->group->name, line));
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek break;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidek }
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidek}
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstruct ipc_connection *ipc_connection_create(int listen_fd, int fd)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek{
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek struct ipc_connection *conn;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn = i_new(struct ipc_connection, 1);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->group = ipc_group_lookup_listen_fd(listen_fd);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (conn->group == NULL)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->group = ipc_group_alloc(listen_fd);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->id = ++connection_id_counter;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (conn->id == 0)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->id = ++connection_id_counter;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->fd = fd;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->io = io_add(fd, IO_READ, ipc_connection_input, conn);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->input = i_stream_create_fd(fd, (size_t)-1);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->output = o_stream_create_fd(fd, (size_t)-1);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek o_stream_set_no_error_handling(conn->output, TRUE);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_array_init(&conn->cmds, 8);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek o_stream_nsend_str(conn->output, IPC_SERVER_HANDSHAKE);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek DLLIST_PREPEND(&conn->group->connections, conn);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return conn;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek}
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekvoid ipc_connection_destroy(struct ipc_connection **_conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek bool log_error, const char *error)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek{
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl struct ipc_connection *conn = *_conn;
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl struct ipc_connection_cmd *const *cmdp, *cmd;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *group_name = conn->group->name != NULL ?
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->group->name :
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek t_strdup_printf("#%d", conn->group->listen_fd);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek *_conn = NULL;
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl error = t_strdup_printf("IPC: '%s' PID %d server connection: %s",
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl group_name, conn->pid, error);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (log_error)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("%s", error);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl DLLIST_REMOVE(&conn->group->connections, conn);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl while (array_count(&conn->cmds) > 0) {
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl cmdp = array_idx(&conn->cmds, 0);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl cmd = *cmdp;
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl ipc_connection_cmd_free(&cmd, error);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl }
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl array_free(&conn->cmds);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl io_remove(&conn->io);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl i_stream_destroy(&conn->input);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl o_stream_destroy(&conn->output);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl if (close(conn->fd) < 0)
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl i_error("close(ipc connection) failed: %m");
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl i_free(conn);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl master_service_client_connection_destroyed(master_service);
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl}
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichlstruct ipc_connection *
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichlipc_connection_lookup_id(struct ipc_group *group, unsigned int id)
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl{
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl struct ipc_connection *conn;
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl
eeac17ebbe38f16deaa8599231cccfc97aaac85cPavel Reichl for (conn = group->connections; conn != NULL; conn = conn->next) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (conn->id == id)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return conn;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return NULL;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek}
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekvoid ipc_connection_cmd(struct ipc_connection *conn, const char *cmd,
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl ipc_cmd_callback_t *callback, void *context)
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl{
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl struct ipc_connection_cmd *ipc_cmd;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_cmd = i_new(struct ipc_connection_cmd, 1);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_cmd->tag = ++conn->cmd_tag_counter;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_cmd->conn = conn;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_cmd->callback = callback;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ipc_cmd->context = context;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek array_append(&conn->cmds, &ipc_cmd, 1);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek T_BEGIN {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek o_stream_nsend_str(conn->output,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek t_strdup_printf("%u\t%s\n", ipc_cmd->tag, cmd));
e210ed5da220acebb6751db4466fe352de08eaebLukas Slebodnik } T_END;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek}
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek