Mercurial > dovecot > core-2.2
changeset 9865:c90ba3f3fa51 HEAD
anvil: Read from FIFOs in packets instead of using streams.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 04 Sep 2009 13:47:16 -0400 |
parents | 5b36fa967538 |
children | 1d2d0aa8e313 |
files | src/anvil/anvil-connection.c src/anvil/anvil-connection.h src/anvil/main.c |
diffstat | 3 files changed, 69 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/src/anvil/anvil-connection.c Fri Sep 04 13:45:33 2009 -0400 +++ b/src/anvil/anvil-connection.c Fri Sep 04 13:47:16 2009 -0400 @@ -24,6 +24,8 @@ struct istream *input; struct ostream *output; struct io *io; + unsigned char *fifo_inbuf; + size_t fifo_inbuf_size; unsigned int version_received:1; unsigned int handshaked:1; @@ -32,16 +34,41 @@ struct anvil_connection *anvil_connections = NULL; +static const char * +anvil_connection_fifo_read_line(struct anvil_connection *conn) +{ + ssize_t ret; + + ret = read(conn->fd, conn->fifo_inbuf, conn->fifo_inbuf_size); + if (ret > 0) { + if (conn->fifo_inbuf[ret-1] != '\n') { + i_error("BUG: Client packet didn't end with LF"); + return NULL; + } + conn->fifo_inbuf[ret-1] = '\0'; + return (const char *)conn->fifo_inbuf; + } + if (ret == 0) { + /* disconnected */ + } else { + if (errno == EAGAIN) + return NULL; + i_error("read() failed: %m"); + } + anvil_connection_destroy(conn); + return NULL; +} + static const char *const * anvil_connection_next_line(struct anvil_connection *conn) { const char *line; - line = i_stream_next_line(conn->input); - if (line == NULL) - return NULL; - - return t_strsplit(line, "\t"); + if (conn->input != NULL) + line = i_stream_next_line(conn->input); + else + line = anvil_connection_fifo_read_line(conn); + return line == NULL ? NULL : t_strsplit(line, "\t"); } static int @@ -86,6 +113,10 @@ *error_r = "LOOKUP: Not enough parameters"; return -1; } + if (conn->output == NULL) { + *error_r = "LOOKUP on a FIFO, can't send reply"; + return -1; + } count = connect_limit_lookup(connect_limit, args[0]); (void)o_stream_send_str(conn->output, t_strdup_printf("%u\n", count)); @@ -99,26 +130,28 @@ static void anvil_connection_input(void *context) { struct anvil_connection *conn = context; - const char *const *args, *line, *error; + const char *const *args, *error; - switch (i_stream_read(conn->input)) { - case -2: - i_error("BUG: Anvil client connection sent too much data"); - anvil_connection_destroy(conn); - return; - case -1: - anvil_connection_destroy(conn); - return; + if (conn->input != NULL) { + switch (i_stream_read(conn->input)) { + case -2: + i_error("BUG: Anvil client connection sent too " + "much data"); + anvil_connection_destroy(conn); + return; + case -1: + anvil_connection_destroy(conn); + return; + } } if (!conn->version_received) { - line = i_stream_next_line(conn->input); - if (line == NULL) + if ((args = anvil_connection_next_line(conn)) == NULL) return; - if (strncmp(line, "VERSION\t", 8) != 0 || - atoi(t_strcut(line + 8, '\t')) != - ANVIL_CLIENT_PROTOCOL_MAJOR_VERSION) { + if (str_array_length(args) < 3 || + strcmp(args[0], "VERSION") != 0 || + atoi(args[1]) != ANVIL_CLIENT_PROTOCOL_MAJOR_VERSION) { i_error("Anvil client not compatible with this server " "(mixed old and new binaries?)"); anvil_connection_destroy(conn); @@ -135,14 +168,20 @@ } } -struct anvil_connection *anvil_connection_create(int fd, bool master) +struct anvil_connection * +anvil_connection_create(int fd, bool master, bool fifo) { struct anvil_connection *conn; conn = i_new(struct anvil_connection, 1); conn->fd = fd; - conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE); - conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE); + if (!fifo) { + conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE); + conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE); + } else { + conn->fifo_inbuf_size = MAX_INBUF_SIZE; + conn->fifo_inbuf = i_malloc(conn->fifo_inbuf_size); + } conn->io = io_add(fd, IO_READ, anvil_connection_input, conn); conn->master = master; DLLIST_PREPEND(&anvil_connections, conn); @@ -154,10 +193,13 @@ DLLIST_REMOVE(&anvil_connections, conn); io_remove(&conn->io); - i_stream_destroy(&conn->input); - o_stream_destroy(&conn->output); + if (conn->input != NULL) + i_stream_destroy(&conn->input); + if (conn->output != NULL) + o_stream_destroy(&conn->output); if (close(conn->fd) < 0) i_error("close(anvil conn) failed: %m"); + i_free(conn->fifo_inbuf); i_free(conn); master_service_client_connection_destroyed(master_service);
--- a/src/anvil/anvil-connection.h Fri Sep 04 13:45:33 2009 -0400 +++ b/src/anvil/anvil-connection.h Fri Sep 04 13:47:16 2009 -0400 @@ -1,7 +1,8 @@ #ifndef ANVIL_CONNECTION_H #define ANVIL_CONNECTION_H -struct anvil_connection *anvil_connection_create(int fd, bool master); +struct anvil_connection * +anvil_connection_create(int fd, bool master, bool fifo); void anvil_connection_destroy(struct anvil_connection *conn); void anvil_connections_destroy_all(void);
--- a/src/anvil/main.c Fri Sep 04 13:45:33 2009 -0400 +++ b/src/anvil/main.c Fri Sep 04 13:47:16 2009 -0400 @@ -17,7 +17,7 @@ { bool master = conn->listen_fd == MASTER_LISTEN_FD_FIRST; - anvil_connection_create(conn->fd, master); + anvil_connection_create(conn->fd, master, conn->fifo); } int main(int argc, char *argv[])