~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/imap/cmd-idle.c

  • Committer: Package Import Robot
  • Author(s): Jaldhar H. Vyas
  • Date: 2013-09-09 00:57:32 UTC
  • mfrom: (1.13.11)
  • mto: (4.8.5 experimental) (1.16.1)
  • mto: This revision was merged to the branch mainline in revision 97.
  • Revision ID: package-import@ubuntu.com-20130909005732-dn1eell8srqbhh0e
Tags: upstream-2.2.5
ImportĀ upstreamĀ versionĀ 2.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "imap-common.h"
 
4
#include "net.h"
4
5
#include "ioloop.h"
5
6
#include "istream.h"
6
7
#include "ostream.h"
115
116
 
116
117
static void keepalive_timeout(struct cmd_idle_context *ctx)
117
118
{
118
 
        if (ctx->client->output_lock != NULL) {
 
119
        if (ctx->client->output_cmd_lock != NULL) {
119
120
                /* it's busy sending output */
120
121
                return;
121
122
        }
143
144
 
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);
147
148
}
148
149
 
149
150
static void idle_callback(struct mailbox *box, struct cmd_idle_context *ctx)
160
161
        }
161
162
}
162
163
 
 
164
static bool remote_ip_is_usable(const struct ip_addr *ip)
 
165
{
 
166
        unsigned int addr;
 
167
 
 
168
        if (ip->family == 0)
 
169
                return FALSE;
 
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 */
 
180
        }
 
181
#ifdef HAVE_IPV6
 
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 */
 
186
        }
 
187
#endif
 
188
        return TRUE;
 
189
}
 
190
 
163
191
static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx)
164
192
{
165
193
        unsigned int interval = ctx->client->set->imap_idle_notify_interval;
 
194
        unsigned int client_hash;
166
195
 
167
196
        if (interval == 0)
168
197
                return;
169
198
 
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.
 
204
 
 
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 :)
 
209
 
 
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;
172
220
 
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);
255
303
 
256
 
        if (client->mailbox != NULL) {
257
 
                const struct mail_storage_settings *set;
258
 
 
259
 
                set = mailbox_get_settings(client->mailbox);
260
 
                mailbox_notify_changes(client->mailbox,
261
 
                                       set->mailbox_idle_check_interval,
262
 
                                       idle_callback, ctx);
263
 
        }
 
304
        if (client->mailbox != NULL)
 
305
                mailbox_notify_changes(client->mailbox, idle_callback, ctx);
264
306
        client_send_line(client, "+ idling");
265
307
 
266
308
        io_remove(&client->io);