{
struct dict_connection_cmd *cmd, *const *first_cmdp;
- i_assert(conn->minor_version < DICT_CLIENT_PROTOCOL_UNORDERED_MIN_VERSION);
+ i_assert(conn->conn.minor_version < DICT_CLIENT_PROTOCOL_UNORDERED_MIN_VERSION);
dict_connection_ref(conn);
while (array_count(&conn->cmds) > 0) {
break;
}
- o_stream_nsend_str(conn->output, cmd->reply);
+ o_stream_nsend_str(conn->conn.output, cmd->reply);
dict_connection_cmd_remove(cmd);
}
dict_connection_unref_safe(conn);
struct dict_connection_cmd *cmd = *_cmd;
*_cmd = NULL;
- if (cmd->conn->minor_version < DICT_CLIENT_PROTOCOL_UNORDERED_MIN_VERSION) {
+ if (cmd->conn->conn.minor_version < DICT_CLIENT_PROTOCOL_UNORDERED_MIN_VERSION) {
dict_connection_cmds_flush(cmd->conn);
return;
}
i_assert(cmd->async_reply_id != 0);
i_assert(cmd->reply != NULL);
- o_stream_nsend_str(cmd->conn->output, t_strdup_printf("%c%u\t%s",
+ o_stream_nsend_str(cmd->conn->conn.output, t_strdup_printf("%c%u\t%s",
DICT_PROTOCOL_REPLY_ASYNC_REPLY,
cmd->async_reply_id, cmd->reply));
+ o_stream_flush(cmd->conn->conn.output);
dict_connection_cmd_remove(cmd);
}
static void dict_connection_cmd_async(struct dict_connection_cmd *cmd)
{
- if (cmd->conn->minor_version < DICT_CLIENT_PROTOCOL_UNORDERED_MIN_VERSION)
+ if (cmd->conn->conn.minor_version < DICT_CLIENT_PROTOCOL_UNORDERED_MIN_VERSION)
return;
i_assert(cmd->async_reply_id == 0);
cmd->async_reply_id = ++cmd->conn->async_id_counter;
if (cmd->async_reply_id == 0)
cmd->async_reply_id = ++cmd->conn->async_id_counter;
- o_stream_nsend_str(cmd->conn->output, t_strdup_printf("%c%u\n",
+ o_stream_nsend_str(cmd->conn->conn.output, t_strdup_printf("%c%u\n",
DICT_PROTOCOL_REPLY_ASYNC_ID, cmd->async_reply_id));
}
io_loop_time_refresh();
cmd_stats_update(cmd, stats);
- if (cmd->conn->minor_version < DICT_CLIENT_PROTOCOL_TIMINGS_MIN_VERSION)
+ if (cmd->conn->conn.minor_version < DICT_CLIENT_PROTOCOL_TIMINGS_MIN_VERSION)
return;
str_printfa(str, "\t%ld\t%u\t%ld\t%u",
(long)cmd->start_timeval.tv_sec,
i_assert(values[0] != NULL);
- if (cmd->conn->minor_version < DICT_CLIENT_PROTOCOL_VERSION_MIN_MULTI_OK ||
+ if (cmd->conn->conn.minor_version < DICT_CLIENT_PROTOCOL_VERSION_MIN_MULTI_OK ||
values[1] == NULL) {
str_append_c(str, DICT_PROTOCOL_REPLY_OK);
str_append_tabescaped(str, values[0]);
static bool dict_connection_flush_if_full(struct dict_connection *conn)
{
- if (o_stream_get_buffer_used_size(conn->output) >
+ if (o_stream_get_buffer_used_size(conn->conn.output) >
DICT_OUTPUT_OPTIMAL_SIZE) {
- if (o_stream_flush(conn->output) <= 0) {
+ if (o_stream_flush(conn->conn.output) <= 0) {
/* continue later when there's more space
in output buffer */
- o_stream_set_flush_pending(conn->output, TRUE);
+ o_stream_set_flush_pending(conn->conn.output, TRUE);
return FALSE;
}
/* flushed everything, continue */
if ((cmd->iter_flags & DICT_ITERATE_FLAG_NO_VALUE) == 0)
str_append_tabescaped(str, value);
str_append_c(str, '\n');
- o_stream_nsend(cmd->conn->output, str_data(str), str_len(str));
+ o_stream_nsend(cmd->conn->conn.output, str_data(str), str_len(str));
if (!dict_connection_flush_if_full(cmd->conn))
return 0;
struct dict_connection *conn = cmd->conn;
dict_connection_ref(conn);
- o_stream_cork(conn->output);
+ o_stream_cork(conn->conn.output);
dict_connection_cmd_output_more(cmd);
- o_stream_uncork(conn->output);
+ o_stream_uncork(conn->conn.output);
dict_connection_unref_safe(conn);
}
/* cmd should be freed now, restart output */
return TRUE;
}
- if (conn->minor_version < DICT_CLIENT_PROTOCOL_TIMINGS_MIN_VERSION)
+ if (conn->conn.minor_version < DICT_CLIENT_PROTOCOL_TIMINGS_MIN_VERSION)
break;
/* try to flush the rest */
}
{
struct dict_connection_cmd *const *first_cmdp;
- if (cmd->conn->minor_version < DICT_CLIENT_PROTOCOL_TIMINGS_MIN_VERSION) {
+ if (cmd->conn->conn.minor_version < DICT_CLIENT_PROTOCOL_TIMINGS_MIN_VERSION) {
first_cmdp = array_front(&cmd->conn->cmds);
if (*first_cmdp != cmd)
return;
return -1;
/* read minor version */
- if (str_parse_uint(line, &conn->minor_version, &line) < 0)
+ if (str_parse_uint(line, &conn->conn.minor_version, &line) < 0)
return -1;
if (*line++ != '\t')
return -1;
return 0;
}
-static void dict_connection_input_more(struct dict_connection *conn)
+static void dict_connection_input_more(struct connection *_conn)
{
+ struct dict_connection *conn = container_of(_conn, struct dict_connection, conn);
const char *line;
int ret;
timeout_remove(&conn->to_input);
- while ((line = i_stream_next_line(conn->input)) != NULL) {
+ while ((line = i_stream_next_line(conn->conn.input)) != NULL) {
T_BEGIN {
ret = dict_command_input(conn, line);
} T_END;
break;
}
if (array_count(&conn->cmds) >= DICT_CONN_MAX_PENDING_COMMANDS) {
- io_remove(&conn->io);
+ io_remove(&conn->conn.io);
timeout_remove(&conn->to_input);
break;
}
}
}
-static void dict_connection_input(struct dict_connection *conn)
+static void dict_connection_input(struct connection *_conn)
{
+ struct dict_connection *conn = container_of(_conn, struct dict_connection, conn);
const char *line;
- switch (i_stream_read(conn->input)) {
+ switch (i_stream_read(conn->conn.input)) {
case 0:
return;
case -1:
if (conn->username == NULL) {
/* handshake not received yet */
- if ((line = i_stream_next_line(conn->input)) == NULL)
+ if ((line = i_stream_next_line(conn->conn.input)) == NULL)
return;
if (dict_connection_parse_handshake(conn, line) < 0) {
}
}
- dict_connection_input_more(conn);
+ dict_connection_input_more(&conn->conn);
}
void dict_connection_continue_input(struct dict_connection *conn)
{
- if (conn->io != NULL || conn->destroyed)
+ if (conn->conn.io != NULL || conn->destroyed)
return;
- conn->io = io_add(conn->fd, IO_READ, dict_connection_input, conn);
+ conn->conn.io = io_add(conn->conn.fd_in, IO_READ, dict_connection_input, &conn->conn);
if (conn->to_input == NULL)
- conn->to_input = timeout_add_short(0, dict_connection_input_more, conn);
+ conn->to_input = timeout_add_short(0, dict_connection_input_more, &conn->conn);
}
-static int dict_connection_output(struct dict_connection *conn)
+static int dict_connection_output(struct connection *_conn)
{
+ struct dict_connection *conn = container_of(_conn, struct dict_connection, conn);
int ret;
- if ((ret = o_stream_flush(conn->output)) < 0) {
+ if ((ret = o_stream_flush(conn->conn.output)) < 0) {
dict_connection_destroy(conn);
return 1;
}
conn = i_new(struct dict_connection, 1);
conn->refcount = 1;
- conn->fd = master_conn->fd;
- conn->input = i_stream_create_fd(master_conn->fd, DICT_CLIENT_MAX_LINE_LENGTH);
- conn->output = o_stream_create_fd(master_conn->fd, 128*1024);
- o_stream_set_no_error_handling(conn->output, TRUE);
- o_stream_set_flush_callback(conn->output, dict_connection_output, conn);
- conn->io = io_add(master_conn->fd, IO_READ, dict_connection_input, conn);
+ conn->conn.fd_in = conn->conn.fd_out = master_conn->fd;
+ conn->conn.input = i_stream_create_fd(conn->conn.fd_in, DICT_CLIENT_MAX_LINE_LENGTH);
+ conn->conn.output = o_stream_create_fd(conn->conn.fd_out, 128*1024);
+ o_stream_set_no_error_handling(conn->conn.output, TRUE);
+ o_stream_set_flush_callback(conn->conn.output, dict_connection_output, &conn->conn);
+ conn->conn.io = io_add(conn->conn.fd_in, IO_READ, dict_connection_input, &conn->conn);
i_array_init(&conn->cmds, DICT_CONN_MAX_PENDING_COMMANDS);
dict_connections_count++;
if (array_is_created(&conn->transactions))
array_free(&conn->transactions);
- i_stream_destroy(&conn->input);
- o_stream_destroy(&conn->output);
+ i_stream_destroy(&conn->conn.input);
+ o_stream_destroy(&conn->conn.output);
array_free(&conn->cmds);
i_free(conn->name);
DLLIST_REMOVE(&dict_connections, conn);
timeout_remove(&conn->to_input);
- io_remove(&conn->io);
- i_stream_close(conn->input);
- o_stream_close(conn->output);
- if (close(conn->fd) < 0)
- i_error("close(dict client) failed: %m");
- conn->fd = -1;
+ io_remove(&conn->conn.io);
+ i_stream_close(conn->conn.input);
+ o_stream_close(conn->conn.output);
+ i_close_fd(&conn->conn.fd_in);
+ conn->conn.fd_out = -1;
/* the connection is closed, but there may still be commands left
running. finish them, even if the calling client can't be notified
#define DICT_CONNECTION_H
#include "dict.h"
+#include "connection.h"
struct dict_connection_transaction {
unsigned int id;
};
struct dict_connection {
+ struct connection conn;
struct dict_connection *prev, *next;
struct dict_server *server;
int refcount;
char *name;
struct dict *dict;
enum dict_data_type value_type;
- unsigned int minor_version;
- int fd;
- struct io *io;
- struct istream *input;
- struct ostream *output;
struct timeout *to_input;
struct timeout *to_unref;