#include "lib.h"
#include "array.h"
#include "base64.h"
+#include "connection.h"
#include "ioloop.h"
#include "net.h"
#include "istream.h"
};
struct server_connection {
+ struct connection conn;
struct doveadm_server *server;
pool_t pool;
-
- int fd;
- unsigned int minor;
-
- struct io *io;
struct io *io_log;
- struct istream *input;
struct istream *log_input;
- struct ostream *output;
struct ssl_iostream *ssl_iostream;
struct istream *cmd_input;
enum server_reply_state state;
- bool version_received:1;
bool authenticate_sent:1;
bool authenticated:1;
bool streaming:1;
conns = array_get(&server->connections, &count);
for (i = 0; i < count; i++) {
- if (conns[i]->io != NULL)
+ if (conns[i]->conn.io != NULL)
continue;
- conns[i]->io = io_add(conns[i]->fd, IO_READ,
- server_connection_input, conns[i]);
- io_set_pending(conns[i]->io);
+ conns[i]->conn.io = io_add(conns[i]->conn.fd_in, IO_READ,
+ server_connection_input, conns[i]);
+ io_set_pending(conns[i]->conn.io);
}
}
if (conn->cmd_input == NULL)
return;
- conn->cmd_output = o_stream_create_dot(conn->output, TRUE);
+ conn->cmd_output = o_stream_create_dot(conn->conn.output, TRUE);
(void)server_connection_send_cmd_input_more(conn);
}
{
int ret;
- ret = o_stream_flush(conn->output);
+ ret = o_stream_flush(conn->conn.output);
if (ret > 0 && conn->cmd_input != NULL && conn->delayed_cmd == NULL)
ret = server_connection_send_cmd_input_more(conn);
if (ret < 0)
/* someone else is printing. don't continue until it
goes away */
server_set_print_pending(conn->server);
- io_remove(&conn->io);
+ io_remove(&conn->conn.io);
return;
}
return;
}
conn->state = SERVER_REPLY_STATE_RET;
- i_stream_skip(conn->input, i + 1);
+ i_stream_skip(conn->conn.input, i + 1);
print_connection_released();
return;
conn->streaming = TRUE;
stream_data(str, data + start, size - start);
}
- i_stream_skip(conn->input, size);
+ i_stream_skip(conn->conn.input, size);
}
static void
i_assert(conn->authenticated);
i_assert(proxy_ttl >= 1);
- if (conn->minor < DOVEADM_PROTO_MINOR_MIN_PROXY_TTL) {
- o_stream_nsend_str(conn->output, cmdline);
+ if (conn->conn.minor_version < DOVEADM_PROTO_MINOR_MIN_PROXY_TTL) {
+ o_stream_nsend_str(conn->conn.output, cmdline);
return;
}
{ proxy_ttl_str, strlen(proxy_ttl_str) },
{ cmdline + prefix_len, strlen(cmdline + prefix_len) },
};
- o_stream_nsendv(conn->output, iov, N_ELEMENTS(iov));
+ o_stream_nsendv(conn->conn.output, iov, N_ELEMENTS(iov));
}
static void server_connection_authenticated(struct server_connection *conn)
base64_encode(plain->data, plain->used, cmd);
str_append_c(cmd, '\n');
- o_stream_nsend(conn->output, cmd->data, cmd->used);
+ o_stream_nsend(conn->conn.output, cmd->data, cmd->used);
conn->authenticate_sent = TRUE;
return 0;
}
error = conn->ssl_iostream == NULL ? NULL :
ssl_iostream_get_last_error(conn->ssl_iostream);
if (error == NULL) {
- error = conn->input->stream_errno == 0 ? "EOF" :
- strerror(conn->input->stream_errno);
+ error = conn->conn.input->stream_errno == 0 ? "EOF" :
+ strerror(conn->conn.input->stream_errno);
}
i_error("doveadm server disconnected before handshake: %s", error);
}
static void server_connection_start_multiplex(struct server_connection *conn)
{
- struct istream *is = conn->input;
- conn->input = i_stream_create_multiplex(is, MAX_INBUF_SIZE);
+ struct istream *is = conn->conn.input;
+ conn->conn.input = i_stream_create_multiplex(is, MAX_INBUF_SIZE);
i_stream_unref(&is);
- io_remove(&conn->io);
- conn->io = io_add_istream(conn->input, server_connection_input, conn);
- conn->log_input = i_stream_multiplex_add_channel(conn->input, DOVEADM_LOG_CHANNEL_ID);
+ io_remove(&conn->conn.io);
+ conn->conn.io = io_add_istream(conn->conn.input,
+ server_connection_input, conn);
+ conn->log_input = i_stream_multiplex_add_channel(conn->conn.input,
+ DOVEADM_LOG_CHANNEL_ID);
conn->io_log = io_add_istream(conn->log_input, server_connection_print_log, conn);
i_stream_set_return_partial_line(conn->log_input, TRUE);
}
const char *line;
const char *error;
- if (i_stream_read(conn->input) < 0) {
+ if (i_stream_read(conn->conn.input) < 0) {
/* disconnected */
server_log_disconnect_error(conn);
server_connection_destroy(&conn);
}
while (!conn->authenticated) {
- if ((line = i_stream_next_line(conn->input)) == NULL) {
- if (conn->input->eof) {
+ if ((line = i_stream_next_line(conn->conn.input)) == NULL) {
+ if (conn->conn.input->eof) {
/* we'll also get here if the line is too long */
server_log_disconnect_error(conn);
server_connection_destroy(&conn);
/* Allow VERSION before or after the "+" or "-" line,
because v2.2.33 sent the version after and newer
versions send before. */
- if (!conn->version_received &&
+ if (!conn->conn.version_received &&
str_begins(line, "VERSION\t")) {
if (!version_string_verify_full(line, "doveadm-client",
DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR,
- &conn->minor)) {
+ &conn->conn.minor_version)) {
i_error("doveadm server not compatible with this client"
"(mixed old and new binaries?)");
server_connection_destroy(&conn);
return;
}
- conn->version_received = TRUE;
+ conn->conn.version_received = TRUE;
} else if (strcmp(line, "+") == 0) {
- if (conn->minor >= DOVEADM_PROTO_MINOR_MIN_MULTIPLEX)
+ if (conn->conn.minor_version >= DOVEADM_PROTO_MINOR_MIN_MULTIPLEX)
server_connection_start_multiplex(conn);
server_connection_authenticated(conn);
} else if (strcmp(line, "-") == 0) {
}
if (!conn->ssl_done &&
(conn->server->ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) != 0) {
- io_remove(&conn->io);
- if (conn->minor < DOVEADM_PROTO_MINOR_MIN_STARTTLS) {
+ io_remove(&conn->conn.io);
+ if (conn->conn.minor_version < DOVEADM_PROTO_MINOR_MIN_STARTTLS) {
i_error("doveadm STARTTLS failed: Server does not support it");
server_connection_destroy(&conn);
return;
}
/* send STARTTLS */
- o_stream_nsend_str(conn->output, "STARTTLS\n");
+ o_stream_nsend_str(conn->conn.output, "STARTTLS\n");
if (server_connection_init_ssl(conn, &error) < 0) {
i_error("doveadm STARTTLS failed: %s", error);
server_connection_destroy(&conn);
return;
}
conn->ssl_done = TRUE;
- conn->io = io_add_istream(conn->input, server_connection_input, conn);
+ conn->conn.io = io_add_istream(conn->conn.input,
+ server_connection_input, conn);
}
if (server_connection_authenticate(conn) < 0) {
server_connection_destroy(&conn);
if (conn->log_input != NULL)
(void)server_connection_print_log(conn);
- data = i_stream_get_data(conn->input, &size);
+ data = i_stream_get_data(conn->conn.input, &size);
if (size == 0)
return FALSE;
return FALSE;
/* fall through */
case SERVER_REPLY_STATE_RET:
- line = i_stream_next_line(conn->input);
+ line = i_stream_next_line(conn->conn.input);
if (line == NULL)
return FALSE;
if (io_stream_create_ssl_client(conn->server->ssl_ctx,
conn->server->hostname, &ssl_set,
- &conn->input, &conn->output,
+ &conn->conn.input, &conn->conn.output,
&conn->ssl_iostream, &error) < 0) {
*error_r = t_strdup_printf(
"Couldn't initialize SSL client: %s", error);
} else {
target = server->name;
}
- conn->fd = doveadm_connect_with_default_port(target,
- doveadm_settings->doveadm_port);
- net_set_nonblock(conn->fd, TRUE);
- conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE);
- conn->output = o_stream_create_fd(conn->fd, SIZE_MAX);
- o_stream_set_flush_callback(conn->output, server_connection_output, conn);
- o_stream_set_no_error_handling(conn->output, TRUE);
+ conn->conn.fd_in = doveadm_connect_with_default_port(target,
+ doveadm_settings->doveadm_port);
+ conn->conn.fd_out = conn->conn.fd_out;
+
+ net_set_nonblock(conn->conn.fd_in, TRUE);
+ conn->conn.input = i_stream_create_fd(conn->conn.fd_in, MAX_INBUF_SIZE);
+ conn->conn.output = o_stream_create_fd(conn->conn.fd_in, SIZE_MAX);
+ o_stream_set_flush_callback(conn->conn.output,
+ server_connection_output, conn);
+ o_stream_set_no_error_handling(conn->conn.output, TRUE);
- i_stream_set_name(conn->input, server->name);
- o_stream_set_name(conn->output, server->name);
+ i_stream_set_name(conn->conn.input, server->name);
+ o_stream_set_name(conn->conn.output, server->name);
array_push_back(&conn->server->connections, &conn);
server_connection_destroy(&conn);
return -1;
}
- conn->io = io_add_istream(conn->input, server_connection_input, conn);
+ conn->conn.io = io_add_istream(conn->conn.input,
+ server_connection_input, conn);
conn->state = SERVER_REPLY_STATE_DONE;
- o_stream_nsend_str(conn->output, DOVEADM_SERVER_PROTOCOL_VERSION_LINE"\n");
+ o_stream_nsend_str(conn->conn.output,
+ DOVEADM_SERVER_PROTOCOL_VERSION_LINE"\n");
*conn_r = conn;
return 0;
error = conn->ssl_iostream == NULL ? NULL :
ssl_iostream_get_last_error(conn->ssl_iostream);
if (error == NULL) {
- error = conn->input->stream_errno == 0 ? "EOF" :
- strerror(conn->input->stream_errno);
+ error = conn->conn.input->stream_errno == 0 ? "EOF" :
+ strerror(conn->conn.input->stream_errno);
}
struct doveadm_server_reply reply = {
.exit_code = SERVER_EXIT_CODE_DISCONNECTED,
if (printing_conn == conn)
print_connection_released();
- i_stream_destroy(&conn->input);
- o_stream_destroy(&conn->output);
+ i_stream_destroy(&conn->conn.input);
+ o_stream_destroy(&conn->conn.output);
i_stream_unref(&conn->cmd_input);
/* close cmd_output after its parent, so the "." isn't sent */
o_stream_destroy(&conn->cmd_output);
if (conn->log_input != NULL)
server_connection_print_log(conn);
i_stream_unref(&conn->log_input);
- io_remove(&conn->io);
- i_close_fd(&conn->fd);
+ io_remove(&conn->conn.io);
+ i_close_fd(&conn->conn.fd_in);
pool_unref(&conn->pool);
}
void server_connection_get_dest(struct server_connection *conn,
struct ip_addr *ip_r, in_port_t *port_r)
{
- if (net_getpeername(conn->fd, ip_r, port_r) < 0) {
+ if (net_getpeername(conn->conn.fd_in, ip_r, port_r) < 0) {
i_zero(ip_r);
*port_r = 0;
}
struct ostream **ostream_r,
struct ssl_iostream **ssl_iostream_r)
{
- *istream_r = conn->input;
- *ostream_r = conn->output;
+ *istream_r = conn->conn.input;
+ *ostream_r = conn->conn.output;
*ssl_iostream_r = conn->ssl_iostream;
- conn->input = NULL;
- conn->output = NULL;
+ conn->conn.input = NULL;
+ conn->conn.output = NULL;
conn->ssl_iostream = NULL;
- io_remove(&conn->io);
- conn->fd = -1;
+ io_remove(&conn->conn.io);
+ conn->conn.fd_in = -1;
+ conn->conn.fd_out = -1;
}