/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
#include "imap-common.h"
#include "connection.h"
#include "istream.h"
#include "istream-unix.h"
#include "ostream.h"
#include "base64.h"
#include "str.h"
#include "strescape.h"
#include "str-sanitize.h"
#include "master-service.h"
#include "mail-storage-service.h"
#include "imap-client.h"
#include "imap-state.h"
#include "imap-master-client.h"
struct imap_master_client {
bool imap_client_created;
};
struct imap_master_input {
/* input we've already read from the IMAP client. */
/* output that imap-hibernate was supposed to send to IMAP client,
but couldn't send it yet. */
/* IMAP connection state */
/* command tag */
const char *tag;
};
{
if (!client->imap_client_created)
}
static int
struct mail_storage_service_input *input_r,
struct imap_master_input *master_input_r,
const char **error_r)
{
/* we never want to do userdb lookup again when restoring the client.
we have the userdb_fields cached already. */
*error_r = "Missing username in input";
return -1;
}
else {
value = "";
}
"Invalid lip value: %s", value);
return -1;
}
"Invalid rip value: %s", value);
return -1;
}
"Invalid peer_dev_major value: %s", value);
return -1;
}
"Invalid peer_dev_minor value: %s", value);
return -1;
}
"Invalid peer_ino value: %s", value);
return -1;
}
"Invalid session_created value: %s", value);
return -1;
}
master_input_r->client_input) < 0) {
"Invalid client_input base64 value: %s", value);
return -1;
}
master_input_r->client_output) < 0) {
"Invalid client_output base64 value: %s", value);
return -1;
}
master_input_r->state) < 0) {
"Invalid state base64 value: %s", value);
return -1;
}
}
}
if (peer_dev_major != 0 || peer_dev_minor != 0) {
}
return 0;
}
{
if (master_input->peer_ino == 0)
return 0;
/* make sure we have the right fd */
return -1;
}
"BUG: Expected peer device=%lu,%lu inode=%s doesn't match "
"client fd's actual device=%lu,%lu inode=%s",
return -1;
}
return 0;
}
static int
{
const char *error;
int ret;
&error) < 0) {
"-Failed to parse client input: %s\n", error));
return -1;
}
"-Failed to verify client input: %s\n", error));
return -1;
}
/* Send a success notification before we start anything that lasts
potentially a long time. imap-hibernate process is waiting for us
to answer. Even if we fail later, we log the error anyway. */
/* NOTE: before client_create_from_input() on failures we need to close
fd_client, but afterward it gets closed by client_destroy() */
&imap_client, &error);
if (ret < 0) {
i_error("imap-master(%s): Failed to create client: %s",
return -1;
}
return -1;
}
/* log prefix is set at this point, so we don't need to add the
username anymore to the log messages */
" bytes to client's input stream",
return -1;
}
i_debug("imap-master: Unhibernated because IDLE was stopped with BAD command");
else if (imap_client->state_import_idle_continue)
i_debug("imap-master: Unhibernated to send mailbox changes");
else
i_debug("imap-master: Unhibernated because IDLE was stopped with DONE");
}
if (ret <= 0) {
return -1;
}
/* make sure all pending input gets handled */
i_debug("imap-master: Pending client input: '%s'",
}
}
/* we'll always disconnect the client afterwards */
return -1;
}
static int
{
char *const *args;
if (!conn->version_received) {
return -1;
return 1;
}
if (fd_client == -1) {
i_error("imap-master: IMAP client fd not received");
return -1;
}
if (imap_debug)
pool_unref(&pool);
return ret;
}
{
/* read the first file descriptor that we can */
}
.service_name_in = "imap-master",
.service_name_out = "imap-master",
.major_version = 1,
.minor_version = 0,
};
};
void imap_master_clients_init(void)
{
}
void imap_master_clients_deinit(void)
{
}