Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/imap/cmd-idle.c @ 9095:9a0aa39a3a14 HEAD
imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent changes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 26 May 2009 14:21:59 -0400 |
parents | 3a4bed08b59d |
children | 373b22cbabac |
rev | line source |
---|---|
8590
b9faf4db2a9f
Updated copyright notices to include year 2009.
Timo Sirainen <tss@iki.fi>
parents:
7817
diff
changeset
|
1 /* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */ |
1172 | 2 |
3 #include "common.h" | |
4 #include "ioloop.h" | |
5 #include "istream.h" | |
1225
8c85c03e0485
cork the output before sending the ending IDLE replies.
Timo Sirainen <tss@iki.fi>
parents:
1221
diff
changeset
|
6 #include "ostream.h" |
1172 | 7 #include "commands.h" |
2322
aae574ed7f4c
Broke mailbox_sync() into iterator.
Timo Sirainen <tss@iki.fi>
parents:
1915
diff
changeset
|
8 #include "imap-sync.h" |
1172 | 9 |
10 #include <stdlib.h> | |
11 | |
12 #define DEFAULT_IDLE_CHECK_INTERVAL 30 | |
3838
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
13 /* Send some noice to client every few minutes to avoid NATs and stateful |
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
14 firewalls from closing the connection */ |
8955
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
15 #define DEFAULT_IMAP_IDLE_NOTIFY_INTERVAL (2*60) |
1172 | 16 |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
17 struct cmd_idle_context { |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
18 struct client *client; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
19 struct client_command_context *cmd; |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
20 |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
21 struct imap_sync_context *sync_ctx; |
6210
da3c8d825f5c
Client is now never disconnected in IDLE because it hasn't sent anything.
Timo Sirainen <tss@iki.fi>
parents:
5805
diff
changeset
|
22 struct timeout *keepalive_to; |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
23 |
4832
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
24 unsigned int manual_cork:1; |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
25 unsigned int sync_pending:1; |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
26 }; |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
27 |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3838
diff
changeset
|
28 static bool cmd_idle_continue(struct client_command_context *cmd); |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
29 |
5431 | 30 static void |
31 idle_finish(struct cmd_idle_context *ctx, bool done_ok, bool free_cmd) | |
1172 | 32 { |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
33 struct client *client = ctx->client; |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
34 |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3863
diff
changeset
|
35 if (ctx->keepalive_to != NULL) |
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3863
diff
changeset
|
36 timeout_remove(&ctx->keepalive_to); |
1212 | 37 |
3727
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
38 if (ctx->sync_ctx != NULL) { |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
39 /* we're here only in connection failure cases */ |
7817
ffaf1ea49704
QRESYNC: Send HIGHESTMODSEQ automatically in all tagged replies whenever it
Timo Sirainen <tss@iki.fi>
parents:
7437
diff
changeset
|
40 (void)imap_sync_deinit(ctx->sync_ctx, ctx->cmd); |
3727
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
41 } |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
42 |
1225
8c85c03e0485
cork the output before sending the ending IDLE replies.
Timo Sirainen <tss@iki.fi>
parents:
1221
diff
changeset
|
43 o_stream_cork(client->output); |
6499 | 44 if (client->io != NULL) |
45 io_remove(&client->io); | |
1172 | 46 |
2322
aae574ed7f4c
Broke mailbox_sync() into iterator.
Timo Sirainen <tss@iki.fi>
parents:
1915
diff
changeset
|
47 if (client->mailbox != NULL) |
4907
5b4c9b20eba0
Replaced void *context from a lot of callbacks with the actual context
Timo Sirainen <tss@iki.fi>
parents:
4832
diff
changeset
|
48 mailbox_notify_changes_stop(client->mailbox); |
1172 | 49 |
1220 | 50 if (done_ok) |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
51 client_send_tagline(ctx->cmd, "OK Idle completed."); |
1220 | 52 else |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
53 client_send_tagline(ctx->cmd, "BAD Expected DONE."); |
1220 | 54 |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2322
diff
changeset
|
55 o_stream_uncork(client->output); |
5431 | 56 if (free_cmd) |
7431
33d8adcc2d44
client_command_free()/cancel(): Take pointer-to-pointer parameter and set it
Timo Sirainen <tss@iki.fi>
parents:
7266
diff
changeset
|
57 client_command_free(&ctx->cmd); |
1172 | 58 } |
59 | |
4907
5b4c9b20eba0
Replaced void *context from a lot of callbacks with the actual context
Timo Sirainen <tss@iki.fi>
parents:
4832
diff
changeset
|
60 static void idle_client_input(struct cmd_idle_context *ctx) |
1172 | 61 { |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
62 struct client *client = ctx->client; |
1172 | 63 char *line; |
64 | |
65 client->last_input = ioloop_time; | |
7126
0861436bfe14
Reset idle timeout also in APPEND/IDLE.
Timo Sirainen <tss@iki.fi>
parents:
7086
diff
changeset
|
66 timeout_reset(client->to_idle); |
1172 | 67 |
68 switch (i_stream_read(client->input)) { | |
69 case -1: | |
70 /* disconnected */ | |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4095
diff
changeset
|
71 client_destroy(client, "Disconnected in IDLE"); |
1172 | 72 return; |
73 case -2: | |
74 client->input_skip_line = TRUE; | |
5431 | 75 idle_finish(ctx, FALSE, TRUE); |
9095
9a0aa39a3a14
imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent changes.
Timo Sirainen <tss@iki.fi>
parents:
9012
diff
changeset
|
76 client_continue_pending_input(client); |
1221 | 77 return; |
1172 | 78 } |
79 | |
3727
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
80 if (ctx->sync_ctx != NULL) { |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
81 /* we're still sending output to client. wait until it's all |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
82 sent so we don't lose any changes. */ |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3863
diff
changeset
|
83 io_remove(&client->io); |
3727
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
84 return; |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
85 } |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
86 |
1172 | 87 while ((line = i_stream_next_line(client->input)) != NULL) { |
88 if (client->input_skip_line) | |
89 client->input_skip_line = FALSE; | |
90 else { | |
9012
3a4bed08b59d
IDLE: Check DONE case-insensitively.
Timo Sirainen <tss@iki.fi>
parents:
8955
diff
changeset
|
91 idle_finish(ctx, strcasecmp(line, "DONE") == 0, TRUE); |
1172 | 92 break; |
93 } | |
94 } | |
9095
9a0aa39a3a14
imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent changes.
Timo Sirainen <tss@iki.fi>
parents:
9012
diff
changeset
|
95 if (client->disconnected) |
9a0aa39a3a14
imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent changes.
Timo Sirainen <tss@iki.fi>
parents:
9012
diff
changeset
|
96 client_destroy(client, NULL); |
9a0aa39a3a14
imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent changes.
Timo Sirainen <tss@iki.fi>
parents:
9012
diff
changeset
|
97 else |
9a0aa39a3a14
imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent changes.
Timo Sirainen <tss@iki.fi>
parents:
9012
diff
changeset
|
98 client_continue_pending_input(client); |
1172 | 99 } |
100 | |
4907
5b4c9b20eba0
Replaced void *context from a lot of callbacks with the actual context
Timo Sirainen <tss@iki.fi>
parents:
4832
diff
changeset
|
101 static void keepalive_timeout(struct cmd_idle_context *ctx) |
3838
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
102 { |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
103 if (ctx->client->output_lock != NULL) { |
3838
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
104 /* it's busy sending output */ |
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
105 return; |
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
106 } |
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
107 |
7437
498975950370
Workaround to never idle-disconnect IDLEing clients got broken by timeout
Timo Sirainen <tss@iki.fi>
parents:
7431
diff
changeset
|
108 /* Sending this keeps NATs/stateful firewalls alive. Sending this |
498975950370
Workaround to never idle-disconnect IDLEing clients got broken by timeout
Timo Sirainen <tss@iki.fi>
parents:
7431
diff
changeset
|
109 also catches dead connections. */ |
3838
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
110 client_send_line(ctx->client, "* OK Still here"); |
7437
498975950370
Workaround to never idle-disconnect IDLEing clients got broken by timeout
Timo Sirainen <tss@iki.fi>
parents:
7431
diff
changeset
|
111 /* Make sure idling connections don't get disconnected. There are |
498975950370
Workaround to never idle-disconnect IDLEing clients got broken by timeout
Timo Sirainen <tss@iki.fi>
parents:
7431
diff
changeset
|
112 several clients that really want to IDLE forever and there's not |
498975950370
Workaround to never idle-disconnect IDLEing clients got broken by timeout
Timo Sirainen <tss@iki.fi>
parents:
7431
diff
changeset
|
113 much harm in letting them do so. */ |
498975950370
Workaround to never idle-disconnect IDLEing clients got broken by timeout
Timo Sirainen <tss@iki.fi>
parents:
7431
diff
changeset
|
114 timeout_reset(ctx->client->to_idle); |
3838
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
115 } |
e0881596af32
When idling, send an OK message every two minutes to break NAT/firewall timeouts.
Timo Sirainen <tss@iki.fi>
parents:
3826
diff
changeset
|
116 |
3777
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
117 static void idle_sync_now(struct mailbox *box, struct cmd_idle_context *ctx) |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
118 { |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
119 i_assert(ctx->sync_ctx == NULL); |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
120 |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
121 ctx->sync_pending = FALSE; |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
122 ctx->sync_ctx = imap_sync_init(ctx->client, box, 0, 0); |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
123 cmd_idle_continue(ctx->cmd); |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
124 } |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
125 |
4907
5b4c9b20eba0
Replaced void *context from a lot of callbacks with the actual context
Timo Sirainen <tss@iki.fi>
parents:
4832
diff
changeset
|
126 static void idle_callback(struct mailbox *box, struct cmd_idle_context *ctx) |
2322
aae574ed7f4c
Broke mailbox_sync() into iterator.
Timo Sirainen <tss@iki.fi>
parents:
1915
diff
changeset
|
127 { |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
128 if (ctx->sync_ctx != NULL) |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
129 ctx->sync_pending = TRUE; |
4832
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
130 else { |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
131 ctx->manual_cork = TRUE; |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
132 idle_sync_now(box, ctx); |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
133 } |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
134 } |
2322
aae574ed7f4c
Broke mailbox_sync() into iterator.
Timo Sirainen <tss@iki.fi>
parents:
1915
diff
changeset
|
135 |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3838
diff
changeset
|
136 static bool cmd_idle_continue(struct client_command_context *cmd) |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
137 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
138 struct client *client = cmd->client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
139 struct cmd_idle_context *ctx = cmd->context; |
8955
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
140 uoff_t orig_offset = client->output->offset; |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
141 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
142 if (cmd->cancel) { |
5431 | 143 idle_finish(ctx, FALSE, FALSE); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
144 return TRUE; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
145 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
146 |
4832
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
147 if (ctx->manual_cork) { |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
148 /* we're coming from idle_callback instead of a normal |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
149 I/O handler, so we'll have to do corking manually */ |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
150 o_stream_cork(client->output); |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
151 } |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
152 |
2474 | 153 if (ctx->sync_ctx != NULL) { |
154 if (imap_sync_more(ctx->sync_ctx) == 0) { | |
155 /* unfinished */ | |
4832
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
156 if (ctx->manual_cork) { |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
157 ctx->manual_cork = FALSE; |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
158 o_stream_uncork(client->output); |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
159 } |
7148
5e3188213724
Added "command state" for running commands. Use it instead of some bitfields
Timo Sirainen <tss@iki.fi>
parents:
7126
diff
changeset
|
160 cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT; |
2474 | 161 return FALSE; |
162 } | |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
163 |
7817
ffaf1ea49704
QRESYNC: Send HIGHESTMODSEQ automatically in all tagged replies whenever it
Timo Sirainen <tss@iki.fi>
parents:
7437
diff
changeset
|
164 if (imap_sync_deinit(ctx->sync_ctx, ctx->cmd) < 0) { |
2474 | 165 client_send_untagged_storage_error(client, |
166 mailbox_get_storage(client->mailbox)); | |
4907
5b4c9b20eba0
Replaced void *context from a lot of callbacks with the actual context
Timo Sirainen <tss@iki.fi>
parents:
4832
diff
changeset
|
167 mailbox_notify_changes_stop(client->mailbox); |
2474 | 168 } |
169 ctx->sync_ctx = NULL; | |
1212 | 170 } |
8955
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
171 if (client->output->offset != orig_offset && |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
172 ctx->keepalive_to != NULL) |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
173 timeout_reset(ctx->keepalive_to); |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
174 |
6210
da3c8d825f5c
Client is now never disconnected in IDLE because it hasn't sent anything.
Timo Sirainen <tss@iki.fi>
parents:
5805
diff
changeset
|
175 if (ctx->sync_pending) { |
3520 | 176 /* more changes occurred while we were sending changes to |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
177 client */ |
3826
20430dbf04d4
Recent changes broke IDLE when no mailbox was opened.
Timo Sirainen <tss@iki.fi>
parents:
3777
diff
changeset
|
178 idle_sync_now(client->mailbox, ctx); |
4786
65bbeb211a30
If mailbox is changed while syncing is being done, and the second sync's
Timo Sirainen <tss@iki.fi>
parents:
4096
diff
changeset
|
179 /* NOTE: this recurses back to this function, |
65bbeb211a30
If mailbox is changed while syncing is being done, and the second sync's
Timo Sirainen <tss@iki.fi>
parents:
4096
diff
changeset
|
180 so we return here instead of doing everything twice. */ |
65bbeb211a30
If mailbox is changed while syncing is being done, and the second sync's
Timo Sirainen <tss@iki.fi>
parents:
4096
diff
changeset
|
181 return FALSE; |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
182 } |
7149
323b425a0f46
Replaced waiting_ambiguity bitmask with a command state.
Timo Sirainen <tss@iki.fi>
parents:
7148
diff
changeset
|
183 cmd->state = CLIENT_COMMAND_STATE_WAIT_INPUT; |
2501
b7eec64e0735
Deinitialize command handlers always.
Timo Sirainen <tss@iki.fi>
parents:
2474
diff
changeset
|
184 |
4832
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
185 if (ctx->manual_cork) { |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
186 ctx->manual_cork = FALSE; |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
187 o_stream_uncork(client->output); |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
188 } |
9ea62a9720ec
When mailbox changes are noticed and they're sent to client, cork before
Timo Sirainen <tss@iki.fi>
parents:
4830
diff
changeset
|
189 |
4830
a642d3df700f
If syncing finished with an error and client had disconnected, we
Timo Sirainen <tss@iki.fi>
parents:
4786
diff
changeset
|
190 if (client->output->closed) { |
5431 | 191 idle_finish(ctx, FALSE, FALSE); |
4830
a642d3df700f
If syncing finished with an error and client had disconnected, we
Timo Sirainen <tss@iki.fi>
parents:
4786
diff
changeset
|
192 return TRUE; |
a642d3df700f
If syncing finished with an error and client had disconnected, we
Timo Sirainen <tss@iki.fi>
parents:
4786
diff
changeset
|
193 } |
3727
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
194 if (client->io == NULL) { |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
195 /* input is pending */ |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
196 client->io = io_add(i_stream_get_fd(client->input), |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
197 IO_READ, idle_client_input, ctx); |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
198 idle_client_input(ctx); |
de92177c8113
If DONE was sent while output was still being sent to clients, we didn't
Timo Sirainen <tss@iki.fi>
parents:
3520
diff
changeset
|
199 } |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
200 return FALSE; |
1212 | 201 } |
202 | |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3838
diff
changeset
|
203 bool cmd_idle(struct client_command_context *cmd) |
1172 | 204 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
205 struct client *client = cmd->client; |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
206 struct cmd_idle_context *ctx; |
1172 | 207 const char *str; |
208 unsigned int interval; | |
209 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
210 ctx = p_new(cmd->pool, struct cmd_idle_context, 1); |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
211 ctx->cmd = cmd; |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
212 ctx->client = client; |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
213 |
8955
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
214 str = getenv("IMAP_IDLE_NOTIFY_INTERVAL"); |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
215 interval = str != NULL ? |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
216 (unsigned int)strtoul(str, NULL, 10) : |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
217 DEFAULT_IMAP_IDLE_NOTIFY_INTERVAL; |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
218 ctx->keepalive_to = interval == 0 ? NULL : |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
219 timeout_add(interval * 1000, |
8de5b2a19a08
Added imap_idle_notify_interval setting.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
220 keepalive_timeout, ctx); |
1212 | 221 |
1172 | 222 str = getenv("MAILBOX_IDLE_CHECK_INTERVAL"); |
223 interval = str == NULL ? 0 : (unsigned int)strtoul(str, NULL, 10); | |
224 if (interval == 0) | |
225 interval = DEFAULT_IDLE_CHECK_INTERVAL; | |
226 | |
2322
aae574ed7f4c
Broke mailbox_sync() into iterator.
Timo Sirainen <tss@iki.fi>
parents:
1915
diff
changeset
|
227 if (client->mailbox != NULL) { |
aae574ed7f4c
Broke mailbox_sync() into iterator.
Timo Sirainen <tss@iki.fi>
parents:
1915
diff
changeset
|
228 mailbox_notify_changes(client->mailbox, interval, |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
229 idle_callback, ctx); |
2322
aae574ed7f4c
Broke mailbox_sync() into iterator.
Timo Sirainen <tss@iki.fi>
parents:
1915
diff
changeset
|
230 } |
1172 | 231 client_send_line(client, "+ idling"); |
232 | |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3863
diff
changeset
|
233 io_remove(&client->io); |
1172 | 234 client->io = io_add(i_stream_get_fd(client->input), |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
235 IO_READ, idle_client_input, ctx); |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
236 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
237 cmd->func = cmd_idle_continue; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2800
diff
changeset
|
238 cmd->context = ctx; |
3777
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
239 |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
240 /* check immediately if there are changes. if they came before we |
39c293635875
Don't crash if client disconnected in IDLE. If mailbox had been changed before IDLE
Timo Sirainen <tss@iki.fi>
parents:
3765
diff
changeset
|
241 added mailbox-notifier, we wouldn't see them otherwise. */ |
3826
20430dbf04d4
Recent changes broke IDLE when no mailbox was opened.
Timo Sirainen <tss@iki.fi>
parents:
3777
diff
changeset
|
242 if (client->mailbox != NULL) |
20430dbf04d4
Recent changes broke IDLE when no mailbox was opened.
Timo Sirainen <tss@iki.fi>
parents:
3777
diff
changeset
|
243 idle_sync_now(client->mailbox, ctx); |
1172 | 244 return FALSE; |
245 } |