]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lmtp proxy: More error handling fixes.
authorTimo Sirainen <tss@iki.fi>
Tue, 24 Nov 2009 20:11:13 +0000 (15:11 -0500)
committerTimo Sirainen <tss@iki.fi>
Tue, 24 Nov 2009 20:11:13 +0000 (15:11 -0500)
--HG--
branch : HEAD

src/lmtp/commands.c
src/lmtp/lmtp-proxy.c
src/lmtp/lmtp-proxy.h

index 4088c82a77ea04f53a77aa333ee5b8d4c549c960..a700929b4911aa5e28f51c98f922a2b8a1359b5a 100644 (file)
@@ -637,12 +637,18 @@ static void client_input_data_finish(struct client *client)
                client_input_handle(client);
 }
 
-static void client_proxy_finish(void *context)
+static void client_proxy_finish(bool timeout, void *context)
 {
        struct client *client = context;
 
        lmtp_proxy_deinit(&client->proxy);
-       client_input_data_finish(client);
+       if (timeout) {
+               client_destroy(client,
+                       t_strdup_printf("421 4.4.2 %s", client->my_domain),
+                       "Disconnected for inactivity");
+       } else {
+               client_input_data_finish(client);
+       }
 }
 
 static const char *client_get_received_line(struct client *client)
index 76d04a88c0113df76e199ac86cd8f0cfde122202..186d62831acfc6d829152156bcc5b56573a989ac 100644 (file)
@@ -39,16 +39,17 @@ struct lmtp_proxy {
 
        struct timeout *to, *to_data_idle;
        struct io *io;
-       struct istream *data_input;
+       struct istream *data_input, *orig_data_input;
        struct ostream *client_output;
        struct tee_istream *tee_data_input;
 
        unsigned int max_timeout_msecs;
 
-       void (*finish_callback)(void *);
+       lmtp_proxy_finish_callback_t *finish_callback;
        void *finish_context;
 
        unsigned int finished:1;
+       unsigned int input_timeout:1;
 };
 
 static void lmtp_conn_finish(void *context);
@@ -168,12 +169,13 @@ static void lmtp_proxy_finish(struct lmtp_proxy *proxy)
        i_assert(!proxy->finished);
 
        proxy->finished = TRUE;
-       proxy->finish_callback(proxy->finish_context);
+       proxy->finish_callback(proxy->input_timeout, proxy->finish_context);
 }
 
 static void lmtp_proxy_try_finish(struct lmtp_proxy *proxy)
 {
-       if (lmtp_proxy_send_data_replies(proxy) && proxy->data_input->eof)
+       if (lmtp_proxy_send_data_replies(proxy) &&
+           (proxy->data_input->eof || proxy->data_input->stream_errno != 0))
                lmtp_proxy_finish(proxy);
 }
 
@@ -200,12 +202,12 @@ static void lmtp_proxy_fail_all(struct lmtp_proxy *proxy, const char *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;
-               }
+               if (!array_is_created(&proxy->connections))
+                       break;
        }
-       i_unreached();
+       pool_unref(&proxy->pool);
+       /* either the whole proxy is destroyed now, or we still have some
+          DATA input to read. */
 }
 
 static void lmtp_proxy_data_input_timeout(struct lmtp_proxy *proxy)
@@ -213,6 +215,9 @@ static void lmtp_proxy_data_input_timeout(struct lmtp_proxy *proxy)
        struct lmtp_proxy_connection *const *conns;
        unsigned int i, count;
 
+       proxy->input_timeout = TRUE;
+       i_stream_close(proxy->orig_data_input);
+
        pool_ref(proxy->pool);
        conns = array_get(&proxy->connections, &count);
        for (i = 0; i < count; i++) {
@@ -223,6 +228,7 @@ static void lmtp_proxy_data_input_timeout(struct lmtp_proxy *proxy)
                        return;
                }
        }
+       /* last client failure should have caused the proxy to be destroyed */
        i_unreached();
 }
 
@@ -389,13 +395,14 @@ static void lmtp_proxy_data_input(struct lmtp_proxy *proxy)
 
 void lmtp_proxy_start(struct lmtp_proxy *proxy, struct istream *data_input,
                      const char *header,
-                     void (*finish_callback)(void *), void *context)
+                     lmtp_proxy_finish_callback_t *callback, void *context)
 {
        struct lmtp_proxy_connection *const *conns;
        unsigned int i, count;
 
-       proxy->finish_callback = finish_callback;
+       proxy->finish_callback = callback;
        proxy->finish_context = context;
+       proxy->orig_data_input = data_input;
        proxy->tee_data_input = tee_i_stream_create(data_input);
        proxy->data_input = tee_i_stream_create_child(proxy->tee_data_input);
        proxy->to_data_idle = timeout_add(LMTP_PROXY_DATA_INPUT_TIMEOUT_MSECS,
index 1208117351db319c5497ca6f8dd3e22dbc769dc1..fdcbc02131181049ad6e50f45fd890845c2211c4 100644 (file)
@@ -11,6 +11,8 @@ struct lmtp_proxy_settings {
        enum lmtp_client_protocol protocol;
 };
 
+typedef void lmtp_proxy_finish_callback_t(bool timeout, void *context);
+
 struct lmtp_proxy *
 lmtp_proxy_init(const char *my_hostname, struct ostream *client_output);
 void lmtp_proxy_deinit(struct lmtp_proxy **proxy);
@@ -24,6 +26,6 @@ int lmtp_proxy_add_rcpt(struct lmtp_proxy *proxy, const char *address,
 /* Start proxying */
 void lmtp_proxy_start(struct lmtp_proxy *proxy, struct istream *data_input,
                      const char *header,
-                     void (*finish_callback)(void *), void *context);
+                     lmtp_proxy_finish_callback_t *callback, void *context);
 
 #endif