struct imapc_client_connection {
struct imapc_connection *conn;
+ struct imapc_client *client;
struct imapc_client_mailbox *box;
};
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))
void imapc_client_run(struct imapc_client *client)
{
- i_assert(client->login_callback != NULL);
imapc_client_run_pre(client);
imapc_client_run_post(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;
}
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 {
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
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)
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);
}
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);
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,
imapc_client_mailbox_reconnect(conn->selected_box);
else {
imapc_connection_disconnect_full(conn, TRUE);
- imapc_connection_connect(conn, NULL, NULL);
+ imapc_connection_connect(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;
}
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 */
};
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,