Mercurial > hg > nginx-quic
annotate src/mail/ngx_mail_proxy_module.c @ 6806:75dbab4ea930
Events: improved error event handling for UDP sockets.
Normally, the epoll module calls the read and write handlers depending
on whether EPOLLIN and EPOLLOUT are reported by epoll_wait(). No error
processing is done in the module, the handlers are expected to get an
error when doing I/O.
If an error event is reported without EPOLLIN and EPOLLOUT, the module
set both EPOLLIN and EPOLLOUT to ensure the error event is handled at
least in one active handler.
This works well unless the error is delivered along with only one of
EPOLLIN or EPOLLOUT, and the corresponding handler does not do any I/O.
For example, it happened when getting EPOLLERR|EPOLLOUT from
epoll_wait() upon receiving "ICMP port unreachable" while proxying UDP.
As the write handler had nothing to send it was not able to detect and
log an error, and did not switch to the next upstream.
The fix is to unconditionally set EPOLLIN and EPOLLOUT in case of an
error event. In the aforementioned case, this causes the read handler
to be called which does recv() and detects an error.
In addition to the epoll module, analogous changes were made in
devpoll/eventport/poll.
author | Dmitry Volyntsev <xeioex@nginx.com> |
---|---|
date | Mon, 21 Nov 2016 16:03:42 +0300 |
parents | f01ab2dbcfdc |
children | 9c29644f6d03 |
rev | line source |
---|---|
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
426
diff
changeset
|
1 |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
426
diff
changeset
|
2 /* |
444
42d11f017717
nginx-0.1.0-2004-09-29-20:00:49 import; remove years from copyright
Igor Sysoev <igor@sysoev.ru>
parents:
441
diff
changeset
|
3 * Copyright (C) Igor Sysoev |
4412 | 4 * Copyright (C) Nginx, Inc. |
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
426
diff
changeset
|
5 */ |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
426
diff
changeset
|
6 |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_config.h> |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_core.h> |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 #include <ngx_event.h> |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
11 #include <ngx_event_connect.h> |
1136 | 12 #include <ngx_mail.h> |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
13 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
14 |
521 | 15 typedef struct { |
16 ngx_flag_t enable; | |
857 | 17 ngx_flag_t pass_error_message; |
1136 | 18 ngx_flag_t xclient; |
539 | 19 size_t buffer_size; |
20 ngx_msec_t timeout; | |
1136 | 21 } ngx_mail_proxy_conf_t; |
521 | 22 |
23 | |
1136 | 24 static void ngx_mail_proxy_block_read(ngx_event_t *rev); |
25 static void ngx_mail_proxy_pop3_handler(ngx_event_t *rev); | |
26 static void ngx_mail_proxy_imap_handler(ngx_event_t *rev); | |
27 static void ngx_mail_proxy_smtp_handler(ngx_event_t *rev); | |
28 static void ngx_mail_proxy_dummy_handler(ngx_event_t *ev); | |
29 static ngx_int_t ngx_mail_proxy_read_response(ngx_mail_session_t *s, | |
663 | 30 ngx_uint_t state); |
1136 | 31 static void ngx_mail_proxy_handler(ngx_event_t *ev); |
32 static void ngx_mail_proxy_upstream_error(ngx_mail_session_t *s); | |
33 static void ngx_mail_proxy_internal_server_error(ngx_mail_session_t *s); | |
34 static void ngx_mail_proxy_close_session(ngx_mail_session_t *s); | |
35 static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf); | |
36 static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, | |
521 | 37 void *child); |
38 | |
39 | |
1136 | 40 static ngx_command_t ngx_mail_proxy_commands[] = { |
539 | 41 |
521 | 42 { ngx_string("proxy"), |
1136 | 43 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, |
521 | 44 ngx_conf_set_flag_slot, |
1136 | 45 NGX_MAIL_SRV_CONF_OFFSET, |
46 offsetof(ngx_mail_proxy_conf_t, enable), | |
521 | 47 NULL }, |
48 | |
539 | 49 { ngx_string("proxy_buffer"), |
1136 | 50 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, |
539 | 51 ngx_conf_set_size_slot, |
1136 | 52 NGX_MAIL_SRV_CONF_OFFSET, |
53 offsetof(ngx_mail_proxy_conf_t, buffer_size), | |
539 | 54 NULL }, |
55 | |
56 { ngx_string("proxy_timeout"), | |
1136 | 57 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, |
539 | 58 ngx_conf_set_msec_slot, |
1136 | 59 NGX_MAIL_SRV_CONF_OFFSET, |
60 offsetof(ngx_mail_proxy_conf_t, timeout), | |
539 | 61 NULL }, |
62 | |
857 | 63 { ngx_string("proxy_pass_error_message"), |
4273
e444e8f6538b
Fixed NGX_CONF_TAKE1/NGX_CONF_FLAG misuse.
Sergey Budnevitch <sb@waeme.net>
parents:
3516
diff
changeset
|
64 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, |
857 | 65 ngx_conf_set_flag_slot, |
1136 | 66 NGX_MAIL_SRV_CONF_OFFSET, |
67 offsetof(ngx_mail_proxy_conf_t, pass_error_message), | |
68 NULL }, | |
69 | |
70 { ngx_string("xclient"), | |
71 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, | |
72 ngx_conf_set_flag_slot, | |
73 NGX_MAIL_SRV_CONF_OFFSET, | |
74 offsetof(ngx_mail_proxy_conf_t, xclient), | |
857 | 75 NULL }, |
76 | |
521 | 77 ngx_null_command |
78 }; | |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
79 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
80 |
1136 | 81 static ngx_mail_module_t ngx_mail_proxy_module_ctx = { |
1487
f69493e8faab
ngx_mail_pop3_module, ngx_mail_imap_module, and ngx_mail_smtp_module
Igor Sysoev <igor@sysoev.ru>
parents:
1342
diff
changeset
|
82 NULL, /* protocol */ |
f69493e8faab
ngx_mail_pop3_module, ngx_mail_imap_module, and ngx_mail_smtp_module
Igor Sysoev <igor@sysoev.ru>
parents:
1342
diff
changeset
|
83 |
521 | 84 NULL, /* create main configuration */ |
85 NULL, /* init main configuration */ | |
86 | |
1136 | 87 ngx_mail_proxy_create_conf, /* create server configuration */ |
88 ngx_mail_proxy_merge_conf /* merge server configuration */ | |
521 | 89 }; |
90 | |
91 | |
1136 | 92 ngx_module_t ngx_mail_proxy_module = { |
521 | 93 NGX_MODULE_V1, |
1136 | 94 &ngx_mail_proxy_module_ctx, /* module context */ |
95 ngx_mail_proxy_commands, /* module directives */ | |
96 NGX_MAIL_MODULE, /* module type */ | |
541 | 97 NULL, /* init master */ |
521 | 98 NULL, /* init module */ |
541 | 99 NULL, /* init process */ |
100 NULL, /* init thread */ | |
101 NULL, /* exit thread */ | |
102 NULL, /* exit process */ | |
103 NULL, /* exit master */ | |
104 NGX_MODULE_V1_PADDING | |
521 | 105 }; |
106 | |
107 | |
2440
939b40aa9ab4
update r2439: make clear name
Igor Sysoev <igor@sysoev.ru>
parents:
2438
diff
changeset
|
108 static u_char smtp_auth_ok[] = "235 2.0.0 OK" CRLF; |
1136 | 109 |
110 | |
521 | 111 void |
3269
f0d596e84634
rename ngx_peer_addr_t to ngx_addr_t
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
112 ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer) |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
113 { |
527 | 114 ngx_int_t rc; |
1136 | 115 ngx_mail_proxy_ctx_t *p; |
116 ngx_mail_proxy_conf_t *pcf; | |
117 ngx_mail_core_srv_conf_t *cscf; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
118 |
587 | 119 s->connection->log->action = "connecting to upstream"; |
120 | |
1136 | 121 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); |
587 | 122 |
1136 | 123 p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t)); |
501 | 124 if (p == NULL) { |
1136 | 125 ngx_mail_session_internal_server_error(s); |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
126 return; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
127 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
128 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
129 s->proxy = p; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
130 |
884 | 131 p->upstream.sockaddr = peer->sockaddr; |
132 p->upstream.socklen = peer->socklen; | |
133 p->upstream.name = &peer->name; | |
134 p->upstream.get = ngx_event_get_peer; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
135 p->upstream.log = s->connection->log; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
136 p->upstream.log_error = NGX_ERROR_ERR; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
137 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
138 rc = ngx_event_connect_peer(&p->upstream); |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
139 |
543 | 140 if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { |
1136 | 141 ngx_mail_proxy_internal_server_error(s); |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
142 return; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
143 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
144 |
527 | 145 ngx_add_timer(p->upstream.connection->read, cscf->timeout); |
146 | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
147 p->upstream.connection->data = s; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
148 p->upstream.connection->pool = s->connection->pool; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
149 |
1136 | 150 s->connection->read->handler = ngx_mail_proxy_block_read; |
151 p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler; | |
152 | |
153 pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); | |
154 | |
155 s->proxy->buffer = ngx_create_temp_buf(s->connection->pool, | |
156 pcf->buffer_size); | |
157 if (s->proxy->buffer == NULL) { | |
158 ngx_mail_proxy_internal_server_error(s); | |
159 return; | |
160 } | |
161 | |
1981 | 162 s->out.len = 0; |
163 | |
1136 | 164 switch (s->protocol) { |
527 | 165 |
1136 | 166 case NGX_MAIL_POP3_PROTOCOL: |
167 p->upstream.connection->read->handler = ngx_mail_proxy_pop3_handler; | |
168 s->mail_state = ngx_pop3_start; | |
169 break; | |
527 | 170 |
1136 | 171 case NGX_MAIL_IMAP_PROTOCOL: |
172 p->upstream.connection->read->handler = ngx_mail_proxy_imap_handler; | |
173 s->mail_state = ngx_imap_start; | |
174 break; | |
175 | |
176 default: /* NGX_MAIL_SMTP_PROTOCOL */ | |
177 p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler; | |
178 s->mail_state = ngx_smtp_start; | |
179 break; | |
527 | 180 } |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
181 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
182 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
183 |
521 | 184 static void |
1136 | 185 ngx_mail_proxy_block_read(ngx_event_t *rev) |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
186 { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
187 ngx_connection_t *c; |
1136 | 188 ngx_mail_session_t *s; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
189 |
1136 | 190 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy block read"); |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
191 |
2388
722b5aff05ae
use "!= NGX_OK" instead of "== NGX_ERROR"
Igor Sysoev <igor@sysoev.ru>
parents:
2311
diff
changeset
|
192 if (ngx_handle_read_event(rev, 0) != NGX_OK) { |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
193 c = rev->data; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
194 s = c->data; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
195 |
1136 | 196 ngx_mail_proxy_close_session(s); |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
197 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
198 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
199 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
200 |
521 | 201 static void |
1136 | 202 ngx_mail_proxy_pop3_handler(ngx_event_t *rev) |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
203 { |
539 | 204 u_char *p; |
205 ngx_int_t rc; | |
206 ngx_str_t line; | |
207 ngx_connection_t *c; | |
1136 | 208 ngx_mail_session_t *s; |
209 ngx_mail_proxy_conf_t *pcf; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
210 |
1136 | 211 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, |
212 "mail proxy pop3 auth handler"); | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
213 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
214 c = rev->data; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
215 s = c->data; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
216 |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
217 if (rev->timedout) { |
527 | 218 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, |
219 "upstream timed out"); | |
577 | 220 c->timedout = 1; |
1136 | 221 ngx_mail_proxy_internal_server_error(s); |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
222 return; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
223 } |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
224 |
1136 | 225 rc = ngx_mail_proxy_read_response(s, 0); |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
226 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
227 if (rc == NGX_AGAIN) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
228 return; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
229 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
230 |
571 | 231 if (rc == NGX_ERROR) { |
1136 | 232 ngx_mail_proxy_upstream_error(s); |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
233 return; |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
234 } |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
235 |
1136 | 236 switch (s->mail_state) { |
587 | 237 |
1136 | 238 case ngx_pop3_start: |
239 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send user"); | |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
240 |
587 | 241 s->connection->log->action = "sending user name to upstream"; |
242 | |
1136 | 243 line.len = sizeof("USER ") - 1 + s->login.len + 2; |
2049 | 244 line.data = ngx_pnalloc(c->pool, line.len); |
527 | 245 if (line.data == NULL) { |
1136 | 246 ngx_mail_proxy_internal_server_error(s); |
527 | 247 return; |
248 } | |
249 | |
1136 | 250 p = ngx_cpymem(line.data, "USER ", sizeof("USER ") - 1); |
251 p = ngx_cpymem(p, s->login.data, s->login.len); | |
252 *p++ = CR; *p = LF; | |
527 | 253 |
1136 | 254 s->mail_state = ngx_pop3_user; |
527 | 255 break; |
256 | |
1136 | 257 case ngx_pop3_user: |
258 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send pass"); | |
527 | 259 |
587 | 260 s->connection->log->action = "sending password to upstream"; |
261 | |
1136 | 262 line.len = sizeof("PASS ") - 1 + s->passwd.len + 2; |
2049 | 263 line.data = ngx_pnalloc(c->pool, line.len); |
501 | 264 if (line.data == NULL) { |
1136 | 265 ngx_mail_proxy_internal_server_error(s); |
527 | 266 return; |
267 } | |
268 | |
1136 | 269 p = ngx_cpymem(line.data, "PASS ", sizeof("PASS ") - 1); |
270 p = ngx_cpymem(p, s->passwd.data, s->passwd.len); | |
527 | 271 *p++ = CR; *p = LF; |
272 | |
1136 | 273 s->mail_state = ngx_pop3_passwd; |
527 | 274 break; |
275 | |
1136 | 276 case ngx_pop3_passwd: |
277 s->connection->read->handler = ngx_mail_proxy_handler; | |
278 s->connection->write->handler = ngx_mail_proxy_handler; | |
279 rev->handler = ngx_mail_proxy_handler; | |
280 c->write->handler = ngx_mail_proxy_handler; | |
663 | 281 |
1136 | 282 pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); |
663 | 283 ngx_add_timer(s->connection->read, pcf->timeout); |
284 ngx_del_timer(c->read); | |
285 | |
286 c->log->action = NULL; | |
287 ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); | |
288 | |
1136 | 289 ngx_mail_proxy_handler(s->connection->write); |
663 | 290 |
291 return; | |
292 | |
527 | 293 default: |
294 #if (NGX_SUPPRESS_WARN) | |
3516
dd1570b6f237
ngx_str_set() and ngx_str_null()
Igor Sysoev <igor@sysoev.ru>
parents:
3505
diff
changeset
|
295 ngx_str_null(&line); |
527 | 296 #endif |
297 break; | |
298 } | |
299 | |
539 | 300 if (c->send(c, line.data, line.len) < (ssize_t) line.len) { |
527 | 301 /* |
302 * we treat the incomplete sending as NGX_ERROR | |
303 * because it is very strange here | |
304 */ | |
1136 | 305 ngx_mail_proxy_internal_server_error(s); |
527 | 306 return; |
307 } | |
308 | |
309 s->proxy->buffer->pos = s->proxy->buffer->start; | |
310 s->proxy->buffer->last = s->proxy->buffer->start; | |
311 } | |
312 | |
313 | |
314 static void | |
1136 | 315 ngx_mail_proxy_imap_handler(ngx_event_t *rev) |
527 | 316 { |
539 | 317 u_char *p; |
318 ngx_int_t rc; | |
319 ngx_str_t line; | |
320 ngx_connection_t *c; | |
1136 | 321 ngx_mail_session_t *s; |
322 ngx_mail_proxy_conf_t *pcf; | |
527 | 323 |
1136 | 324 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, |
325 "mail proxy imap auth handler"); | |
527 | 326 |
327 c = rev->data; | |
328 s = c->data; | |
329 | |
330 if (rev->timedout) { | |
331 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, | |
332 "upstream timed out"); | |
577 | 333 c->timedout = 1; |
1136 | 334 ngx_mail_proxy_internal_server_error(s); |
527 | 335 return; |
336 } | |
337 | |
1136 | 338 rc = ngx_mail_proxy_read_response(s, s->mail_state); |
527 | 339 |
340 if (rc == NGX_AGAIN) { | |
341 return; | |
342 } | |
343 | |
571 | 344 if (rc == NGX_ERROR) { |
1136 | 345 ngx_mail_proxy_upstream_error(s); |
527 | 346 return; |
347 } | |
348 | |
1136 | 349 switch (s->mail_state) { |
527 | 350 |
1136 | 351 case ngx_imap_start: |
352 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, | |
353 "mail proxy send login"); | |
527 | 354 |
1136 | 355 s->connection->log->action = "sending LOGIN command to upstream"; |
587 | 356 |
1136 | 357 line.len = s->tag.len + sizeof("LOGIN ") - 1 |
358 + 1 + NGX_SIZE_T_LEN + 1 + 2; | |
2049 | 359 line.data = ngx_pnalloc(c->pool, line.len); |
527 | 360 if (line.data == NULL) { |
1136 | 361 ngx_mail_proxy_internal_server_error(s); |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
362 return; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
363 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
364 |
1136 | 365 line.len = ngx_sprintf(line.data, "%VLOGIN {%uz}" CRLF, |
366 &s->tag, s->login.len) | |
367 - line.data; | |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
368 |
1136 | 369 s->mail_state = ngx_imap_login; |
527 | 370 break; |
371 | |
1136 | 372 case ngx_imap_login: |
373 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send user"); | |
374 | |
375 s->connection->log->action = "sending user name to upstream"; | |
376 | |
377 line.len = s->login.len + 1 + 1 + NGX_SIZE_T_LEN + 1 + 2; | |
2049 | 378 line.data = ngx_pnalloc(c->pool, line.len); |
1136 | 379 if (line.data == NULL) { |
380 ngx_mail_proxy_internal_server_error(s); | |
381 return; | |
382 } | |
383 | |
384 line.len = ngx_sprintf(line.data, "%V {%uz}" CRLF, | |
385 &s->login, s->passwd.len) | |
386 - line.data; | |
387 | |
388 s->mail_state = ngx_imap_user; | |
389 break; | |
390 | |
391 case ngx_imap_user: | |
392 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, | |
393 "mail proxy send passwd"); | |
527 | 394 |
587 | 395 s->connection->log->action = "sending password to upstream"; |
396 | |
1136 | 397 line.len = s->passwd.len + 2; |
2049 | 398 line.data = ngx_pnalloc(c->pool, line.len); |
527 | 399 if (line.data == NULL) { |
1136 | 400 ngx_mail_proxy_internal_server_error(s); |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
401 return; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
402 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
403 |
1136 | 404 p = ngx_cpymem(line.data, s->passwd.data, s->passwd.len); |
527 | 405 *p++ = CR; *p = LF; |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
406 |
1136 | 407 s->mail_state = ngx_imap_passwd; |
527 | 408 break; |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
409 |
1136 | 410 case ngx_imap_passwd: |
411 s->connection->read->handler = ngx_mail_proxy_handler; | |
412 s->connection->write->handler = ngx_mail_proxy_handler; | |
413 rev->handler = ngx_mail_proxy_handler; | |
414 c->write->handler = ngx_mail_proxy_handler; | |
663 | 415 |
1136 | 416 pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); |
663 | 417 ngx_add_timer(s->connection->read, pcf->timeout); |
418 ngx_del_timer(c->read); | |
419 | |
420 c->log->action = NULL; | |
421 ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); | |
422 | |
1136 | 423 ngx_mail_proxy_handler(s->connection->write); |
663 | 424 |
425 return; | |
426 | |
527 | 427 default: |
428 #if (NGX_SUPPRESS_WARN) | |
3516
dd1570b6f237
ngx_str_set() and ngx_str_null()
Igor Sysoev <igor@sysoev.ru>
parents:
3505
diff
changeset
|
429 ngx_str_null(&line); |
527 | 430 #endif |
431 break; | |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
432 } |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
433 |
539 | 434 if (c->send(c, line.data, line.len) < (ssize_t) line.len) { |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
435 /* |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
436 * we treat the incomplete sending as NGX_ERROR |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
437 * because it is very strange here |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
438 */ |
1136 | 439 ngx_mail_proxy_internal_server_error(s); |
422
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
440 return; |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
441 } |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
442 |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
443 s->proxy->buffer->pos = s->proxy->buffer->start; |
edaefb2a20fc
nginx-0.0.10-2004-09-12-00:22:11 import
Igor Sysoev <igor@sysoev.ru>
parents:
419
diff
changeset
|
444 s->proxy->buffer->last = s->proxy->buffer->start; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
445 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
446 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
447 |
521 | 448 static void |
1136 | 449 ngx_mail_proxy_smtp_handler(ngx_event_t *rev) |
450 { | |
451 u_char *p; | |
452 ngx_int_t rc; | |
453 ngx_str_t line; | |
2309 | 454 ngx_buf_t *b; |
1136 | 455 ngx_connection_t *c; |
456 ngx_mail_session_t *s; | |
457 ngx_mail_proxy_conf_t *pcf; | |
458 ngx_mail_core_srv_conf_t *cscf; | |
459 | |
460 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, | |
461 "mail proxy smtp auth handler"); | |
462 | |
463 c = rev->data; | |
464 s = c->data; | |
465 | |
466 if (rev->timedout) { | |
467 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, | |
468 "upstream timed out"); | |
469 c->timedout = 1; | |
470 ngx_mail_proxy_internal_server_error(s); | |
471 return; | |
472 } | |
473 | |
474 rc = ngx_mail_proxy_read_response(s, s->mail_state); | |
475 | |
476 if (rc == NGX_AGAIN) { | |
477 return; | |
478 } | |
479 | |
480 if (rc == NGX_ERROR) { | |
481 ngx_mail_proxy_upstream_error(s); | |
482 return; | |
483 } | |
484 | |
485 switch (s->mail_state) { | |
486 | |
487 case ngx_smtp_start: | |
488 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send ehlo"); | |
489 | |
490 s->connection->log->action = "sending HELO/EHLO to upstream"; | |
491 | |
492 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
493 | |
494 line.len = sizeof("HELO ") - 1 + cscf->server_name.len + 2; | |
2049 | 495 line.data = ngx_pnalloc(c->pool, line.len); |
1136 | 496 if (line.data == NULL) { |
497 ngx_mail_proxy_internal_server_error(s); | |
498 return; | |
499 } | |
500 | |
501 pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); | |
502 | |
503 p = ngx_cpymem(line.data, | |
504 ((s->esmtp || pcf->xclient) ? "EHLO " : "HELO "), | |
505 sizeof("HELO ") - 1); | |
506 | |
507 p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); | |
508 *p++ = CR; *p = LF; | |
509 | |
2309 | 510 if (pcf->xclient) { |
511 s->mail_state = ngx_smtp_helo_xclient; | |
512 | |
513 } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { | |
514 s->mail_state = ngx_smtp_helo_from; | |
515 | |
516 } else { | |
517 s->mail_state = ngx_smtp_helo; | |
518 } | |
1136 | 519 |
520 break; | |
521 | |
2309 | 522 case ngx_smtp_helo_xclient: |
1136 | 523 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, |
524 "mail proxy send xclient"); | |
525 | |
526 s->connection->log->action = "sending XCLIENT to upstream"; | |
527 | |
2497 | 528 line.len = sizeof("XCLIENT ADDR= LOGIN= NAME=" |
1892
057d362ee50e
resolver in smtp proxy module
Igor Sysoev <igor@sysoev.ru>
parents:
1487
diff
changeset
|
529 CRLF) - 1 |
057d362ee50e
resolver in smtp proxy module
Igor Sysoev <igor@sysoev.ru>
parents:
1487
diff
changeset
|
530 + s->connection->addr_text.len + s->login.len + s->host.len; |
1136 | 531 |
5522
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
532 #if (NGX_HAVE_INET6) |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
533 if (s->connection->sockaddr->sa_family == AF_INET6) { |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
534 line.len += sizeof("IPV6:") - 1; |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
535 } |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
536 #endif |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
537 |
2049 | 538 line.data = ngx_pnalloc(c->pool, line.len); |
1136 | 539 if (line.data == NULL) { |
540 ngx_mail_proxy_internal_server_error(s); | |
541 return; | |
542 } | |
543 | |
5522
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
544 p = ngx_cpymem(line.data, "XCLIENT ADDR=", sizeof("XCLIENT ADDR=") - 1); |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
545 |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
546 #if (NGX_HAVE_INET6) |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
547 if (s->connection->sockaddr->sa_family == AF_INET6) { |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
548 p = ngx_cpymem(p, "IPV6:", sizeof("IPV6:") - 1); |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
549 } |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
550 #endif |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
551 |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
552 p = ngx_copy(p, s->connection->addr_text.data, |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
553 s->connection->addr_text.len); |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
554 |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
555 if (s->login.len) { |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
556 p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1); |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
557 p = ngx_copy(p, s->login.data, s->login.len); |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
558 } |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
559 |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
560 p = ngx_cpymem(p, " NAME=", sizeof(" NAME=") - 1); |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
561 p = ngx_copy(p, s->host.data, s->host.len); |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
562 |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
563 *p++ = CR; *p++ = LF; |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
564 |
bb3dc21c89ef
Mail: fixed passing of IPv6 client address in XCLIENT.
Ruslan Ermilov <ru@nginx.com>
parents:
5399
diff
changeset
|
565 line.len = p - line.data; |
2309 | 566 |
2497 | 567 if (s->smtp_helo.len) { |
568 s->mail_state = ngx_smtp_xclient_helo; | |
569 | |
570 } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { | |
571 s->mail_state = ngx_smtp_xclient_from; | |
572 | |
573 } else { | |
574 s->mail_state = ngx_smtp_xclient; | |
575 } | |
576 | |
577 break; | |
578 | |
579 case ngx_smtp_xclient_helo: | |
580 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, | |
581 "mail proxy send client ehlo"); | |
582 | |
583 s->connection->log->action = "sending client HELO/EHLO to upstream"; | |
584 | |
585 line.len = sizeof("HELO " CRLF) - 1 + s->smtp_helo.len; | |
586 | |
587 line.data = ngx_pnalloc(c->pool, line.len); | |
588 if (line.data == NULL) { | |
589 ngx_mail_proxy_internal_server_error(s); | |
590 return; | |
591 } | |
592 | |
593 line.len = ngx_sprintf(line.data, | |
594 ((s->esmtp) ? "EHLO %V" CRLF : "HELO %V" CRLF), | |
595 &s->smtp_helo) | |
596 - line.data; | |
597 | |
2309 | 598 s->mail_state = (s->auth_method == NGX_MAIL_AUTH_NONE) ? |
2497 | 599 ngx_smtp_helo_from : ngx_smtp_helo; |
2309 | 600 |
601 break; | |
602 | |
603 case ngx_smtp_helo_from: | |
604 case ngx_smtp_xclient_from: | |
605 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, | |
606 "mail proxy send mail from"); | |
607 | |
608 s->connection->log->action = "sending MAIL FROM to upstream"; | |
609 | |
610 line.len = s->smtp_from.len + sizeof(CRLF) - 1; | |
611 line.data = ngx_pnalloc(c->pool, line.len); | |
612 if (line.data == NULL) { | |
613 ngx_mail_proxy_internal_server_error(s); | |
614 return; | |
1136 | 615 } |
616 | |
2309 | 617 p = ngx_cpymem(line.data, s->smtp_from.data, s->smtp_from.len); |
618 *p++ = CR; *p = LF; | |
619 | |
620 s->mail_state = ngx_smtp_from; | |
621 | |
1136 | 622 break; |
623 | |
2309 | 624 case ngx_smtp_from: |
625 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, | |
626 "mail proxy send rcpt to"); | |
627 | |
628 s->connection->log->action = "sending RCPT TO to upstream"; | |
629 | |
630 line.len = s->smtp_to.len + sizeof(CRLF) - 1; | |
631 line.data = ngx_pnalloc(c->pool, line.len); | |
632 if (line.data == NULL) { | |
633 ngx_mail_proxy_internal_server_error(s); | |
634 return; | |
635 } | |
636 | |
637 p = ngx_cpymem(line.data, s->smtp_to.data, s->smtp_to.len); | |
638 *p++ = CR; *p = LF; | |
639 | |
640 s->mail_state = ngx_smtp_to; | |
1136 | 641 |
2309 | 642 break; |
643 | |
644 case ngx_smtp_helo: | |
645 case ngx_smtp_xclient: | |
646 case ngx_smtp_to: | |
647 | |
648 b = s->proxy->buffer; | |
1136 | 649 |
2309 | 650 if (s->auth_method == NGX_MAIL_AUTH_NONE) { |
2311
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
651 b->pos = b->start; |
2309 | 652 |
653 } else { | |
2440
939b40aa9ab4
update r2439: make clear name
Igor Sysoev <igor@sysoev.ru>
parents:
2438
diff
changeset
|
654 ngx_memcpy(b->start, smtp_auth_ok, sizeof(smtp_auth_ok) - 1); |
939b40aa9ab4
update r2439: make clear name
Igor Sysoev <igor@sysoev.ru>
parents:
2438
diff
changeset
|
655 b->last = b->start + sizeof(smtp_auth_ok) - 1; |
2309 | 656 } |
657 | |
1136 | 658 s->connection->read->handler = ngx_mail_proxy_handler; |
659 s->connection->write->handler = ngx_mail_proxy_handler; | |
660 rev->handler = ngx_mail_proxy_handler; | |
661 c->write->handler = ngx_mail_proxy_handler; | |
662 | |
663 pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); | |
664 ngx_add_timer(s->connection->read, pcf->timeout); | |
665 ngx_del_timer(c->read); | |
666 | |
667 c->log->action = NULL; | |
668 ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); | |
669 | |
5398
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
670 if (s->buffer->pos == s->buffer->last) { |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
671 ngx_mail_proxy_handler(s->connection->write); |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
672 |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
673 } else { |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
674 ngx_mail_proxy_handler(c->write); |
04e43d03e153
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
675 } |
1136 | 676 |
677 return; | |
678 | |
679 default: | |
680 #if (NGX_SUPPRESS_WARN) | |
3516
dd1570b6f237
ngx_str_set() and ngx_str_null()
Igor Sysoev <igor@sysoev.ru>
parents:
3505
diff
changeset
|
681 ngx_str_null(&line); |
1136 | 682 #endif |
683 break; | |
684 } | |
685 | |
686 if (c->send(c, line.data, line.len) < (ssize_t) line.len) { | |
687 /* | |
688 * we treat the incomplete sending as NGX_ERROR | |
689 * because it is very strange here | |
690 */ | |
691 ngx_mail_proxy_internal_server_error(s); | |
692 return; | |
693 } | |
694 | |
695 s->proxy->buffer->pos = s->proxy->buffer->start; | |
696 s->proxy->buffer->last = s->proxy->buffer->start; | |
697 } | |
698 | |
699 | |
700 static void | |
701 ngx_mail_proxy_dummy_handler(ngx_event_t *wev) | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
702 { |
583 | 703 ngx_connection_t *c; |
1136 | 704 ngx_mail_session_t *s; |
583 | 705 |
1136 | 706 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy dummy handler"); |
583 | 707 |
2388
722b5aff05ae
use "!= NGX_OK" instead of "== NGX_ERROR"
Igor Sysoev <igor@sysoev.ru>
parents:
2311
diff
changeset
|
708 if (ngx_handle_write_event(wev, 0) != NGX_OK) { |
583 | 709 c = wev->data; |
710 s = c->data; | |
711 | |
1136 | 712 ngx_mail_proxy_close_session(s); |
583 | 713 } |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
714 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
715 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
716 |
521 | 717 static ngx_int_t |
1136 | 718 ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state) |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
719 { |
5399
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
720 u_char *p, *m; |
857 | 721 ssize_t n; |
722 ngx_buf_t *b; | |
1136 | 723 ngx_mail_proxy_conf_t *pcf; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
724 |
587 | 725 s->connection->log->action = "reading response from upstream"; |
726 | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
727 b = s->proxy->buffer; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
728 |
539 | 729 n = s->proxy->upstream.connection->recv(s->proxy->upstream.connection, |
730 b->last, b->end - b->last); | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
731 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
732 if (n == NGX_ERROR || n == 0) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
733 return NGX_ERROR; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
734 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
735 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
736 if (n == NGX_AGAIN) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
737 return NGX_AGAIN; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
738 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
739 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
740 b->last += n; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
741 |
3505
c631ef8beaaa
Zimbra IMAP server may return only 4 bytes: "+ \r\n"
Igor Sysoev <igor@sysoev.ru>
parents:
3269
diff
changeset
|
742 if (b->last - b->pos < 4) { |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
743 return NGX_AGAIN; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
744 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
745 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
746 if (*(b->last - 2) != CR || *(b->last - 1) != LF) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
747 if (b->last == b->end) { |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
748 *(b->last - 1) = '\0'; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
749 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
750 "upstream sent too long response line: \"%s\"", |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
751 b->pos); |
571 | 752 return NGX_ERROR; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
753 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
754 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
755 return NGX_AGAIN; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
756 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
757 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
758 p = b->pos; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
759 |
1136 | 760 switch (s->protocol) { |
761 | |
762 case NGX_MAIL_POP3_PROTOCOL: | |
527 | 763 if (p[0] == '+' && p[1] == 'O' && p[2] == 'K') { |
764 return NGX_OK; | |
765 } | |
1136 | 766 break; |
527 | 767 |
1136 | 768 case NGX_MAIL_IMAP_PROTOCOL: |
663 | 769 switch (state) { |
770 | |
771 case ngx_imap_start: | |
527 | 772 if (p[0] == '*' && p[1] == ' ' && p[2] == 'O' && p[3] == 'K') { |
773 return NGX_OK; | |
774 } | |
663 | 775 break; |
527 | 776 |
663 | 777 case ngx_imap_login: |
778 case ngx_imap_user: | |
529 | 779 if (p[0] == '+') { |
527 | 780 return NGX_OK; |
781 } | |
663 | 782 break; |
783 | |
784 case ngx_imap_passwd: | |
785 if (ngx_strncmp(p, s->tag.data, s->tag.len) == 0) { | |
786 p += s->tag.len; | |
787 if (p[0] == 'O' && p[1] == 'K') { | |
788 return NGX_OK; | |
789 } | |
790 } | |
791 break; | |
527 | 792 } |
1136 | 793 |
794 break; | |
795 | |
796 default: /* NGX_MAIL_SMTP_PROTOCOL */ | |
5399
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
797 |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
798 if (p[3] == '-') { |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
799 /* multiline reply, check if we got last line */ |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
800 |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
801 m = b->last - (sizeof(CRLF "200" CRLF) - 1); |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
802 |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
803 while (m > p) { |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
804 if (m[0] == CR && m[1] == LF) { |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
805 break; |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
806 } |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
807 |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
808 m--; |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
809 } |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
810 |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
811 if (m <= p || m[5] == '-') { |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
812 return NGX_AGAIN; |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
813 } |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
814 } |
d3e09aa03a7a
Mail: handle smtp multiline replies.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5398
diff
changeset
|
815 |
1136 | 816 switch (state) { |
817 | |
2311
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
818 case ngx_smtp_start: |
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
819 if (p[0] == '2' && p[1] == '2' && p[2] == '0') { |
1166 | 820 return NGX_OK; |
821 } | |
822 break; | |
1136 | 823 |
2311
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
824 case ngx_smtp_helo: |
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
825 case ngx_smtp_helo_xclient: |
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
826 case ngx_smtp_helo_from: |
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
827 case ngx_smtp_from: |
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
828 if (p[0] == '2' && p[1] == '5' && p[2] == '0') { |
2309 | 829 return NGX_OK; |
830 } | |
831 break; | |
832 | |
1136 | 833 case ngx_smtp_xclient: |
2309 | 834 case ngx_smtp_xclient_from: |
2497 | 835 case ngx_smtp_xclient_helo: |
2309 | 836 if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') { |
1166 | 837 return NGX_OK; |
838 } | |
839 break; | |
2311
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
840 |
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
841 case ngx_smtp_to: |
6bad42a41dd8
do not close session if SMTP backend returned an error on RCPT TO
Igor Sysoev <igor@sysoev.ru>
parents:
2309
diff
changeset
|
842 return NGX_OK; |
1136 | 843 } |
844 | |
1166 | 845 break; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
846 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
847 |
1136 | 848 pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); |
857 | 849 |
850 if (pcf->pass_error_message == 0) { | |
851 *(b->last - 2) = '\0'; | |
852 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, | |
853 "upstream sent invalid response: \"%s\"", p); | |
854 return NGX_ERROR; | |
855 } | |
856 | |
857 s->out.len = b->last - p - 2; | |
858 s->out.data = p; | |
859 | |
860 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, | |
861 "upstream sent invalid response: \"%V\"", &s->out); | |
862 | |
863 s->out.len = b->last - b->pos; | |
864 s->out.data = b->pos; | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
865 |
571 | 866 return NGX_ERROR; |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
867 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
868 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
869 |
521 | 870 static void |
1136 | 871 ngx_mail_proxy_handler(ngx_event_t *ev) |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
872 { |
583 | 873 char *action, *recv_action, *send_action; |
539 | 874 size_t size; |
875 ssize_t n; | |
876 ngx_buf_t *b; | |
583 | 877 ngx_uint_t do_write; |
539 | 878 ngx_connection_t *c, *src, *dst; |
1136 | 879 ngx_mail_session_t *s; |
880 ngx_mail_proxy_conf_t *pcf; | |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
881 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
882 c = ev->data; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
883 s = c->data; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
884 |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
885 if (ev->timedout) { |
583 | 886 c->log->action = "proxying"; |
887 | |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
888 if (c == s->connection) { |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
889 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
890 "client timed out"); |
577 | 891 c->timedout = 1; |
892 | |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
893 } else { |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
894 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
895 "upstream timed out"); |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
896 } |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
897 |
1136 | 898 ngx_mail_proxy_close_session(s); |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
899 return; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
900 } |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
901 |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
902 if (c == s->connection) { |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
903 if (ev->write) { |
583 | 904 recv_action = "proxying and reading from upstream"; |
905 send_action = "proxying and sending to client"; | |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
906 src = s->proxy->upstream.connection; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
907 dst = c; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
908 b = s->proxy->buffer; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
909 |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
910 } else { |
583 | 911 recv_action = "proxying and reading from client"; |
912 send_action = "proxying and sending to upstream"; | |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
913 src = c; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
914 dst = s->proxy->upstream.connection; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
915 b = s->buffer; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
916 } |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
917 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
918 } else { |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
919 if (ev->write) { |
589 | 920 recv_action = "proxying and reading from client"; |
921 send_action = "proxying and sending to upstream"; | |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
922 src = s->connection; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
923 dst = c; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
924 b = s->buffer; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
925 |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
926 } else { |
589 | 927 recv_action = "proxying and reading from upstream"; |
928 send_action = "proxying and sending to client"; | |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
929 src = c; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
930 dst = s->connection; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
931 b = s->proxy->buffer; |
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
932 } |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
933 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
934 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
935 do_write = ev->write ? 1 : 0; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
936 |
1136 | 937 ngx_log_debug3(NGX_LOG_DEBUG_MAIL, ev->log, 0, |
6480 | 938 "mail proxy handler: %ui, #%d > #%d", |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
939 do_write, src->fd, dst->fd); |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
940 |
583 | 941 for ( ;; ) { |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
942 |
583 | 943 if (do_write) { |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
944 |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
945 size = b->last - b->pos; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
946 |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
947 if (size && dst->write->ready) { |
583 | 948 c->log->action = send_action; |
949 | |
539 | 950 n = dst->send(dst, b->pos, size); |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
951 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
952 if (n == NGX_ERROR) { |
1136 | 953 ngx_mail_proxy_close_session(s); |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
954 return; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
955 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
956 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
957 if (n > 0) { |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
958 b->pos += n; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
959 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
960 if (b->pos == b->last) { |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
961 b->pos = b->start; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
962 b->last = b->start; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
963 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
964 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
965 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
966 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
967 |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
968 size = b->end - b->last; |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
969 |
423
fda5987b188d
nginx-0.0.10-2004-09-13-20:18:09 import
Igor Sysoev <igor@sysoev.ru>
parents:
422
diff
changeset
|
970 if (size && src->read->ready) { |
583 | 971 c->log->action = recv_action; |
972 | |
539 | 973 n = src->recv(src, b->last, size); |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
974 |
583 | 975 if (n == NGX_AGAIN || n == 0) { |
976 break; | |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
977 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
978 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
979 if (n > 0) { |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
980 do_write = 1; |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
981 b->last += n; |
583 | 982 |
983 continue; | |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
984 } |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
985 |
583 | 986 if (n == NGX_ERROR) { |
987 src->read->eof = 1; | |
539 | 988 } |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
989 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
990 |
583 | 991 break; |
992 } | |
993 | |
994 c->log->action = "proxying"; | |
995 | |
1342
be2e13691c60
fix case when client has closed connection but upstream buffer is not empty
Igor Sysoev <igor@sysoev.ru>
parents:
1166
diff
changeset
|
996 if ((s->connection->read->eof && s->buffer->pos == s->buffer->last) |
be2e13691c60
fix case when client has closed connection but upstream buffer is not empty
Igor Sysoev <igor@sysoev.ru>
parents:
1166
diff
changeset
|
997 || (s->proxy->upstream.connection->read->eof |
be2e13691c60
fix case when client has closed connection but upstream buffer is not empty
Igor Sysoev <igor@sysoev.ru>
parents:
1166
diff
changeset
|
998 && s->proxy->buffer->pos == s->proxy->buffer->last) |
be2e13691c60
fix case when client has closed connection but upstream buffer is not empty
Igor Sysoev <igor@sysoev.ru>
parents:
1166
diff
changeset
|
999 || (s->connection->read->eof |
be2e13691c60
fix case when client has closed connection but upstream buffer is not empty
Igor Sysoev <igor@sysoev.ru>
parents:
1166
diff
changeset
|
1000 && s->proxy->upstream.connection->read->eof)) |
583 | 1001 { |
1002 action = c->log->action; | |
1003 c->log->action = NULL; | |
1004 ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxied session done"); | |
1005 c->log->action = action; | |
1006 | |
1136 | 1007 ngx_mail_proxy_close_session(s); |
583 | 1008 return; |
1009 } | |
1010 | |
2388
722b5aff05ae
use "!= NGX_OK" instead of "== NGX_ERROR"
Igor Sysoev <igor@sysoev.ru>
parents:
2311
diff
changeset
|
1011 if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { |
1136 | 1012 ngx_mail_proxy_close_session(s); |
583 | 1013 return; |
1014 } | |
1015 | |
2388
722b5aff05ae
use "!= NGX_OK" instead of "== NGX_ERROR"
Igor Sysoev <igor@sysoev.ru>
parents:
2311
diff
changeset
|
1016 if (ngx_handle_read_event(dst->read, 0) != NGX_OK) { |
1136 | 1017 ngx_mail_proxy_close_session(s); |
583 | 1018 return; |
1019 } | |
1020 | |
2388
722b5aff05ae
use "!= NGX_OK" instead of "== NGX_ERROR"
Igor Sysoev <igor@sysoev.ru>
parents:
2311
diff
changeset
|
1021 if (ngx_handle_write_event(src->write, 0) != NGX_OK) { |
1136 | 1022 ngx_mail_proxy_close_session(s); |
583 | 1023 return; |
1024 } | |
1025 | |
2388
722b5aff05ae
use "!= NGX_OK" instead of "== NGX_ERROR"
Igor Sysoev <igor@sysoev.ru>
parents:
2311
diff
changeset
|
1026 if (ngx_handle_read_event(src->read, 0) != NGX_OK) { |
1136 | 1027 ngx_mail_proxy_close_session(s); |
583 | 1028 return; |
1029 } | |
1030 | |
1031 if (c == s->connection) { | |
1136 | 1032 pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); |
583 | 1033 ngx_add_timer(c->read, pcf->timeout); |
1034 } | |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
1035 } |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
1036 |
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
1037 |
521 | 1038 static void |
1136 | 1039 ngx_mail_proxy_upstream_error(ngx_mail_session_t *s) |
857 | 1040 { |
1041 if (s->proxy->upstream.connection) { | |
1136 | 1042 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, |
1043 "close mail proxy connection: %d", | |
857 | 1044 s->proxy->upstream.connection->fd); |
1045 | |
1046 ngx_close_connection(s->proxy->upstream.connection); | |
1047 } | |
1048 | |
1049 if (s->out.len == 0) { | |
1136 | 1050 ngx_mail_session_internal_server_error(s); |
857 | 1051 return; |
1052 } | |
1053 | |
1054 s->quit = 1; | |
1136 | 1055 ngx_mail_send(s->connection->write); |
857 | 1056 } |
1057 | |
1058 | |
1059 static void | |
1136 | 1060 ngx_mail_proxy_internal_server_error(ngx_mail_session_t *s) |
527 | 1061 { |
1062 if (s->proxy->upstream.connection) { | |
1136 | 1063 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, |
1064 "close mail proxy connection: %d", | |
527 | 1065 s->proxy->upstream.connection->fd); |
1066 | |
1067 ngx_close_connection(s->proxy->upstream.connection); | |
1068 } | |
1069 | |
1136 | 1070 ngx_mail_session_internal_server_error(s); |
527 | 1071 } |
1072 | |
1073 | |
1074 static void | |
1136 | 1075 ngx_mail_proxy_close_session(ngx_mail_session_t *s) |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
1076 { |
521 | 1077 if (s->proxy->upstream.connection) { |
1136 | 1078 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, |
1079 "close mail proxy connection: %d", | |
521 | 1080 s->proxy->upstream.connection->fd); |
1081 | |
1082 ngx_close_connection(s->proxy->upstream.connection); | |
419
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
1083 } |
47709bff4468
nginx-0.0.10-2004-09-09-19:40:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
418
diff
changeset
|
1084 |
1136 | 1085 ngx_mail_close_connection(s->connection); |
418
cf072d26d6d6
nginx-0.0.10-2004-09-08-09:18:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
1086 } |
521 | 1087 |
1088 | |
1089 static void * | |
1136 | 1090 ngx_mail_proxy_create_conf(ngx_conf_t *cf) |
577 | 1091 { |
1136 | 1092 ngx_mail_proxy_conf_t *pcf; |
577 | 1093 |
1136 | 1094 pcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_proxy_conf_t)); |
521 | 1095 if (pcf == NULL) { |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2497
diff
changeset
|
1096 return NULL; |
521 | 1097 } |
1098 | |
1099 pcf->enable = NGX_CONF_UNSET; | |
857 | 1100 pcf->pass_error_message = NGX_CONF_UNSET; |
1136 | 1101 pcf->xclient = NGX_CONF_UNSET; |
539 | 1102 pcf->buffer_size = NGX_CONF_UNSET_SIZE; |
1103 pcf->timeout = NGX_CONF_UNSET_MSEC; | |
521 | 1104 |
1105 return pcf; | |
1106 } | |
1107 | |
1108 | |
1109 static char * | |
1136 | 1110 ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
521 | 1111 { |
1136 | 1112 ngx_mail_proxy_conf_t *prev = parent; |
1113 ngx_mail_proxy_conf_t *conf = child; | |
521 | 1114 |
539 | 1115 ngx_conf_merge_value(conf->enable, prev->enable, 0); |
857 | 1116 ngx_conf_merge_value(conf->pass_error_message, prev->pass_error_message, 0); |
1136 | 1117 ngx_conf_merge_value(conf->xclient, prev->xclient, 1); |
539 | 1118 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, |
1119 (size_t) ngx_pagesize); | |
1120 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); | |
521 | 1121 |
1122 return NGX_CONF_OK; | |
1123 } |