Mercurial > dovecot > core-2.2
changeset 10277:09dd23dd6ee0 HEAD
lmtp client: Handle failures better.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 09 Nov 2009 14:59:54 -0500 |
parents | e556ff1dbab1 |
children | 84a1776dd1c3 |
files | src/lib-lda/lmtp-client.c |
diffstat | 1 files changed, 39 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- 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 { pool_t pool; const char *mail_from; + int refcount; const char *my_hostname; const char *host; @@ -41,6 +42,7 @@ 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 @@ 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 @@ 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,7 +117,7 @@ *_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) @@ -108,18 +125,24 @@ 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++) { recipients[i].rcpt_to_callback(FALSE, line, 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 @@ { 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 @@ { 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 @@ 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 @@ 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"); }