Skip to content

Commit

Permalink
lib-imap-client: Call the public login callback exactly once.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sirainen committed Apr 10, 2017
1 parent 19762b4 commit b522906
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 52 deletions.
1 change: 1 addition & 0 deletions src/lib-imap-client/imapc-client-private.h
Expand Up @@ -7,6 +7,7 @@

struct imapc_client_connection {
struct imapc_connection *conn;
struct imapc_client *client;
struct imapc_client_mailbox *box;
};

Expand Down
59 changes: 35 additions & 24 deletions src/lib-imap-client/imapc-client.c
Expand Up @@ -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))
Expand All @@ -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);
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion src/lib-imap-client/imapc-client.h
Expand Up @@ -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);
Expand Down
34 changes: 11 additions & 23 deletions src/lib-imap-client/imapc-connection.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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 */
Expand Down
8 changes: 4 additions & 4 deletions src/lib-imap-client/imapc-connection.h
Expand Up @@ -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,
Expand Down

0 comments on commit b522906

Please sign in to comment.