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