if (reply->state == IMAPC_COMMAND_STATE_OK) {
/* reopen the mailbox */
box->reopen_callback(box->reopen_context);
+ imapc_connection_set_reconnected(box->conn);
} 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
+ to a server that keeps disconnecting us (e.g. some of the commands
+ we send keeps crashing it always) */
return box->reopen_callback != NULL && box->reconnect_ok;
}
imapc_connection_connect(box->conn,
imapc_client_reconnect_cb, box);
}
+ /* if we fail again, avoid reconnecting immediately. if the server is
+ broken we could just get into an infinitely failing reconnection
+ loop. */
box->reconnect_ok = FALSE;
}
timeout_add_short(IMAPC_CLIENT_IDLE_SEND_DELAY_MSECS,
imapc_client_mailbox_idle_send, box);
}
+ /* we're done with all work at this point. */
box->reconnect_ok = TRUE;
}
ARRAY_TYPE(imapc_command) cmd_send_queue;
/* commands that have been sent, waiting for their tagged reply */
ARRAY_TYPE(imapc_command) cmd_wait_list;
+ unsigned int reconnect_command_count;
unsigned int ips_count, prev_connect_idx;
struct ip_addr *ips;
imapc_connection_unselect(conn->selected_box);
}
+ if (conn->reconnect_command_count > 0) {
+ if (--conn->reconnect_command_count == 0) {
+ /* we've received replies for all the commands started
+ before reconnection. if we get disconnected now, we
+ can safely reconnect without worrying about infinite
+ reconnect loops. */
+ if (conn->selected_box != NULL)
+ conn->selected_box->reconnect_ok = TRUE;
+ }
+ }
imapc_connection_input_reset(conn);
imapc_command_reply_free(cmd, &reply);
imapc_command_send_more(conn);
cmd->idle = TRUE;
imapc_command_send(cmd, "IDLE");
}
+
+void imapc_connection_set_reconnected(struct imapc_connection *conn)
+{
+ conn->reconnect_command_count = array_count(&conn->cmd_wait_list) +
+ array_count(&conn->cmd_send_queue);
+}
imapc_connection_get_mailbox(struct imapc_connection *conn);
void imapc_connection_idle(struct imapc_connection *conn);
+void imapc_connection_set_reconnected(struct imapc_connection *conn);
#endif