Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 983 lines (763 sloc) 26.395 kB
4a79fb3 @yappo first
authored
1 #include <ngx_config.h>
2 #include <ngx_core.h>
3 #include <ngx_event.h>
4 #include <ngx_http.h>
5
6 typedef struct {
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
7 ngx_connection_t *connection;
8
9 ngx_str_t out;
10 ngx_str_t out_buffer;
11 ngx_buf_t *buffer;
12
13 } ngx_http_memcachedp_session_t;
14
15 typedef struct {
4a79fb3 @yappo first
authored
16 ngx_msec_t timeout;
17 ngx_msec_t resolver_timeout;
18
19 ngx_flag_t so_keepalive;
20
21 ngx_str_t server_name;
22
23 u_char *file_name;
24 ngx_int_t line;
25
26 ngx_array_t listen; /* ngx_http_memcachep_listen_t */
27
28 ngx_resolver_t *resolver;
29 } ngx_http_memcachedp_srv_conf_t;
30
31 typedef struct {
32 u_char sockaddr[NGX_SOCKADDRLEN];
33 socklen_t socklen;
34
35 ngx_http_conf_ctx_t *ctx;
36
37 unsigned bind:1;
38 unsigned wildcard:1;
39 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
40 unsigned ipv6only:2;
41 #endif
42 } ngx_http_memcachep_listen_t;
43
44 typedef struct {
45 /* ngx_mail_in_addr_t or ngx_mail_in6_addr_t */
46 void *addrs;
47 ngx_uint_t naddrs;
48 } ngx_http_memcachep_mport_t;
49
50 typedef struct {
51 int family;
52 in_port_t port;
53 ngx_array_t addrs; /* array of ngx_http_memcachep_addr_t */
54 } ngx_http_memcachep_port_t;
55
56 typedef struct {
57 struct sockaddr *sockaddr;
58 socklen_t socklen;
59
60 ngx_http_conf_ctx_t *ctx;
61
62 unsigned bind:1;
63 unsigned wildcard:1;
64 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
65 unsigned ipv6only:2;
66 #endif
67 } ngx_http_memcachep_addr_t;
68
69 typedef struct {
70 ngx_http_conf_ctx_t *ctx;
71 ngx_str_t addr_text;
72 } ngx_http_memcachep_addr_conf_t;
73
74 typedef struct {
75 in_addr_t addr;
76 ngx_http_memcachep_addr_conf_t conf;
77 } ngx_http_memcachep_in_addr_t;
78
79
80 static char *ngx_http_memcachep_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
81 static void *ngx_http_memcachep_create_srv_conf(ngx_conf_t *cf);
82 static char *ngx_http_memcachep_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child);
83
84 static char *ngx_http_memcachep_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
85 static ngx_int_t ngx_http_memcachep_add_addrs(ngx_conf_t *cf, ngx_http_memcachep_mport_t *mport, ngx_http_memcachep_addr_t *addr);
86 static ngx_int_t ngx_http_memcachep_add_ports(ngx_conf_t *cf, ngx_array_t *ports, ngx_http_memcachep_listen_t *listen);
87 static ngx_int_t ngx_http_memcachep_cmp_conf_addrs(const void *one, const void *two);
88
89
90 static ngx_command_t ngx_http_memcachep_commands[] = {
91 { ngx_string("memcached_listen"),
92 NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
93 ngx_http_memcachep_listen,
94 0,
95 0,
96 NULL },
97
98 ngx_null_command
99 };
100
101 static ngx_http_module_t ngx_http_memcachep_module_ctx = {
102 NULL, /* preconfiguration */
103 NULL, /* postconfiguration */
104
105 NULL, /* create main configuration */
106 NULL, /* init main configuration */
107
108 ngx_http_memcachep_create_srv_conf, /* create server configuration */
109 ngx_http_memcachep_merge_srv_conf, /* merge server configuration */
110
111 NULL, /* create location configuration */
112 NULL /* merge location configuration */
113 };
114
115 ngx_module_t ngx_http_memcachep_module = {
116 NGX_MODULE_V1,
117 &ngx_http_memcachep_module_ctx, /* module context */
118 ngx_http_memcachep_commands, /* module directives */
119 NGX_HTTP_MODULE, /* module type */
120 NULL, /* init master */
121 NULL, /* init module */
122 NULL, /* init process */
123 NULL, /* init thread */
124 NULL, /* exit thread */
125 NULL, /* exit process */
126 NULL, /* exit master */
127 NGX_MODULE_V1_PADDING
128 };
129
130
131 static void *
132 ngx_http_memcachep_create_srv_conf(ngx_conf_t *cf)
133 {
134 ngx_http_memcachedp_srv_conf_t *cscf;
135
136 cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_memcachedp_srv_conf_t));
137 if (cscf == NULL) {
138 return NULL;
139 }
140
141 /*
142 * set by ngx_pcalloc():
143 *
144 */
145
146 cscf->timeout = NGX_CONF_UNSET_MSEC;
147 cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
148 cscf->so_keepalive = NGX_CONF_UNSET;
149
150 cscf->resolver = NGX_CONF_UNSET_PTR;
151
152 cscf->file_name = cf->conf_file->file.name.data;
153 cscf->line = cf->conf_file->line;
154
155
156 if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_memcachep_listen_t))
157 != NGX_OK)
158 {
159 return NGX_CONF_ERROR;
160 }
161
162 return cscf;
163 }
164
165 static char *
166 ngx_http_memcachep_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
167 {
168 ngx_http_memcachedp_srv_conf_t *prev = parent;
169 ngx_http_memcachedp_srv_conf_t *conf = child;
170
171 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
172 ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout, 30000);
173
174 ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 1);
175
176
177 ngx_conf_merge_str_value(conf->server_name, prev->server_name, "");
178
179 if (conf->server_name.len == 0) {
180 conf->server_name = cf->cycle->hostname;
181 }
182
183 ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL);
184
185 return NGX_CONF_OK;
186 }
187
188 static char *
189 ngx_http_memcachep_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
190 {
191 size_t len, off;
192 in_port_t port;
193 ngx_str_t *value;
194 ngx_url_t u;
195 ngx_uint_t i;
196 struct sockaddr *sa;
197 struct sockaddr_in *sin;
198 #if (NGX_HAVE_INET6)
199 struct sockaddr_in6 *sin6;
200 #endif
201 ngx_http_memcachedp_srv_conf_t *cscf;
202 ngx_http_memcachep_listen_t *ls, *listen;
203
204 ngx_array_t ports;
205
206 value = cf->args->elts;
207
208 ngx_memzero(&u, sizeof(ngx_url_t));
209
210 u.url = value[1];
211 u.listen = 1;
212
213 if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
214 if (u.err) {
215 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
216 "%s in \"%V\" of the \"listen\" directive",
217 u.err, &u.url);
218 }
219
220 return NGX_CONF_ERROR;
221 }
222
223 cscf = (ngx_http_memcachedp_srv_conf_t *) ngx_http_conf_get_module_srv_conf(cf, ngx_http_memcachep_module);
224
225 ls = cscf->listen.elts;
226 for (i = 0; i < cscf->listen.nelts; i++) {
227
228 sa = (struct sockaddr *) ls[i].sockaddr;
229
230 if (sa->sa_family != u.family) {
231 continue;
232 }
233
234 switch (sa->sa_family) {
235
236 #if (NGX_HAVE_INET6)
237 case AF_INET6:
238 off = offsetof(struct sockaddr_in6, sin6_addr);
239 len = 16;
240 sin6 = (struct sockaddr_in6 *) sa;
241 port = sin6->sin6_port;
242 break;
243 #endif
244 default: /* AF_INET */
245 off = offsetof(struct sockaddr_in, sin_addr);
246 len = 4;
247 sin = (struct sockaddr_in *) sa;
248 port = sin->sin_port;
249
250 break;
251 }
252
253 if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) {
254 continue;
255 }
256
257 if (port != u.port) {
258 continue;
259 }
260
261 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
262 "duplicate \"%V\" address and port pair", &u.url);
263 return NGX_CONF_ERROR;
264 }
265
266 ls = ngx_array_push(&cscf->listen);
267
268 if (ls == NULL) {
269 return NGX_CONF_ERROR;
270 }
271
272 ngx_memzero(ls, sizeof(ngx_http_memcachep_listen_t));
273
274 ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
275
276 ls->socklen = u.socklen;
277 ls->wildcard = u.wildcard;
278 ls->ctx = cf->ctx; /* srv conf ctx (ngx_http_conf_ctx_t) */
279
280 for (i = 2; i < cf->args->nelts; i++) {
281
282 if (ngx_strcmp(value[i].data, "bind") == 0) {
283 ls->bind = 1;
284 continue;
285 }
286
287 if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
288 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
289 struct sockaddr *sa;
290 u_char buf[NGX_SOCKADDR_STRLEN];
291
292 sa = (struct sockaddr *) ls->sockaddr;
293
294 if (sa->sa_family == AF_INET6) {
295
296 if (ngx_strcmp(&value[i].data[10], "n") == 0) {
297 ls->ipv6only = 1;
298
299 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
300 ls->ipv6only = 2;
301
302 } else {
303 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
304 "invalid ipv6only flags \"%s\"",
305 &value[i].data[9]);
306 return NGX_CONF_ERROR;
307 }
308
309 ls->bind = 1;
310
311 } else {
312 len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1);
313
314 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
315 "ipv6only is not supported "
316 "on addr \"%*s\", ignored", len, buf);
317 }
318
319 continue;
320 #else
321 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
322 "bind ipv6only is not supported "
323 "on this platform");
324 return NGX_CONF_ERROR;
325 #endif
326 }
327
328 if (ngx_strcmp(value[i].data, "ssl") == 0) {
329 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
330 "the \"ssl\" parameter requires "
331 "ngx_mail_ssl_module");
332 return NGX_CONF_ERROR;
333 }
334
335 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
336 "the invalid \"%V\" parameter", &value[i]);
337 return NGX_CONF_ERROR;
338 }
339
340
341
342 if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_http_memcachep_port_t))
343 != NGX_OK)
344 {
345 return NGX_CONF_ERROR;
346 }
347
348 listen = cscf->listen.elts;
349
350 for (i = 0; i < cscf->listen.nelts; i++) {
351 if (ngx_http_memcachep_add_ports(cf, &ports, &listen[i]) != NGX_OK) {
352 return NGX_CONF_ERROR;
353 }
354 }
355
356
357 return ngx_http_memcachep_optimize_servers(cf, &ports);
358 }
359
360 void
361 ngx_http_memcachep_close_connection(ngx_connection_t *c)
362 {
363 ngx_pool_t *pool;
364
365 c->destroyed = 1;
366 pool = c->pool;
367
368 ngx_close_connection(c);
369 ngx_destroy_pool(pool);
370 }
371
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
372 void ngx_http_memcachep_process(ngx_event_t *wev, ngx_str_t uri);
357e1ce @yappo event loop から書き込みできるようになった時のハンドラを設定してなくて大変な事になってたのでハンドラつけた
authored
373
4a79fb3 @yappo first
authored
374 static void
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
375 ngx_http_memcachep_send(ngx_event_t *wev)
4a79fb3 @yappo first
authored
376 {
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
377 ssize_t n;
378 ngx_http_memcachedp_session_t *s;
379 ngx_connection_t *c;
db4aff0 @yappo nginx の hack 泣きそうです。素人で良くわからないから ngx_mail_proxy_module.c 参考にコード書いたらうま…
authored
380 size_t outlen;
381 u_char *outstr;
357e1ce @yappo event loop から書き込みできるようになった時のハンドラを設定してなくて大変な事になってたのでハンドラつけた
authored
382
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
383 c = wev->data;
384 s = c->data;
357e1ce @yappo event loop から書き込みできるようになった時のハンドラを設定してなくて大変な事になってたのでハンドラつけた
authored
385
386 if (wev->timedout) {
387 c->timedout = 1;
388 ngx_http_memcachep_close_connection(c);
389 return;
390 }
391
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
392 if (s->out.len == 0) {
4a79fb3 @yappo first
authored
393 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
394 ngx_http_memcachep_close_connection(c);
395 }
396 return;
397 }
398
db4aff0 @yappo nginx の hack 泣きそうです。素人で良くわからないから ngx_mail_proxy_module.c 参考にコード書いたらうま…
authored
399 #if 1
400 // バッファ吐けるまでループしてsendするんだけど、このコードってasyncしてなくね?
401 outstr = s->out.data;
402 outlen = s->out.len;
403 for ( ;; ) {
404 n = c->send(c, outstr, outlen);
405
406 if (n == NGX_ERROR) {
407 ngx_http_memcachep_close_connection(c);
408 return;
409 }
410
411 if (n > 0) {
412 outstr += n;
413 outlen -= n;
414 }
415 if (outlen) {
416 continue;
417 }
418 break;
419 }
420 #else
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
421 n = c->send(c, s->out.data, s->out.len);
4a79fb3 @yappo first
authored
422
423 if (n > 0) {
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
424 s->out.len -= n;
357e1ce @yappo event loop から書き込みできるようになった時のハンドラを設定してなくて大変な事になってたのでハンドラつけた
authored
425
db4aff0 @yappo nginx の hack 泣きそうです。素人で良くわからないから ngx_mail_proxy_module.c 参考にコード書いたらうま…
authored
426 // 送りきれなかったので、もう一度バッファに突っ込む
427 if (s->out.len > 0) {
428 s->out.data = s->out.data + n;
429
430 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
431 ngx_http_memcachep_close_connection(c);
432 return;
433 }
434 ngx_http_memcachep_send(wev);
435 }
436
357e1ce @yappo event loop から書き込みできるようになった時のハンドラを設定してなくて大変な事になってたのでハンドラつけた
authored
437 if (wev->timer_set) {
438 ngx_del_timer(wev);
439 }
440
4a79fb3 @yappo first
authored
441 return;
442 }
443
444 if (n == NGX_ERROR) {
445 ngx_http_memcachep_close_connection(c);
446 return;
447 }
448
db4aff0 @yappo nginx の hack 泣きそうです。素人で良くわからないから ngx_mail_proxy_module.c 参考にコード書いたらうま…
authored
449 // ngx_add_timer(c->write, 30000);
450 ngx_add_timer(c->write, 300);
4a79fb3 @yappo first
authored
451 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
452 ngx_http_memcachep_close_connection(c);
453 return;
454 }
db4aff0 @yappo nginx の hack 泣きそうです。素人で良くわからないから ngx_mail_proxy_module.c 参考にコード書いたらうま…
authored
455 #endif
456
4a79fb3 @yappo first
authored
457 }
458
459 static void
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
460 ngx_http_memcachep_send_error(ngx_event_t *wev)
4a79fb3 @yappo first
authored
461 {
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
462 ngx_str_t msg = ngx_string("ERROR\r\n");
463 ngx_http_memcachedp_session_t *s;
464 ngx_connection_t *c;
465
466 c = wev->data;
467 s = c->data;
468 s->out = msg;
469 ngx_http_memcachep_send(wev);
4a79fb3 @yappo first
authored
470 }
471
472
473 ngx_int_t
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
474 ngx_http_memcachep_parse_command(ngx_event_t *wev)
4a79fb3 @yappo first
authored
475 {
476 ssize_t len, line_len;
477 u_char ch, *p, *sc, *keystartp, *keyendp;
478 ngx_str_t uri;
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
479 ngx_buf_t *buffer;
480 ngx_connection_t *c;
481 ngx_http_memcachedp_session_t *s;
4a79fb3 @yappo first
authored
482 enum {
483 sw_start = 0,
484 sw_searchkey,
485 sw_fetchkey
486 } state;
487
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
488 c = wev->data;
489 s = c->data;
490 buffer = s->buffer;
491
4a79fb3 @yappo first
authored
492 state = sw_start;
493
494 len = buffer->last - buffer->pos;
495
496 // 行末までの長さを測る
497 line_len = 0;
498 keystartp = buffer->pos;
499 for (p = buffer->pos; p < buffer->last; p++) {
500 ch = *p;
501
502 if (buffer->last - buffer->pos -1 < p - buffer->pos) {
503 goto invalid;
504 }
505
506 switch (state) {
507 case sw_start:
508 if (ch == ' ') {
509 sc = buffer->start;
510 if (p - sc == 3 && sc[0] == 'g' && sc[1] == 'e' && sc[2] == 't') {
511 state = sw_searchkey;
512 } else {
513 goto invalid;
514 }
515 } else if (ch == CR || ch == LF) {
516 goto invalid;
517 }
518 break;
519 case sw_searchkey:
520 if (ch == CR || ch == LF) {
521 goto invalid;
522 }
523 if (ch != ' ') {
524 keystartp = p;
525 state = sw_fetchkey;
526 }
527 break;
528 case sw_fetchkey:
529 if (ch == CR || ch == LF || ch == ' ') {
530 keyendp = p;
531 goto found;
532 }
533 break;
534 }
535 }
536
537 return NGX_AGAIN;
538
539 found:
540
541 *keystartp = '/';
542 uri.data = keystartp;
543 uri.len = keyendp - keystartp;
544 uri.data[uri.len] = '\0';
545
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
546 ngx_http_memcachep_process(wev, uri);
4a79fb3 @yappo first
authored
547
548 return NGX_AGAIN;
549 invalid:
550 return NGX_ERROR;
551 }
552
553
554 void
555 ngx_http_memcachep_read_line(ngx_event_t *wev)
556 {
557 ngx_int_t rc;
558 ssize_t n;
559 ngx_buf_t *buffer;
560 ngx_connection_t *c;
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
561 ngx_http_memcachedp_session_t *s;
4a79fb3 @yappo first
authored
562
563 c = wev->data;
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
564 s = c->data;
565 buffer = s->buffer;
4a79fb3 @yappo first
authored
566
567 n = c->recv(c, buffer->last, buffer->end - buffer->last);
568
569 // バッファのサイズ以上の読み込みはソケット閉じる そんなにぉっきぃのはぃらなぃょぉ
570 if (n == NGX_ERROR || n == 0) {
571 ngx_http_memcachep_close_connection(c);
572 return;
573 }
574
575 if (n > 0) {
576 buffer->last += n;
577 }
578
579 if (n == NGX_AGAIN) {
580 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
581 ngx_http_memcachep_close_connection(c);
582 return;
583 }
584 return;
585 }
586
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
587 rc = ngx_http_memcachep_parse_command(wev);
4a79fb3 @yappo first
authored
588
589 // パースに失敗したので ERROR を返す
590 if (rc == NGX_ERROR) {
591 buffer->last = buffer->pos;
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
592 ngx_http_memcachep_send_error(wev);
4a79fb3 @yappo first
authored
593 return;
594 }
595
596 // パース成功して処理終わってる
597 if (rc == NGX_AGAIN) {
598 buffer->last = buffer->pos;
599 return;
600 }
601 }
602
603 void
604 ngx_http_memcachep_init_connection(ngx_connection_t *c)
605 {
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
606 ngx_http_memcachedp_session_t *s;
4a79fb3 @yappo first
authored
607
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
608 s = ngx_pcalloc(c->pool, sizeof(ngx_http_memcachedp_session_t));
609 s->connection = c;
610 s->buffer = ngx_create_temp_buf(c->pool, 1024);
611 s->out_buffer.data = ngx_pcalloc(c->pool, 4096);
4a79fb3 @yappo first
authored
612
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
613 c->data = s;
614 c->write->handler = ngx_http_memcachep_send;
615 c->read->handler = ngx_http_memcachep_read_line;
4a79fb3 @yappo first
authored
616
617 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
618 ngx_http_memcachep_close_connection(c);
619 return;
620 }
621 }
622
623 void
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
624 ngx_http_memcachep_process(ngx_event_t *wev, ngx_str_t uri)
4a79fb3 @yappo first
authored
625 {
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
626 ngx_connection_t *c;
627 ngx_http_memcachedp_session_t *s;
628 ngx_http_conf_ctx_t *ctx;
629
630 c = wev->data;
631 s = c->data;
632 ctx = (ngx_http_conf_ctx_t *) c->listening->servers;
4a79fb3 @yappo first
authored
633
634 if (1) {
635 ngx_http_request_t *r;
636
637
638 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
639 r->main = r;
640
641 r->pool = c->pool;
642
643 r->main_conf = ctx->main_conf;
644 r->srv_conf = ctx->srv_conf;
645 r->loc_conf = ctx->loc_conf;
646
647 r->ctx = (void *) ngx_modules;
648
649 r->connection = ngx_pcalloc(c->pool, sizeof(ngx_connection_t));
650 r->connection->log = c->log;
651
652
653 r->connection->read = ngx_pcalloc(c->pool, sizeof(ngx_event_t));
654 r->connection->write = r->connection->read;
655
656 r->connection->write->data = c;
657 r->connection->write->ready = 1;
658 r->connection->write->delayed = 1;
659
660 r->subrequest_in_memory = 1;
661 r->buffered = 1;
662 r->connection->buffered = 1;
663 r->main_filter_need_in_memory = 1;
664 r->filter_need_in_memory = 1;
665
666 r->method = NGX_HTTP_GET;
667
668 r->out = ngx_pcalloc(c->pool, sizeof(ngx_chain_t));
669
670 r->variables = ngx_pcalloc(r->pool, 1 * sizeof(ngx_http_variable_value_t));
671 if (r->variables == NULL) {
672 ngx_http_memcachep_close_connection(c);
673 return;
674 }
675
676 r->method_name.data = ngx_pcalloc(c->pool, sizeof(u_char *) * (uri.len + 30));
677 r->method_name.len = ngx_sprintf(r->method_name.data, "GET %s HTTP/1.1", uri.data) - r->method_name.data;
678
679 if (ngx_http_internal_redirect(r, &uri, NULL) != NGX_DONE) {
680 ngx_http_memcachep_close_connection(c);
681 return;
682 }
683
684 // ngx_http_postponed_request_t に入って r->postponed の中に response body が入ってる?
685
686 // データが帰って来たのでレスポンス返す
687 if (r->postponed && r->postponed->out && r->postponed->out->buf) {
688 ngx_chain_t *cl;
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
689 ngx_str_t crlf = ngx_string("\r\n");
690 ngx_str_t end = ngx_string("END\r\n");
4a79fb3 @yappo first
authored
691
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
692 s->out.len = (10 + uri.len) * 3;
693 s->out.data = ngx_pnalloc(c->pool, s->out.len);
694 if (s->out.data == NULL) {
4a79fb3 @yappo first
authored
695 ngx_http_memcachep_close_connection(c);
696 return;
697 }
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
698 s->out.len = ngx_sprintf(s->out.data, "VALUE %s 0 %d" CRLF, (char *)uri.data, (int)r->headers_out.content_length_n) - s->out.data;
4a79fb3 @yappo first
authored
699
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
700 ngx_http_memcachep_send(wev);
4a79fb3 @yappo first
authored
701
702 for (cl = r->postponed->out; cl; cl = cl->next) {
703 ssize_t n, size;
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
704 s->out.data = cl->buf->pos;
705 s->out.len = cl->buf->last - cl->buf->pos;
706 ngx_http_memcachep_send(wev);
4a79fb3 @yappo first
authored
707
708 if (!cl->buf->file || !cl->buf->file->fd) {
709 continue;
710 }
711
712 // 4096 のサイズずつ転送
713 while (1) {
714 size = (r->headers_out.content_length_n - cl->buf->file_last);
715 if (size == 0) {
716 break;
717 }
718
719 if (size > 4096) {
720 size = 4096;
721 }
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
722 n = ngx_read_file(cl->buf->file, s->out_buffer.data, (size_t) size, cl->buf->file_last);
4a79fb3 @yappo first
authored
723 if (n != size) {
724 ngx_http_memcachep_close_connection(c);
725 return;
726 }
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
727 s->out.data = s->out_buffer.data;
728 s->out.len = n;
729 ngx_http_memcachep_send(wev);
4a79fb3 @yappo first
authored
730 cl->buf->file_last += n;
731 }
732 }
733
b08a962 @yappo 接続毎にセッションコンテキストを設けた
authored
734 s->out = crlf;
735 ngx_http_memcachep_send(wev);
736 s->out = end;
737 ngx_http_memcachep_send(wev);
4a79fb3 @yappo first
authored
738 }
739 }
740 }
741
742 static char *
743 ngx_http_memcachep_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
744 {
745 ngx_uint_t i, p, last, bind_wildcard;
746 ngx_listening_t *ls;
747 ngx_http_memcachep_mport_t *mport;
748 ngx_http_memcachep_port_t *port;
749 ngx_http_memcachep_addr_t *addr;
750
751 port = ports->elts;
752 for (p = 0; p < ports->nelts; p++) {
753 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
754 sizeof(ngx_http_memcachep_addr_t), ngx_http_memcachep_cmp_conf_addrs);
755
756 addr = port[p].addrs.elts;
757 last = port[p].addrs.nelts;
758
759 /*
760 * if there is the binding to the "*:port" then we need to bind()
761 * to the "*:port" only and ignore the other bindings
762 */
763 if (addr[last - 1].wildcard) {
764 addr[last - 1].bind = 1;
765 bind_wildcard = 1;
766
767 } else {
768 bind_wildcard = 0;
769 }
770
771 i = 0;
772
773 while (i < last) {
774 if (bind_wildcard && !addr[i].bind) {
775 i++;
776 continue;
777 }
778
779 ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen);
780 if (ls == NULL) {
781 return NGX_CONF_ERROR;
782 }
783
784 ls->addr_ntop = 1;
785 ls->handler = ngx_http_memcachep_init_connection;
786 ls->pool_size = 256;
787
788 /* TODO: error_log directive */
789 ls->logp = &cf->cycle->new_log;
790 ls->log.data = &ls->addr_text;
791 ls->log.handler = ngx_accept_log_error;
792
793 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
794 ls->ipv6only = addr[i].ipv6only;
795 #endif
796
797 mport = ngx_palloc(cf->pool, sizeof(ngx_http_memcachep_port_t));
798 if (mport == NULL) {
799 return NGX_CONF_ERROR;
800 }
801
802 ls->servers = cf->ctx;
803
804 if (i == last - 1) {
805 mport->naddrs = last;
806
807 } else {
808 mport->naddrs = 1;
809 i = 0;
810 }
811
812 switch (ls->sockaddr->sa_family) {
813 #if (NGX_HAVE_INET6)
814 case AF_INET6:
815 if (ngx_http_memcachep_add_addrs6(cf, mport, addr) != NGX_OK) {
816 return NGX_CONF_ERROR;
817 }
818 break;
819 #endif
820 default: /* AF_INET */
821 if (ngx_http_memcachep_add_addrs(cf, mport, addr) != NGX_OK) {
822 return NGX_CONF_ERROR;
823 }
824 break;
825 }
826
827 addr++;
828 last--;
829 }
830 }
831 return NGX_CONF_OK;
832 }
833
834
835 static ngx_int_t
836 ngx_http_memcachep_add_addrs(ngx_conf_t *cf, ngx_http_memcachep_mport_t *mport,
837 ngx_http_memcachep_addr_t *addr)
838 {
839 u_char *p;
840 size_t len;
841 ngx_uint_t i;
842 ngx_http_memcachep_in_addr_t *addrs;
843 struct sockaddr_in *sin;
844 u_char buf[NGX_SOCKADDR_STRLEN];
845
846 mport->addrs = ngx_pcalloc(cf->pool,
847 mport->naddrs * sizeof(ngx_http_memcachep_in_addr_t));
848 if (mport->addrs == NULL) {
849 return NGX_ERROR;
850 }
851
852 addrs = mport->addrs;
853
854 for (i = 0; i < mport->naddrs; i++) {
855
856 sin = (struct sockaddr_in *) addr[i].sockaddr;
857 addrs[i].addr = sin->sin_addr.s_addr;
858
859 addrs[i].conf.ctx = addr[i].ctx;
860
861 len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
862
863 p = ngx_pnalloc(cf->pool, len);
864 if (p == NULL) {
865 return NGX_ERROR;
866 }
867
868 ngx_memcpy(p, buf, len);
869
870 addrs[i].conf.addr_text.len = len;
871 addrs[i].conf.addr_text.data = p;
872 }
873
874 return NGX_OK;
875 }
876
877
878 static ngx_int_t
879 ngx_http_memcachep_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
880 ngx_http_memcachep_listen_t *listen)
881 {
882 in_port_t p;
883 ngx_uint_t i;
884 struct sockaddr *sa;
885 struct sockaddr_in *sin;
886 ngx_http_memcachep_port_t *port;
887 ngx_http_memcachep_addr_t *addr;
888 #if (NGX_HAVE_INET6)
889 struct sockaddr_in6 *sin6;
890 #endif
891
892 sa = (struct sockaddr *) &listen->sockaddr;
893
894 switch (sa->sa_family) {
895
896 #if (NGX_HAVE_INET6)
897 case AF_INET6:
898 sin6 = (struct sockaddr_in6 *) sa;
899 p = sin6->sin6_port;
900 break;
901 #endif
902
903 default: /* AF_INET */
904 sin = (struct sockaddr_in *) sa;
905 p = sin->sin_port;
906 break;
907 }
908
909 port = ports->elts;
910 for (i = 0; i < ports->nelts; i++) {
911 if (p == port[i].port && sa->sa_family == port[i].family) {
912
913 /* a port is already in the port list */
914
915 port = &port[i];
916 goto found;
917 }
918 }
919
920 /* add a port to the port list */
921
922 port = ngx_array_push(ports);
923 if (port == NULL) {
924 return NGX_ERROR;
925 }
926
927 port->family = sa->sa_family;
928 port->port = p;
929
930 if (ngx_array_init(&port->addrs, cf->temp_pool, 2,
931 sizeof(ngx_http_memcachep_addr_t))
932 != NGX_OK)
933 {
934 return NGX_ERROR;
935 }
936
937 found:
938
939 addr = ngx_array_push(&port->addrs);
940 if (addr == NULL) {
941 return NGX_ERROR;
942 }
943
944 addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
945 addr->socklen = listen->socklen;
946 addr->ctx = listen->ctx;
947 addr->bind = listen->bind;
948 addr->wildcard = listen->wildcard;
949 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
950 addr->ipv6only = listen->ipv6only;
951 #endif
952
953 return NGX_OK;
954 }
955
956 static ngx_int_t
957 ngx_http_memcachep_cmp_conf_addrs(const void *one, const void *two)
958 {
959 ngx_http_memcachep_addr_t *first, *second;
960
961 first = (ngx_http_memcachep_addr_t *) one;
962 second = (ngx_http_memcachep_addr_t *) two;
963
964 if (first->wildcard) {
965 /* a wildcard must be the last resort, shift it to the end */
966 return 1;
967 }
968
969 if (first->bind && !second->bind) {
970 /* shift explicit bind()ed addresses to the start */
971 return -1;
972 }
973
974 if (!first->bind && second->bind) {
975 /* shift explicit bind()ed addresses to the start */
976 return 1;
977 }
978
979 /* do not sort by default */
980
981 return 0;
982 }
Something went wrong with that request. Please try again.