Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/imap/client.c @ 4939:ff2272c228cc HEAD
Dovecot is now able to execute multiple commands at the same time.
Practically this means commands: FETCH, LIST, SEARCH and syncing output for
all commands. For example it's possible that doing two FETCH commands at the
same time makes their output mixed together.
Non-blocking SEARCH is done by doing search for 20 mails at a time, and then
checking if another command is pending.
Also added X-CANCEL <tag> command to cancel running commands.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 20 Dec 2006 21:23:43 +0200 |
parents | 5b4c9b20eba0 |
children | f612d2086448 |
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> | |
3960
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
12 #include <unistd.h> |
0 | 13 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
14 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
|
15 |
903
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 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
|
17 static struct timeout *to_idle; |
0 | 18 |
3960
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
19 struct client *client_create(int fd_in, int fd_out, |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
20 struct namespace *namespaces) |
0 | 21 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
22 struct client *client; |
0 | 23 |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
24 /* always use nonblocking I/O */ |
3960
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
25 net_set_nonblock(fd_in, TRUE); |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
26 net_set_nonblock(fd_out, TRUE); |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
27 |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
28 client = i_new(struct client, 1); |
3960
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
29 client->fd_in = fd_in; |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
30 client->fd_out = fd_out; |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
31 client->input = i_stream_create_file(fd_in, 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
|
32 imap_max_line_length, FALSE); |
3960
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
33 client->output = o_stream_create_file(fd_out, default_pool, |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
34 (size_t)-1, FALSE); |
0 | 35 |
2878 | 36 o_stream_set_flush_callback(client->output, _client_output, client); |
0 | 37 |
3960
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
38 client->io = io_add(fd_in, IO_READ, _client_input, client); |
0 | 39 client->last_input = ioloop_time; |
40 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
41 client->command_pool = pool_alloconly_create("client command", 8192); |
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 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
59 void client_command_cancel(struct client_command_context *cmd) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
60 { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
61 bool cmd_ret; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
62 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
63 cmd->cancel = TRUE; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
64 cmd_ret = cmd->func(cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
65 if (!cmd_ret) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
66 if (cmd->client->output->closed) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
67 i_panic("command didn't cancel itself: %s", cmd->name); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
68 } else { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
69 client_command_free(cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
70 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
71 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
72 |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
73 void client_destroy(struct client *client, const char *reason) |
0 | 74 { |
3871
2506e4077e7a
Don't crash if closing with signal while IDLEing.
Timo Sirainen <tss@iki.fi>
parents:
3866
diff
changeset
|
75 i_assert(!client->destroyed); |
2506e4077e7a
Don't crash if closing with signal while IDLEing.
Timo Sirainen <tss@iki.fi>
parents:
3866
diff
changeset
|
76 client->destroyed = TRUE; |
2506e4077e7a
Don't crash if closing with signal while IDLEing.
Timo Sirainen <tss@iki.fi>
parents:
3866
diff
changeset
|
77 |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
78 if (!client->disconnected) { |
4787
62f534a0fd68
Don't crash if client disconnected while IDLEing.
Timo Sirainen <tss@iki.fi>
parents:
4773
diff
changeset
|
79 client->disconnected = TRUE; |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
80 if (reason == NULL) |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
81 reason = "Disconnected"; |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
82 i_info("%s", reason); |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
83 } |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
84 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
85 i_stream_close(client->input); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
86 o_stream_close(client->output); |
3871
2506e4077e7a
Don't crash if closing with signal while IDLEing.
Timo Sirainen <tss@iki.fi>
parents:
3866
diff
changeset
|
87 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
88 /* finish off all the queued commands. */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
89 if (client->output_lock != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
90 client_command_cancel(client->output_lock); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
91 if (client->input_lock != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
92 client_command_cancel(client->input_lock); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
93 while (client->command_queue != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
94 client_command_cancel(client->command_queue); |
2501
b7eec64e0735
Deinitialize command handlers always.
Timo Sirainen <tss@iki.fi>
parents:
2462
diff
changeset
|
95 |
0 | 96 if (client->mailbox != NULL) |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3871
diff
changeset
|
97 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
|
98 namespace_deinit(client->namespaces); |
0 | 99 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
100 if (client->free_parser != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
101 imap_parser_destroy(&client->free_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
|
102 if (client->io != NULL) |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3871
diff
changeset
|
103 io_remove(&client->io); |
0 | 104 |
4070
71b8faa84ec6
Added i_stream_destroy() and o_stream_destroy() and used them instead of
Timo Sirainen <tss@iki.fi>
parents:
3963
diff
changeset
|
105 i_stream_destroy(&client->input); |
71b8faa84ec6
Added i_stream_destroy() and o_stream_destroy() and used them instead of
Timo Sirainen <tss@iki.fi>
parents:
3963
diff
changeset
|
106 o_stream_destroy(&client->output); |
0 | 107 |
3960
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
108 if (close(client->fd_in) < 0) |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
109 i_error("close(client in) failed: %m"); |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
110 if (client->fd_in != client->fd_out) { |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
111 if (close(client->fd_out) < 0) |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
112 i_error("close(client out) failed: %m"); |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
113 } |
aeb424e64f24
Call io_remove() before closing the fd. It's required by kqueue.
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
114 |
1958 | 115 pool_unref(client->keywords.pool); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
116 pool_unref(client->command_pool); |
0 | 117 i_free(client); |
118 | |
119 /* quit the program */ | |
120 my_client = NULL; | |
121 io_loop_stop(ioloop); | |
122 } | |
123 | |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
124 void client_disconnect(struct client *client, const char *reason) |
0 | 125 { |
4291
c78bd7fb7ce8
Added assert against NULL reason for client_disconnect().
Timo Sirainen <tss@iki.fi>
parents:
4096
diff
changeset
|
126 i_assert(reason != NULL); |
c78bd7fb7ce8
Added assert against NULL reason for client_disconnect().
Timo Sirainen <tss@iki.fi>
parents:
4096
diff
changeset
|
127 |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
128 if (client->disconnected) |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
129 return; |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
130 |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
131 i_info("Disconnected: %s", reason); |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
132 client->disconnected = TRUE; |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
133 (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
|
134 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
135 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
|
136 o_stream_close(client->output); |
0 | 137 } |
138 | |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
139 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
|
140 { |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
141 client_send_line(client, t_strconcat("* BYE ", msg, NULL)); |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
142 client_disconnect(client, msg); |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
143 } |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
144 |
2425
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
145 int client_send_line(struct client *client, const char *data) |
0 | 146 { |
2425
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
147 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
|
148 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
149 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
|
150 return -1; |
0 | 151 |
2425
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
152 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
|
153 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
|
154 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
|
155 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
|
156 |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
157 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
|
158 return -1; |
8267d11cacfb
LIST command interrupts itself when output buffer gets full and continues
Timo Sirainen <tss@iki.fi>
parents:
2421
diff
changeset
|
159 |
3601
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
160 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
|
161 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
|
162 /* 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
|
163 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
|
164 } |
edc6e213048f
client_send_line(): Try flushing output immediately if buffer gets full.
Timo Sirainen <tss@iki.fi>
parents:
3469
diff
changeset
|
165 return 1; |
0 | 166 } |
167 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
168 void client_send_tagline(struct client_command_context *cmd, const char *data) |
0 | 169 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
170 struct client *client = cmd->client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
171 const char *tag = cmd->tag; |
0 | 172 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
173 if (client->output->closed || cmd->cancel) |
0 | 174 return; |
175 | |
176 if (tag == NULL || *tag == '\0') | |
177 tag = "*"; | |
178 | |
807
35abd7a5d381
Buffer related cleanups. Use PATH_MAX instead of hardcoded 1024 for paths.
Timo Sirainen <tss@iki.fi>
parents:
805
diff
changeset
|
179 (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
|
180 (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
|
181 (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
|
182 (void)o_stream_send(client->output, "\r\n", 2); |
0 | 183 } |
184 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
185 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
|
186 const char *msg) |
0 | 187 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
188 struct client *client = cmd->client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
189 const char *error, *cmd_name; |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3811
diff
changeset
|
190 bool fatal; |
0 | 191 |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
192 if (msg == NULL) { |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
193 msg = imap_parser_get_error(cmd->parser, &fatal); |
1023
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
194 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
|
195 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
|
196 return; |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
197 } |
dc660f588218
Disconnect client if given non-sync literal size is too large. Better than
Timo Sirainen <tss@iki.fi>
parents:
1015
diff
changeset
|
198 } |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
199 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
200 if (cmd->tag == NULL) |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
201 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
|
202 else if (cmd->name == NULL) |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
203 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
|
204 else { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
205 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
|
206 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
|
207 cmd_name, ": ", msg, NULL); |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
208 } |
0 | 209 |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
210 client_send_tagline(cmd, error); |
0 | 211 |
212 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
|
213 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
|
214 "Too many invalid IMAP commands."); |
0 | 215 } |
2508
467af814d5e2
Command parameter errors weren't handled right. This was broken a few
Timo Sirainen <tss@iki.fi>
parents:
2501
diff
changeset
|
216 |
467af814d5e2
Command parameter errors weren't handled right. This was broken a few
Timo Sirainen <tss@iki.fi>
parents:
2501
diff
changeset
|
217 /* 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
|
218 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
|
219 FALSE. */ |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
220 cmd->param_error = TRUE; |
0 | 221 } |
222 | |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3811
diff
changeset
|
223 bool client_read_args(struct client_command_context *cmd, unsigned int count, |
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3811
diff
changeset
|
224 unsigned int flags, struct imap_arg **args) |
0 | 225 { |
226 int ret; | |
227 | |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
228 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
|
229 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
230 ret = imap_parser_read_args(cmd->parser, count, flags, args); |
720 | 231 if (ret >= (int)count) { |
0 | 232 /* all parameters read successfully */ |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
233 i_assert(cmd->client->input_lock == NULL || |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
234 cmd->client->input_lock == cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
235 cmd->client->input_lock = NULL; |
0 | 236 return TRUE; |
237 } else if (ret == -2) { | |
238 /* need more data */ | |
239 return FALSE; | |
240 } else { | |
241 /* error, or missing arguments */ | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
242 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
|
243 "Missing arguments"); |
0 | 244 return FALSE; |
245 } | |
246 } | |
247 | |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3811
diff
changeset
|
248 bool client_read_string_args(struct client_command_context *cmd, |
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3811
diff
changeset
|
249 unsigned int count, ...) |
0 | 250 { |
903
fd8888f6f037
Naming style changes, finally got tired of most of the typedefs. Also the
Timo Sirainen <tss@iki.fi>
parents:
807
diff
changeset
|
251 struct imap_arg *imap_args; |
0 | 252 va_list va; |
253 const char *str; | |
254 unsigned int i; | |
255 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
256 if (!client_read_args(cmd, count, 0, &imap_args)) |
0 | 257 return FALSE; |
258 | |
259 va_start(va, count); | |
260 for (i = 0; i < count; i++) { | |
261 const char **ret = va_arg(va, const char **); | |
262 | |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
263 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
|
264 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
|
265 break; |
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
266 } |
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
267 |
0 | 268 str = imap_arg_string(&imap_args[i]); |
269 if (str == NULL) { | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
270 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
|
271 break; |
0 | 272 } |
273 | |
274 if (ret != NULL) | |
275 *ret = str; | |
276 } | |
277 va_end(va); | |
278 | |
1015
40a327d356de
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
Timo Sirainen <tss@iki.fi>
parents:
1001
diff
changeset
|
279 return i == count; |
0 | 280 } |
281 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
282 static struct client_command_context * |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
283 client_command_new(struct client *client) |
0 | 284 { |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
285 struct client_command_context *cmd; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
286 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
287 cmd = p_new(client->command_pool, struct client_command_context, 1); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
288 cmd->client = client; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
289 cmd->pool = client->command_pool; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
290 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
291 if (client->free_parser != NULL) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
292 cmd->parser = client->free_parser; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
293 client->free_parser = NULL; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
294 } else { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
295 cmd->parser = imap_parser_create(client->input, client->output, |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
296 imap_max_line_length); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
297 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
298 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
299 /* add to beginning of the queue */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
300 if (client->command_queue != NULL) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
301 client->command_queue->prev = cmd; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
302 cmd->next = client->command_queue; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
303 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
304 client->command_queue = cmd; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
305 client->command_queue_size++; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
306 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
307 return cmd; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
308 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
309 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
310 void client_command_free(struct client_command_context *cmd) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
311 { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
312 struct client *client = cmd->client; |
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
|
313 size_t size; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
314 |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
315 /* 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
|
316 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
|
317 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
|
318 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
319 if (cmd->cancel) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
320 cmd->cancel = FALSE; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
321 client_send_tagline(cmd, "NO Command cancelled."); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
322 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
323 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
324 if (!cmd->param_error) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
325 client->bad_counter = 0; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
326 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
327 if (client->input_lock == cmd) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
328 /* reset the input handler in case it was changed */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
329 client->input_lock = NULL; |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
330 } |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
331 if (client->output_lock == cmd) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
332 /* reset the output handler in case it was changed */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
333 o_stream_set_flush_callback(client->output, |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
334 _client_output, client); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
335 client->output_lock = NULL; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
336 } |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
337 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
338 if (client->free_parser != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
339 imap_parser_destroy(&cmd->parser); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
340 else { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
341 imap_parser_reset(cmd->parser); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
342 client->free_parser = cmd->parser; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
343 } |
0 | 344 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
345 client->command_queue_size--; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
346 if (cmd->prev != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
347 cmd->prev->next = cmd->next; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
348 else |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
349 client->command_queue = cmd->next; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
350 if (cmd->next != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
351 cmd->next->prev = cmd->prev; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
352 cmd = NULL; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
353 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
354 if (client->command_queue == NULL) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
355 /* no commands left in the queue, we can clear the pool */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
356 p_clear(client->command_pool); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
357 } |
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
|
358 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
359 if (client->input_lock == NULL && !client->disconnected) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
360 if (client->io == NULL) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
361 i_assert(i_stream_get_fd(client->input) >= 0); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
362 client->io = io_add(i_stream_get_fd(client->input), |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
363 IO_READ, _client_input, client); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
364 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
365 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
366 /* if there's unread data in buffer, handle it. */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
367 if (!client->handling_input) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
368 (void)i_stream_get_data(client->input, &size); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
369 if (size > 0 && !client->destroyed) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
370 _client_input(client); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
371 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
372 } |
0 | 373 } |
374 | |
375 /* Skip incoming data until newline is found, | |
376 returns TRUE if newline was found. */ | |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3811
diff
changeset
|
377 static bool client_skip_line(struct client *client) |
0 | 378 { |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
379 const unsigned char *data; |
184 | 380 size_t i, data_size; |
0 | 381 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
382 data = i_stream_get_data(client->input, &data_size); |
0 | 383 |
384 for (i = 0; i < data_size; i++) { | |
385 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
|
386 client->input_skip_line = FALSE; |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
387 i++; |
0 | 388 break; |
389 } | |
390 } | |
391 | |
1538
4d1c65eded2c
Give more verbose protocol level errors + some fixes.
Timo Sirainen <tss@iki.fi>
parents:
1499
diff
changeset
|
392 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
|
393 return !client->input_skip_line; |
0 | 394 } |
395 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
396 static bool client_command_input(struct client_command_context *cmd) |
0 | 397 { |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
398 struct client *client = cmd->client; |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
399 |
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
400 if (cmd->func != NULL) { |
0 | 401 /* 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
|
402 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
|
403 /* command execution was finished */ |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
404 client_command_free(cmd); |
0 | 405 return TRUE; |
406 } | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
407 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
408 /* unfinished */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
409 if (cmd->output_pending) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
410 o_stream_set_flush_pending(client->output, TRUE); |
0 | 411 return FALSE; |
412 } | |
413 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
414 if (cmd->tag == NULL) { |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
415 cmd->tag = imap_parser_read_word(cmd->parser); |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
416 if (cmd->tag == NULL) |
0 | 417 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
|
418 cmd->tag = p_strdup(cmd->pool, cmd->tag); |
0 | 419 } |
420 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
421 if (cmd->name == NULL) { |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
422 cmd->name = imap_parser_read_word(cmd->parser); |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
423 if (cmd->name == NULL) |
0 | 424 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
|
425 cmd->name = p_strdup(cmd->pool, cmd->name); |
0 | 426 } |
427 | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
428 if (cmd->name == '\0') { |
0 | 429 /* command not given - cmd_func is already NULL. */ |
430 } else { | |
431 /* find the command function */ | |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
432 cmd->func = command_find(cmd->name); |
0 | 433 } |
434 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
435 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
|
436 if (cmd->func == NULL) { |
0 | 437 /* unknown command */ |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
438 client_send_command_error(cmd, "Unknown command."); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
439 cmd->param_error = TRUE; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
440 client_command_free(cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
441 return TRUE; |
0 | 442 } else { |
4831 | 443 i_assert(!client->disconnected); |
444 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
445 return client_command_input(cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
446 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
447 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
448 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
449 static bool client_handle_next_command(struct client *client) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
450 { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
451 size_t size; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
452 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
453 if (client->input_lock != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
454 return client_command_input(client->input_lock); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
455 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
456 if (client->input_skip_line) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
457 /* first eat the previous command line */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
458 if (!client_skip_line(client)) |
1172 | 459 return FALSE; |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
460 client->input_skip_line = FALSE; |
0 | 461 } |
462 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
463 /* don't bother creating a new client command before there's at least |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
464 some input */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
465 (void)i_stream_get_data(client->input, &size); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
466 if (size == 0) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
467 return FALSE; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
468 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
469 /* beginning a new command */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
470 if (client->command_queue_size >= CLIENT_COMMAND_QUEUE_MAX_SIZE || |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
471 client->output_lock != NULL) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
472 /* wait for some of the commands to finish */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
473 io_remove(&client->io); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
474 return FALSE; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
475 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
476 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
477 client->input_lock = client_command_new(client); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
478 return client_command_input(client->input_lock); |
0 | 479 } |
480 | |
4907
5b4c9b20eba0
Replaced void *context from a lot of callbacks with the actual context
Timo Sirainen <tss@iki.fi>
parents:
4831
diff
changeset
|
481 void _client_input(struct client *client) |
0 | 482 { |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
483 struct client_command_context *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
|
484 int ret; |
953
411006be3c66
Naming change for function typedefs.
Timo Sirainen <tss@iki.fi>
parents:
903
diff
changeset
|
485 |
0 | 486 client->last_input = ioloop_time; |
487 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
488 switch (i_stream_read(client->input)) { |
0 | 489 case -1: |
490 /* disconnected */ | |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
491 client_destroy(client, NULL); |
0 | 492 return; |
493 case -2: | |
494 /* parameter word is longer than max. input buffer size. | |
495 this is most likely an error, so skip the new data | |
496 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
|
497 client->input_skip_line = TRUE; |
0 | 498 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
499 cmd = client->input_lock != NULL ? client->input_lock : |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
500 client_command_new(client); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
501 cmd->param_error = TRUE; |
3141
61abed5f7864
Moved command-specific variables from struct client to struct
Timo Sirainen <tss@iki.fi>
parents:
2979
diff
changeset
|
502 client_send_command_error(cmd, "Too long argument."); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
503 client_command_free(cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
504 return; |
0 | 505 } |
506 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
507 o_stream_cork(client->output); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
508 client->handling_input = TRUE; |
3469
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
509 do { |
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
510 t_push(); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
511 ret = client_handle_next_command(client); |
3469
7e39590da48a
Call t_push/t_pop around client command execution function, so if client
Timo Sirainen <tss@iki.fi>
parents:
3402
diff
changeset
|
512 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
|
513 } while (ret); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
514 client->handling_input = 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
|
515 o_stream_uncork(client->output); |
0 | 516 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
720
diff
changeset
|
517 if (client->output->closed) |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
518 client_destroy(client, NULL); |
0 | 519 } |
520 | |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
521 static void client_output_cmd(struct client_command_context *cmd) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
522 { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
523 struct client *client = cmd->client; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
524 bool finished; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
525 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
526 /* continue processing command */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
527 finished = cmd->func(cmd) || cmd->param_error; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
528 |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
529 if (!finished) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
530 if (cmd->output_pending) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
531 o_stream_set_flush_pending(client->output, TRUE); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
532 } else { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
533 /* command execution was finished */ |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
534 client_command_free(cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
535 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
536 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
537 |
4907
5b4c9b20eba0
Replaced void *context from a lot of callbacks with the actual context
Timo Sirainen <tss@iki.fi>
parents:
4831
diff
changeset
|
538 int _client_output(struct client *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
|
539 { |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
540 struct client_command_context *cmd; |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3811
diff
changeset
|
541 int 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
|
542 |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
543 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
|
544 |
2790
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
545 if ((ret = o_stream_flush(client->output)) < 0) { |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
546 client_destroy(client, NULL); |
2790
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
547 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
|
548 } |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
549 |
02c0b8d532c2
Changed ostream's flush callback to have return value which can tell if
Timo Sirainen <tss@iki.fi>
parents:
2640
diff
changeset
|
550 o_stream_cork(client->output); |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
551 if (client->output_lock != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
552 client_output_cmd(client->output_lock); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
553 if (client->output_lock == NULL) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
554 cmd = client->command_queue; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
555 for (; cmd != NULL; cmd = cmd->next) { |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
556 client_output_cmd(cmd); |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
557 if (client->output_lock != NULL) |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
558 break; |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
559 } |
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
560 } |
3402
513abd166949
Changed output handler to work a bit differently to avoid useless
Timo Sirainen <tss@iki.fi>
parents:
3336
diff
changeset
|
561 o_stream_uncork(client->output); |
2800 | 562 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
|
563 } |
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
564 |
1036
f782b3319553
Removed useless parameters from io_callback_t and timeout_callback_t.
Timo Sirainen <tss@iki.fi>
parents:
1023
diff
changeset
|
565 static void idle_timeout(void *context __attr_unused__) |
0 | 566 { |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
567 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
|
568 |
0 | 569 if (my_client == NULL) |
570 return; | |
571 | |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
572 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
|
573 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
|
574 |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
575 if (o_stream_get_buffer_used_size(my_client->output) > 0 && |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
576 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
|
577 /* client isn't reading our output */ |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
578 client_destroy(my_client, "Disconnected for inactivity " |
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
579 "in reading our output"); |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
580 } 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
|
581 /* client isn't sending us anything */ |
4939
ff2272c228cc
Dovecot is now able to execute multiple commands at the same time.
Timo Sirainen <tss@iki.fi>
parents:
4907
diff
changeset
|
582 if (my_client->output_lock == NULL) { |
2421
d141e1bfdd63
We never do blocking reads/writes to network anymore. Changed imap and pop3
Timo Sirainen <tss@iki.fi>
parents:
2058
diff
changeset
|
583 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
|
584 "* 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
|
585 } |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
586 client_destroy(my_client, "Disconnected for inactivity"); |
0 | 587 } |
588 } | |
589 | |
590 void clients_init(void) | |
591 { | |
592 my_client = NULL; | |
593 to_idle = timeout_add(10000, idle_timeout, NULL); | |
594 } | |
595 | |
596 void clients_deinit(void) | |
597 { | |
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
|
598 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
|
599 client_send_line(my_client, "* BYE Server shutting down."); |
4096
904c53275e83
Log a line when IMAP client disconnects with a reason why it happened.
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
600 client_destroy(my_client, "Server shutting down"); |
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
|
601 } |
0 | 602 |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3871
diff
changeset
|
603 timeout_remove(&to_idle); |
0 | 604 } |