Mercurial > dovecot > core-2.2
changeset 10398:a144e918938c HEAD
LMTP client API changes. Should be easier to use now.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 24 Nov 2009 14:17:06 -0500 |
parents | 9500cfbe5dbf |
children | 8f6995923fbd |
files | src/lib-lda/lmtp-client.c src/lib-lda/lmtp-client.h src/lmtp/lmtp-proxy.c |
diffstat | 3 files changed, 55 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-lda/lmtp-client.c Tue Nov 24 13:29:02 2009 -0500 +++ b/src/lib-lda/lmtp-client.c Tue Nov 24 14:17:06 2009 -0500 @@ -49,6 +49,9 @@ struct io *io; int fd; + lmtp_finish_callback_t *finish_callback; + void *finish_context; + const char *data_header; ARRAY_DEFINE(recipients, struct lmtp_rcpt); unsigned int rcpt_next_receive_idx; @@ -57,14 +60,16 @@ struct istream *data_input; unsigned char output_last; + unsigned int rcpt_to_successes:1; unsigned int output_finished:1; - unsigned int rcpt_to_successes:1; + unsigned int finish_called:1; }; static void lmtp_client_send_rcpts(struct lmtp_client *client); struct lmtp_client * -lmtp_client_init(const char *mail_from, const char *my_hostname) +lmtp_client_init(const char *mail_from, const char *my_hostname, + lmtp_finish_callback_t *finish_callback, void *context) { struct lmtp_client *client; pool_t pool; @@ -78,6 +83,8 @@ client->pool = pool; client->mail_from = p_strdup(pool, mail_from); client->my_hostname = p_strdup(pool, my_hostname); + client->finish_callback = finish_callback; + client->finish_context = context; client->fd = -1; p_array_init(&client->recipients, pool, 16); return client; @@ -98,6 +105,11 @@ if (client->data_input != NULL) i_stream_unref(&client->data_input); client->output_finished = TRUE; + + if (!client->finish_called) { + client->finish_called = TRUE; + client->finish_callback(client->finish_context); + } } static void lmtp_client_ref(struct lmtp_client *client) @@ -201,7 +213,7 @@ } } -static bool +static int lmtp_client_data_next(struct lmtp_client *client, const char *line) { struct lmtp_rcpt *rcpt; @@ -214,14 +226,18 @@ continue; } + client->rcpt_next_data_idx = i + 1; rcpt[i].failed = line[0] != '2'; rcpt[i].data_callback(!rcpt[i].failed, line, rcpt[i].context); - client->rcpt_next_data_idx = i + 1; if (client->protocol == LMTP_CLIENT_PROTOCOL_LMTP) break; } - return i < count; + if (i < count) + return 0; + + lmtp_client_close(client); + return -1; } static void lmtp_client_send_data(struct lmtp_client *client) @@ -379,7 +395,7 @@ break; case LMTP_INPUT_STATE_DATA: /* DATA replies */ - if (!lmtp_client_data_next(client, line)) + if (lmtp_client_data_next(client, line) < 0) return -1; break; } @@ -521,11 +537,6 @@ 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)
--- a/src/lib-lda/lmtp-client.h Tue Nov 24 13:29:02 2009 -0500 +++ b/src/lib-lda/lmtp-client.h Tue Nov 24 14:17:06 2009 -0500 @@ -13,9 +13,13 @@ /* reply contains the reply coming from remote server, or NULL if it's a connection error. */ typedef void lmtp_callback_t(bool success, const char *reply, void *context); +/* called when session is finished, either because all RCPT TOs failed or + because all DATA replies have been received. */ +typedef void lmtp_finish_callback_t(void *context); struct lmtp_client * -lmtp_client_init(const char *mail_from, const char *my_hostname); +lmtp_client_init(const char *mail_from, const char *my_hostname, + lmtp_finish_callback_t *finish_callback, void *context); void lmtp_client_deinit(struct lmtp_client **client); int lmtp_client_connect_tcp(struct lmtp_client *client, @@ -34,8 +38,6 @@ 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);
--- a/src/lmtp/lmtp-proxy.c Tue Nov 24 13:29:02 2009 -0500 +++ b/src/lmtp/lmtp-proxy.c Tue Nov 24 14:17:06 2009 -0500 @@ -25,10 +25,6 @@ struct lmtp_proxy *proxy; struct lmtp_proxy_settings set; - /* points to proxy->rcpt_to array. */ - unsigned int rcpt_next_reply_low_idx; - unsigned int data_next_reply_low_idx; - struct lmtp_client *client; struct istream *data_input; unsigned int failed:1; @@ -39,7 +35,7 @@ const char *mail_from, *my_hostname; ARRAY_DEFINE(connections, struct lmtp_proxy_connection *); ARRAY_DEFINE(rcpt_to, struct lmtp_proxy_recipient); - unsigned int rcpt_next_reply_idx; + unsigned int next_data_reply_idx; struct timeout *to, *to_data_idle; struct io *io; @@ -55,6 +51,7 @@ unsigned int finished:1; }; +static void lmtp_conn_finish(void *context); static void lmtp_proxy_data_input(struct lmtp_proxy *proxy); struct lmtp_proxy * @@ -136,7 +133,8 @@ conn->set.port = set->port; conn->set.timeout_msecs = set->timeout_msecs; array_append(&proxy->connections, &conn, 1); - conn->client = lmtp_client_init(proxy->mail_from, proxy->my_hostname); + conn->client = lmtp_client_init(proxy->mail_from, proxy->my_hostname, + lmtp_conn_finish, conn); if (lmtp_client_connect_tcp(conn->client, set->protocol, conn->set.host, conn->set.port) < 0) conn->failed = TRUE; @@ -146,28 +144,21 @@ return conn; } -static void lmtp_proxy_conn_close(struct lmtp_proxy_connection *conn) -{ - lmtp_client_close(conn->client); - if (conn->data_input != NULL) - i_stream_unref(&conn->data_input); -} - -static bool lmtp_proxy_send_replies(struct lmtp_proxy *proxy) +static bool lmtp_proxy_send_data_replies(struct lmtp_proxy *proxy) { const struct lmtp_proxy_recipient *rcpt; unsigned int i, count; o_stream_cork(proxy->client_output); rcpt = array_get(&proxy->rcpt_to, &count); - for (i = proxy->rcpt_next_reply_idx; i < count; i++) { + for (i = proxy->next_data_reply_idx; i < count; i++) { if (!(rcpt[i].rcpt_to_failed || rcpt[i].data_reply_received)) break; o_stream_send_str(proxy->client_output, t_strconcat(rcpt[i].reply, "\r\n", NULL)); } o_stream_uncork(proxy->client_output); - proxy->rcpt_next_reply_idx = i; + proxy->next_data_reply_idx = i; return i == count; } @@ -182,10 +173,18 @@ static void lmtp_proxy_try_finish(struct lmtp_proxy *proxy) { - if (lmtp_proxy_send_replies(proxy) && proxy->data_input->eof) + if (lmtp_proxy_send_data_replies(proxy) && proxy->data_input->eof) lmtp_proxy_finish(proxy); } +static void lmtp_conn_finish(void *context) +{ + struct lmtp_proxy_connection *conn = context; + + i_stream_unref(&conn->data_input); + lmtp_proxy_try_finish(conn->proxy); +} + static void lmtp_proxy_fail_all(struct lmtp_proxy *proxy, const char *reason) { struct lmtp_proxy_connection *const *conns; @@ -229,57 +228,26 @@ static void lmtp_proxy_conn_rcpt_to(bool success, const char *reply, void *context) { - struct lmtp_proxy_connection *conn = context; - struct lmtp_proxy_recipient *rcpt; - unsigned int i, count; + struct lmtp_proxy_recipient *rcpt = context; + struct lmtp_proxy_connection *conn = rcpt->conn; - rcpt = array_get_modifiable(&conn->proxy->rcpt_to, &count); - for (i = conn->rcpt_next_reply_low_idx; i < count; i++) { - if (rcpt[i].conn == conn) { - i_assert(rcpt[i].reply == NULL); - rcpt[i].reply = p_strdup(conn->proxy->pool, reply); - rcpt[i].rcpt_to_failed = !success; - conn->rcpt_next_reply_low_idx = i + 1; - break; - } - } - i_assert(i != count); + i_assert(rcpt->reply == NULL); - 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); + rcpt->reply = p_strdup(conn->proxy->pool, reply); + rcpt->rcpt_to_failed = !success; } static void lmtp_proxy_conn_data(bool success ATTR_UNUSED, const char *reply, void *context) { - struct lmtp_proxy_connection *conn = context; - struct lmtp_proxy_recipient *rcpt; - unsigned int i, count; - - i_assert(conn->proxy->data_input != NULL); + struct lmtp_proxy_recipient *rcpt = context; + struct lmtp_proxy_connection *conn = rcpt->conn; - rcpt = array_get_modifiable(&conn->proxy->rcpt_to, &count); - for (i = conn->data_next_reply_low_idx; i < count; i++) { - if (rcpt[i].conn == conn && !rcpt[i].rcpt_to_failed) { - i_assert(rcpt[i].reply != NULL); - rcpt[i].reply = p_strdup(conn->proxy->pool, reply); - rcpt[i].data_reply_received = TRUE; - conn->data_next_reply_low_idx = i + 1; - break; - } - } - i_assert(i != count); + i_assert(!rcpt->rcpt_to_failed); + i_assert(rcpt->reply != NULL); - 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); + rcpt->reply = p_strdup(conn->proxy->pool, reply); + rcpt->data_reply_received = TRUE; } int lmtp_proxy_add_rcpt(struct lmtp_proxy *proxy, const char *address, @@ -297,7 +265,7 @@ rcpt->address = p_strdup(proxy->pool, address); lmtp_client_add_rcpt(conn->client, address, lmtp_proxy_conn_rcpt_to, - lmtp_proxy_conn_data, conn); + lmtp_proxy_conn_data, rcpt); return 0; }