bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen#include "lib.h"
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen#include "array.h"
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen#include "ipc-connection.h"
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen#include "ipc-group.h"
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenstruct ipc_group_cmd {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen ipc_cmd_callback_t *callback;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen void *context;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen int refcount;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen char *first_error;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen};
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ARRAY(struct ipc_group *) ipc_groups;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenstruct ipc_group *ipc_group_alloc(int listen_fd)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_group *group;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_assert(ipc_group_lookup_listen_fd(listen_fd) == NULL);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group = i_new(struct ipc_group, 1);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group->listen_fd = listen_fd;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen array_append(&ipc_groups, &group, 1);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen return group;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenvoid ipc_group_free(struct ipc_group **_group)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_group *const *groups, *group = *_group;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen unsigned int i, count;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_assert(group->connections == NULL);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen *_group = NULL;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen groups = array_get(&ipc_groups, &count);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen for (i = 0; i < count; i++) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if (groups[i] == group) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen array_delete(&ipc_groups, i, 1);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen break;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_free(group->name);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_free(group);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenstruct ipc_group *ipc_group_lookup_listen_fd(int listen_fd)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_group *const *groupp;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen array_foreach(&ipc_groups, groupp) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if ((*groupp)->listen_fd == listen_fd)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen return *groupp;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen return NULL;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenstruct ipc_group *ipc_group_lookup_name(const char *name)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_group *const *groupp;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen array_foreach(&ipc_groups, groupp) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if ((*groupp)->name != NULL &&
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen strcmp((*groupp)->name, name) == 0)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen return *groupp;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen return NULL;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenint ipc_group_update_name(struct ipc_group *group, const char *name)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if (group->name == NULL)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group->name = i_strdup(name);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen else if (strcmp(group->name, name) != 0)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen return -1;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen return 0;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenstatic void ipc_group_cmd_callback(enum ipc_cmd_status status,
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen const char *line, void *context)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_group_cmd *group_cmd = context;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_assert(group_cmd->refcount > 0);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen switch (status) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen case IPC_CMD_STATUS_REPLY:
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->callback(IPC_CMD_STATUS_REPLY, line,
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->context);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen break;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen case IPC_CMD_STATUS_ERROR:
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if (group_cmd->first_error == NULL)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->first_error = i_strdup(line);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen /* fall through */
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen case IPC_CMD_STATUS_OK:
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if (--group_cmd->refcount > 0)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen break;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if (group_cmd->first_error == NULL) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->callback(IPC_CMD_STATUS_OK, line,
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->context);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen } else {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->callback(IPC_CMD_STATUS_ERROR,
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->first_error,
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->context);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_free(group_cmd->first_error);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_free(group_cmd);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen break;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
eef20a55e19a239244b14963d716cf0d070fe1bbTimo Sirainenbool ipc_group_cmd(struct ipc_group *group, const char *cmd,
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen ipc_cmd_callback_t *callback, void *context)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_connection *conn, *next;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_group_cmd *group_cmd;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen if (group->connections == NULL) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen callback(IPC_CMD_STATUS_OK, NULL, context);
eef20a55e19a239244b14963d716cf0d070fe1bbTimo Sirainen return FALSE;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd = i_new(struct ipc_group_cmd, 1);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->callback = callback;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->context = context;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen for (conn = group->connections; conn != NULL; conn = next) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen next = conn->next;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group_cmd->refcount++;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen ipc_connection_cmd(conn, cmd,
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen ipc_group_cmd_callback, group_cmd);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
eef20a55e19a239244b14963d716cf0d070fe1bbTimo Sirainen return TRUE;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenvoid ipc_groups_init(void)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen i_array_init(&ipc_groups, 16);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainenvoid ipc_groups_deinit(void)
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen{
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_group *const *groupp, *group;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen while (array_count(&ipc_groups) > 0) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen groupp = array_idx(&ipc_groups, 0);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen group = *groupp;
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen while ((*groupp)->connections != NULL) {
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen struct ipc_connection *conn = (*groupp)->connections;
68c4b2cd63f7225fda4a61f28030edace3298b53Timo Sirainen ipc_connection_destroy(&conn, FALSE, "Shutting down");
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen ipc_group_free(&group);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen }
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen array_free(&ipc_groups);
83942ac160cdfb922c3a2f29ddfae2a13ebf8b5dTimo Sirainen}