dovecot-2.0-sslstream: lmtp proxy: If remote hangs without reply...
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/26eb1b52a23f
changeset: 10341:26eb1b52a23f
user: Timo Sirainen <tss at iki.fi>
date: Tue Nov 17 13:16:11 2009 -0500
description:
lmtp proxy: If remote hangs without replying to end-of-DATA dot, don't crash.
diffstat:
1 file changed, 60 insertions(+), 17 deletions(-)
src/lmtp/lmtp-proxy.c | 77 ++++++++++++++++++++++++++++++++++++++-----------
diffs (92 lines):
diff -r 278d4da53141 -r 26eb1b52a23f src/lmtp/lmtp-proxy.c
--- a/src/lmtp/lmtp-proxy.c Mon Nov 16 20:00:33 2009 -0500
+++ b/src/lmtp/lmtp-proxy.c Tue Nov 17 13:16:11 2009 -0500
@@ -293,28 +293,71 @@ int lmtp_proxy_add_rcpt(struct lmtp_prox
return 0;
}
+static size_t lmtp_proxy_find_max_data_input_size(struct lmtp_proxy *proxy)
+{
+ struct lmtp_proxy_connection *const *conns;
+ unsigned int i, count;
+ size_t size, max_size = 0;
+
+ conns = array_get(&proxy->connections, &count);
+ for (i = 0; i < count; i++) {
+ (void)i_stream_get_data(conns[i]->data_input, &size);
+ if (max_size < size)
+ max_size = size;
+ }
+ return max_size;
+}
+
+static bool lmtp_proxy_disconnect_hanging_output(struct lmtp_proxy *proxy)
+{
+ struct lmtp_proxy_connection *const *conns;
+ unsigned int i, count;
+ size_t size, max_size;
+
+ max_size = lmtp_proxy_find_max_data_input_size(proxy);
+ if (max_size == 0)
+ return FALSE;
+
+ /* disconnect all connections that are keeping us from reading
+ more input. */
+ conns = array_get(&proxy->connections, &count);
+ for (i = 0; i < count; i++) {
+ (void)i_stream_get_data(conns[i]->data_input, &size);
+ if (size == max_size) {
+ lmtp_proxy_conn_deinit(conns[i],
+ ERRSTR_TEMP_REMOTE_FAILURE
+ " (DATA output timeout)");
+ }
+ }
+ 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)
{
- struct lmtp_proxy_connection *const *conns, *max_conn = NULL;
- unsigned int i, count;
- size_t size, max_size = 0;
-
timeout_remove(&proxy->to);
/* drop the connection with the most unread data */
- conns = array_get(&proxy->connections, &count);
- for (i = 0; i < count; i++) {
- (void)i_stream_get_data(conns[i]->data_input, &size);
- if (max_size < size) {
- max_size = size;
- max_conn = conns[i];
- }
- }
- i_assert(max_conn != NULL);
-
- lmtp_proxy_conn_deinit(max_conn, ERRSTR_TEMP_REMOTE_FAILURE
- " (timeout)");
- lmtp_proxy_data_input(proxy);
+ if (lmtp_proxy_disconnect_hanging_output(proxy))
+ lmtp_proxy_data_input(proxy);
+ else {
+ /* 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);
+ }
}
static void lmtp_proxy_wait_for_output(struct lmtp_proxy *proxy)
More information about the dovecot-cvs
mailing list