From: Timo Sirainen Date: Thu, 15 Oct 2009 22:31:11 +0000 (-0400) Subject: imap: IDLE now sends "Still here" notifications to same user's connections at the... X-Git-Tag: 2.0.alpha2~88 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2e705e574eb916181ce91f920d4d6f66bebce5ba;p=thirdparty%2Fdovecot%2Fcore.git imap: IDLE now sends "Still here" notifications to same user's connections at the same time. Perhaps this will save some battery power with mobile clients that open multiple connections. --HG-- branch : HEAD --- diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c index 6574bd67e3..56507299d2 100644 --- a/src/imap/cmd-idle.c +++ b/src/imap/cmd-idle.c @@ -4,6 +4,7 @@ #include "ioloop.h" #include "istream.h" #include "ostream.h" +#include "crc32.h" #include "mail-storage-settings.h" #include "imap-commands.h" #include "imap-sync.h" @@ -21,6 +22,7 @@ struct cmd_idle_context { unsigned int sync_pending:1; }; +static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx); static bool cmd_idle_continue(struct client_command_context *cmd); static void @@ -108,6 +110,8 @@ static void keepalive_timeout(struct cmd_idle_context *ctx) several clients that really want to IDLE forever and there's not much harm in letting them do so. */ timeout_reset(ctx->client->to_idle); + /* recalculate time for the next keepalive timeout */ + idle_add_keepalive_timeout(ctx); } static void idle_sync_now(struct mailbox *box, struct cmd_idle_context *ctx) @@ -129,6 +133,22 @@ static void idle_callback(struct mailbox *box, struct cmd_idle_context *ctx) } } +static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx) +{ + unsigned int interval = ctx->client->set->imap_idle_notify_interval; + + if (interval == 0) + return; + + interval -= (time(NULL) + + crc32_str(ctx->client->user->username)) % interval; + + if (ctx->keepalive_to != NULL) + timeout_remove(&ctx->keepalive_to); + ctx->keepalive_to = timeout_add(interval * 1000, + keepalive_timeout, ctx); +} + static bool cmd_idle_continue(struct client_command_context *cmd) { struct client *client = cmd->client; @@ -166,7 +186,7 @@ static bool cmd_idle_continue(struct client_command_context *cmd) } if (client->output->offset != orig_offset && ctx->keepalive_to != NULL) - timeout_reset(ctx->keepalive_to); + idle_add_keepalive_timeout(ctx); if (ctx->sync_pending) { /* more changes occurred while we were sending changes to @@ -204,10 +224,7 @@ bool cmd_idle(struct client_command_context *cmd) ctx = p_new(cmd->pool, struct cmd_idle_context, 1); ctx->cmd = cmd; ctx->client = client; - - ctx->keepalive_to = client->set->imap_idle_notify_interval == 0 ? NULL : - timeout_add(client->set->imap_idle_notify_interval * 1000, - keepalive_timeout, ctx); + idle_add_keepalive_timeout(ctx); if (client->mailbox != NULL) { const struct mail_storage_settings *set;