144
145
ctx->sync_pending = FALSE;
145
146
ctx->sync_ctx = imap_sync_init(ctx->client, box, 0, 0);
146
cmd_idle_continue(ctx->cmd);
147
(void)cmd_idle_continue(ctx->cmd);
149
150
static void idle_callback(struct mailbox *box, struct cmd_idle_context *ctx)
164
static bool remote_ip_is_usable(const struct ip_addr *ip)
170
if (ip->family == AF_INET) {
171
addr = ip->u.ip4.s_addr;
172
if (addr >= 167772160 && addr <= 184549375)
173
return FALSE; /* 10/8 */
174
if (addr >= 3232235520 && addr <= 3232301055)
175
return FALSE; /* 192.168/16 */
176
if (addr >= 2886729728 && addr <= 2887778303)
177
return FALSE; /* 172.16/12 */
178
if (addr >= 2130706432 && addr <= 2147483647)
179
return FALSE; /* 127/8 */
182
else if (ip->family == AF_INET6) {
183
addr = ip->u.ip6.s6_addr[0];
184
if (addr == 0xfc || addr == 0xfd)
185
return FALSE; /* fc00::/7 */
163
191
static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx)
165
193
unsigned int interval = ctx->client->set->imap_idle_notify_interval;
194
unsigned int client_hash;
167
196
if (interval == 0)
170
interval -= (time(NULL) +
171
crc32_str(ctx->client->user->username)) % interval;
199
/* set the interval so that the client gets the keepalive notifications
200
at exactly the same time for all the connections. this helps to
201
reduce battery usage in mobile devices. but we don't really want to
202
send this notification for everyone at the same time, because it
203
would cause huge peaks of activity.
205
basing the notifications on the username works well for one account,
206
but basing it on the IP address allows the client to get all of the
207
notifications at the same time for multiple accounts as well (of
208
course assuming Dovecot is running on all the servers :)
210
one potential downside to using IP is that if a proxy hides the
211
client's IP address notifications are sent to everyone at the same
212
time, but this can be avoided by using a properly configured Dovecot
213
proxy. we'll also try to avoid this by not doing it for the commonly
214
used intranet IP ranges. */
215
client_hash = ctx->client->user->remote_ip != NULL &&
216
remote_ip_is_usable(ctx->client->user->remote_ip) ?
217
net_ip_hash(ctx->client->user->remote_ip) :
218
crc32_str(ctx->client->user->username);
219
interval -= (time(NULL) + client_hash) % interval;
173
221
if (ctx->keepalive_to != NULL)
174
222
timeout_remove(&ctx->keepalive_to);
253
301
ctx->client = client;
254
302
idle_add_keepalive_timeout(ctx);
256
if (client->mailbox != NULL) {
257
const struct mail_storage_settings *set;
259
set = mailbox_get_settings(client->mailbox);
260
mailbox_notify_changes(client->mailbox,
261
set->mailbox_idle_check_interval,
304
if (client->mailbox != NULL)
305
mailbox_notify_changes(client->mailbox, idle_callback, ctx);
264
306
client_send_line(client, "+ idling");
266
308
io_remove(&client->io);