]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lmtp: Error handling fixes.
authorTimo Sirainen <tss@iki.fi>
Mon, 23 Nov 2009 23:19:01 +0000 (18:19 -0500)
committerTimo Sirainen <tss@iki.fi>
Mon, 23 Nov 2009 23:19:01 +0000 (18:19 -0500)
--HG--
branch : HEAD

src/lib-lda/lmtp-client.c
src/lib-lda/lmtp-client.h
src/lmtp/lmtp-proxy.c

index 3ac4d300ec9a95a4163a1b9646164aa7aae9f32a..01ee4167e5309f394622b16cff49a69d78a571ea 100644 (file)
@@ -502,9 +502,14 @@ void lmtp_client_add_rcpt(struct lmtp_client *client, const char *address,
        rcpt->data_callback = data_callback;
        rcpt->context = context;
 
-       if (client->global_fail_string != NULL)
+       if (client->global_fail_string != NULL) {
+               client->rcpt_next_receive_idx++;
+               i_assert(client->rcpt_next_receive_idx ==
+                        array_count(&client->recipients));
+
+               rcpt->failed = TRUE;
                rcpt_to_callback(FALSE, client->global_fail_string, context);
-       else if (client->input_state == LMTP_INPUT_STATE_RCPT_TO)
+       else if (client->input_state == LMTP_INPUT_STATE_RCPT_TO)
                lmtp_client_send_rcpts(client);
 }
 
@@ -516,6 +521,11 @@ void lmtp_client_send(struct lmtp_client *client, struct istream *data_input)
        lmtp_client_send_data_cmd(client);
 }
 
+bool lmtp_client_is_data_input_finished(struct lmtp_client *client)
+{
+       return client->data_input != NULL;
+}
+
 void lmtp_client_send_more(struct lmtp_client *client)
 {
        if (client->input_state == LMTP_INPUT_STATE_DATA)
index 115c4833f95b14990cacb85b4c013420ffcb9a6e..2b9b1e8ccb4c9f8b90ef65dacf673e7bdf51bafc 100644 (file)
@@ -33,6 +33,8 @@ void lmtp_client_add_rcpt(struct lmtp_client *client, const char *address,
                          lmtp_callback_t *data_callback, void *context);
 /* Start sending input stream as DATA. */
 void lmtp_client_send(struct lmtp_client *client, struct istream *data_input);
+/* Returns TRUE if data_input is no longer needed. */
+bool lmtp_client_is_data_input_finished(struct lmtp_client *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);
index 4b62aea7498b92f8cb3749efaffca048afef1140..4876b01675378472243c919efc315c83ae15a33d 100644 (file)
@@ -55,8 +55,6 @@ struct lmtp_proxy {
        unsigned int finished:1;
 };
 
-static void lmtp_proxy_conn_deinit(struct lmtp_proxy_connection *conn,
-                                  const char *reason);
 static void lmtp_proxy_data_input(struct lmtp_proxy *proxy);
 
 struct lmtp_proxy *
@@ -84,7 +82,7 @@ static void lmtp_proxy_connections_deinit(struct lmtp_proxy *proxy)
 
        conns = array_get(&proxy->connections, &count);
        for (i = 0; i < count; i++)
-               lmtp_proxy_conn_deinit(conns[i], "451 4.3.0 Aborting");
+               lmtp_client_fail(conns[i]->client, "451 4.3.0 Aborting");
 }
 
 void lmtp_proxy_deinit(struct lmtp_proxy **_proxy)
@@ -146,22 +144,12 @@ lmtp_proxy_get_connection(struct lmtp_proxy *proxy,
        return conn;
 }
 
-static void lmtp_proxy_conn_deinit(struct lmtp_proxy_connection *conn,
-                                  const char *reason)
+static void lmtp_proxy_conn_close(struct lmtp_proxy_connection *conn)
 {
-       struct lmtp_proxy_recipient *rcpt;
-
-       /* set failure replies to all recipients in this connection */
-       array_foreach_modifiable(&conn->proxy->rcpt_to, rcpt) {
-               if (rcpt->conn == conn && !rcpt->rcpt_to_failed)
-                       rcpt->reply = reason;
-       }
-
        if (conn->client != NULL)
                lmtp_client_deinit(&conn->client);
        if (conn->data_input != NULL)
                i_stream_unref(&conn->data_input);
-       conn->failed = TRUE;
 }
 
 static bool lmtp_proxy_send_replies(struct lmtp_proxy *proxy)
@@ -256,6 +244,10 @@ lmtp_proxy_conn_rcpt_to(bool success, const char *reply, void *context)
        }
        i_assert(i != count);
 
+       if (!success && conn->rcpt_next_reply_low_idx == count &&
+           lmtp_client_is_data_input_finished(conn->client))
+               lmtp_proxy_conn_close(conn);
+
        /* send replies only if we've already sent DATA. */
        if (conn->proxy->data_input != NULL)
                lmtp_proxy_try_finish(conn->proxy);
@@ -281,6 +273,11 @@ lmtp_proxy_conn_data(bool success ATTR_UNUSED, const char *reply, void *context)
                }
        }
        i_assert(i != count);
+
+       if (conn->data_next_reply_low_idx == count &&
+           lmtp_client_is_data_input_finished(conn->client))
+               lmtp_proxy_conn_close(conn);
+
        lmtp_proxy_try_finish(conn->proxy);
 }
 
@@ -334,9 +331,9 @@ static bool lmtp_proxy_disconnect_hanging_output(struct lmtp_proxy *proxy)
        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)");
+                       lmtp_client_fail(conns[i]->client,
+                                        ERRSTR_TEMP_REMOTE_FAILURE
+                                        " (DATA output timeout)");
                }
        }
        return TRUE;