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