Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/imap/client.c @ 805:5ac361acb316 HEAD
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
cleanups and a couple of minor bugfixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 18 Dec 2002 17:15:41 +0200 |
parents | f17a1f59ac3f |
children | 35abd7a5d381 |
rev | line source |
---|---|
0 | 1 /* Copyright (C) 2002 Timo Sirainen */ |
2 | |
3 #include "common.h" | |
532
3b53dd1280c6
I/O buffers now use real blocking instead of setting up a sub-ioloop to
Timo Sirainen <tss@iki.fi>
parents:
410
diff
changeset
|
4 #include "ioloop.h" |
164
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
5 #include "network.h" |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
6 #include "istream.h" |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
7 #include "ostream.h" |
0 | 8 #include "commands.h" |
9 | |
10 #include <stdlib.h> | |
11 | |
12 /* max. size of one parameter in line */ | |
13 #define MAX_INBUF_SIZE 8192 | |
14 | |
768
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
15 /* max. number of IMAP argument elements to accept. The maximum memory usage |
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
16 for command from user is around MAX_INBUF_SIZE * MAX_IMAP_ARG_ELEMENTS */ |
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
17 #define MAX_IMAP_ARG_ELEMENTS 128 |
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
18 |
0 | 19 /* If we can't send a buffer in a minute, disconnect the client */ |
20 #define CLIENT_OUTPUT_TIMEOUT (60*1000) | |
21 | |
164
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
22 /* If we don't soon receive expected data from client while processing |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
23 a command, disconnect the client */ |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
24 #define CLIENT_CMDINPUT_TIMEOUT CLIENT_OUTPUT_TIMEOUT |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
25 |
0 | 26 /* Disconnect client when it sends too many bad commands */ |
27 #define CLIENT_MAX_BAD_COMMANDS 20 | |
28 | |
29 /* Disconnect client after idling this many seconds */ | |
30 #define CLIENT_IDLE_TIMEOUT (60*30) | |
31 | |
674
b7aefd0d7611
Locking changes triggered a bit larger cleanup :) If we have to wait for a
Timo Sirainen <tss@iki.fi>
parents:
532
diff
changeset
|
32 extern MailStorageCallbacks mail_storage_callbacks; |
b7aefd0d7611
Locking changes triggered a bit larger cleanup :) If we have to wait for a
Timo Sirainen <tss@iki.fi>
parents:
532
diff
changeset
|
33 |
0 | 34 static Client *my_client; /* we don't need more than one currently */ |
35 static Timeout to_idle; | |
36 | |
37 static void client_input(Client *client); | |
38 | |
532
3b53dd1280c6
I/O buffers now use real blocking instead of setting up a sub-ioloop to
Timo Sirainen <tss@iki.fi>
parents:
410
diff
changeset
|
39 static void client_output_timeout(void *context) |
0 | 40 { |
164
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
41 Client *client = context; |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
42 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
43 i_stream_close(client->input); |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
44 o_stream_close(client->output); |
0 | 45 } |
46 | |
532
3b53dd1280c6
I/O buffers now use real blocking instead of setting up a sub-ioloop to
Timo Sirainen <tss@iki.fi>
parents:
410
diff
changeset
|
47 static void client_input_timeout(void *context) |
164
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
48 { |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
49 Client *client = context; |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
50 |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
51 client_send_line(my_client, "* BYE Disconnected for inactivity " |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
52 "while waiting for command data."); |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
53 o_stream_close(client->output); |
164
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
54 } |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
55 |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
56 Client *client_create(int hin, int hout, MailStorage *storage) |
0 | 57 { |
58 Client *client; | |
59 | |
60 client = i_new(Client, 1); | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
61 client->input = i_stream_create_file(hin, default_pool, |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
62 MAX_INBUF_SIZE, FALSE); |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
63 client->output = o_stream_create_file(hout, default_pool, 4096, |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
64 IO_PRIORITY_DEFAULT, FALSE); |
0 | 65 |
164
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
66 /* set timeout for reading expected data (eg. APPEND). This is |
2660a5684515
Added io_buffer_read_blocking() which can be used to read data blockingly,
Timo Sirainen <tss@iki.fi>
parents:
158
diff
changeset
|
67 different from the actual idle time. */ |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
68 i_stream_set_blocking(client->input, CLIENT_CMDINPUT_TIMEOUT, |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
69 client_input_timeout, client); |
0 | 70 |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
71 /* set timeout for sending data */ |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
72 o_stream_set_blocking(client->output, CLIENT_OUTPUT_TIMEOUT, |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
73 client_output_timeout, client); |
0 | 74 |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
75 client->io = io_add(hin, IO_READ, (IOFunc) client_input, client); |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
76 client->parser = imap_parser_create(client->input, client->output, |
768
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
77 MAX_INBUF_SIZE, |
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
78 MAX_IMAP_ARG_ELEMENTS); |
0 | 79 client->last_input = ioloop_time; |
80 | |
81 client->storage = storage; | |
674
b7aefd0d7611
Locking changes triggered a bit larger cleanup :) If we have to wait for a
Timo Sirainen <tss@iki.fi>
parents:
532
diff
changeset
|
82 storage->set_callbacks(storage, &mail_storage_callbacks, client); |
0 | 83 |
84 i_assert(my_client == NULL); | |
85 my_client = client; | |
86 return client; | |
87 } | |
88 | |
89 void client_destroy(Client *client) | |
90 { | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
91 o_stream_flush(client->output); |
158
a1204e882bc7
Flush output buffer to client at exit, and send a nice "BYE Server shutting
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
92 |
0 | 93 if (client->mailbox != NULL) |
94 client->mailbox->close(client->mailbox); | |
95 mail_storage_destroy(client->storage); | |
96 | |
97 imap_parser_destroy(client->parser); | |
98 io_remove(client->io); | |
99 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
100 i_stream_unref(client->input); |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
101 o_stream_unref(client->output); |
0 | 102 |
103 i_free(client); | |
104 | |
105 /* quit the program */ | |
106 my_client = NULL; | |
107 io_loop_stop(ioloop); | |
108 } | |
109 | |
110 void client_disconnect(Client *client) | |
111 { | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
112 o_stream_flush(client->output); |
222
cf4d065f2f85
lots of cleanups. also index/datafile is now capable of staying in memory,
Timo Sirainen <tss@iki.fi>
parents:
184
diff
changeset
|
113 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
114 i_stream_close(client->input); |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
115 o_stream_close(client->output); |
0 | 116 } |
117 | |
118 void client_send_line(Client *client, const char *data) | |
119 { | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
120 if (client->output->closed) |
0 | 121 return; |
122 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
123 (void)o_stream_send(client->output, data, strlen(data)); |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
124 (void)o_stream_send(client->output, "\r\n", 2); |
0 | 125 } |
126 | |
127 void client_send_tagline(Client *client, const char *data) | |
128 { | |
129 const char *tag = client->cmd_tag; | |
130 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
131 if (client->output->closed) |
0 | 132 return; |
133 | |
134 if (tag == NULL || *tag == '\0') | |
135 tag = "*"; | |
136 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
137 (void)o_stream_send(client->output, tag, strlen(tag)); |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
138 (void)o_stream_send(client->output, " ", 1); |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
139 (void)o_stream_send(client->output, data, strlen(data)); |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
140 (void)o_stream_send(client->output, "\r\n", 2); |
0 | 141 } |
142 | |
143 void client_send_command_error(Client *client, const char *msg) | |
144 { | |
145 const char *error; | |
146 | |
147 if (msg == NULL) | |
768
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
148 msg = imap_parser_get_error(client->parser); |
8b3518bb327e
Limited max. command argument elements to 128. Added more verbose error
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
149 error = t_strconcat("BAD Error in IMAP command: ", msg, NULL); |
0 | 150 |
151 client->cmd_error = TRUE; | |
152 client_send_tagline(client, error); | |
153 | |
154 if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) { | |
155 client_send_line(client, | |
156 "* BYE Too many invalid IMAP commands."); | |
157 client_disconnect(client); | |
158 } | |
159 } | |
160 | |
161 int client_read_args(Client *client, unsigned int count, unsigned int flags, | |
162 ImapArg **args) | |
163 { | |
164 int ret; | |
165 | |
166 ret = imap_parser_read_args(client->parser, count, flags, args); | |
720 | 167 if (ret >= (int)count) { |
0 | 168 /* all parameters read successfully */ |
169 return TRUE; | |
170 } else if (ret == -2) { | |
171 /* need more data */ | |
172 return FALSE; | |
173 } else { | |
174 /* error, or missing arguments */ | |
769
f17a1f59ac3f
Fixed "Missing arguments" error msg to work again
Timo Sirainen <tss@iki.fi>
parents:
768
diff
changeset
|
175 client_send_command_error(client, ret < 0 ? NULL : |
f17a1f59ac3f
Fixed "Missing arguments" error msg to work again
Timo Sirainen <tss@iki.fi>
parents:
768
diff
changeset
|
176 "Missing arguments"); |
0 | 177 return FALSE; |
178 } | |
179 } | |
180 | |
181 int client_read_string_args(Client *client, unsigned int count, ...) | |
182 { | |
183 ImapArg *imap_args; | |
184 va_list va; | |
185 const char *str; | |
186 unsigned int i; | |
187 | |
188 if (!client_read_args(client, count, 0, &imap_args)) | |
189 return FALSE; | |
190 | |
191 va_start(va, count); | |
192 for (i = 0; i < count; i++) { | |
193 const char **ret = va_arg(va, const char **); | |
194 | |
195 str = imap_arg_string(&imap_args[i]); | |
196 if (str == NULL) { | |
197 client_send_command_error(client, "Missing arguments."); | |
198 va_end(va); | |
199 return FALSE; | |
200 } | |
201 | |
202 if (ret != NULL) | |
203 *ret = str; | |
204 } | |
205 va_end(va); | |
206 | |
207 return TRUE; | |
208 } | |
209 | |
210 static void client_reset_command(Client *client) | |
211 { | |
212 client->cmd_tag = NULL; | |
213 client->cmd_name = NULL; | |
214 client->cmd_func = NULL; | |
215 client->cmd_error = FALSE; | |
216 client->cmd_uid = FALSE; | |
217 | |
218 imap_parser_reset(client->parser); | |
219 } | |
220 | |
221 static void client_command_finished(Client *client) | |
222 { | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
223 client->input_skip_line = TRUE; |
0 | 224 client_reset_command(client); |
225 } | |
226 | |
227 /* Skip incoming data until newline is found, | |
228 returns TRUE if newline was found. */ | |
229 static int client_skip_line(Client *client) | |
230 { | |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
231 const unsigned char *data; |
184 | 232 size_t i, data_size; |
0 | 233 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
234 data = i_stream_get_data(client->input, &data_size); |
0 | 235 |
236 for (i = 0; i < data_size; i++) { | |
237 if (data[i] == '\n') { | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
238 client->input_skip_line = FALSE; |
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
239 i_stream_skip(client->input, i+1); |
0 | 240 break; |
241 } | |
242 } | |
243 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
244 return !client->input_skip_line; |
0 | 245 } |
246 | |
247 static int client_handle_input(Client *client) | |
248 { | |
249 if (client->cmd_func != NULL) { | |
250 /* command is being executed - continue it */ | |
717
3f817df5eba4
Input parsing was a bit broken in some conditions. Mostly visible with
Timo Sirainen <tss@iki.fi>
parents:
674
diff
changeset
|
251 if (client->cmd_func(client) || client->cmd_error) { |
3f817df5eba4
Input parsing was a bit broken in some conditions. Mostly visible with
Timo Sirainen <tss@iki.fi>
parents:
674
diff
changeset
|
252 /* command execution was finished */ |
0 | 253 client_command_finished(client); |
254 return TRUE; | |
255 } | |
256 return FALSE; | |
257 } | |
258 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
259 if (client->input_skip_line) { |
0 | 260 /* we're just waiting for new line.. */ |
261 if (!client_skip_line(client)) | |
262 return FALSE; | |
263 | |
264 /* got the newline */ | |
265 client_reset_command(client); | |
266 | |
267 /* pass through to parse next command */ | |
268 } | |
269 | |
270 if (client->cmd_tag == NULL) { | |
271 client->cmd_tag = imap_parser_read_word(client->parser); | |
272 if (client->cmd_tag == NULL) | |
273 return FALSE; /* need more data */ | |
274 } | |
275 | |
276 if (client->cmd_name == NULL) { | |
277 client->cmd_name = imap_parser_read_word(client->parser); | |
278 if (client->cmd_name == NULL) | |
279 return FALSE; /* need more data */ | |
280 } | |
281 | |
282 if (client->cmd_name == '\0') { | |
283 /* command not given - cmd_func is already NULL. */ | |
284 } else { | |
285 /* find the command function */ | |
286 client->cmd_func = client_command_find(client->cmd_name); | |
287 } | |
288 | |
289 if (client->cmd_func == NULL) { | |
290 /* unknown command */ | |
291 client_send_command_error(client, t_strconcat( | |
292 "Unknown command '", client->cmd_name, "'", NULL)); | |
293 client_command_finished(client); | |
294 } else { | |
295 if (client->cmd_func(client) || client->cmd_error) { | |
296 /* command execution was finished */ | |
297 client_command_finished(client); | |
298 } | |
299 } | |
300 | |
301 return TRUE; | |
302 } | |
303 | |
304 static void client_input(Client *client) | |
305 { | |
306 client->last_input = ioloop_time; | |
307 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
308 switch (i_stream_read(client->input)) { |
0 | 309 case -1: |
310 /* disconnected */ | |
311 client_destroy(client); | |
312 return; | |
313 case -2: | |
314 /* parameter word is longer than max. input buffer size. | |
315 this is most likely an error, so skip the new data | |
316 until newline is found. */ | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
317 client->input_skip_line = TRUE; |
0 | 318 |
319 client_send_command_error(client, "Too long argument."); | |
320 client_command_finished(client); | |
321 break; | |
322 } | |
323 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
324 o_stream_cork(client->output); |
0 | 325 while (client_handle_input(client)) |
326 ; | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
327 o_stream_flush(client->output); |
0 | 328 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
329 if (client->output->closed) |
0 | 330 client_destroy(client); |
331 } | |
332 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
333 static void idle_timeout(void *context __attr_unused__, |
0 | 334 Timeout timeout __attr_unused__) |
335 { | |
336 if (my_client == NULL) | |
337 return; | |
338 | |
339 if (ioloop_time - my_client->last_input >= CLIENT_IDLE_TIMEOUT) { | |
340 client_send_line(my_client, | |
341 "* BYE Disconnected for inactivity."); | |
342 client_destroy(my_client); | |
343 } | |
344 } | |
345 | |
346 void clients_init(void) | |
347 { | |
348 my_client = NULL; | |
349 to_idle = timeout_add(10000, idle_timeout, NULL); | |
350 } | |
351 | |
352 void clients_deinit(void) | |
353 { | |
158
a1204e882bc7
Flush output buffer to client at exit, and send a nice "BYE Server shutting
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
354 if (my_client != NULL) { |
a1204e882bc7
Flush output buffer to client at exit, and send a nice "BYE Server shutting
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
355 client_send_line(my_client, "* BYE Server shutting down."); |
0 | 356 client_destroy(my_client); |
158
a1204e882bc7
Flush output buffer to client at exit, and send a nice "BYE Server shutting
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
357 } |
0 | 358 |
359 timeout_remove(to_idle); | |
360 } |