dovecot-2.0-sslstream: lmtp proxy: Fixes to error handling.

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


details:   http://hg.dovecot.org/dovecot-2.0-sslstream/rev/d784be144b4d
changeset: 10342:d784be144b4d
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Nov 17 13:47:14 2009 -0500
description:
lmtp proxy: Fixes to error handling.

diffstat:

3 files changed, 65 insertions(+), 44 deletions(-)
src/lib-lda/lmtp-client.c |   23 ++++++++++++
src/lib-lda/lmtp-client.h |    5 ++
src/lmtp/lmtp-proxy.c     |   81 +++++++++++++++++++++------------------------

diffs (183 lines):

diff -r 26eb1b52a23f -r d784be144b4d src/lib-lda/lmtp-client.c
--- a/src/lib-lda/lmtp-client.c	Tue Nov 17 13:16:11 2009 -0500
+++ b/src/lib-lda/lmtp-client.c	Tue Nov 17 13:47:14 2009 -0500
@@ -122,13 +122,33 @@ void lmtp_client_deinit(struct lmtp_clie
 	lmtp_client_unref(&client);
 }
 
-static void lmtp_client_fail(struct lmtp_client *client, const char *line)
+const char *lmtp_client_state_to_string(struct lmtp_client *client)
+{
+	switch (client->input_state) {
+	case LMTP_INPUT_STATE_GREET:
+		return "greeting";
+	case LMTP_INPUT_STATE_LHLO:
+		return "LHLO";
+	case LMTP_INPUT_STATE_MAIL_FROM:
+		return "MAIL FROM";
+	case LMTP_INPUT_STATE_RCPT_TO:
+		return "RCPT TO";
+	case LMTP_INPUT_STATE_DATA_CONTINUE:
+		return "DATA";
+	case LMTP_INPUT_STATE_DATA:
+		return "end-of-DATA";
+	}
+	return "??";
+}
+
+void lmtp_client_fail(struct lmtp_client *client, const char *line)
 {
 	struct lmtp_rcpt *recipients;
 	unsigned int i, count;
 
 	client->global_fail_string = p_strdup(client->pool, line);
 
+	lmtp_client_ref(client);
 	recipients = array_get_modifiable(&client->recipients, &count);
 	for (i = client->rcpt_next_receive_idx; i < count; i++) {
 		recipients[i].rcpt_to_callback(FALSE, line,
@@ -146,6 +166,7 @@ static void lmtp_client_fail(struct lmtp
 	client->rcpt_next_data_idx = count;
 
 	lmtp_client_close(client);
+	lmtp_client_unref(&client);
 }
 
 static void
diff -r 26eb1b52a23f -r d784be144b4d src/lib-lda/lmtp-client.h
--- a/src/lib-lda/lmtp-client.h	Tue Nov 17 13:16:11 2009 -0500
+++ b/src/lib-lda/lmtp-client.h	Tue Nov 17 13:47:14 2009 -0500
@@ -36,5 +36,10 @@ void lmtp_client_send(struct lmtp_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);
+/* Fail the connection with line as the reply to unfinished RCPT TO/DATA
+   replies. */
+void lmtp_client_fail(struct lmtp_client *client, const char *line);
+/* Return the state (command reply) the client is currently waiting for. */
+const char *lmtp_client_state_to_string(struct lmtp_client *client);
 
 #endif
diff -r 26eb1b52a23f -r d784be144b4d src/lmtp/lmtp-proxy.c
--- a/src/lmtp/lmtp-proxy.c	Tue Nov 17 13:16:11 2009 -0500
+++ b/src/lmtp/lmtp-proxy.c	Tue Nov 17 13:47:14 2009 -0500
@@ -197,34 +197,44 @@ static void lmtp_proxy_try_finish(struct
 		lmtp_proxy_finish(proxy);
 }
 
-static void lmtp_proxy_fail_all(struct lmtp_proxy *proxy, const char *line)
-{
-	struct lmtp_proxy_recipient *rcpt;
-	unsigned int i, count;
-	bool ret;
-
-	rcpt = array_get_modifiable(&proxy->rcpt_to, &count);
-	for (i = proxy->rcpt_next_reply_idx; i < count; i++) {
-		if (!rcpt[i].rcpt_to_failed) {
-			i_assert(!rcpt[i].data_reply_received);
-			rcpt[i].reply = line;
-			rcpt[i].data_reply_received = TRUE;
-		}
-	}
-	ret = lmtp_proxy_send_replies(proxy);
-	i_assert(ret);
-
-	lmtp_proxy_finish(proxy);
+static void lmtp_proxy_fail_all(struct lmtp_proxy *proxy, const char *reason)
+{
+	struct lmtp_proxy_connection *const *conns;
+	unsigned int i, count;
+	const char *line;
+
+	pool_ref(proxy->pool);
+	conns = array_get(&proxy->connections, &count);
+	for (i = 0; i < count; i++) {
+		line = t_strdup_printf(ERRSTR_TEMP_REMOTE_FAILURE
+				" (%s while waiting for reply to %s)", reason,
+				lmtp_client_state_to_string(conns[i]->client));
+		lmtp_client_fail(conns[i]->client, line);
+
+		if (!array_is_created(&proxy->connections)) {
+			pool_unref(&proxy->pool);
+			return;
+		}
+	}
+	i_unreached();
 }
 
 static void lmtp_proxy_data_input_timeout(struct lmtp_proxy *proxy)
 {
-	lmtp_proxy_fail_all(proxy, "451 4.4.2 Input timeout in DATA");
-}
-
-static void lmtp_proxy_data_disconnected(struct lmtp_proxy *proxy)
-{
-	lmtp_proxy_fail_all(proxy, "451 4.4.2 Client disconnected in DATA");
+	struct lmtp_proxy_connection *const *conns;
+	unsigned int i, count;
+
+	pool_ref(proxy->pool);
+	conns = array_get(&proxy->connections, &count);
+	for (i = 0; i < count; i++) {
+		lmtp_client_fail(conns[i]->client, ERRSTR_TEMP_REMOTE_FAILURE
+				 " (timeout in DATA input)");
+		if (!array_is_created(&proxy->connections)) {
+			pool_unref(&proxy->pool);
+			return;
+		}
+	}
+	i_unreached();
 }
 
 static void
@@ -332,18 +342,6 @@ static bool lmtp_proxy_disconnect_hangin
 	return TRUE;
 }
 
-static void lmtp_proxy_disconnect_unfinished(struct lmtp_proxy *proxy)
-{
-	struct lmtp_proxy_connection *const *conns;
-	unsigned int i, count;
-
-	conns = array_get(&proxy->connections, &count);
-	for (i = 0; i < count; i++) {
-		lmtp_client_fail(conns[i]->client, ERRSTR_TEMP_REMOTE_FAILURE
-				 " (DATA input timeout)");
-	}
-}
-
 static void lmtp_proxy_output_timeout(struct lmtp_proxy *proxy)
 {
 	timeout_remove(&proxy->to);
@@ -355,8 +353,7 @@ static void lmtp_proxy_output_timeout(st
 		/* no such connection, so we've already sent everything but
 		   some servers aren't replying to us. disconnect all of
 		   them. */
-		lmtp_proxy_disconnect_unfinished(proxy);
-		lmtp_proxy_try_finish(proxy);
+		lmtp_proxy_fail_all(proxy, "timeout");
 	}
 }
 
@@ -366,10 +363,8 @@ static void lmtp_proxy_wait_for_output(s
 
 	if (proxy->io != NULL)
 		io_remove(&proxy->io);
-	if (array_count(&proxy->connections) > 1) {
-		proxy->to = timeout_add(proxy->max_timeout_msecs,
-					lmtp_proxy_output_timeout, proxy);
-	}
+	proxy->to = timeout_add(proxy->max_timeout_msecs,
+				lmtp_proxy_output_timeout, proxy);
 }
 
 static bool lmtp_proxy_data_read(struct lmtp_proxy *proxy)
@@ -385,7 +380,7 @@ static bool lmtp_proxy_data_read(struct 
 		return FALSE;
 	case -1:
 		if (proxy->data_input->stream_errno != 0)
-			lmtp_proxy_data_disconnected(proxy);
+			lmtp_proxy_fail_all(proxy, "disconnect");
 		else {
 			/* finished reading data input. now we'll just have to
 			   wait for replies. */


More information about the dovecot-cvs mailing list