# HG changeset patch # User Timo Sirainen # Date 1491828564 -10800 # Node ID a892db12fd6ab9304e8c7b7562af7386625b5d7f # Parent 742783900e505177563e6cff5fdd6d47c5a702d2 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. diff -r 742783900e50 -r a892db12fd6a src/lib-imap-client/imapc-client-private.h --- a/src/lib-imap-client/imapc-client-private.h Mon Apr 10 14:14:40 2017 +0300 +++ b/src/lib-imap-client/imapc-client-private.h Mon Apr 10 15:49:24 2017 +0300 @@ -7,6 +7,7 @@ struct imapc_client_connection { struct imapc_connection *conn; + struct imapc_client *client; struct imapc_client_mailbox *box; }; diff -r 742783900e50 -r a892db12fd6a src/lib-imap-client/imapc-client.c --- a/src/lib-imap-client/imapc-client.c Mon Apr 10 14:14:40 2017 +0300 +++ b/src/lib-imap-client/imapc-client.c Mon Apr 10 15:49:24 2017 +0300 @@ -176,8 +176,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -r 742783900e50 -r a892db12fd6a src/lib-imap-client/imapc-client.h --- a/src/lib-imap-client/imapc-client.h Mon Apr 10 14:14:40 2017 +0300 +++ b/src/lib-imap-client/imapc-client.h Mon Apr 10 15:49:24 2017 +0300 @@ -174,7 +174,9 @@ 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 -r 742783900e50 -r a892db12fd6a src/lib-imap-client/imapc-connection.c --- a/src/lib-imap-client/imapc-connection.c Mon Apr 10 14:14:40 2017 +0300 +++ b/src/lib-imap-client/imapc-connection.c Mon Apr 10 15:49:24 2017 +0300 @@ -179,13 +179,17 @@ } 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 @@ 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 @@ 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 @@ 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_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 -r 742783900e50 -r a892db12fd6a src/lib-imap-client/imapc-connection.h --- a/src/lib-imap-client/imapc-connection.h Mon Apr 10 14:14:40 2017 +0300 +++ b/src/lib-imap-client/imapc-connection.h Mon Apr 10 15:49:24 2017 +0300 @@ -26,12 +26,12 @@ }; 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,