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