dovecot-2.0: lmtp client, proxy: Several bugfixes.
dovecot at dovecot.org
dovecot at dovecot.org
Tue Sep 8 20:28:52 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/22d27318bb18
changeset: 9900:22d27318bb18
user: Timo Sirainen <tss at iki.fi>
date: Tue Sep 08 13:28:40 2009 -0400
description:
lmtp client, proxy: Several bugfixes.
diffstat:
5 files changed, 131 insertions(+), 66 deletions(-)
src/lib-lda/lmtp-client.c | 96 +++++++++++++++++++++++++++++----------------
src/lib-lda/lmtp-client.h | 2
src/lmtp/commands.c | 25 ++++++++++-
src/lmtp/lmtp-proxy.c | 70 +++++++++++++++++++-------------
src/lmtp/lmtp-proxy.h | 4 -
diffs (truncated from 446 to 300 lines):
diff -r 6e5cc5d4cec4 -r 22d27318bb18 src/lib-lda/lmtp-client.c
--- a/src/lib-lda/lmtp-client.c Mon Sep 07 12:06:15 2009 -0400
+++ b/src/lib-lda/lmtp-client.c Tue Sep 08 13:28:40 2009 -0400
@@ -53,6 +53,8 @@ struct lmtp_client {
unsigned int rcpt_next_send_idx;
struct istream *data_input;
unsigned char output_last;
+
+ unsigned int output_finished:1;
};
static void lmtp_client_send_rcpts(struct lmtp_client *client);
@@ -124,36 +126,52 @@ static bool
static bool
lmtp_client_rcpt_next(struct lmtp_client *client, const char *line)
{
- struct lmtp_rcpt *recipients;
+ struct lmtp_rcpt *rcpt;
+ bool success, all_sent;
+
+ success = line[0] == '2';
+
+ rcpt = array_idx_modifiable(&client->recipients,
+ client->rcpt_next_receive_idx);
+ rcpt->failed = !success;
+ rcpt->rcpt_to_callback(success, line, rcpt->context);
+
+ all_sent = ++client->rcpt_next_receive_idx ==
+ array_count(&client->recipients);
+ return all_sent && client->data_input != NULL;
+}
+
+static bool
+lmtp_client_data_next(struct lmtp_client *client, const char *line)
+{
+ struct lmtp_rcpt *rcpt;
unsigned int i, count;
- bool success, all_sent;
-
- success = line[0] == '2';
-
- recipients = array_get_modifiable(&client->recipients, &count);
- for (i = client->rcpt_next_receive_idx; i < count; i++) {
- recipients[i].failed = !success;
- recipients[i].rcpt_to_callback(success, line,
- recipients[i].context);
- }
- all_sent = i == client->rcpt_next_receive_idx;
- client->rcpt_next_receive_idx = i;
- return all_sent && client->data_input != NULL;
-}
-
-static int
-lmtp_client_data_next(struct lmtp_client *client, const char *line)
-{
- struct lmtp_rcpt *rcpt;
bool last;
- rcpt = array_idx_modifiable(&client->recipients,
- client->rcpt_next_data_idx);
- rcpt->failed = line[0] != '2';
- last = ++client->rcpt_next_data_idx == array_count(&client->recipients);
-
- rcpt->data_callback(!rcpt->failed, line, rcpt->context);
- return last ? -1 : 0;
+ switch (client->protocol) {
+ case LMTP_CLIENT_PROTOCOL_SMTP:
+ i_assert(client->rcpt_next_data_idx == 0);
+
+ rcpt = array_get_modifiable(&client->recipients, &count);
+ for (i = 0; i < count; i++) {
+ rcpt[i].failed = line[0] != '2';
+ rcpt[i].data_callback(!rcpt->failed, line,
+ rcpt[i].context);
+ }
+ client->rcpt_next_data_idx = count;
+ last = TRUE;
+ break;
+ case LMTP_CLIENT_PROTOCOL_LMTP:
+ rcpt = array_idx_modifiable(&client->recipients,
+ client->rcpt_next_data_idx);
+ rcpt->failed = line[0] != '2';
+ last = ++client->rcpt_next_data_idx ==
+ array_count(&client->recipients);
+
+ rcpt->data_callback(!rcpt->failed, line, rcpt->context);
+ break;
+ }
+ return !last;
}
static void lmtp_client_send_data(struct lmtp_client *client)
@@ -162,6 +180,9 @@ static void lmtp_client_send_data(struct
unsigned char add;
size_t i, size;
int ret;
+
+ if (client->output_finished)
+ return;
while ((ret = i_stream_read_data(client->data_input,
&data, &size, 0)) > 0) {
@@ -216,6 +237,7 @@ static void lmtp_client_send_data(struct
(void)o_stream_send(client->output, "\r\n", 2);
}
(void)o_stream_send(client->output, ".\r\n", 3);
+ client->output_finished = TRUE;
}
static void lmtp_client_send_handshake(struct lmtp_client *client)
@@ -289,8 +311,9 @@ static int lmtp_client_input_line(struct
case LMTP_INPUT_STATE_RCPT_TO:
if (!lmtp_client_rcpt_next(client, line))
break;
- /* fall through */
- client->input_state++;
+ client->input_state++;
+ o_stream_send_str(client->output, "DATA\r\n");
+ break;
case LMTP_INPUT_STATE_DATA_CONTINUE:
/* Start sending DATA */
if (strncmp(line, "354", 3) != 0) {
@@ -304,7 +327,7 @@ static int lmtp_client_input_line(struct
break;
case LMTP_INPUT_STATE_DATA:
/* DATA replies */
- if (lmtp_client_data_next(client, line) < 0)
+ if (!lmtp_client_data_next(client, line))
return -1;
break;
}
@@ -334,7 +357,8 @@ static void lmtp_client_wait_connect(str
if (err != 0) {
i_error("lmtp client: connect(%s, %u) failed: %s",
client->host, client->port, strerror(err));
- lmtp_client_fail(client, NULL);
+ lmtp_client_fail(client, ERRSTR_TEMP_REMOTE_FAILURE
+ " (connect)");
return;
}
io_remove(&client->io);
@@ -348,7 +372,8 @@ static int lmtp_client_output(struct lmt
o_stream_cork(client->output);
if ((ret = o_stream_flush(client->output)) < 0)
- lmtp_client_fail(client, NULL);
+ lmtp_client_fail(client, ERRSTR_TEMP_REMOTE_FAILURE
+ " (disconnected in output)");
else if (client->input_state == LMTP_INPUT_STATE_DATA)
lmtp_client_send_data(client);
o_stream_uncork(client->output);
@@ -415,8 +440,13 @@ void lmtp_client_add_rcpt(struct lmtp_cl
void lmtp_client_send(struct lmtp_client *client, struct istream *data_input)
{
+ i_stream_ref(data_input);
client->data_input = data_input;
- o_stream_send_str(client->output, "DATA\r\n");
+
+ if (client->rcpt_next_receive_idx == array_count(&client->recipients)) {
+ client->input_state++;
+ o_stream_send_str(client->output, "DATA\r\n");
+ }
}
void lmtp_client_send_more(struct lmtp_client *client)
diff -r 6e5cc5d4cec4 -r 22d27318bb18 src/lib-lda/lmtp-client.h
--- a/src/lib-lda/lmtp-client.h Mon Sep 07 12:06:15 2009 -0400
+++ b/src/lib-lda/lmtp-client.h Tue Sep 08 13:28:40 2009 -0400
@@ -1,5 +1,7 @@
#ifndef LMTP_CLIENT_H
#define LMTP_CLIENT_H
+
+#define ERRSTR_TEMP_REMOTE_FAILURE "451 4.4.0 Remote server not answering"
/* LMTP/SMTP client code. */
diff -r 6e5cc5d4cec4 -r 22d27318bb18 src/lmtp/commands.c
--- a/src/lmtp/commands.c Mon Sep 07 12:06:15 2009 -0400
+++ b/src/lmtp/commands.c Tue Sep 08 13:28:40 2009 -0400
@@ -24,6 +24,8 @@
#define ERRSTR_TEMP_MAILBOX_FAIL "451 4.3.0 <%s> Temporary internal error"
#define ERRSTR_TEMP_USERDB_FAIL "451 4.3.0 <%s> Temporary user lookup failure"
+#define LMTP_PROXY_DEFAULT_TIMEOUT_MSECS (1000*30)
+
int cmd_lhlo(struct client *client, const char *args ATTR_UNUSED)
{
client_state_reset(client);
@@ -94,7 +96,7 @@ client_proxy_rcpt_parse_fields(struct lm
const char *const *args, const char **address)
{
const char *p, *key, *value;
- bool proxying = FALSE;
+ bool proxying = FALSE, port_set = FALSE;
for (; *args != NULL; args++) {
p = strchr(*args, '=');
@@ -110,9 +112,23 @@ client_proxy_rcpt_parse_fields(struct lm
proxying = TRUE;
else if (strcmp(key, "host") == 0)
set->host = value;
- else if (strcmp(key, "port") == 0)
+ else if (strcmp(key, "port") == 0) {
set->port = atoi(value);
- else if (strcmp(key, "user") == 0) {
+ port_set = TRUE;
+ } else if (strcmp(key, "proxy_timeout") == 0)
+ set->timeout_msecs = atoi(value)*1000;
+ else if (strcmp(key, "protocol") == 0) {
+ if (strcmp(value, "lmtp") == 0)
+ set->protocol = LMTP_CLIENT_PROTOCOL_LMTP;
+ else if (strcmp(value, "smtp") == 0) {
+ set->protocol = LMTP_CLIENT_PROTOCOL_SMTP;
+ if (!port_set)
+ set->port = 25;
+ } else {
+ i_error("proxy: Unknown protocol %s", value);
+ return FALSE;
+ }
+ } else if (strcmp(key, "user") == 0) {
/* changing the username */
*address = value;
} else {
@@ -176,6 +192,9 @@ static bool client_proxy_rcpt(struct cli
memset(&set, 0, sizeof(set));
set.port = client->local_port;
+ set.protocol = LMTP_CLIENT_PROTOCOL_LMTP;
+ set.timeout_msecs = LMTP_PROXY_DEFAULT_TIMEOUT_MSECS;
+
if (!client_proxy_rcpt_parse_fields(&set, fields, &address)) {
/* not proxying this user */
pool_unref(&pool);
diff -r 6e5cc5d4cec4 -r 22d27318bb18 src/lmtp/lmtp-proxy.c
--- a/src/lmtp/lmtp-proxy.c Mon Sep 07 12:06:15 2009 -0400
+++ b/src/lmtp/lmtp-proxy.c Tue Sep 08 13:28:40 2009 -0400
@@ -10,7 +10,6 @@
#include "lmtp-proxy.h"
#define LMTP_MAX_LINE_LEN 1024
-#define LMTP_PROXY_OUTPUT_TIMEOUT_MSECS 1000
struct lmtp_proxy_recipient {
struct lmtp_proxy_connection *conn;
@@ -47,13 +46,16 @@ struct lmtp_proxy {
struct ostream *client_output;
struct tee_istream *tee_data_input;
+ unsigned int max_timeout_msecs;
+
void (*finish_callback)(void *);
void *finish_context;
unsigned int finished:1;
};
-static void lmtp_proxy_conn_deinit(struct lmtp_proxy_connection *conn);
+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 *
@@ -81,7 +83,7 @@ static void lmtp_proxy_connections_deini
conns = array_get(&proxy->connections, &count);
for (i = 0; i < count; i++)
- lmtp_proxy_conn_deinit(conns[i]);
+ lmtp_proxy_conn_deinit(conns[i], "451 4.3.0 Aborting");
}
void lmtp_proxy_deinit(struct lmtp_proxy **_proxy)
@@ -116,6 +118,8 @@ lmtp_proxy_get_connection(struct lmtp_pr
struct lmtp_proxy_connection *const *conns, *conn;
unsigned int i, count;
+ i_assert(set->timeout_msecs > 0);
+
conns = array_get(&proxy->connections, &count);
for (i = 0; i < count; i++) {
if (conns[i]->set.port == set->port &&
@@ -130,13 +134,17 @@ lmtp_proxy_get_connection(struct lmtp_pr
conn->set.timeout_msecs = set->timeout_msecs;
array_append(&proxy->connections, &conn, 1);
conn->client = lmtp_client_init(proxy->mail_from, proxy->my_hostname);
- if (lmtp_client_connect_tcp(conn->client, LMTP_CLIENT_PROTOCOL_LMTP,
+ if (lmtp_client_connect_tcp(conn->client, set->protocol,
conn->set.host, conn->set.port) < 0)
conn->failed = TRUE;
+
+ if (proxy->max_timeout_msecs < set->timeout_msecs)
+ proxy->max_timeout_msecs = set->timeout_msecs;
return conn;
}
-static void lmtp_proxy_conn_deinit(struct lmtp_proxy_connection *conn)
+static void lmtp_proxy_conn_deinit(struct lmtp_proxy_connection *conn,
+ const char *reason)
{
struct lmtp_proxy_recipient *rcpt;
More information about the dovecot-cvs
mailing list