dovecot-2.0: LMTP client API changes. Should be easier to use now.
dovecot at dovecot.org
dovecot at dovecot.org
Tue Nov 24 21:17:11 EET 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/a144e918938c
changeset: 10398:a144e918938c
user: Timo Sirainen <tss at iki.fi>
date: Tue Nov 24 14:17:06 2009 -0500
description:
LMTP client API changes. Should be easier to use now.
diffstat:
3 files changed, 59 insertions(+), 78 deletions(-)
src/lib-lda/lmtp-client.c | 33 ++++++++++-----
src/lib-lda/lmtp-client.h | 8 ++-
src/lmtp/lmtp-proxy.c | 96 +++++++++++++++------------------------------
diffs (truncated from 304 to 300 lines):
diff -r 9500cfbe5dbf -r a144e918938c src/lib-lda/lmtp-client.c
--- 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 lmtp_client {
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 lmtp_client {
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 @@ lmtp_client_init(const char *mail_from,
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 @@ void lmtp_client_close(struct lmtp_clien
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 void lmtp_client_send_data_cmd(st
}
}
-static bool
+static int
lmtp_client_data_next(struct lmtp_client *client, const char *line)
{
struct lmtp_rcpt *rcpt;
@@ -214,14 +226,18 @@ lmtp_client_data_next(struct lmtp_client
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 @@ static int lmtp_client_input_line(struct
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 @@ void lmtp_client_send(struct lmtp_client
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)
diff -r 9500cfbe5dbf -r a144e918938c src/lib-lda/lmtp-client.h
--- 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 @@ enum lmtp_client_protocol {
/* 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 @@ void lmtp_client_add_rcpt(struct lmtp_cl
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);
diff -r 9500cfbe5dbf -r a144e918938c src/lmtp/lmtp-proxy.c
--- 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_connection {
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 @@ struct lmtp_proxy {
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 @@ struct lmtp_proxy {
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 @@ lmtp_proxy_get_connection(struct lmtp_pr
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 @@ lmtp_proxy_get_connection(struct lmtp_pr
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,8 +173,16 @@ static void lmtp_proxy_finish(struct lmt
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)
@@ -229,57 +228,26 @@ static void
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;
-
- 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);
-
- 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);
+ struct lmtp_proxy_recipient *rcpt = context;
+ struct lmtp_proxy_connection *conn = rcpt->conn;
+
+ i_assert(rcpt->reply == NULL);
+
+ 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);
-
- 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);
-
- 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);
+ struct lmtp_proxy_recipient *rcpt = context;
+ struct lmtp_proxy_connection *conn = rcpt->conn;
+
+ i_assert(!rcpt->rcpt_to_failed);
+ i_assert(rcpt->reply != NULL);
+
+ 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 @@ int lmtp_proxy_add_rcpt(struct lmtp_prox
rcpt->address = p_strdup(proxy->pool, address);
lmtp_client_add_rcpt(conn->client, address, lmtp_proxy_conn_rcpt_to,
- lmtp_proxy_conn_data, conn);
More information about the dovecot-cvs
mailing list