dovecot-2.0-sslstream: lmtp client: Handle failures better.

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


details:   http://hg.dovecot.org/dovecot-2.0-sslstream/rev/09dd23dd6ee0
changeset: 10278:09dd23dd6ee0
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Nov 09 14:59:54 2009 -0500
description:
lmtp client: Handle failures better.

diffstat:

1 file changed, 39 insertions(+), 4 deletions(-)
src/lib-lda/lmtp-client.c |   43 +++++++++++++++++++++++++++++++++++++++----

diffs (147 lines):

diff -r e556ff1dbab1 -r 09dd23dd6ee0 src/lib-lda/lmtp-client.c
--- a/src/lib-lda/lmtp-client.c	Mon Nov 09 14:34:22 2009 -0500
+++ b/src/lib-lda/lmtp-client.c	Mon Nov 09 14:59:54 2009 -0500
@@ -34,6 +34,7 @@ struct lmtp_client {
 struct lmtp_client {
 	pool_t pool;
 	const char *mail_from;
+	int refcount;
 
 	const char *my_hostname;
 	const char *host;
@@ -41,6 +42,7 @@ struct lmtp_client {
 	unsigned int port;
 	enum lmtp_client_protocol protocol;
 	enum lmtp_input_state input_state;
+	const char *global_fail_string;
 
 	struct istream *input;
 	struct ostream *output;
@@ -66,9 +68,11 @@ lmtp_client_init(const char *mail_from, 
 	pool_t pool;
 
 	i_assert(*mail_from == '<');
+	i_assert(*my_hostname != '\0');
 
 	pool = pool_alloconly_create("lmtp client", 512);
 	client = p_new(pool, struct lmtp_client, 1);
+	client->refcount = 1;
 	client->pool = pool;
 	client->mail_from = p_strdup(pool, mail_from);
 	client->my_hostname = p_strdup(pool, my_hostname);
@@ -93,6 +97,19 @@ static void lmtp_client_close(struct lmt
 		i_stream_unref(&client->data_input);
 }
 
+static void lmtp_client_ref(struct lmtp_client *client)
+{
+	pool_ref(client->pool);
+}
+
+static void lmtp_client_unref(struct lmtp_client **_client)
+{
+	struct lmtp_client *client = *_client;
+
+	*_client = NULL;
+	pool_unref(&client->pool);
+}
+
 void lmtp_client_deinit(struct lmtp_client **_client)
 {
 	struct lmtp_client *client = *_client;
@@ -100,13 +117,15 @@ void lmtp_client_deinit(struct lmtp_clie
 	*_client = NULL;
 
 	lmtp_client_close(client);
-	pool_unref(&client->pool);
+	lmtp_client_unref(&client);
 }
 
 static 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);
 
 	recipients = array_get_modifiable(&client->recipients, &count);
 	for (i = client->rcpt_next_receive_idx; i < count; i++) {
@@ -114,12 +133,16 @@ static void lmtp_client_fail(struct lmtp
 					       recipients[i].context);
 		recipients[i].failed = TRUE;
 	}
+	client->rcpt_next_receive_idx = count;
+
 	for (i = client->rcpt_next_data_idx; i < count; i++) {
 		if (!recipients[i].failed) {
 			recipients[i].data_callback(FALSE, line,
 						    recipients[i].context);
 		}
 	}
+	client->rcpt_next_data_idx = count;
+
 	lmtp_client_close(client);
 }
 
@@ -337,15 +360,19 @@ static void lmtp_client_input(struct lmt
 {
 	const char *line;
 
+	lmtp_client_ref(client);
 	while ((line = i_stream_read_next_line(client->input)) != NULL) {
-		if (lmtp_client_input_line(client, line) < 0)
+		if (lmtp_client_input_line(client, line) < 0) {
+			lmtp_client_unref(&client);
 			return;
+		}
 	}
 
 	if (client->input->stream_errno != 0) {
 		errno = client->input->stream_errno;
 		i_error("lmtp client: read() failed: %m");
 	}
+	lmtp_client_unref(&client);
 }
 
 static void lmtp_client_wait_connect(struct lmtp_client *client)
@@ -369,6 +396,7 @@ static int lmtp_client_output(struct lmt
 {
 	int ret;
 
+	lmtp_client_ref(client);
 	o_stream_cork(client->output);
 	if ((ret = o_stream_flush(client->output)) < 0)
 		lmtp_client_fail(client, ERRSTR_TEMP_REMOTE_FAILURE
@@ -376,6 +404,7 @@ static int lmtp_client_output(struct lmt
 	else if (client->input_state == LMTP_INPUT_STATE_DATA)
 		lmtp_client_send_data(client);
 	o_stream_uncork(client->output);
+	lmtp_client_unref(&client);
 	return ret;
 }
 
@@ -433,16 +462,22 @@ void lmtp_client_add_rcpt(struct lmtp_cl
 	rcpt->data_callback = data_callback;
 	rcpt->context = context;
 
-	if (client->input_state == LMTP_INPUT_STATE_RCPT_TO)
+	if (client->global_fail_string != NULL)
+		rcpt_to_callback(FALSE, client->global_fail_string, context);
+	else if (client->input_state == LMTP_INPUT_STATE_RCPT_TO)
 		lmtp_client_send_rcpts(client);
 }
 
 void lmtp_client_send(struct lmtp_client *client, struct istream *data_input)
 {
+	unsigned int rcpt_count = array_count(&client->recipients);
+
 	i_stream_ref(data_input);
 	client->data_input = data_input;
 
-	if (client->rcpt_next_receive_idx == array_count(&client->recipients)) {
+	if (client->global_fail_string != NULL) {
+		lmtp_client_fail(client, client->global_fail_string);
+	} else if (client->rcpt_next_receive_idx == rcpt_count) {
 		client->input_state++;
 		o_stream_send_str(client->output, "DATA\r\n");
 	}


More information about the dovecot-cvs mailing list