]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap-client: Call the public login callback exactly once.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 10 Apr 2017 12:49:24 +0000 (15:49 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 10 Apr 2017 15:00:13 +0000 (18:00 +0300)
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
src/lib-imap-client/imapc-client.c
src/lib-imap-client/imapc-client.h
src/lib-imap-client/imapc-connection.c
src/lib-imap-client/imapc-connection.h

index 6efe17dadda7c64128261a2a29d05230a6e97301..ce809f0bc41a2f80bb54de1cb68beb9bcd9e752f 100644 (file)
@@ -7,6 +7,7 @@
 
 struct imapc_client_connection {
        struct imapc_connection *conn;
+       struct imapc_client *client;
        struct imapc_client_mailbox *box;
 };
 
index ca3af9419d5ad7d0dcec1de477cc9ecf29955538..db690e6f331f367fee46eb40db66c77174ebb268 100644 (file)
@@ -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)
index fd461802bb0fcd320218cce77d96cf32952b0f17..08863f25b4f7b44b2be3d6207ade02396077e24a 100644 (file)
@@ -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);
index 46e82bf8c289eb9abc750422446ab5cd761a60ac..5c919422a14c6f8455c9055145200a5b21d9cba4 100644 (file)
@@ -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 */
index 611d0d5ce74245d650adc661ee5e1d585fb45396..46632df91833b346e5a28e7de09e4b089767b096 100644 (file)
@@ -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,