Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/imap/client.c @ 3763:454863612b5c HEAD
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 25 Dec 2005 12:51:25 +0200 |
parents | edc6e213048f |
children | 03a2ff05bd12 |
rev | line source |
---|---|
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
1 /* Copyright (C) 2002-2004 Timo Sirainen */ |
0 | 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" |
1654
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
9 #include "namespace.h" |
0 | 10 |
11 #include <stdlib.h> | |
12 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
13 extern struct mail_storage_callbacks mail_storage_callbacks; |
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
|
14 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
15 static struct client *my_client; /* we don't need more than one currently */ |
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
16 static struct timeout *to_idle; |
0 | 17 |
1654
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
18 struct client *client_create(int hin, int hout, struct namespace *namespaces) |
0 | 19 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
20 struct client *client; |
0 | 21 |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
22 /* always use nonblocking I/O */ |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
23 net_set_nonblock(hin, TRUE); |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
24 net_set_nonblock(hout, TRUE); |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
25 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
26 client = i_new(struct client, 1); |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
27 client->input = i_stream_create_file(hin, default_pool, |
1591
6eca99b727a0
IMAP parser memory limits are now enforced by bytes per line rather than
Timo Sirainen <tss@iki.fi>
parents:
1538
diff
changeset
|
28 imap_max_line_length, FALSE); |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
29 client->output = o_stream_create_file(hout, default_pool, |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
30 (size_t)-1, FALSE); |
0 | 31 |
2878 | 32 o_stream_set_flush_callback(client->output, _client_output, client); |
0 | 33 |
2460 | 34 client->io = io_add(hin, IO_READ, _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
|
35 client->parser = imap_parser_create(client->input, client->output, |
1591
6eca99b727a0
IMAP parser memory limits are now enforced by bytes per line rather than
Timo Sirainen <tss@iki.fi>
parents:
1538
diff
changeset
|
36 imap_max_line_length); |
0 | 37 client->last_input = ioloop_time; |
38 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
39 client->cmd.pool = pool_alloconly_create("command pool", 8192); |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
40 client->cmd.client = client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
41 |
1958 | 42 client->keywords.pool = pool_alloconly_create("mailbox_keywords", 512); |
1654
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
43 client->namespaces = namespaces; |
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
44 |
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
45 while (namespaces != NULL) { |
1915
79790750c349
importing new index code. mbox still broken.
Timo Sirainen <tss@iki.fi>
parents:
1654
diff
changeset
|
46 mail_storage_set_callbacks(namespaces->storage, |
79790750c349
importing new index code. mbox still broken.
Timo Sirainen <tss@iki.fi>
parents:
1654
diff
changeset
|
47 &mail_storage_callbacks, client); |
1654
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
48 namespaces = namespaces->next; |
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
49 } |
0 | 50 |
51 i_assert(my_client == NULL); | |
52 my_client = client; | |
1641
6498f3cb9d2c
Added hook_client_created and hook_mail_storage_created for modules.
Timo Sirainen <tss@iki.fi>
parents:
1591
diff
changeset
|
53 |
6498f3cb9d2c
Added hook_client_created and hook_mail_storage_created for modules.
Timo Sirainen <tss@iki.fi>
parents:
1591
diff
changeset
|
54 if (hook_client_created != NULL) |
1643 | 55 hook_client_created(&client); |
0 | 56 return client; |
57 } | |
58 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
59 void client_destroy(struct client *client) |
0 | 60 { |
2947 | 61 int ret; |
62 | |
2979
10d1fd8d0865
Deinitialize pending command only if it's actually executing. Fixes crash if
Timo Sirainen <tss@iki.fi>
parents:
2947
diff
changeset
|
63 if (client->command_pending) { |
2501
b7eec64e0735
Deinitialize command handlers always.
Timo Sirainen <tss@iki.fi>
parents:
2462
diff
changeset
|
64 /* try to deinitialize the command */ |
b7eec64e0735
Deinitialize command handlers always.
Timo Sirainen <tss@iki.fi>
parents:
2462
diff
changeset
|
65 i_stream_close(client->input); |
b7eec64e0735
Deinitialize command handlers always.
Timo Sirainen <tss@iki.fi>
parents:
2462
diff
changeset
|
66 o_stream_close(client->output); |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
67 ret = client->cmd.func(&client->cmd); |
2947 | 68 i_assert(ret); |
2501
b7eec64e0735
Deinitialize command handlers always.
Timo Sirainen <tss@iki.fi>
parents:
2462
diff
changeset
|
69 } |
b7eec64e0735
Deinitialize command handlers always.
Timo Sirainen <tss@iki.fi>
parents:
2462
diff
changeset
|
70 |
0 | 71 if (client->mailbox != NULL) |
1915
79790750c349
importing new index code. mbox still broken.
Timo Sirainen <tss@iki.fi>
parents:
1654
diff
changeset
|
72 mailbox_close(client->mailbox); |
1654
31c4bb26a1e9
Getting ready for namespaces. LIST is still broken with them.
Timo Sirainen <tss@iki.fi>
parents:
1643
diff
changeset
|
73 namespace_deinit(client->namespaces); |
0 | 74 |
75 imap_parser_destroy(client->parser); | |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
76 if (client->io != NULL) |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
77 io_remove(client->io); |
0 | 78 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
79 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
|
80 o_stream_unref(client->output); |
0 | 81 |
1958 | 82 pool_unref(client->keywords.pool); |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
83 pool_unref(client->cmd.pool); |
0 | 84 i_free(client); |
85 | |
86 /* quit the program */ | |
87 my_client = NULL; | |
88 io_loop_stop(ioloop); | |
89 } | |
90 | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
91 void client_disconnect(struct client *client) |
0 | 92 { |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
93 (void)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
|
94 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
95 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
|
96 o_stream_close(client->output); |
0 | 97 } |
98 | |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
99 void client_disconnect_with_error(struct client *client, const char *msg) |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
100 { |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
101 client_send_line(client, t_strconcat("* BYE ", msg, NULL)); |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
102 client_disconnect(client); |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
103 } |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
104 |
2425
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
105 int client_send_line(struct client *client, const char *data) |
0 | 106 { |
2425
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
107 struct const_iovec iov[2]; |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
108 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
109 if (client->output->closed) |
2425
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
110 return -1; |
0 | 111 |
2425
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
112 iov[0].iov_base = data; |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
113 iov[0].iov_len = strlen(data); |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
114 iov[1].iov_base = "\r\n"; |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
115 iov[1].iov_len = 2; |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
116 |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
117 if (o_stream_sendv(client->output, iov, 2) < 0) |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
118 return -1; |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
119 |
3601
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
120 if (o_stream_get_buffer_used_size(client->output) >= |
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
121 CLIENT_OUTPUT_OPTIMAL_SIZE) { |
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
122 /* buffer full, try flushing */ |
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
123 return o_stream_flush(client->output); |
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
124 } |
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
125 return 1; |
0 | 126 } |
127 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
128 void client_send_tagline(struct client_command_context *cmd, const char *data) |
0 | 129 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
130 struct client *client = cmd->client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
131 const char *tag = cmd->tag; |
0 | 132 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
133 if (client->output->closed) |
0 | 134 return; |
135 | |
136 if (tag == NULL || *tag == '\0') | |
137 tag = "*"; | |
138 | |
807
35abd7a5d381
Buffer related cleanups. Use PATH_MAX instead of hardcoded 1024 for paths.
Timo Sirainen <tss@iki.fi>
parents:
805
diff
changeset
|
139 (void)o_stream_send_str(client->output, tag); |
764
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, " ", 1); |
807
35abd7a5d381
Buffer related cleanups. Use PATH_MAX instead of hardcoded 1024 for paths.
Timo Sirainen <tss@iki.fi>
parents:
805
diff
changeset
|
141 (void)o_stream_send_str(client->output, data); |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
142 (void)o_stream_send(client->output, "\r\n", 2); |
0 | 143 } |
144 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
145 void client_send_command_error(struct client_command_context *cmd, |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
146 const char *msg) |
0 | 147 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
148 struct client *client = cmd->client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
149 const char *error, *cmd_name; |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
150 int fatal; |
0 | 151 |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
152 if (msg == NULL) { |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
153 msg = imap_parser_get_error(client->parser, &fatal); |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
154 if (fatal) { |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
155 client_disconnect_with_error(client, msg); |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
156 return; |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
157 } |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
158 } |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
159 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
160 if (cmd->tag == NULL) |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
161 error = t_strconcat("BAD Error in IMAP tag: ", msg, NULL); |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
162 else if (cmd->name == NULL) |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
163 error = t_strconcat("BAD Error in IMAP command: ", msg, NULL); |
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
164 else { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
165 cmd_name = t_str_ucase(cmd->name); |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
166 error = t_strconcat("BAD Error in IMAP command ", |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
167 cmd_name, ": ", msg, NULL); |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
168 } |
0 | 169 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
170 client_send_tagline(cmd, error); |
0 | 171 |
172 if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) { | |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
173 client_disconnect_with_error(client, |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
174 "Too many invalid IMAP commands."); |
0 | 175 } |
2508
467af814d5e2
Command parameter errors weren't handled right. This was broken a few
Timo Sirainen <tss@iki.fi>
parents:
2501
diff
changeset
|
176 |
467af814d5e2
Command parameter errors weren't handled right. This was broken a few
Timo Sirainen <tss@iki.fi>
parents:
2501
diff
changeset
|
177 /* client_read_args() failures rely on this being set, so that the |
467af814d5e2
Command parameter errors weren't handled right. This was broken a few
Timo Sirainen <tss@iki.fi>
parents:
2501
diff
changeset
|
178 command processing is stopped even while command function returns |
467af814d5e2
Command parameter errors weren't handled right. This was broken a few
Timo Sirainen <tss@iki.fi>
parents:
2501
diff
changeset
|
179 FALSE. */ |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
180 cmd->param_error = TRUE; |
0 | 181 } |
182 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
183 int client_read_args(struct client_command_context *cmd, unsigned int count, |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
184 unsigned int flags, struct imap_arg **args) |
0 | 185 { |
186 int ret; | |
187 | |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
188 i_assert(count <= INT_MAX); |
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
189 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
190 ret = imap_parser_read_args(cmd->client->parser, count, flags, args); |
720 | 191 if (ret >= (int)count) { |
0 | 192 /* all parameters read successfully */ |
193 return TRUE; | |
194 } else if (ret == -2) { | |
195 /* need more data */ | |
196 return FALSE; | |
197 } else { | |
198 /* error, or missing arguments */ | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
199 client_send_command_error(cmd, ret < 0 ? NULL : |
769
f17a1f59ac3f
Fixed "Missing arguments" error msg to work again
Timo Sirainen <tss@iki.fi>
parents:
768
diff
changeset
|
200 "Missing arguments"); |
0 | 201 return FALSE; |
202 } | |
203 } | |
204 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
205 int client_read_string_args(struct client_command_context *cmd, |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
206 unsigned int count, ...) |
0 | 207 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
208 struct imap_arg *imap_args; |
0 | 209 va_list va; |
210 const char *str; | |
211 unsigned int i; | |
212 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
213 if (!client_read_args(cmd, count, 0, &imap_args)) |
0 | 214 return FALSE; |
215 | |
216 va_start(va, count); | |
217 for (i = 0; i < count; i++) { | |
218 const char **ret = va_arg(va, const char **); | |
219 | |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
220 if (imap_args[i].type == IMAP_ARG_EOL) { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
221 client_send_command_error(cmd, "Missing arguments."); |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
222 break; |
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
223 } |
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
224 |
0 | 225 str = imap_arg_string(&imap_args[i]); |
226 if (str == NULL) { | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
227 client_send_command_error(cmd, "Invalid arguments."); |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
228 break; |
0 | 229 } |
230 | |
231 if (ret != NULL) | |
232 *ret = str; | |
233 } | |
234 va_end(va); | |
235 | |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
236 return i == count; |
0 | 237 } |
238 | |
1172 | 239 void _client_reset_command(struct client *client) |
0 | 240 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
241 pool_t pool; |
3763
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
242 size_t size; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
243 |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
244 /* reset input idle time because command output might have taken a |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
245 long time and we don't want to disconnect client immediately then */ |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
246 client->last_input = ioloop_time; |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
247 |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
248 client->command_pending = FALSE; |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
249 if (client->io == NULL) { |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
250 client->io = io_add(i_stream_get_fd(client->input), |
2460 | 251 IO_READ, _client_input, client); |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
252 } |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
253 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
254 pool = client->cmd.pool; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
255 memset(&client->cmd, 0, sizeof(client->cmd)); |
0 | 256 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
257 p_clear(pool); |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
258 client->cmd.pool = pool; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
259 client->cmd.client = client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
260 |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2425
diff
changeset
|
261 imap_parser_reset(client->parser); |
3763
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
262 |
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
263 /* if there's unread data in buffer, remember that there's input |
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
264 pending and we should get around to calling client_input() soon. |
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
265 This is mostly for APPEND/IDLE. */ |
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
266 (void)i_stream_get_data(client->input, &size); |
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
267 if (size > 0) |
454863612b5c
IDLE: Sending "DONE" + next command in same TCP packet caused the next command not to be executed until yet another command came (which usually didn't happen).
Timo Sirainen <tss@iki.fi>
parents:
3601
diff
changeset
|
268 client->input_pending = TRUE; |
0 | 269 } |
270 | |
271 /* Skip incoming data until newline is found, | |
272 returns TRUE if newline was found. */ | |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
273 static int client_skip_line(struct client *client) |
0 | 274 { |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
275 const unsigned char *data; |
184 | 276 size_t i, data_size; |
0 | 277 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
278 data = i_stream_get_data(client->input, &data_size); |
0 | 279 |
280 for (i = 0; i < data_size; i++) { | |
281 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
|
282 client->input_skip_line = FALSE; |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
283 i++; |
0 | 284 break; |
285 } | |
286 } | |
287 | |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
288 i_stream_skip(client->input, i); |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
289 return !client->input_skip_line; |
0 | 290 } |
291 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
292 static int client_handle_input(struct client_command_context *cmd) |
0 | 293 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
294 struct client *client = cmd->client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
295 |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
296 if (cmd->func != NULL) { |
0 | 297 /* command is being executed - continue it */ |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
298 if (cmd->func(cmd) || cmd->param_error) { |
717
3f817df5eba4
Input parsing was a bit broken in some conditions. Mostly visible with
Timo Sirainen <tss@iki.fi>
parents:
674
diff
changeset
|
299 /* command execution was finished */ |
2445
5376a3c388c0
Set bad_counter before calling client_command_reset because it may parse
Timo Sirainen <tss@iki.fi>
parents:
2427
diff
changeset
|
300 client->bad_counter = 0; |
1172 | 301 _client_reset_command(client); |
0 | 302 return TRUE; |
303 } | |
304 return FALSE; | |
305 } | |
306 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
307 if (client->input_skip_line) { |
0 | 308 /* we're just waiting for new line.. */ |
309 if (!client_skip_line(client)) | |
310 return FALSE; | |
311 | |
312 /* got the newline */ | |
1172 | 313 _client_reset_command(client); |
0 | 314 |
315 /* pass through to parse next command */ | |
316 } | |
317 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
318 if (cmd->tag == NULL) { |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
319 cmd->tag = imap_parser_read_word(client->parser); |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
320 if (cmd->tag == NULL) |
0 | 321 return FALSE; /* need more data */ |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
322 cmd->tag = p_strdup(cmd->pool, cmd->tag); |
0 | 323 } |
324 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
325 if (cmd->name == NULL) { |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
326 cmd->name = imap_parser_read_word(client->parser); |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
327 if (cmd->name == NULL) |
0 | 328 return FALSE; /* need more data */ |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
329 cmd->name = p_strdup(cmd->pool, cmd->name); |
0 | 330 } |
331 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
332 if (cmd->name == '\0') { |
0 | 333 /* command not given - cmd_func is already NULL. */ |
334 } else { | |
335 /* find the command function */ | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
336 cmd->func = command_find(cmd->name); |
0 | 337 } |
338 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
339 if (cmd->func == NULL) { |
0 | 340 /* unknown command */ |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
341 client_send_command_error(cmd, "Unknown command."); |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
342 client->input_skip_line = TRUE; |
1172 | 343 _client_reset_command(client); |
0 | 344 } else { |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
345 client->input_skip_line = TRUE; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
346 if (cmd->func(cmd) || cmd->param_error) { |
2508
467af814d5e2
Command parameter errors weren't handled right. This was broken a few
Timo Sirainen <tss@iki.fi>
parents:
2501
diff
changeset
|
347 /* command execution was finished. */ |
2445
5376a3c388c0
Set bad_counter before calling client_command_reset because it may parse
Timo Sirainen <tss@iki.fi>
parents:
2427
diff
changeset
|
348 client->bad_counter = 0; |
1172 | 349 _client_reset_command(client); |
350 } else { | |
351 /* unfinished */ | |
3336
a3a72d5bdfce
o_stream_uncork() was previously always setting IO_WRITE handler even if
Timo Sirainen <tss@iki.fi>
parents:
3141
diff
changeset
|
352 if (client->command_pending) { |
a3a72d5bdfce
o_stream_uncork() was previously always setting IO_WRITE handler even if
Timo Sirainen <tss@iki.fi>
parents:
3141
diff
changeset
|
353 o_stream_set_flush_pending(client->output, |
a3a72d5bdfce
o_stream_uncork() was previously always setting IO_WRITE handler even if
Timo Sirainen <tss@iki.fi>
parents:
3141
diff
changeset
|
354 TRUE); |
a3a72d5bdfce
o_stream_uncork() was previously always setting IO_WRITE handler even if
Timo Sirainen <tss@iki.fi>
parents:
3141
diff
changeset
|
355 } |
1172 | 356 return FALSE; |
0 | 357 } |
358 } | |
359 | |
360 return TRUE; | |
361 } | |
362 | |
2460 | 363 void _client_input(void *context) |
0 | 364 { |
953
411006be3c66
Naming change for function typedefs.
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
365 struct client *client = context; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
366 struct client_command_context *cmd = &client->cmd; |
3469
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
367 int ret; |
953
411006be3c66
Naming change for function typedefs.
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
368 |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
369 if (client->command_pending) { |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
370 /* already processing one command. wait. */ |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
371 io_remove(client->io); |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
372 client->io = NULL; |
2513
f6fdf9048a01
Input handler tried to process multiple commands at once which broke things.
Timo Sirainen <tss@iki.fi>
parents:
2508
diff
changeset
|
373 return; |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
374 } |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
375 |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2425
diff
changeset
|
376 client->input_pending = FALSE; |
0 | 377 client->last_input = ioloop_time; |
378 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
379 switch (i_stream_read(client->input)) { |
0 | 380 case -1: |
381 /* disconnected */ | |
382 client_destroy(client); | |
383 return; | |
384 case -2: | |
385 /* parameter word is longer than max. input buffer size. | |
386 this is most likely an error, so skip the new data | |
387 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
|
388 client->input_skip_line = TRUE; |
0 | 389 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
390 client_send_command_error(cmd, "Too long argument."); |
1172 | 391 _client_reset_command(client); |
0 | 392 break; |
393 } | |
394 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
395 o_stream_cork(client->output); |
3469
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
396 do { |
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
397 t_push(); |
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
398 ret = client_handle_input(cmd); |
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
399 t_pop(); |
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
400 } while (ret); |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
401 o_stream_uncork(client->output); |
0 | 402 |
2427
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2425
diff
changeset
|
403 if (client->command_pending) |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2425
diff
changeset
|
404 client->input_pending = TRUE; |
e1616067df5c
Syncing works now too without buffering everything. Also fixed handling
Timo Sirainen <tss@iki.fi>
parents:
2425
diff
changeset
|
405 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
406 if (client->output->closed) |
0 | 407 client_destroy(client); |
408 } | |
409 | |
2878 | 410 int _client_output(void *context) |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
411 { |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
412 struct client *client = context; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
413 struct client_command_context *cmd = &client->cmd; |
2790
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
414 int ret, finished; |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
415 |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
416 client->last_output = ioloop_time; |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
417 |
2790
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
418 if ((ret = o_stream_flush(client->output)) < 0) { |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
419 client_destroy(client); |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
420 return 1; |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
421 } |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
422 |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
423 if (!client->command_pending) |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
424 return 1; |
2462 | 425 |
2790
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
426 /* continue processing command */ |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
427 o_stream_cork(client->output); |
2800 | 428 client->output_pending = TRUE; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
429 finished = cmd->func(cmd) || cmd->param_error; |
2462 | 430 |
3402
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
431 /* a bit kludgy check. normally we would want to get back to this |
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
432 output handler, but IDLE is a special case which has command |
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
433 pending but without necessarily anything to write. */ |
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
434 if (!finished && client->output_pending) |
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
435 o_stream_set_flush_pending(client->output, TRUE); |
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
436 |
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
437 o_stream_uncork(client->output); |
2800 | 438 |
2790
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
439 if (finished) { |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
440 /* command execution was finished */ |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
441 client->bad_counter = 0; |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
442 _client_reset_command(client); |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
443 |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
444 if (client->input_pending) |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
445 _client_input(client); |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
446 } |
2800 | 447 return ret; |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
448 } |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
449 |
1036
f782b3319553
Removed useless parameters from io_callback_t and timeout_callback_t.
Timo Sirainen <tss@iki.fi>
parents:
1023
diff
changeset
|
450 static void idle_timeout(void *context __attr_unused__) |
0 | 451 { |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
452 time_t idle_time; |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
453 |
0 | 454 if (my_client == NULL) |
455 return; | |
456 | |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
457 idle_time = ioloop_time - |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
458 I_MAX(my_client->last_input, my_client->last_output); |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
459 |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
460 if (my_client->command_pending && |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
461 o_stream_get_buffer_used_size(my_client->output) > 0 && |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
462 idle_time >= CLIENT_OUTPUT_TIMEOUT) { |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
463 /* client isn't reading our output */ |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
464 client_destroy(my_client); |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
465 } else if (idle_time >= CLIENT_IDLE_TIMEOUT) { |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
466 /* client isn't sending us anything */ |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
467 if (!my_client->command_pending) { |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
468 client_send_line(my_client, |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
469 "* BYE Disconnected for inactivity."); |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
470 } |
0 | 471 client_destroy(my_client); |
472 } | |
473 } | |
474 | |
475 void clients_init(void) | |
476 { | |
477 my_client = NULL; | |
478 to_idle = timeout_add(10000, idle_timeout, NULL); | |
479 } | |
480 | |
481 void clients_deinit(void) | |
482 { | |
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
|
483 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
|
484 client_send_line(my_client, "* BYE Server shutting down."); |
0 | 485 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
|
486 } |
0 | 487 |
488 timeout_remove(to_idle); | |
489 } |