dovecot-2.1: imapc: Initial support for automatically reconnecti...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Oct 9 16:32:57 EEST 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/8fdd22504aab
changeset: 13621:8fdd22504aab
user: Timo Sirainen <tss at iki.fi>
date: Sun Oct 09 16:41:17 2011 +0300
description:
imapc: Initial support for automatically reconnecting to remote server.
diffstat:
src/lib-imap-client/imapc-client-private.h | 5 +
src/lib-imap-client/imapc-client.c | 76 +++++++++++++++------
src/lib-imap-client/imapc-client.h | 19 ++++-
src/lib-imap-client/imapc-connection.c | 99 +++++++++++++++++-----------
src/lib-imap-client/imapc-connection.h | 4 +-
src/lib-imap-client/imapc-msgmap.c | 6 +
src/lib-imap-client/imapc-msgmap.h | 1 +
src/lib-storage/index/imapc/imapc-mail.c | 2 +-
src/lib-storage/index/imapc/imapc-mailbox.c | 2 +-
src/lib-storage/index/imapc/imapc-storage.c | 66 ++++++++++++++++---
src/lib-storage/index/imapc/imapc-storage.h | 1 +
11 files changed, 200 insertions(+), 81 deletions(-)
diffs (truncated from 659 to 300 lines):
diff -r 7e0bdfa76f12 -r 8fdd22504aab src/lib-imap-client/imapc-client-private.h
--- a/src/lib-imap-client/imapc-client-private.h Sat Oct 08 20:31:22 2011 +0300
+++ b/src/lib-imap-client/imapc-client-private.h Sun Oct 09 16:41:17 2011 +0300
@@ -28,8 +28,13 @@
struct imapc_connection *conn;
struct imapc_msgmap *msgmap;
+ void (*reopen_callback)(void *context);
+ void *reopen_context;
+
void *untagged_box_context;
unsigned int pending_box_command_count;
+
+ bool reconnect_ok;
};
void imapc_client_ref(struct imapc_client *client);
diff -r 7e0bdfa76f12 -r 8fdd22504aab src/lib-imap-client/imapc-client.c
--- a/src/lib-imap-client/imapc-client.c Sat Oct 08 20:31:22 2011 +0300
+++ b/src/lib-imap-client/imapc-client.c Sun Oct 09 16:41:17 2011 +0300
@@ -118,7 +118,7 @@
client->untagged_context = context;
}
-void imapc_client_run_pre(struct imapc_client *client)
+static void imapc_client_run_pre(struct imapc_client *client)
{
struct imapc_client_connection *const *connp;
struct ioloop *prev_ioloop = current_ioloop;
@@ -138,7 +138,7 @@
current_ioloop = prev_ioloop;
}
-void imapc_client_run_post(struct imapc_client *client)
+static void imapc_client_run_post(struct imapc_client *client)
{
struct imapc_client_connection *const *connp;
struct ioloop *ioloop = client->ioloop;
@@ -151,6 +151,12 @@
io_loop_destroy(&ioloop);
}
+void imapc_client_run(struct imapc_client *client)
+{
+ imapc_client_run_pre(client);
+ imapc_client_run_post(client);
+}
+
void imapc_client_stop(struct imapc_client *client)
{
if (client->ioloop != NULL)
@@ -238,10 +244,34 @@
return box;
}
-void imapc_client_mailbox_disconnect(struct imapc_client_mailbox *box)
+void imapc_client_mailbox_set_reopen_cb(struct imapc_client_mailbox *box,
+ void (*callback)(void *context),
+ void *context)
{
- if (box->conn != NULL)
- imapc_connection_disconnect(box->conn);
+ box->reopen_callback = callback;
+ box->reopen_context = context;
+}
+
+static void
+imapc_client_reconnect_cb(const struct imapc_command_reply *reply,
+ void *context)
+{
+ struct imapc_client_mailbox *box = context;
+
+ if (reply->state == IMAPC_COMMAND_STATE_OK) {
+ /* reopen the mailbox */
+ box->reopen_callback(box->reopen_context);
+ }
+}
+
+void imapc_client_mailbox_reconnect(struct imapc_client_mailbox *box)
+{
+ imapc_connection_disconnect(box->conn);
+ if (box->reopen_callback != NULL && box->reconnect_ok) {
+ imapc_connection_connect(box->conn,
+ imapc_client_reconnect_cb, box);
+ }
+ box->reconnect_ok = FALSE;
}
void imapc_client_mailbox_close(struct imapc_client_mailbox **_box)
@@ -249,6 +279,13 @@
struct imapc_client_mailbox *box = *_box;
struct imapc_client_connection *const *connp;
+ /* cancel any pending commands */
+ imapc_connection_unselect(box);
+
+ /* set this only after unselect, which may cancel some commands that
+ reference this box */
+ *_box = NULL;
+
array_foreach(&box->client->conns, connp) {
if ((*connp)->box == box) {
(*connp)->box = NULL;
@@ -256,14 +293,8 @@
}
}
- if (box->conn != NULL)
- imapc_connection_unselect(box);
imapc_msgmap_deinit(&box->msgmap);
i_free(box);
-
- /* set this only after unselect, which may cancel some commands that
- reference this box */
- *_box = NULL;
}
struct imapc_command *
@@ -285,24 +316,25 @@
void imapc_client_mailbox_idle(struct imapc_client_mailbox *box)
{
- if (imapc_client_mailbox_is_connected(box))
+ if (imapc_client_mailbox_is_opened(box))
imapc_connection_idle(box->conn);
+ box->reconnect_ok = TRUE;
}
-bool imapc_client_mailbox_is_connected(struct imapc_client_mailbox *box)
+bool imapc_client_mailbox_is_opened(struct imapc_client_mailbox *box)
{
struct imapc_client_mailbox *selected_box;
- selected_box = box->conn == NULL ? NULL :
- imapc_connection_get_mailbox(box->conn);
- if (selected_box == box)
- return TRUE;
+ if (imapc_connection_get_state(box->conn) != IMAPC_CONNECTION_STATE_DONE)
+ return FALSE;
- if (selected_box != NULL)
- i_error("imapc: Selected mailbox changed unexpectedly");
-
- box->conn = NULL;
- return FALSE;
+ selected_box = imapc_connection_get_mailbox(box->conn);
+ if (selected_box != box) {
+ if (selected_box != NULL)
+ i_error("imapc: Selected mailbox changed unexpectedly");
+ return FALSE;
+ }
+ return TRUE;
}
enum imapc_capability
diff -r 7e0bdfa76f12 -r 8fdd22504aab src/lib-imap-client/imapc-client.h
--- a/src/lib-imap-client/imapc-client.h Sat Oct 08 20:31:22 2011 +0300
+++ b/src/lib-imap-client/imapc-client.h Sun Oct 09 16:41:17 2011 +0300
@@ -27,7 +27,14 @@
enum imapc_command_flags {
/* The command changes the selected mailbox (SELECT, EXAMINE) */
- IMAPC_COMMAND_FLAG_SELECT = 0x01
+ IMAPC_COMMAND_FLAG_SELECT = 0x01,
+ /* The command is sent to server before login (or is the login
+ command itself). Non-prelogin commands will be queued until login
+ is successful. */
+ IMAPC_COMMAND_FLAG_PRELOGIN = 0x02,
+ /* Allow command to be automatically retried if disconnected before it
+ finishes. */
+ IMAPC_COMMAND_FLAG_RETRIABLE = 0x04
};
enum imapc_client_ssl_mode {
@@ -129,16 +136,18 @@
imapc_untagged_callback_t *callback,
void *context);
-void imapc_client_run_pre(struct imapc_client *client);
-void imapc_client_run_post(struct imapc_client *client);
+void imapc_client_run(struct imapc_client *client);
void imapc_client_stop(struct imapc_client *client);
bool imapc_client_is_running(struct imapc_client *client);
struct imapc_client_mailbox *
imapc_client_mailbox_open(struct imapc_client *client,
void *untagged_box_context);
+void imapc_client_mailbox_set_reopen_cb(struct imapc_client_mailbox *box,
+ void (*callback)(void *context),
+ void *context);
void imapc_client_mailbox_close(struct imapc_client_mailbox **box);
-void imapc_client_mailbox_disconnect(struct imapc_client_mailbox *box);
+void imapc_client_mailbox_reconnect(struct imapc_client_mailbox *box);
struct imapc_command *
imapc_client_mailbox_cmd(struct imapc_client_mailbox *box,
imapc_command_callback_t *callback, void *context);
@@ -146,7 +155,7 @@
imapc_client_mailbox_get_msgmap(struct imapc_client_mailbox *box);
void imapc_client_mailbox_idle(struct imapc_client_mailbox *box);
-bool imapc_client_mailbox_is_connected(struct imapc_client_mailbox *box);
+bool imapc_client_mailbox_is_opened(struct imapc_client_mailbox *box);
enum imapc_capability
imapc_client_get_capabilities(struct imapc_client *client);
diff -r 7e0bdfa76f12 -r 8fdd22504aab src/lib-imap-client/imapc-connection.c
--- a/src/lib-imap-client/imapc-connection.c Sat Oct 08 20:31:22 2011 +0300
+++ b/src/lib-imap-client/imapc-connection.c Sun Oct 09 16:41:17 2011 +0300
@@ -122,8 +122,7 @@
static int imapc_connection_output(struct imapc_connection *conn);
static int imapc_connection_ssl_init(struct imapc_connection *conn);
static void imapc_command_free(struct imapc_command *cmd);
-static void imapc_command_send_more(struct imapc_connection *conn,
- struct imapc_command *cmd);
+static void imapc_command_send_more(struct imapc_connection *conn);
struct imapc_connection *
imapc_connection_init(struct imapc_client *client)
@@ -253,9 +252,12 @@
static void imapc_connection_set_state(struct imapc_connection *conn,
enum imapc_connection_state state)
{
- if (state == IMAPC_CONNECTION_STATE_DISCONNECTED) {
- struct imapc_command_reply reply;
+ struct imapc_command_reply reply;
+ conn->state = state;
+
+ switch (state) {
+ case IMAPC_CONNECTION_STATE_DISCONNECTED:
memset(&reply, 0, sizeof(reply));
reply.state = IMAPC_COMMAND_STATE_DISCONNECTED;
reply.text_without_resp = reply.text_full =
@@ -269,15 +271,13 @@
conn->selecting_box = NULL;
conn->selected_box = NULL;
+ break;
+ case IMAPC_CONNECTION_STATE_DONE:
+ imapc_command_send_more(conn);
+ break;
+ default:
+ break;
}
- if (state == IMAPC_CONNECTION_STATE_DONE) {
- if (array_count(&conn->cmd_send_queue) > 0) {
- struct imapc_command *const *cmd_p =
- array_idx(&conn->cmd_send_queue, 0);
- imapc_command_send_more(conn, *cmd_p);
- }
- }
- conn->state = state;
}
static void imapc_connection_lfiles_free(struct imapc_connection *conn)
@@ -330,6 +330,14 @@
imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_DISCONNECTED);
}
+static void imapc_connection_reconnect(struct imapc_connection *conn)
+{
+ if (conn->selected_box != NULL)
+ imapc_client_mailbox_reconnect(conn->selected_box);
+ else
+ imapc_connection_disconnect(conn);
+}
+
static void ATTR_FORMAT(2, 3)
imapc_connection_input_error(struct imapc_connection *conn,
const char *fmt, ...)
@@ -339,7 +347,6 @@
va_start(va, fmt);
i_error("imapc(%s): Server sent invalid input: %s",
conn->name, t_strdup_vprintf(fmt, va));
- sleep(3600);
imapc_connection_disconnect(conn);
va_end(va);
}
@@ -636,6 +643,8 @@
timeout_remove(&conn->to);
imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_DONE);
imapc_login_callback(conn, reply);
+
+ imapc_command_send_more(conn);
}
static const char *
@@ -678,6 +687,7 @@
cmd = imapc_connection_cmd(conn, imapc_connection_login_cb,
conn);
+ imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_PRELOGIN);
if ((set->master_user == NULL &&
need_literal(set->username) && need_literal(set->password)) ||
@@ -727,6 +737,7 @@
}
cmd = imapc_connection_cmd(conn, imapc_connection_starttls_cb,
conn);
+ imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_PRELOGIN);
More information about the dovecot-cvs
mailing list