Mercurial > dovecot > core-2.2
changeset 18301:9a384f83b2a3
lib-lda: lmtp client now supports checking for timeouts internally.
The default is still to have no timeout.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 06 Mar 2015 16:30:55 +0200 |
parents | 0effbc9afeee |
children | bf2dbc8ec74b |
files | src/lib-lda/lmtp-client.c src/lib-lda/lmtp-client.h |
diffstat | 2 files changed, 50 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-lda/lmtp-client.c Fri Mar 06 11:55:45 2015 +0200 +++ b/src/lib-lda/lmtp-client.c Fri Mar 06 16:30:55 2015 +0200 @@ -55,6 +55,7 @@ struct istream *input; struct ostream *output; struct io *io; + struct timeout *to; int fd; void (*data_output_callback)(void *); @@ -103,6 +104,7 @@ client->set.source_port = set->source_port; client->set.proxy_ttl = set->proxy_ttl; client->set.proxy_timeout_secs = set->proxy_timeout_secs; + client->set.timeout_secs = set->timeout_secs; client->finish_callback = finish_callback; client->finish_context = context; client->fd = -1; @@ -115,6 +117,8 @@ { if (client->dns_lookup != NULL) dns_lookup_abort(&client->dns_lookup); + if (client->to != NULL) + timeout_remove(&client->to); if (client->io != NULL) io_remove(&client->io); if (client->input != NULL) @@ -604,6 +608,8 @@ " (disconnected in input)"); } o_stream_uncork(client->output); + if (client->to != NULL) + timeout_reset(client->to); lmtp_client_unref(&client); } @@ -619,11 +625,21 @@ " (connect)"); return; } + if (client->to != NULL) + timeout_remove(&client->to); io_remove(&client->io); client->io = io_add(client->fd, IO_READ, lmtp_client_input, client); lmtp_client_input(client); } +static void lmtp_client_connect_timeout(struct lmtp_client *client) +{ + i_error("lmtp client: connect(%s, %u) failed: Timed out in %u secs", + client->host, client->port, client->set.timeout_secs); + lmtp_client_fail(client, ERRSTR_TEMP_REMOTE_FAILURE + " (connect timeout)"); +} + static int lmtp_client_output(struct lmtp_client *client) { int ret; @@ -636,12 +652,16 @@ else if (client->input_state == LMTP_INPUT_STATE_DATA) (void)lmtp_client_send_data(client); o_stream_uncork(client->output); + if (client->to != NULL) + timeout_reset(client->to); lmtp_client_unref(&client); return ret; } static int lmtp_client_connect(struct lmtp_client *client) { + i_assert(client->fd == -1); + client->fd = net_connect_ip(&client->ip, client->port, NULL); if (client->fd == -1) { i_error("lmtp client: connect(%s, %u) failed: %m", @@ -656,6 +676,10 @@ /* we're already sending data in ostream, so can't use IO_WRITE here */ client->io = io_add(client->fd, IO_READ, lmtp_client_wait_connect, client); + if (client->set.timeout_secs > 0) { + client->to = timeout_add(client->set.timeout_secs*1000, + lmtp_client_connect_timeout, client); + } return 0; } @@ -808,11 +832,34 @@ lmtp_client_send_rcpts(client); } +static void lmtp_client_timeout(struct lmtp_client *client) +{ + const char *line; + + line = t_strdup_printf(ERRSTR_TEMP_REMOTE_FAILURE + " (Timed out after %u secs while waiting for reply to %s)", + client->set.timeout_secs, lmtp_client_state_to_string(client)); + lmtp_client_fail(client, line); +} + void lmtp_client_send(struct lmtp_client *client, struct istream *data_input) { + i_assert(client->data_input == NULL); + i_stream_ref(data_input); client->data_input = data_input; + /* now we actually want to start doing I/O. start the timeout + handling. */ + if (client->set.timeout_secs > 0) { + if (client->to != NULL) { + /* still waiting for connect to finish */ + timeout_remove(&client->to); + } + client->to = timeout_add(client->set.timeout_secs*1000, + lmtp_client_timeout, client); + } + (void)lmtp_client_send_data_cmd(client); }
--- a/src/lib-lda/lmtp-client.h Fri Mar 06 11:55:45 2015 +0200 +++ b/src/lib-lda/lmtp-client.h Fri Mar 06 16:30:55 2015 +0200 @@ -42,6 +42,9 @@ this many seconds, so it should try to keep lock waits and such lower than this. */ unsigned int proxy_timeout_secs; + /* Don't wait an answer from destination server longer than this many + seconds (0 = unlimited) */ + unsigned int timeout_secs; }; /* reply contains the reply coming from remote server, or NULL