dovecot-2.0: anvil: Read from FIFOs in packets instead of using ...

dovecot at dovecot.org dovecot at dovecot.org
Fri Sep 4 20:48:06 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/c90ba3f3fa51
changeset: 9865:c90ba3f3fa51
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Sep 04 13:47:16 2009 -0400
description:
anvil: Read from FIFOs in packets instead of using streams.

diffstat:

3 files changed, 72 insertions(+), 29 deletions(-)
src/anvil/anvil-connection.c |   96 ++++++++++++++++++++++++++++++------------
src/anvil/anvil-connection.h |    3 -
src/anvil/main.c             |    2 

diffs (181 lines):

diff -r 5b36fa967538 -r c90ba3f3fa51 src/anvil/anvil-connection.c
--- 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 anvil_connection {
 	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 {
 
 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 @@ anvil_connection_request(struct anvil_co
 			*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 
 static void anvil_connection_input(void *context)
 {
 	struct anvil_connection *conn = context;
-	const char *const *args, *line, *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;
+	const char *const *args, *error;
+
+	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)
-			return;
-
-		if (strncmp(line, "VERSION\t", 8) != 0 ||
-		    atoi(t_strcut(line + 8, '\t')) !=
-		    ANVIL_CLIENT_PROTOCOL_MAJOR_VERSION) {
+		if ((args = anvil_connection_next_line(conn)) == NULL)
+			return;
+
+		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 @@ static void anvil_connection_input(void 
 	}
 }
 
-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 @@ void anvil_connection_destroy(struct anv
 	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);
diff -r 5b36fa967538 -r c90ba3f3fa51 src/anvil/anvil-connection.h
--- 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);
diff -r 5b36fa967538 -r c90ba3f3fa51 src/anvil/main.c
--- 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 @@ static void client_connected(const struc
 {
 	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[])


More information about the dovecot-cvs mailing list