From: Timo Sirainen Date: Thu, 24 Feb 2011 09:27:42 +0000 (+0200) Subject: imapc: Fixed crashing in IDLE handling when server got disconnected. X-Git-Tag: 2.1.alpha1~328 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=18aeafbbc2919898504e32a857e49fca2f7b83cf;p=thirdparty%2Fdovecot%2Fcore.git imapc: Fixed crashing in IDLE handling when server got disconnected. --- diff --git a/src/lib-storage/index/imapc/imapc-connection.c b/src/lib-storage/index/imapc/imapc-connection.c index 6f3c33a351..bdff698eb9 100644 --- a/src/lib-storage/index/imapc/imapc-connection.c +++ b/src/lib-storage/index/imapc/imapc-connection.c @@ -47,6 +47,8 @@ struct imapc_command { imapc_command_callback_t *callback; void *context; + + unsigned int idle:1; }; struct imapc_connection_literal { @@ -158,6 +160,10 @@ static void imapc_connection_set_state(struct imapc_connection *conn, reply.text_without_resp = reply.text_full = "Disconnected from server"; + conn->idling = FALSE; + conn->idle_plus_waiting = FALSE; + conn->idle_stopping = FALSE; + while (array_count(&conn->cmd_wait_list) > 0) { cmdp = array_idx(&conn->cmd_wait_list, 0); cmd = *cmdp; @@ -1179,6 +1185,9 @@ parse_sync_literal(const unsigned char *data, unsigned int pos, static void imapc_command_send_done(struct imapc_connection *conn, struct imapc_command *cmd) { + if (cmd->idle) + conn->idle_plus_waiting = TRUE; + /* everything sent. move command to wait list. */ i_assert(*array_idx(&conn->cmd_send_queue, 0) == cmd); array_delete(&conn->cmd_send_queue, 0, 1); @@ -1287,15 +1296,25 @@ static void imapc_command_send(struct imapc_connection *conn, } } -void imapc_connection_cmd(struct imapc_connection *conn, const char *cmdline, - imapc_command_callback_t *callback, void *context) +static struct imapc_command * +imapc_connection_cmd_build(const char *cmdline, + imapc_command_callback_t *callback, void *context) { struct imapc_command *cmd; unsigned int len = strlen(cmdline); cmd = imapc_command_begin(callback, context); - cmd->data = str_new(cmd->pool, len + 2); + cmd->data = str_new(cmd->pool, 6 + len + 2); str_printfa(cmd->data, "%u %s\r\n", cmd->tag, cmdline); + return cmd; +} + +void imapc_connection_cmd(struct imapc_connection *conn, const char *cmdline, + imapc_command_callback_t *callback, void *context) +{ + struct imapc_command *cmd; + + cmd = imapc_connection_cmd_build(cmdline, callback, context); imapc_command_send(conn, cmd); } @@ -1437,13 +1456,16 @@ imapc_connection_idle_callback(const struct imapc_command_reply *reply ATTR_UNUS void imapc_connection_idle(struct imapc_connection *conn) { + struct imapc_command *cmd; + if (array_count(&conn->cmd_send_queue) != 0 || array_count(&conn->cmd_wait_list) != 0 || conn->idling || conn->idle_plus_waiting || (conn->capabilities & IMAPC_CAPABILITY_IDLE) == 0) return; - imapc_connection_cmd(conn, "IDLE", - imapc_connection_idle_callback, conn); - conn->idle_plus_waiting = TRUE; + cmd = imapc_connection_cmd_build("IDLE", imapc_connection_idle_callback, + conn); + cmd->idle = TRUE; + imapc_command_send(conn, cmd); }