From b522906dc1071a5008c87bb702aa2d6d4ac6451a Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 10 Apr 2017 15:49:24 +0300 Subject: [PATCH] lib-imap-client: Call the public login callback exactly once. Previously it was also called only once, as long as there were only a single imap connection. (The current imapc code wouldn't create more than one connection.) It was a bit confusing what the expectation was, so now the callback is never called more than once. --- src/lib-imap-client/imapc-client-private.h | 1 + src/lib-imap-client/imapc-client.c | 59 +++++++++++++--------- src/lib-imap-client/imapc-client.h | 4 +- src/lib-imap-client/imapc-connection.c | 34 ++++--------- src/lib-imap-client/imapc-connection.h | 8 +-- 5 files changed, 54 insertions(+), 52 deletions(-) diff --git a/src/lib-imap-client/imapc-client-private.h b/src/lib-imap-client/imapc-client-private.h index 6efe17dadd..ce809f0bc4 100644 --- a/src/lib-imap-client/imapc-client-private.h +++ b/src/lib-imap-client/imapc-client-private.h @@ -7,6 +7,7 @@ struct imapc_client_connection { struct imapc_connection *conn; + struct imapc_client *client; struct imapc_client_mailbox *box; }; diff --git a/src/lib-imap-client/imapc-client.c b/src/lib-imap-client/imapc-client.c index ca3af9419d..db690e6f33 100644 --- a/src/lib-imap-client/imapc-client.c +++ b/src/lib-imap-client/imapc-client.c @@ -176,8 +176,7 @@ static void imapc_client_run_pre(struct imapc_client *client) array_foreach(&client->conns, connp) { imapc_connection_ioloop_changed((*connp)->conn); if (imapc_connection_get_state((*connp)->conn) == IMAPC_CONNECTION_STATE_DISCONNECTED) - imapc_connection_connect((*connp)->conn, client->login_callback, - client->login_context); + imapc_connection_connect((*connp)->conn); } if (io_loop_is_running(client->ioloop)) @@ -200,7 +199,6 @@ static void imapc_client_run_post(struct imapc_client *client) void imapc_client_run(struct imapc_client *client) { - i_assert(client->login_callback != NULL); imapc_client_run_pre(client); imapc_client_run_post(client); } @@ -225,13 +223,44 @@ bool imapc_client_is_running(struct imapc_client *client) return client->ioloop != NULL; } +static void imapc_client_login_callback(const struct imapc_command_reply *reply, + void *context) +{ + struct imapc_client_connection *conn = context; + struct imapc_client *client = conn->client; + struct imapc_client_mailbox *box = conn->box; + + if (box != NULL && box->reconnecting) { + box->reconnecting = FALSE; + + if (reply->state == IMAPC_COMMAND_STATE_OK) { + /* reopen the mailbox */ + box->reopen_callback(box->reopen_context); + } else { + imapc_connection_abort_commands(box->conn, NULL, FALSE); + } + } + + /* call the login callback only once */ + if (client->login_callback != NULL) { + imapc_command_callback_t *callback = client->login_callback; + void *context = client->login_context; + + client->login_callback = NULL; + client->login_context = NULL; + callback(reply, context); + } +} + static struct imapc_client_connection * imapc_client_add_connection(struct imapc_client *client) { struct imapc_client_connection *conn; conn = i_new(struct imapc_client_connection, 1); - conn->conn = imapc_connection_init(client); + conn->client = client; + conn->conn = imapc_connection_init(client, imapc_client_login_callback, + conn); array_append(&client->conns, &conn, 1); return conn; } @@ -281,8 +310,7 @@ void imapc_client_login(struct imapc_client *client) i_assert(array_count(&client->conns) == 0); conn = imapc_client_add_connection(client); - imapc_connection_connect(conn->conn, - client->login_callback, client->login_context); + imapc_connection_connect(conn->conn); } struct imapc_logout_ctx { @@ -360,23 +388,6 @@ void imapc_client_mailbox_set_reopen_cb(struct imapc_client_mailbox *box, box->reopen_context = context; } -static void -imapc_client_reconnect_cb(const struct imapc_command_reply *reply, - void *context) -{ - struct imapc_client_mailbox *box = context; - - i_assert(box->reconnecting); - box->reconnecting = FALSE; - - if (reply->state == IMAPC_COMMAND_STATE_OK) { - /* reopen the mailbox */ - box->reopen_callback(box->reopen_context); - } else { - imapc_connection_abort_commands(box->conn, NULL, FALSE); - } -} - bool imapc_client_mailbox_can_reconnect(struct imapc_client_mailbox *box) { /* the reconnect_ok flag attempts to avoid infinite reconnection loops @@ -396,7 +407,7 @@ void imapc_client_mailbox_reconnect(struct imapc_client_mailbox *box) box->reconnect_ok = FALSE; imapc_connection_disconnect_full(box->conn, TRUE); - imapc_connection_connect(box->conn, imapc_client_reconnect_cb, box); + imapc_connection_connect(box->conn); } void imapc_client_mailbox_close(struct imapc_client_mailbox **_box) diff --git a/src/lib-imap-client/imapc-client.h b/src/lib-imap-client/imapc-client.h index fd461802bb..08863f25b4 100644 --- a/src/lib-imap-client/imapc-client.h +++ b/src/lib-imap-client/imapc-client.h @@ -174,7 +174,9 @@ imapc_client_init(const struct imapc_client_settings *set); void imapc_client_disconnect(struct imapc_client *client); void imapc_client_deinit(struct imapc_client **client); -/* Set login callback, must be set before calling other commands */ +/* Set login callback, must be set before calling other commands. + This is called only for the first login, not for any reconnects or if there + are multiple connections created. */ void imapc_client_set_login_callback(struct imapc_client *client, imapc_command_callback_t *callback, void *context); diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c index 46e82bf8c2..5c919422a1 100644 --- a/src/lib-imap-client/imapc-connection.c +++ b/src/lib-imap-client/imapc-connection.c @@ -179,13 +179,17 @@ imapc_auth_failed(struct imapc_connection *conn, const struct imapc_command_repl } struct imapc_connection * -imapc_connection_init(struct imapc_client *client) +imapc_connection_init(struct imapc_client *client, + imapc_command_callback_t *login_callback, + void *login_context) { struct imapc_connection *conn; conn = i_new(struct imapc_connection, 1); conn->refcount = 1; conn->client = client; + conn->login_callback = login_callback; + conn->login_context = login_context; conn->fd = -1; conn->name = i_strdup_printf("%s:%u", client->set.host, client->set.port); @@ -345,15 +349,8 @@ static void imapc_login_callback(struct imapc_connection *conn, const struct imapc_command_reply *reply) { - imapc_command_callback_t *login_callback = conn->login_callback; - void *login_context = conn->login_context; - - if (login_callback == NULL) - return; - - conn->login_callback = NULL; - conn->login_context = NULL; - login_callback(reply, login_context); + if (conn->login_callback != NULL) + conn->login_callback(reply, conn->login_context); } static void imapc_connection_set_state(struct imapc_connection *conn, @@ -510,7 +507,7 @@ static void imapc_connection_reconnect(struct imapc_connection *conn) imapc_client_mailbox_reconnect(conn->selected_box); else { imapc_connection_disconnect_full(conn, TRUE); - imapc_connection_connect(conn, NULL, NULL); + imapc_connection_connect(conn); } } @@ -521,7 +518,7 @@ imapc_connection_try_reconnect(struct imapc_connection *conn, if (conn->prev_connect_idx + 1 < conn->ips_count) { conn->reconnect_ok = TRUE; imapc_connection_disconnect_full(conn, TRUE); - imapc_connection_connect(conn, NULL, NULL); + imapc_connection_connect(conn); return; } @@ -1777,24 +1774,15 @@ imapc_connection_dns_callback(const struct dns_lookup_result *result, imapc_connection_connect_next_ip(conn); } -void imapc_connection_connect(struct imapc_connection *conn, - imapc_command_callback_t *login_callback, - void *login_context) +void imapc_connection_connect(struct imapc_connection *conn) { struct dns_lookup_settings dns_set; struct ip_addr ip, *ips; unsigned int ips_count; int ret; - if (conn->fd != -1 || conn->dns_lookup != NULL) { - i_assert(login_callback == NULL); + if (conn->fd != -1 || conn->dns_lookup != NULL) return; - } - i_assert(conn->login_callback == NULL || conn->reconnecting); - if (!conn->reconnecting) { - conn->login_callback = login_callback; - conn->login_context = login_context; - } conn->reconnecting = FALSE; /* if we get disconnected before we've finished all the pending commands, don't reconnect */ diff --git a/src/lib-imap-client/imapc-connection.h b/src/lib-imap-client/imapc-connection.h index 611d0d5ce7..46632df918 100644 --- a/src/lib-imap-client/imapc-connection.h +++ b/src/lib-imap-client/imapc-connection.h @@ -26,12 +26,12 @@ enum imapc_connection_state { }; struct imapc_connection * -imapc_connection_init(struct imapc_client *client); +imapc_connection_init(struct imapc_client *client, + imapc_command_callback_t *login_callback, + void *login_context); void imapc_connection_deinit(struct imapc_connection **conn); -void imapc_connection_connect(struct imapc_connection *conn, - imapc_command_callback_t *login_callback, - void *login_context) ATTR_NULL(2, 3); +void imapc_connection_connect(struct imapc_connection *conn); void imapc_connection_set_no_reconnect(struct imapc_connection *conn); void imapc_connection_disconnect(struct imapc_connection *conn); void imapc_connection_disconnect_full(struct imapc_connection *conn,