Mercurial > hg > nginx
annotate src/imap/ngx_imap.c @ 647:95d7da23ea53 release-0.3.45
nginx-0.3.45-RELEASE import
*) Feature: the "ssl_verify_client", "ssl_verify_depth", and
"ssl_client_certificate" directives.
*) Change: the $request_method variable now returns the main request
method.
*) Change: the ° symbol codes were changed in koi-win conversion
table.
*) Feature: the euro and N symbols were added to koi-win conversion
table.
*) Bugfix: if nginx distributed the requests among several backends and
some backend failed, then requests intended for this backend was
directed to one live backend only instead of being distributed among
the rest.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 06 May 2006 16:28:56 +0000 |
parents | 5e8fb59c18c1 |
children |
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:
419
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:
419
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:
419
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:
419
diff
changeset
|
5 |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
6 |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 #include <ngx_config.h> |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_core.h> |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_event.h> |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
10 #include <ngx_imap.h> |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
11 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
12 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
13 static char *ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
641 | 14 static int ngx_libc_cdecl ngx_imap_cmp_conf_in_addrs(const void *one, |
15 const void *two); | |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
16 |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
17 |
521 | 18 ngx_uint_t ngx_imap_max_module; |
19 | |
20 | |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
21 static ngx_command_t ngx_imap_commands[] = { |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
22 |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
23 { ngx_string("imap"), |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
24 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
25 ngx_imap_block, |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
26 0, |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
27 0, |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
28 NULL }, |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
29 |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
30 ngx_null_command |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
31 }; |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
32 |
577 | 33 |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
34 static ngx_core_module_t ngx_imap_module_ctx = { |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
35 ngx_string("imap"), |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
36 NULL, |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
37 NULL |
577 | 38 }; |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
39 |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
40 |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
41 ngx_module_t ngx_imap_module = { |
509 | 42 NGX_MODULE_V1, |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
43 &ngx_imap_module_ctx, /* module context */ |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
44 ngx_imap_commands, /* module directives */ |
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
45 NGX_CORE_MODULE, /* module type */ |
541 | 46 NULL, /* init master */ |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
47 NULL, /* init module */ |
541 | 48 NULL, /* init process */ |
49 NULL, /* init thread */ | |
50 NULL, /* exit thread */ | |
51 NULL, /* exit process */ | |
52 NULL, /* exit master */ | |
53 NGX_MODULE_V1_PADDING | |
413
de9d4726e28a
nginx-0.0.10-2004-08-31-23:05:39 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
54 }; |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
55 |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
56 |
521 | 57 static char * |
58 ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
59 { |
521 | 60 char *rv; |
641 | 61 u_char *text; |
62 size_t len; | |
63 ngx_uint_t i, a, l, m, mi, s, p, last, bind_all, done; | |
521 | 64 ngx_conf_t pcf; |
641 | 65 ngx_array_t in_ports; |
66 ngx_listening_t *ls; | |
67 ngx_imap_listen_t *imls; | |
521 | 68 ngx_imap_module_t *module; |
641 | 69 ngx_imap_in_port_t *imip; |
521 | 70 ngx_imap_conf_ctx_t *ctx; |
641 | 71 ngx_imap_conf_in_port_t *in_port; |
72 ngx_imap_conf_in_addr_t *in_addr; | |
521 | 73 ngx_imap_core_srv_conf_t **cscfp; |
74 ngx_imap_core_main_conf_t *cmcf; | |
75 | |
76 /* the main imap context */ | |
77 | |
78 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_imap_conf_ctx_t)); | |
79 if (ctx == NULL) { | |
80 return NGX_CONF_ERROR; | |
81 } | |
82 | |
83 *(ngx_imap_conf_ctx_t **) conf = ctx; | |
84 | |
85 /* count the number of the http modules and set up their indices */ | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
86 |
521 | 87 ngx_imap_max_module = 0; |
88 for (m = 0; ngx_modules[m]; m++) { | |
89 if (ngx_modules[m]->type != NGX_IMAP_MODULE) { | |
90 continue; | |
91 } | |
92 | |
93 ngx_modules[m]->ctx_index = ngx_imap_max_module++; | |
94 } | |
95 | |
96 | |
97 /* the imap main_conf context, it is the same in the all imap contexts */ | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
98 |
521 | 99 ctx->main_conf = ngx_pcalloc(cf->pool, |
100 sizeof(void *) * ngx_imap_max_module); | |
101 if (ctx->main_conf == NULL) { | |
102 return NGX_CONF_ERROR; | |
103 } | |
104 | |
105 | |
106 /* | |
107 * the imap null srv_conf context, it is used to merge | |
108 * the server{}s' srv_conf's | |
109 */ | |
110 | |
111 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_imap_max_module); | |
112 if (ctx->srv_conf == NULL) { | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
113 return NGX_CONF_ERROR; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
114 } |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
115 |
521 | 116 |
117 /* | |
118 * create the main_conf's, the null srv_conf's, and the null loc_conf's | |
119 * of the all imap modules | |
120 */ | |
121 | |
122 for (m = 0; ngx_modules[m]; m++) { | |
123 if (ngx_modules[m]->type != NGX_IMAP_MODULE) { | |
124 continue; | |
125 } | |
126 | |
127 module = ngx_modules[m]->ctx; | |
128 mi = ngx_modules[m]->ctx_index; | |
129 | |
130 if (module->create_main_conf) { | |
131 ctx->main_conf[mi] = module->create_main_conf(cf); | |
132 if (ctx->main_conf[mi] == NULL) { | |
133 return NGX_CONF_ERROR; | |
134 } | |
135 } | |
136 | |
137 if (module->create_srv_conf) { | |
138 ctx->srv_conf[mi] = module->create_srv_conf(cf); | |
139 if (ctx->srv_conf[mi] == NULL) { | |
140 return NGX_CONF_ERROR; | |
141 } | |
142 } | |
143 } | |
144 | |
145 | |
146 /* parse inside the imap{} block */ | |
147 | |
148 pcf = *cf; | |
149 cf->ctx = ctx; | |
150 | |
151 cf->module_type = NGX_IMAP_MODULE; | |
152 cf->cmd_type = NGX_IMAP_MAIN_CONF; | |
153 rv = ngx_conf_parse(cf, NULL); | |
154 | |
155 if (rv != NGX_CONF_OK) { | |
156 *cf = pcf; | |
157 return rv; | |
158 } | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
159 |
521 | 160 |
161 /* init imap{} main_conf's, merge the server{}s' srv_conf's */ | |
162 | |
163 cmcf = ctx->main_conf[ngx_imap_core_module.ctx_index]; | |
164 cscfp = cmcf->servers.elts; | |
165 | |
166 for (m = 0; ngx_modules[m]; m++) { | |
167 if (ngx_modules[m]->type != NGX_IMAP_MODULE) { | |
168 continue; | |
169 } | |
170 | |
171 module = ngx_modules[m]->ctx; | |
172 mi = ngx_modules[m]->ctx_index; | |
173 | |
174 /* init imap{} main_conf's */ | |
175 | |
176 if (module->init_main_conf) { | |
577 | 177 rv = module->init_main_conf(cf, ctx->main_conf[mi]); |
521 | 178 if (rv != NGX_CONF_OK) { |
179 *cf = pcf; | |
180 return rv; | |
181 } | |
182 } | |
183 | |
184 for (s = 0; s < cmcf->servers.nelts; s++) { | |
577 | 185 |
521 | 186 /* merge the server{}s' srv_conf's */ |
577 | 187 |
521 | 188 if (module->merge_srv_conf) { |
189 rv = module->merge_srv_conf(cf, | |
190 ctx->srv_conf[mi], | |
191 cscfp[s]->ctx->srv_conf[mi]); | |
192 if (rv != NGX_CONF_OK) { | |
193 *cf = pcf; | |
194 return rv; | |
195 } | |
196 } | |
197 } | |
198 } | |
199 | |
577 | 200 /* imap{}'s cf->ctx was needed while the configuration merging */ |
201 | |
202 *cf = pcf; | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
203 |
641 | 204 |
205 if (ngx_array_init(&in_ports, cf->temp_pool, 4, | |
206 sizeof(ngx_imap_conf_in_port_t)) | |
207 != NGX_OK) | |
208 { | |
209 return NGX_CONF_ERROR; | |
210 } | |
211 | |
212 imls = cmcf->listen.elts; | |
213 | |
214 for (l = 0; l < cmcf->listen.nelts; l++) { | |
215 | |
216 /* AF_INET only */ | |
217 | |
218 in_port = in_ports.elts; | |
219 for (p = 0; p < in_ports.nelts; p++) { | |
220 if (in_port[p].port == imls[l].port) { | |
221 in_port = &in_port[p]; | |
222 goto found; | |
223 } | |
224 } | |
225 | |
226 in_port = ngx_array_push(&in_ports); | |
227 if (in_port == NULL) { | |
228 return NGX_CONF_ERROR; | |
229 } | |
230 | |
231 in_port->port = imls[l].port; | |
232 | |
233 if (ngx_array_init(&in_port->addrs, cf->temp_pool, 2, | |
234 sizeof(ngx_imap_conf_in_addr_t)) | |
235 != NGX_OK) | |
236 { | |
237 return NGX_CONF_ERROR; | |
238 } | |
239 | |
240 found: | |
241 | |
242 in_addr = ngx_array_push(&in_port->addrs); | |
243 if (in_addr == NULL) { | |
244 return NGX_CONF_ERROR; | |
245 } | |
246 | |
247 in_addr->addr = imls[l].addr; | |
248 in_addr->ctx = imls[l].ctx; | |
249 in_addr->bind = imls[l].bind; | |
250 } | |
251 | |
252 /* optimize the lists of ports and addresses */ | |
253 | |
254 /* AF_INET only */ | |
255 | |
256 in_port = in_ports.elts; | |
257 for (p = 0; p < in_ports.nelts; p++) { | |
258 | |
259 ngx_qsort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, | |
260 sizeof(ngx_imap_conf_in_addr_t), ngx_imap_cmp_conf_in_addrs); | |
261 | |
262 in_addr = in_port[p].addrs.elts; | |
263 last = in_port[p].addrs.nelts; | |
264 | |
265 /* | |
266 * if there is the binding to the "*:port" then we need to bind() | |
267 * to the "*:port" only and ignore the other bindings | |
268 */ | |
269 | |
270 if (in_addr[last - 1].addr == INADDR_ANY) { | |
271 in_addr[last - 1].bind = 1; | |
272 bind_all = 0; | |
273 | |
274 } else { | |
275 bind_all = 1; | |
276 } | |
277 | |
278 for (a = 0; a < last; /* void */ ) { | |
279 | |
280 if (!bind_all && !in_addr[a].bind) { | |
281 a++; | |
282 continue; | |
283 } | |
284 | |
285 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr, | |
286 in_port[p].port); | |
287 if (ls == NULL) { | |
288 return NGX_CONF_ERROR; | |
289 } | |
290 | |
291 ls->backlog = -1; | |
292 ls->rcvbuf = -1; | |
293 ls->sndbuf = -1; | |
294 | |
295 ls->addr_ntop = 1; | |
296 ls->handler = ngx_imap_init_connection; | |
297 ls->pool_size = 256; | |
298 | |
299 /* STUB */ | |
300 ls->log = *cf->cycle->new_log; | |
301 ls->log.data = &ls->addr_text; | |
302 ls->log.handler = ngx_accept_log_error; | |
303 /**/ | |
304 | |
305 imip = ngx_palloc(cf->pool, sizeof(ngx_imap_in_port_t)); | |
306 if (imip == NULL) { | |
307 return NGX_CONF_ERROR; | |
308 } | |
309 | |
310 ls->servers = imip; | |
311 | |
312 in_addr = in_port[p].addrs.elts; | |
313 | |
314 if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { | |
315 imip->naddrs = 1; | |
316 done = 0; | |
317 | |
318 } else if (in_port[p].addrs.nelts > 1 | |
319 && in_addr[last - 1].addr == INADDR_ANY) | |
320 { | |
321 imip->naddrs = last; | |
322 done = 1; | |
323 | |
324 } else { | |
325 imip->naddrs = 1; | |
326 done = 0; | |
327 } | |
328 | |
329 #if 0 | |
330 ngx_log_error(NGX_LOG_ALERT, cf->log, 0, | |
331 "%ui: %V %d %ui %ui", | |
332 a, &ls->addr_text, in_addr[a].bind, | |
333 imip->naddrs, last); | |
334 #endif | |
335 | |
336 imip->addrs = ngx_pcalloc(cf->pool, | |
337 imip->naddrs * sizeof(ngx_imap_in_addr_t)); | |
338 if (imip->addrs == NULL) { | |
339 return NGX_CONF_ERROR; | |
340 } | |
341 | |
342 for (i = 0; i < imip->naddrs; i++) { | |
343 imip->addrs[i].addr = in_addr[i].addr; | |
344 imip->addrs[i].ctx = in_addr[i].ctx; | |
345 | |
346 text = ngx_palloc(cf->pool, | |
347 INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1); | |
348 if (text == NULL) { | |
349 return NGX_CONF_ERROR; | |
350 } | |
351 | |
352 len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text, | |
353 INET_ADDRSTRLEN); | |
354 | |
355 len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text; | |
356 | |
357 imip->addrs[i].addr_text.len = len; | |
358 imip->addrs[i].addr_text.data = text; | |
359 } | |
360 | |
361 if (done) { | |
362 break; | |
363 } | |
364 | |
365 in_addr++; | |
366 in_port[p].addrs.elts = in_addr; | |
367 last--; | |
368 | |
369 a = 0; | |
370 } | |
371 } | |
372 | |
417
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
373 return NGX_CONF_OK; |
0526206251f6
nginx-0.0.10-2004-09-07-19:29:22 import
Igor Sysoev <igor@sysoev.ru>
parents:
415
diff
changeset
|
374 } |
641 | 375 |
376 | |
377 static int ngx_libc_cdecl | |
378 ngx_imap_cmp_conf_in_addrs(const void *one, const void *two) | |
379 { | |
380 ngx_imap_conf_in_addr_t *first, *second; | |
381 | |
382 first = (ngx_imap_conf_in_addr_t *) one; | |
383 second = (ngx_imap_conf_in_addr_t *) two; | |
384 | |
385 if (first->addr == INADDR_ANY) { | |
386 /* the INADDR_ANY must be the last resort, shift it to the end */ | |
387 return 1; | |
388 } | |
389 | |
390 if (first->bind && !second->bind) { | |
391 /* shift explicit bind()ed addresses to the start */ | |
392 return -1; | |
393 } | |
394 | |
395 if (!first->bind && second->bind) { | |
396 /* shift explicit bind()ed addresses to the start */ | |
397 return 1; | |
398 } | |
399 | |
400 /* do not sort by default */ | |
401 | |
402 return 0; | |
403 } |