dovecot-2.0-sslstream: LMTP client API changes. Should be easier...

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 13 02:56:42 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0-sslstream/rev/a144e918938c
changeset: 10399:a144e918938c
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Nov 24 14:17:06 2009 -0500
description:
LMTP client API changes. Should be easier to use now.

diffstat:

3 files changed, 59 insertions(+), 78 deletions(-)
src/lib-lda/lmtp-client.c |   33 ++++++++++-----
src/lib-lda/lmtp-client.h |    8 ++-
src/lmtp/lmtp-proxy.c     |   96 +++++++++++++++------------------------------

diffs (truncated from 304 to 300 lines):

diff -r 9500cfbe5dbf -r a144e918938c src/lib-lda/lmtp-client.c
--- a/src/lib-lda/lmtp-client.c	Tue Nov 24 13:29:02 2009 -0500
+++ b/src/lib-lda/lmtp-client.c	Tue Nov 24 14:17:06 2009 -0500
@@ -49,6 +49,9 @@ struct lmtp_client {
 	struct io *io;
 	int fd;
 
+	lmtp_finish_callback_t *finish_callback;
+	void *finish_context;
+
 	const char *data_header;
 	ARRAY_DEFINE(recipients, struct lmtp_rcpt);
 	unsigned int rcpt_next_receive_idx;
@@ -57,14 +60,16 @@ struct lmtp_client {
 	struct istream *data_input;
 	unsigned char output_last;
 
+	unsigned int rcpt_to_successes:1;
 	unsigned int output_finished:1;
-	unsigned int rcpt_to_successes:1;
+	unsigned int finish_called:1;
 };
 
 static void lmtp_client_send_rcpts(struct lmtp_client *client);
 
 struct lmtp_client *
-lmtp_client_init(const char *mail_from, const char *my_hostname)
+lmtp_client_init(const char *mail_from, const char *my_hostname,
+		 lmtp_finish_callback_t *finish_callback, void *context)
 {
 	struct lmtp_client *client;
 	pool_t pool;
@@ -78,6 +83,8 @@ lmtp_client_init(const char *mail_from, 
 	client->pool = pool;
 	client->mail_from = p_strdup(pool, mail_from);
 	client->my_hostname = p_strdup(pool, my_hostname);
+	client->finish_callback = finish_callback;
+	client->finish_context = context;
 	client->fd = -1;
 	p_array_init(&client->recipients, pool, 16);
 	return client;
@@ -98,6 +105,11 @@ void lmtp_client_close(struct lmtp_clien
 	if (client->data_input != NULL)
 		i_stream_unref(&client->data_input);
 	client->output_finished = TRUE;
+
+	if (!client->finish_called) {
+		client->finish_called = TRUE;
+		client->finish_callback(client->finish_context);
+	}
 }
 
 static void lmtp_client_ref(struct lmtp_client *client)
@@ -201,7 +213,7 @@ static void lmtp_client_send_data_cmd(st
 	}
 }
 
-static bool
+static int
 lmtp_client_data_next(struct lmtp_client *client, const char *line)
 {
 	struct lmtp_rcpt *rcpt;
@@ -214,14 +226,18 @@ lmtp_client_data_next(struct lmtp_client
 			continue;
 		}
 
+		client->rcpt_next_data_idx = i + 1;
 		rcpt[i].failed = line[0] != '2';
 		rcpt[i].data_callback(!rcpt[i].failed, line,
 				      rcpt[i].context);
-		client->rcpt_next_data_idx = i + 1;
 		if (client->protocol == LMTP_CLIENT_PROTOCOL_LMTP)
 			break;
 	}
-	return i < count;
+	if (i < count)
+		return 0;
+
+	lmtp_client_close(client);
+	return -1;
 }
 
 static void lmtp_client_send_data(struct lmtp_client *client)
@@ -379,7 +395,7 @@ static int lmtp_client_input_line(struct
 		break;
 	case LMTP_INPUT_STATE_DATA:
 		/* DATA replies */
-		if (!lmtp_client_data_next(client, line))
+		if (lmtp_client_data_next(client, line) < 0)
 			return -1;
 		break;
 	}
@@ -521,11 +537,6 @@ void lmtp_client_send(struct lmtp_client
 	lmtp_client_send_data_cmd(client);
 }
 
-bool lmtp_client_is_data_input_finished(struct lmtp_client *client)
-{
-	return client->data_input != NULL;
-}
-
 void lmtp_client_send_more(struct lmtp_client *client)
 {
 	if (client->input_state == LMTP_INPUT_STATE_DATA)
diff -r 9500cfbe5dbf -r a144e918938c src/lib-lda/lmtp-client.h
--- a/src/lib-lda/lmtp-client.h	Tue Nov 24 13:29:02 2009 -0500
+++ b/src/lib-lda/lmtp-client.h	Tue Nov 24 14:17:06 2009 -0500
@@ -13,9 +13,13 @@ enum lmtp_client_protocol {
 /* reply contains the reply coming from remote server, or NULL
    if it's a connection error. */
 typedef void lmtp_callback_t(bool success, const char *reply, void *context);
+/* called when session is finished, either because all RCPT TOs failed or
+   because all DATA replies have been received. */
+typedef void lmtp_finish_callback_t(void *context);
 
 struct lmtp_client *
-lmtp_client_init(const char *mail_from, const char *my_hostname);
+lmtp_client_init(const char *mail_from, const char *my_hostname,
+		 lmtp_finish_callback_t *finish_callback, void *context);
 void lmtp_client_deinit(struct lmtp_client **client);
 
 int lmtp_client_connect_tcp(struct lmtp_client *client,
@@ -34,8 +38,6 @@ void lmtp_client_add_rcpt(struct lmtp_cl
 			  lmtp_callback_t *data_callback, void *context);
 /* Start sending input stream as DATA. */
 void lmtp_client_send(struct lmtp_client *client, struct istream *data_input);
-/* Returns TRUE if data_input is no longer needed. */
-bool lmtp_client_is_data_input_finished(struct lmtp_client *client);
 /* Call this function whenever input stream can potentially be read forward.
    This is useful with non-blocking istreams and tee-istreams. */
 void lmtp_client_send_more(struct lmtp_client *client);
diff -r 9500cfbe5dbf -r a144e918938c src/lmtp/lmtp-proxy.c
--- a/src/lmtp/lmtp-proxy.c	Tue Nov 24 13:29:02 2009 -0500
+++ b/src/lmtp/lmtp-proxy.c	Tue Nov 24 14:17:06 2009 -0500
@@ -25,10 +25,6 @@ struct lmtp_proxy_connection {
 	struct lmtp_proxy *proxy;
 	struct lmtp_proxy_settings set;
 
-	/* points to proxy->rcpt_to array. */
-	unsigned int rcpt_next_reply_low_idx;
-	unsigned int data_next_reply_low_idx;
-
 	struct lmtp_client *client;
 	struct istream *data_input;
 	unsigned int failed:1;
@@ -39,7 +35,7 @@ struct lmtp_proxy {
 	const char *mail_from, *my_hostname;
 	ARRAY_DEFINE(connections, struct lmtp_proxy_connection *);
 	ARRAY_DEFINE(rcpt_to, struct lmtp_proxy_recipient);
-	unsigned int rcpt_next_reply_idx;
+	unsigned int next_data_reply_idx;
 
 	struct timeout *to, *to_data_idle;
 	struct io *io;
@@ -55,6 +51,7 @@ struct lmtp_proxy {
 	unsigned int finished:1;
 };
 
+static void lmtp_conn_finish(void *context);
 static void lmtp_proxy_data_input(struct lmtp_proxy *proxy);
 
 struct lmtp_proxy *
@@ -136,7 +133,8 @@ lmtp_proxy_get_connection(struct lmtp_pr
 	conn->set.port = set->port;
 	conn->set.timeout_msecs = set->timeout_msecs;
 	array_append(&proxy->connections, &conn, 1);
-	conn->client = lmtp_client_init(proxy->mail_from, proxy->my_hostname);
+	conn->client = lmtp_client_init(proxy->mail_from, proxy->my_hostname,
+					lmtp_conn_finish, conn);
 	if (lmtp_client_connect_tcp(conn->client, set->protocol,
 				    conn->set.host, conn->set.port) < 0)
 		conn->failed = TRUE;
@@ -146,28 +144,21 @@ lmtp_proxy_get_connection(struct lmtp_pr
 	return conn;
 }
 
-static void lmtp_proxy_conn_close(struct lmtp_proxy_connection *conn)
-{
-	lmtp_client_close(conn->client);
-	if (conn->data_input != NULL)
-		i_stream_unref(&conn->data_input);
-}
-
-static bool lmtp_proxy_send_replies(struct lmtp_proxy *proxy)
+static bool lmtp_proxy_send_data_replies(struct lmtp_proxy *proxy)
 {
 	const struct lmtp_proxy_recipient *rcpt;
 	unsigned int i, count;
 
 	o_stream_cork(proxy->client_output);
 	rcpt = array_get(&proxy->rcpt_to, &count);
-	for (i = proxy->rcpt_next_reply_idx; i < count; i++) {
+	for (i = proxy->next_data_reply_idx; i < count; i++) {
 		if (!(rcpt[i].rcpt_to_failed || rcpt[i].data_reply_received))
 			break;
 		o_stream_send_str(proxy->client_output,
 				  t_strconcat(rcpt[i].reply, "\r\n", NULL));
 	}
 	o_stream_uncork(proxy->client_output);
-	proxy->rcpt_next_reply_idx = i;
+	proxy->next_data_reply_idx = i;
 
 	return i == count;
 }
@@ -182,8 +173,16 @@ static void lmtp_proxy_finish(struct lmt
 
 static void lmtp_proxy_try_finish(struct lmtp_proxy *proxy)
 {
-	if (lmtp_proxy_send_replies(proxy) && proxy->data_input->eof)
+	if (lmtp_proxy_send_data_replies(proxy) && proxy->data_input->eof)
 		lmtp_proxy_finish(proxy);
+}
+
+static void lmtp_conn_finish(void *context)
+{
+	struct lmtp_proxy_connection *conn = context;
+
+	i_stream_unref(&conn->data_input);
+	lmtp_proxy_try_finish(conn->proxy);
 }
 
 static void lmtp_proxy_fail_all(struct lmtp_proxy *proxy, const char *reason)
@@ -229,57 +228,26 @@ static void
 static void
 lmtp_proxy_conn_rcpt_to(bool success, const char *reply, void *context)
 {
-	struct lmtp_proxy_connection *conn = context;
-	struct lmtp_proxy_recipient *rcpt;
-	unsigned int i, count;
-
-	rcpt = array_get_modifiable(&conn->proxy->rcpt_to, &count);
-	for (i = conn->rcpt_next_reply_low_idx; i < count; i++) {
-		if (rcpt[i].conn == conn) {
-			i_assert(rcpt[i].reply == NULL);
-			rcpt[i].reply = p_strdup(conn->proxy->pool, reply);
-			rcpt[i].rcpt_to_failed = !success;
-			conn->rcpt_next_reply_low_idx = i + 1;
-			break;
-		}
-	}
-	i_assert(i != count);
-
-	if (!success && conn->rcpt_next_reply_low_idx == count &&
-	    lmtp_client_is_data_input_finished(conn->client))
-		lmtp_proxy_conn_close(conn);
-
-	/* send replies only if we've already sent DATA. */
-	if (conn->proxy->data_input != NULL)
-		lmtp_proxy_try_finish(conn->proxy);
+	struct lmtp_proxy_recipient *rcpt = context;
+	struct lmtp_proxy_connection *conn = rcpt->conn;
+
+	i_assert(rcpt->reply == NULL);
+
+	rcpt->reply = p_strdup(conn->proxy->pool, reply);
+	rcpt->rcpt_to_failed = !success;
 }
 
 static void
 lmtp_proxy_conn_data(bool success ATTR_UNUSED, const char *reply, void *context)
 {
-	struct lmtp_proxy_connection *conn = context;
-	struct lmtp_proxy_recipient *rcpt;
-	unsigned int i, count;
-
-	i_assert(conn->proxy->data_input != NULL);
-
-	rcpt = array_get_modifiable(&conn->proxy->rcpt_to, &count);
-	for (i = conn->data_next_reply_low_idx; i < count; i++) {
-		if (rcpt[i].conn == conn && !rcpt[i].rcpt_to_failed) {
-			i_assert(rcpt[i].reply != NULL);
-			rcpt[i].reply = p_strdup(conn->proxy->pool, reply);
-			rcpt[i].data_reply_received = TRUE;
-			conn->data_next_reply_low_idx = i + 1;
-			break;
-		}
-	}
-	i_assert(i != count);
-
-	if (conn->data_next_reply_low_idx == count &&
-	    lmtp_client_is_data_input_finished(conn->client))
-		lmtp_proxy_conn_close(conn);
-
-	lmtp_proxy_try_finish(conn->proxy);
+	struct lmtp_proxy_recipient *rcpt = context;
+	struct lmtp_proxy_connection *conn = rcpt->conn;
+
+	i_assert(!rcpt->rcpt_to_failed);
+	i_assert(rcpt->reply != NULL);
+
+	rcpt->reply = p_strdup(conn->proxy->pool, reply);
+	rcpt->data_reply_received = TRUE;
 }
 
 int lmtp_proxy_add_rcpt(struct lmtp_proxy *proxy, const char *address,
@@ -297,7 +265,7 @@ int lmtp_proxy_add_rcpt(struct lmtp_prox
 	rcpt->address = p_strdup(proxy->pool, address);
 
 	lmtp_client_add_rcpt(conn->client, address, lmtp_proxy_conn_rcpt_to,
-			     lmtp_proxy_conn_data, conn);


More information about the dovecot-cvs mailing list