nginxtra 1.0.15.0 → 1.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/VERSION +1 -1
  2. data/bin/nginxtra +1 -1
  3. data/lib/nginxtra/action.rb +10 -0
  4. data/lib/nginxtra/actions/compile.rb +16 -2
  5. data/lib/nginxtra/actions/start.rb +18 -2
  6. data/lib/nginxtra/actions/status.rb +1 -10
  7. data/lib/nginxtra/actions/stop.rb +18 -0
  8. data/lib/nginxtra/cli.rb +12 -3
  9. data/lib/nginxtra/config.rb +10 -0
  10. data/src/nginx/CHANGES +311 -90
  11. data/src/nginx/CHANGES.ru +315 -88
  12. data/src/nginx/auto/lib/pcre/conf +22 -5
  13. data/src/nginx/auto/lib/pcre/make +1 -1
  14. data/src/nginx/auto/modules +14 -3
  15. data/src/nginx/auto/options +17 -3
  16. data/src/nginx/auto/os/freebsd +8 -0
  17. data/src/nginx/auto/os/linux +5 -4
  18. data/src/nginx/auto/os/solaris +2 -1
  19. data/src/nginx/auto/sources +10 -2
  20. data/src/nginx/auto/summary +2 -0
  21. data/src/nginx/auto/types/sizeof +2 -1
  22. data/src/nginx/auto/types/typedef +1 -1
  23. data/src/nginx/auto/types/uintptr_t +7 -4
  24. data/src/nginx/auto/unix +82 -21
  25. data/src/nginx/conf/fastcgi.conf +1 -0
  26. data/src/nginx/conf/fastcgi_params +1 -0
  27. data/src/nginx/conf/scgi_params +1 -0
  28. data/src/nginx/conf/uwsgi_params +1 -0
  29. data/src/nginx/man/nginx.8 +49 -49
  30. data/src/nginx/src/core/nginx.c +10 -12
  31. data/src/nginx/src/core/nginx.h +2 -2
  32. data/src/nginx/src/core/ngx_buf.c +9 -7
  33. data/src/nginx/src/core/ngx_buf.h +2 -2
  34. data/src/nginx/src/core/ngx_conf_file.c +4 -11
  35. data/src/nginx/src/core/ngx_conf_file.h +1 -1
  36. data/src/nginx/src/core/ngx_connection.c +52 -1
  37. data/src/nginx/src/core/ngx_connection.h +6 -0
  38. data/src/nginx/src/core/ngx_core.h +5 -0
  39. data/src/nginx/src/core/ngx_cycle.c +1 -1
  40. data/src/nginx/src/core/ngx_cycle.h +2 -2
  41. data/src/nginx/src/core/ngx_file.c +1 -1
  42. data/src/nginx/src/core/ngx_inet.c +11 -8
  43. data/src/nginx/src/core/ngx_murmurhash.h +1 -1
  44. data/src/nginx/src/core/ngx_open_file_cache.c +343 -38
  45. data/src/nginx/src/core/ngx_open_file_cache.h +10 -0
  46. data/src/nginx/src/core/ngx_output_chain.c +2 -1
  47. data/src/nginx/src/core/ngx_parse.h +0 -3
  48. data/src/nginx/src/core/ngx_rbtree.c +1 -2
  49. data/src/nginx/src/core/ngx_regex.c +263 -5
  50. data/src/nginx/src/core/ngx_regex.h +6 -2
  51. data/src/nginx/src/core/ngx_resolver.c +88 -21
  52. data/src/nginx/src/core/ngx_resolver.h +7 -8
  53. data/src/nginx/src/core/ngx_shmtx.c +69 -44
  54. data/src/nginx/src/core/ngx_shmtx.h +12 -1
  55. data/src/nginx/src/core/ngx_slab.c +3 -3
  56. data/src/nginx/src/core/ngx_slab.h +1 -1
  57. data/src/nginx/src/core/ngx_string.c +19 -16
  58. data/src/nginx/src/core/ngx_times.c +2 -2
  59. data/src/nginx/src/event/modules/ngx_epoll_module.c +2 -2
  60. data/src/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  61. data/src/nginx/src/event/modules/ngx_kqueue_module.c +1 -1
  62. data/src/nginx/src/event/ngx_event.c +25 -17
  63. data/src/nginx/src/event/ngx_event_openssl.c +3 -1
  64. data/src/nginx/src/event/ngx_event_pipe.c +108 -85
  65. data/src/nginx/src/event/ngx_event_pipe.h +1 -2
  66. data/src/nginx/src/event/ngx_event_timer.c +2 -3
  67. data/src/nginx/src/http/modules/ngx_http_access_module.c +9 -4
  68. data/src/nginx/src/http/modules/ngx_http_browser_module.c +5 -3
  69. data/src/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -1
  70. data/src/nginx/src/http/modules/ngx_http_degradation_module.c +1 -1
  71. data/src/nginx/src/http/modules/ngx_http_fastcgi_module.c +144 -22
  72. data/src/nginx/src/http/modules/ngx_http_flv_module.c +8 -0
  73. data/src/nginx/src/http/modules/ngx_http_geo_module.c +3 -3
  74. data/src/nginx/src/http/modules/ngx_http_gzip_filter_module.c +20 -6
  75. data/src/nginx/src/http/modules/ngx_http_gzip_static_module.c +8 -0
  76. data/src/nginx/src/http/modules/ngx_http_headers_filter_module.c +23 -27
  77. data/src/nginx/src/http/modules/ngx_http_image_filter_module.c +1 -3
  78. data/src/nginx/src/http/modules/ngx_http_index_module.c +24 -0
  79. data/src/nginx/src/http/modules/ngx_http_limit_conn_module.c +747 -0
  80. data/src/nginx/src/http/modules/ngx_http_limit_req_module.c +289 -133
  81. data/src/nginx/src/http/modules/ngx_http_log_module.c +34 -6
  82. data/src/nginx/src/http/modules/ngx_http_memcached_module.c +19 -3
  83. data/src/nginx/src/http/modules/ngx_http_mp4_module.c +8 -0
  84. data/src/nginx/src/http/modules/ngx_http_proxy_module.c +1446 -239
  85. data/src/nginx/src/http/modules/ngx_http_realip_module.c +4 -10
  86. data/src/nginx/src/http/modules/ngx_http_scgi_module.c +90 -21
  87. data/src/nginx/src/http/modules/ngx_http_split_clients_module.c +8 -11
  88. data/src/nginx/src/http/modules/ngx_http_ssi_filter_module.c +16 -6
  89. data/src/nginx/src/http/modules/ngx_http_static_module.c +8 -0
  90. data/src/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +2 -2
  91. data/src/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +570 -0
  92. data/src/nginx/src/http/modules/ngx_http_userid_filter_module.c +1 -5
  93. data/src/nginx/src/http/modules/ngx_http_uwsgi_module.c +77 -26
  94. data/src/nginx/src/http/modules/ngx_http_xslt_filter_module.c +171 -37
  95. data/src/nginx/src/http/modules/perl/nginx.pm +2 -1
  96. data/src/nginx/src/http/modules/perl/nginx.xs +4 -0
  97. data/src/nginx/src/http/ngx_http.c +8 -1
  98. data/src/nginx/src/http/ngx_http.h +1 -0
  99. data/src/nginx/src/http/ngx_http_busy_lock.c +2 -2
  100. data/src/nginx/src/http/ngx_http_cache.h +12 -1
  101. data/src/nginx/src/http/ngx_http_copy_filter_module.c +4 -3
  102. data/src/nginx/src/http/ngx_http_core_module.c +303 -37
  103. data/src/nginx/src/http/ngx_http_core_module.h +15 -0
  104. data/src/nginx/src/http/ngx_http_file_cache.c +226 -52
  105. data/src/nginx/src/http/ngx_http_parse.c +69 -3
  106. data/src/nginx/src/http/ngx_http_postpone_filter_module.c +4 -4
  107. data/src/nginx/src/http/ngx_http_request.c +61 -27
  108. data/src/nginx/src/http/ngx_http_request.h +3 -3
  109. data/src/nginx/src/http/ngx_http_request_body.c +1 -1
  110. data/src/nginx/src/http/ngx_http_script.c +6 -0
  111. data/src/nginx/src/http/ngx_http_upstream.c +200 -47
  112. data/src/nginx/src/http/ngx_http_upstream.h +20 -1
  113. data/src/nginx/src/http/ngx_http_upstream_round_robin.c +22 -6
  114. data/src/nginx/src/http/ngx_http_upstream_round_robin.h +1 -0
  115. data/src/nginx/src/http/ngx_http_variables.c +123 -4
  116. data/src/nginx/src/mail/ngx_mail.c +13 -0
  117. data/src/nginx/src/mail/ngx_mail.h +12 -0
  118. data/src/nginx/src/mail/ngx_mail_core_module.c +100 -15
  119. data/src/nginx/src/os/unix/ngx_daemon.c +2 -1
  120. data/src/nginx/src/os/unix/ngx_darwin.h +3 -0
  121. data/src/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  122. data/src/nginx/src/os/unix/ngx_darwin_init.c +30 -0
  123. data/src/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +11 -5
  124. data/src/nginx/src/os/unix/ngx_errno.h +5 -0
  125. data/src/nginx/src/os/unix/ngx_files.h +50 -1
  126. data/src/nginx/src/os/unix/ngx_freebsd.h +2 -1
  127. data/src/nginx/src/os/unix/ngx_freebsd_config.h +2 -0
  128. data/src/nginx/src/os/unix/ngx_freebsd_init.c +4 -3
  129. data/src/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +2 -2
  130. data/src/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +12 -6
  131. data/src/nginx/src/os/unix/ngx_gcc_atomic_sparc64.h +1 -1
  132. data/src/nginx/src/os/unix/ngx_linux_config.h +1 -0
  133. data/src/nginx/src/os/unix/ngx_linux_sendfile_chain.c +6 -4
  134. data/src/nginx/src/os/unix/ngx_os.h +0 -1
  135. data/src/nginx/src/os/unix/ngx_posix_config.h +3 -0
  136. data/src/nginx/src/os/unix/ngx_process.c +50 -11
  137. data/src/nginx/src/os/unix/ngx_process.h +1 -0
  138. data/src/nginx/src/os/unix/ngx_process_cycle.c +6 -15
  139. data/src/nginx/src/os/unix/ngx_readv_chain.c +8 -0
  140. data/src/nginx/src/os/unix/ngx_setaffinity.c +69 -0
  141. data/src/nginx/src/os/unix/ngx_setaffinity.h +23 -0
  142. data/src/nginx/src/os/unix/ngx_setproctitle.c +1 -1
  143. data/src/nginx/src/os/unix/ngx_solaris_config.h +2 -0
  144. data/src/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +11 -3
  145. data/src/nginx/src/os/unix/ngx_writev_chain.c +7 -3
  146. metadata +7 -4
  147. data/src/nginx/src/http/modules/ngx_http_limit_zone_module.c +0 -553
@@ -16,13 +16,7 @@
16
16
 
17
17
 
18
18
  typedef struct {
19
- in_addr_t mask;
20
- in_addr_t addr;
21
- } ngx_http_realip_from_t;
22
-
23
-
24
- typedef struct {
25
- ngx_array_t *from; /* array of ngx_http_realip_from_t */
19
+ ngx_array_t *from; /* array of ngx_in_cidr_t */
26
20
  ngx_uint_t type;
27
21
  ngx_uint_t hash;
28
22
  ngx_str_t header;
@@ -114,9 +108,9 @@ ngx_http_realip_handler(ngx_http_request_t *r)
114
108
  ngx_list_part_t *part;
115
109
  ngx_table_elt_t *header;
116
110
  struct sockaddr_in *sin;
111
+ ngx_in_cidr_t *from;
117
112
  ngx_connection_t *c;
118
113
  ngx_http_realip_ctx_t *ctx;
119
- ngx_http_realip_from_t *from;
120
114
  ngx_http_realip_loc_conf_t *rlcf;
121
115
 
122
116
  ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
@@ -317,7 +311,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
317
311
  ngx_int_t rc;
318
312
  ngx_str_t *value;
319
313
  ngx_cidr_t cidr;
320
- ngx_http_realip_from_t *from;
314
+ ngx_in_cidr_t *from;
321
315
 
322
316
  value = cf->args->elts;
323
317
 
@@ -332,7 +326,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
332
326
 
333
327
  if (rlcf->from == NULL) {
334
328
  rlcf->from = ngx_array_create(cf->pool, 2,
335
- sizeof(ngx_http_realip_from_t));
329
+ sizeof(ngx_in_cidr_t));
336
330
  if (rlcf->from == NULL) {
337
331
  return NGX_CONF_ERROR;
338
332
  }
@@ -247,6 +247,20 @@ static ngx_command_t ngx_http_scgi_commands[] = {
247
247
  offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_methods),
248
248
  &ngx_http_upstream_cache_method_mask },
249
249
 
250
+ { ngx_string("scgi_cache_lock"),
251
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
252
+ ngx_conf_set_flag_slot,
253
+ NGX_HTTP_LOC_CONF_OFFSET,
254
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock),
255
+ NULL },
256
+
257
+ { ngx_string("scgi_cache_lock_timeout"),
258
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
259
+ ngx_conf_set_msec_slot,
260
+ NGX_HTTP_LOC_CONF_OFFSET,
261
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout),
262
+ NULL },
263
+
250
264
  #endif
251
265
 
252
266
  { ngx_string("scgi_temp_path"),
@@ -278,8 +292,8 @@ static ngx_command_t ngx_http_scgi_commands[] = {
278
292
  &ngx_http_scgi_next_upstream_masks },
279
293
 
280
294
  { ngx_string("scgi_param"),
281
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
282
- ngx_conf_set_keyval_slot,
295
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
296
+ ngx_http_upstream_param_set_slot,
283
297
  NGX_HTTP_LOC_CONF_OFFSET,
284
298
  offsetof(ngx_http_scgi_loc_conf_t, params_source),
285
299
  NULL },
@@ -519,10 +533,10 @@ static ngx_int_t
519
533
  ngx_http_scgi_create_request(ngx_http_request_t *r)
520
534
  {
521
535
  u_char ch, *key, *val, *lowcase_key;
522
- size_t len, allocated;
536
+ size_t len, key_len, val_len, allocated;
523
537
  ngx_buf_t *b;
524
538
  ngx_str_t *content_length;
525
- ngx_uint_t i, n, hash, header_params;
539
+ ngx_uint_t i, n, hash, skip_empty, header_params;
526
540
  ngx_chain_t *cl, *body;
527
541
  ngx_list_part_t *part;
528
542
  ngx_table_elt_t *header, **ignored;
@@ -554,15 +568,21 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
554
568
  while (*(uintptr_t *) le.ip) {
555
569
 
556
570
  lcode = *(ngx_http_script_len_code_pt *) le.ip;
557
- len += lcode(&le);
571
+ key_len = lcode(&le);
558
572
 
559
- while (*(uintptr_t *) le.ip) {
573
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
574
+ skip_empty = lcode(&le);
575
+
576
+ for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
560
577
  lcode = *(ngx_http_script_len_code_pt *) le.ip;
561
- len += lcode(&le);
562
578
  }
563
- len++;
564
-
565
579
  le.ip += sizeof(uintptr_t);
580
+
581
+ if (skip_empty && val_len == 0) {
582
+ continue;
583
+ }
584
+
585
+ len += key_len + val_len + 1;
566
586
  }
567
587
  }
568
588
 
@@ -665,7 +685,34 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
665
685
  e.request = r;
666
686
  e.flushed = 1;
667
687
 
668
- while (*(uintptr_t *) e.ip) {
688
+ le.ip = scf->params_len->elts;
689
+
690
+ while (*(uintptr_t *) le.ip) {
691
+
692
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
693
+ lcode(&le); /* key length */
694
+
695
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
696
+ skip_empty = lcode(&le);
697
+
698
+ for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
699
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
700
+ }
701
+ le.ip += sizeof(uintptr_t);
702
+
703
+ if (skip_empty && val_len == 0) {
704
+ e.skip = 1;
705
+
706
+ while (*(uintptr_t *) e.ip) {
707
+ code = *(ngx_http_script_code_pt *) e.ip;
708
+ code((ngx_http_script_engine_t *) &e);
709
+ }
710
+ e.ip += sizeof(uintptr_t);
711
+
712
+ e.skip = 0;
713
+
714
+ continue;
715
+ }
669
716
 
670
717
  #if (NGX_DEBUG)
671
718
  key = e.pos;
@@ -1032,6 +1079,8 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
1032
1079
  conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
1033
1080
  conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
1034
1081
  conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
1082
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
1083
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
1035
1084
  #endif
1036
1085
 
1037
1086
  conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -1124,8 +1173,8 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1124
1173
 
1125
1174
  if (conf->upstream.busy_buffers_size < size) {
1126
1175
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1127
- "\"scgi_busy_buffers_size\" must be equal or bigger "
1128
- "than maximum of the value of \"scgi_buffer_size\" and "
1176
+ "\"scgi_busy_buffers_size\" must be equal to or greater "
1177
+ "than the maximum of the value of \"scgi_buffer_size\" and "
1129
1178
  "one of the \"scgi_buffers\"");
1130
1179
 
1131
1180
  return NGX_CONF_ERROR;
@@ -1155,8 +1204,8 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1155
1204
 
1156
1205
  if (conf->upstream.temp_file_write_size < size) {
1157
1206
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1158
- "\"scgi_temp_file_write_size\" must be equal or bigger than "
1159
- "maximum of the value of \"scgi_buffer_size\" and "
1207
+ "\"scgi_temp_file_write_size\" must be equal to or greater than "
1208
+ "the maximum of the value of \"scgi_buffer_size\" and "
1160
1209
  "one of the \"scgi_buffers\"");
1161
1210
 
1162
1211
  return NGX_CONF_ERROR;
@@ -1178,8 +1227,8 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1178
1227
  && conf->upstream.max_temp_file_size < size) {
1179
1228
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1180
1229
  "\"scgi_max_temp_file_size\" must be equal to zero to disable "
1181
- "the temporary files usage or must be equal or bigger than "
1182
- "maximum of the value of \"scgi_buffer_size\" and "
1230
+ "temporary files usage or must be equal to or greater than "
1231
+ "the maximum of the value of \"scgi_buffer_size\" and "
1183
1232
  "one of the \"scgi_buffers\"");
1184
1233
 
1185
1234
  return NGX_CONF_ERROR;
@@ -1263,6 +1312,12 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1263
1312
  conf->cache_key = prev->cache_key;
1264
1313
  }
1265
1314
 
1315
+ ngx_conf_merge_value(conf->upstream.cache_lock,
1316
+ prev->upstream.cache_lock, 0);
1317
+
1318
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
1319
+ prev->upstream.cache_lock_timeout, 5000);
1320
+
1266
1321
  #endif
1267
1322
 
1268
1323
  ngx_conf_merge_value(conf->upstream.pass_request_headers,
@@ -1320,9 +1375,9 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
1320
1375
  #if (NGX_HTTP_CACHE)
1321
1376
  ngx_array_t params_merged;
1322
1377
  #endif
1323
- ngx_keyval_t *src;
1324
1378
  ngx_hash_key_t *hk;
1325
1379
  ngx_hash_init_t hash;
1380
+ ngx_http_upstream_param_t *src;
1326
1381
  ngx_http_script_compile_t sc;
1327
1382
  ngx_http_script_copy_code_t *copy;
1328
1383
 
@@ -1331,7 +1386,8 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
1331
1386
 
1332
1387
  if (prev->headers_hash.buckets
1333
1388
  #if (NGX_HTTP_CACHE)
1334
- && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))
1389
+ && ((conf->upstream.cache == NULL)
1390
+ == (prev->upstream.cache == NULL))
1335
1391
  #endif
1336
1392
  )
1337
1393
  {
@@ -1383,9 +1439,11 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
1383
1439
  #if (NGX_HTTP_CACHE)
1384
1440
 
1385
1441
  if (conf->upstream.cache) {
1386
- ngx_keyval_t *h, *s;
1442
+ ngx_keyval_t *h;
1443
+ ngx_http_upstream_param_t *s;
1387
1444
 
1388
- if (ngx_array_init(&params_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
1445
+ if (ngx_array_init(&params_merged, cf->temp_pool, 4,
1446
+ sizeof(ngx_http_upstream_param_t))
1389
1447
  != NGX_OK)
1390
1448
  {
1391
1449
  return NGX_ERROR;
@@ -1419,7 +1477,9 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
1419
1477
  return NGX_ERROR;
1420
1478
  }
1421
1479
 
1422
- *s = *h;
1480
+ s->key = h->key;
1481
+ s->value = h->value;
1482
+ s->skip_empty = 0;
1423
1483
 
1424
1484
  next:
1425
1485
 
@@ -1461,6 +1521,15 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
1461
1521
  copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
1462
1522
  copy->len = src[i].key.len + 1;
1463
1523
 
1524
+ copy = ngx_array_push_n(conf->params_len,
1525
+ sizeof(ngx_http_script_copy_code_t));
1526
+ if (copy == NULL) {
1527
+ return NGX_ERROR;
1528
+ }
1529
+
1530
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
1531
+ copy->len = src[i].skip_empty;
1532
+
1464
1533
 
1465
1534
  size = (sizeof(ngx_http_script_copy_code_t)
1466
1535
  + src[i].key.len + 1 + sizeof(uintptr_t) - 1)
@@ -97,7 +97,7 @@ ngx_http_split_clients_variable(ngx_http_request_t *r,
97
97
  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
98
98
  "http split: %uD %uD", hash, part[i].percent);
99
99
 
100
- if (hash < part[i].percent) {
100
+ if (hash < part[i].percent || part[i].percent == 0) {
101
101
  *v = part[i].value;
102
102
  return NGX_OK;
103
103
  }
@@ -111,8 +111,9 @@ static char *
111
111
  ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
112
112
  {
113
113
  char *rv;
114
+ uint32_t sum, last;
114
115
  ngx_str_t *value, name;
115
- ngx_uint_t i, sum, last;
116
+ ngx_uint_t i;
116
117
  ngx_conf_t save;
117
118
  ngx_http_variable_t *var;
118
119
  ngx_http_split_clients_ctx_t *ctx;
@@ -175,19 +176,15 @@ ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
175
176
  for (i = 0; i < ctx->parts.nelts; i++) {
176
177
  sum = part[i].percent ? sum + part[i].percent : 10000;
177
178
  if (sum > 10000) {
178
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
179
- "percent sum is more than 100%%");
180
- return NGX_CONF_ERROR;
179
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
180
+ "percent total is greater than 100%%");
181
+ return NGX_CONF_ERROR;
181
182
  }
182
183
 
183
184
  if (part[i].percent) {
184
- part[i].percent = (uint32_t)
185
- (last + 0xffffffff / 10000 * part[i].percent);
186
- } else {
187
- part[i].percent = 0xffffffff;
185
+ last += part[i].percent * (uint64_t) 0xffffffff / 10000;
186
+ part[i].percent = last;
188
187
  }
189
-
190
- last = part[i].percent;
191
188
  }
192
189
 
193
190
  return rv;
@@ -714,7 +714,7 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
714
714
 
715
715
  if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) {
716
716
  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
717
- "too many SSI command paramters: \"%V\"",
717
+ "too many SSI command parameters: \"%V\"",
718
718
  &ctx->command);
719
719
  goto ssi_error;
720
720
  }
@@ -1204,7 +1204,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
1204
1204
 
1205
1205
  if (ctx->value_buf == NULL) {
1206
1206
  ctx->param->value.data = ngx_pnalloc(r->pool,
1207
- ctx->value_len);
1207
+ ctx->value_len + 1);
1208
1208
  if (ctx->param->value.data == NULL) {
1209
1209
  return NGX_ERROR;
1210
1210
  }
@@ -1375,6 +1375,16 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
1375
1375
  case ssi_quoted_symbol_state:
1376
1376
  state = ctx->saved_state;
1377
1377
 
1378
+ if (ctx->param->value.len == ctx->value_len) {
1379
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1380
+ "too long \"%V%c...\" value of \"%V\" "
1381
+ "parameter in \"%V\" SSI command",
1382
+ &ctx->param->value, ch, &ctx->param->key,
1383
+ &ctx->command);
1384
+ state = ssi_error_state;
1385
+ break;
1386
+ }
1387
+
1378
1388
  ctx->param->value.data[ctx->param->value.len++] = ch;
1379
1389
 
1380
1390
  break;
@@ -1993,7 +2003,7 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
1993
2003
 
1994
2004
  if (set && stub) {
1995
2005
  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1996
- "\"set\" and \"stub\" may not be used together "
2006
+ "\"set\" and \"stub\" cannot be used together "
1997
2007
  "in \"include\" SSI command");
1998
2008
  return NGX_HTTP_SSI_ERROR;
1999
2009
  }
@@ -2001,7 +2011,7 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
2001
2011
  if (wait) {
2002
2012
  if (uri == NULL) {
2003
2013
  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2004
- "\"wait\" may not be used with file=\"%V\"", file);
2014
+ "\"wait\" cannot be used with file=\"%V\"", file);
2005
2015
  return NGX_HTTP_SSI_ERROR;
2006
2016
  }
2007
2017
 
@@ -2178,7 +2188,7 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
2178
2188
 
2179
2189
  } else {
2180
2190
  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2181
- "only one subrequest may be waited at the same time");
2191
+ "can only wait for one subrequest at a time");
2182
2192
  }
2183
2193
 
2184
2194
  return NGX_OK;
@@ -2886,7 +2896,7 @@ ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2886
2896
  prev->ignore_recycled_buffers, 0);
2887
2897
 
2888
2898
  ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024);
2889
- ngx_conf_merge_size_value(conf->value_len, prev->value_len, 256);
2899
+ ngx_conf_merge_size_value(conf->value_len, prev->value_len, 255);
2890
2900
 
2891
2901
  if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
2892
2902
  &prev->types_keys, &prev->types,
@@ -95,6 +95,10 @@ ngx_http_static_handler(ngx_http_request_t *r)
95
95
  of.errors = clcf->open_file_cache_errors;
96
96
  of.events = clcf->open_file_cache_events;
97
97
 
98
+ if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
99
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
100
+ }
101
+
98
102
  if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
99
103
  != NGX_OK)
100
104
  {
@@ -112,6 +116,10 @@ ngx_http_static_handler(ngx_http_request_t *r)
112
116
  break;
113
117
 
114
118
  case NGX_EACCES:
119
+ #if (NGX_HAVE_OPENAT)
120
+ case NGX_EMLINK:
121
+ case NGX_ELOOP:
122
+ #endif
115
123
 
116
124
  level = NGX_LOG_ERR;
117
125
  rc = NGX_HTTP_FORBIDDEN;
@@ -186,8 +186,8 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
186
186
  break;
187
187
  }
188
188
 
189
- if (now - peer->accessed > peer->fail_timeout) {
190
- peer->fails = 0;
189
+ if (now - peer->checked > peer->fail_timeout) {
190
+ peer->checked = now;
191
191
  break;
192
192
  }
193
193
  }
@@ -0,0 +1,570 @@
1
+
2
+ /*
3
+ * Copyright (C) Maxim Dounin
4
+ * Copyright (C) Nginx, Inc.
5
+ */
6
+
7
+
8
+ #include <ngx_config.h>
9
+ #include <ngx_core.h>
10
+ #include <ngx_http.h>
11
+
12
+
13
+ typedef struct {
14
+ ngx_uint_t max_cached;
15
+ ngx_uint_t single; /* unsigned:1 */
16
+
17
+ ngx_queue_t cache;
18
+ ngx_queue_t free;
19
+
20
+ ngx_http_upstream_init_pt original_init_upstream;
21
+ ngx_http_upstream_init_peer_pt original_init_peer;
22
+
23
+ } ngx_http_upstream_keepalive_srv_conf_t;
24
+
25
+
26
+ typedef struct {
27
+ ngx_http_upstream_keepalive_srv_conf_t *conf;
28
+
29
+ ngx_http_upstream_t *upstream;
30
+
31
+ void *data;
32
+
33
+ ngx_event_get_peer_pt original_get_peer;
34
+ ngx_event_free_peer_pt original_free_peer;
35
+
36
+ #if (NGX_HTTP_SSL)
37
+ ngx_event_set_peer_session_pt original_set_session;
38
+ ngx_event_save_peer_session_pt original_save_session;
39
+ #endif
40
+
41
+ ngx_uint_t failed; /* unsigned:1 */
42
+
43
+ } ngx_http_upstream_keepalive_peer_data_t;
44
+
45
+
46
+ typedef struct {
47
+ ngx_http_upstream_keepalive_srv_conf_t *conf;
48
+
49
+ ngx_queue_t queue;
50
+ ngx_connection_t *connection;
51
+
52
+ socklen_t socklen;
53
+ u_char sockaddr[NGX_SOCKADDRLEN];
54
+
55
+ } ngx_http_upstream_keepalive_cache_t;
56
+
57
+
58
+ static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
59
+ ngx_http_upstream_srv_conf_t *us);
60
+ static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc,
61
+ void *data);
62
+ static void ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc,
63
+ void *data, ngx_uint_t state);
64
+
65
+ static void ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev);
66
+ static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev);
67
+ static void ngx_http_upstream_keepalive_close(ngx_connection_t *c);
68
+
69
+
70
+ #if (NGX_HTTP_SSL)
71
+ static ngx_int_t ngx_http_upstream_keepalive_set_session(
72
+ ngx_peer_connection_t *pc, void *data);
73
+ static void ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc,
74
+ void *data);
75
+ #endif
76
+
77
+ static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf);
78
+ static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
79
+ void *conf);
80
+
81
+
82
+ static ngx_command_t ngx_http_upstream_keepalive_commands[] = {
83
+
84
+ { ngx_string("keepalive"),
85
+ NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12,
86
+ ngx_http_upstream_keepalive,
87
+ 0,
88
+ 0,
89
+ NULL },
90
+
91
+ ngx_null_command
92
+ };
93
+
94
+
95
+ static ngx_http_module_t ngx_http_upstream_keepalive_module_ctx = {
96
+ NULL, /* preconfiguration */
97
+ NULL, /* postconfiguration */
98
+
99
+ NULL, /* create main configuration */
100
+ NULL, /* init main configuration */
101
+
102
+ ngx_http_upstream_keepalive_create_conf, /* create server configuration */
103
+ NULL, /* merge server configuration */
104
+
105
+ NULL, /* create location configuration */
106
+ NULL /* merge location configuration */
107
+ };
108
+
109
+
110
+ ngx_module_t ngx_http_upstream_keepalive_module = {
111
+ NGX_MODULE_V1,
112
+ &ngx_http_upstream_keepalive_module_ctx, /* module context */
113
+ ngx_http_upstream_keepalive_commands, /* module directives */
114
+ NGX_HTTP_MODULE, /* module type */
115
+ NULL, /* init master */
116
+ NULL, /* init module */
117
+ NULL, /* init process */
118
+ NULL, /* init thread */
119
+ NULL, /* exit thread */
120
+ NULL, /* exit process */
121
+ NULL, /* exit master */
122
+ NGX_MODULE_V1_PADDING
123
+ };
124
+
125
+
126
+ static ngx_int_t
127
+ ngx_http_upstream_init_keepalive(ngx_conf_t *cf,
128
+ ngx_http_upstream_srv_conf_t *us)
129
+ {
130
+ ngx_uint_t i;
131
+ ngx_http_upstream_keepalive_srv_conf_t *kcf;
132
+ ngx_http_upstream_keepalive_cache_t *cached;
133
+
134
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
135
+ "init keepalive");
136
+
137
+ kcf = ngx_http_conf_upstream_srv_conf(us,
138
+ ngx_http_upstream_keepalive_module);
139
+
140
+ if (kcf->original_init_upstream(cf, us) != NGX_OK) {
141
+ return NGX_ERROR;
142
+ }
143
+
144
+ kcf->original_init_peer = us->peer.init;
145
+
146
+ us->peer.init = ngx_http_upstream_init_keepalive_peer;
147
+
148
+ /* allocate cache items and add to free queue */
149
+
150
+ cached = ngx_pcalloc(cf->pool,
151
+ sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached);
152
+ if (cached == NULL) {
153
+ return NGX_ERROR;
154
+ }
155
+
156
+ ngx_queue_init(&kcf->cache);
157
+ ngx_queue_init(&kcf->free);
158
+
159
+ for (i = 0; i < kcf->max_cached; i++) {
160
+ ngx_queue_insert_head(&kcf->free, &cached[i].queue);
161
+ cached[i].conf = kcf;
162
+ }
163
+
164
+ return NGX_OK;
165
+ }
166
+
167
+
168
+ static ngx_int_t
169
+ ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
170
+ ngx_http_upstream_srv_conf_t *us)
171
+ {
172
+ ngx_http_upstream_keepalive_peer_data_t *kp;
173
+ ngx_http_upstream_keepalive_srv_conf_t *kcf;
174
+
175
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
176
+ "init keepalive peer");
177
+
178
+ kcf = ngx_http_conf_upstream_srv_conf(us,
179
+ ngx_http_upstream_keepalive_module);
180
+
181
+ kp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_keepalive_peer_data_t));
182
+ if (kp == NULL) {
183
+ return NGX_ERROR;
184
+ }
185
+
186
+ if (kcf->original_init_peer(r, us) != NGX_OK) {
187
+ return NGX_ERROR;
188
+ }
189
+
190
+ kp->conf = kcf;
191
+ kp->upstream = r->upstream;
192
+ kp->data = r->upstream->peer.data;
193
+ kp->original_get_peer = r->upstream->peer.get;
194
+ kp->original_free_peer = r->upstream->peer.free;
195
+
196
+ r->upstream->peer.data = kp;
197
+ r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer;
198
+ r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer;
199
+
200
+ #if (NGX_HTTP_SSL)
201
+ kp->original_set_session = r->upstream->peer.set_session;
202
+ kp->original_save_session = r->upstream->peer.save_session;
203
+ r->upstream->peer.set_session = ngx_http_upstream_keepalive_set_session;
204
+ r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session;
205
+ #endif
206
+
207
+ return NGX_OK;
208
+ }
209
+
210
+
211
+ static ngx_int_t
212
+ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
213
+ {
214
+ ngx_http_upstream_keepalive_peer_data_t *kp = data;
215
+ ngx_http_upstream_keepalive_cache_t *item;
216
+
217
+ ngx_int_t rc;
218
+ ngx_queue_t *q, *cache;
219
+ ngx_connection_t *c;
220
+
221
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
222
+ "get keepalive peer");
223
+
224
+ kp->failed = 0;
225
+
226
+ /* single pool of cached connections */
227
+
228
+ if (kp->conf->single && !ngx_queue_empty(&kp->conf->cache)) {
229
+
230
+ q = ngx_queue_head(&kp->conf->cache);
231
+
232
+ item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
233
+ c = item->connection;
234
+
235
+ ngx_queue_remove(q);
236
+ ngx_queue_insert_head(&kp->conf->free, q);
237
+
238
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
239
+ "get keepalive peer: using connection %p", c);
240
+
241
+ c->idle = 0;
242
+ c->log = pc->log;
243
+ c->read->log = pc->log;
244
+ c->write->log = pc->log;
245
+ c->pool->log = pc->log;
246
+
247
+ pc->connection = c;
248
+ pc->cached = 1;
249
+
250
+ return NGX_DONE;
251
+ }
252
+
253
+ rc = kp->original_get_peer(pc, kp->data);
254
+
255
+ if (kp->conf->single || rc != NGX_OK) {
256
+ return rc;
257
+ }
258
+
259
+ /* search cache for suitable connection */
260
+
261
+ cache = &kp->conf->cache;
262
+
263
+ for (q = ngx_queue_head(cache);
264
+ q != ngx_queue_sentinel(cache);
265
+ q = ngx_queue_next(q))
266
+ {
267
+ item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
268
+ c = item->connection;
269
+
270
+ if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr,
271
+ item->socklen, pc->socklen)
272
+ == 0)
273
+ {
274
+ ngx_queue_remove(q);
275
+ ngx_queue_insert_head(&kp->conf->free, q);
276
+
277
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
278
+ "get keepalive peer: using connection %p", c);
279
+
280
+ c->idle = 0;
281
+ c->log = pc->log;
282
+ c->read->log = pc->log;
283
+ c->write->log = pc->log;
284
+ c->pool->log = pc->log;
285
+
286
+ pc->connection = c;
287
+ pc->cached = 1;
288
+
289
+ return NGX_DONE;
290
+ }
291
+ }
292
+
293
+ return NGX_OK;
294
+ }
295
+
296
+
297
+ static void
298
+ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
299
+ ngx_uint_t state)
300
+ {
301
+ ngx_http_upstream_keepalive_peer_data_t *kp = data;
302
+ ngx_http_upstream_keepalive_cache_t *item;
303
+
304
+ ngx_queue_t *q;
305
+ ngx_connection_t *c;
306
+ ngx_http_upstream_t *u;
307
+
308
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
309
+ "free keepalive peer");
310
+
311
+ /* remember failed state - peer.free() may be called more than once */
312
+
313
+ if (state & NGX_PEER_FAILED) {
314
+ kp->failed = 1;
315
+ }
316
+
317
+ /* cache valid connections */
318
+
319
+ u = kp->upstream;
320
+ c = pc->connection;
321
+
322
+ if (kp->failed
323
+ || c == NULL
324
+ || c->read->eof
325
+ || c->read->error
326
+ || c->read->timedout
327
+ || c->write->error
328
+ || c->write->timedout)
329
+ {
330
+ goto invalid;
331
+ }
332
+
333
+ if (!u->keepalive) {
334
+ goto invalid;
335
+ }
336
+
337
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
338
+ goto invalid;
339
+ }
340
+
341
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
342
+ "free keepalive peer: saving connection %p", c);
343
+
344
+ if (ngx_queue_empty(&kp->conf->free)) {
345
+
346
+ q = ngx_queue_last(&kp->conf->cache);
347
+ ngx_queue_remove(q);
348
+
349
+ item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
350
+
351
+ ngx_http_upstream_keepalive_close(item->connection);
352
+
353
+ } else {
354
+ q = ngx_queue_head(&kp->conf->free);
355
+ ngx_queue_remove(q);
356
+
357
+ item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
358
+ }
359
+
360
+ item->connection = c;
361
+ ngx_queue_insert_head(&kp->conf->cache, q);
362
+
363
+ pc->connection = NULL;
364
+
365
+ if (c->read->timer_set) {
366
+ ngx_del_timer(c->read);
367
+ }
368
+ if (c->write->timer_set) {
369
+ ngx_del_timer(c->write);
370
+ }
371
+
372
+ c->write->handler = ngx_http_upstream_keepalive_dummy_handler;
373
+ c->read->handler = ngx_http_upstream_keepalive_close_handler;
374
+
375
+ c->data = item;
376
+ c->idle = 1;
377
+ c->log = ngx_cycle->log;
378
+ c->read->log = ngx_cycle->log;
379
+ c->write->log = ngx_cycle->log;
380
+ c->pool->log = ngx_cycle->log;
381
+
382
+ item->socklen = pc->socklen;
383
+ ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen);
384
+
385
+ if (c->read->ready) {
386
+ ngx_http_upstream_keepalive_close_handler(c->read);
387
+ }
388
+
389
+ invalid:
390
+
391
+ kp->original_free_peer(pc, kp->data, state);
392
+ }
393
+
394
+
395
+ static void
396
+ ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev)
397
+ {
398
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
399
+ "keepalive dummy handler");
400
+ }
401
+
402
+
403
+ static void
404
+ ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev)
405
+ {
406
+ ngx_http_upstream_keepalive_srv_conf_t *conf;
407
+ ngx_http_upstream_keepalive_cache_t *item;
408
+
409
+ int n;
410
+ char buf[1];
411
+ ngx_connection_t *c;
412
+
413
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
414
+ "keepalive close handler");
415
+
416
+ c = ev->data;
417
+
418
+ if (c->close) {
419
+ goto close;
420
+ }
421
+
422
+ n = recv(c->fd, buf, 1, MSG_PEEK);
423
+
424
+ if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
425
+ /* stale event */
426
+
427
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
428
+ goto close;
429
+ }
430
+
431
+ return;
432
+ }
433
+
434
+ close:
435
+
436
+ item = c->data;
437
+ conf = item->conf;
438
+
439
+ ngx_http_upstream_keepalive_close(c);
440
+
441
+ ngx_queue_remove(&item->queue);
442
+ ngx_queue_insert_head(&conf->free, &item->queue);
443
+ }
444
+
445
+
446
+ static void
447
+ ngx_http_upstream_keepalive_close(ngx_connection_t *c)
448
+ {
449
+
450
+ #if (NGX_HTTP_SSL)
451
+
452
+ if (c->ssl) {
453
+ c->ssl->no_wait_shutdown = 1;
454
+ c->ssl->no_send_shutdown = 1;
455
+
456
+ if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
457
+ c->ssl->handler = ngx_http_upstream_keepalive_close;
458
+ return;
459
+ }
460
+ }
461
+
462
+ #endif
463
+
464
+ ngx_destroy_pool(c->pool);
465
+ ngx_close_connection(c);
466
+ }
467
+
468
+
469
+ #if (NGX_HTTP_SSL)
470
+
471
+ static ngx_int_t
472
+ ngx_http_upstream_keepalive_set_session(ngx_peer_connection_t *pc, void *data)
473
+ {
474
+ ngx_http_upstream_keepalive_peer_data_t *kp = data;
475
+
476
+ return kp->original_set_session(pc, kp->data);
477
+ }
478
+
479
+
480
+ static void
481
+ ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, void *data)
482
+ {
483
+ ngx_http_upstream_keepalive_peer_data_t *kp = data;
484
+
485
+ kp->original_save_session(pc, kp->data);
486
+ return;
487
+ }
488
+
489
+ #endif
490
+
491
+
492
+ static void *
493
+ ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
494
+ {
495
+ ngx_http_upstream_keepalive_srv_conf_t *conf;
496
+
497
+ conf = ngx_pcalloc(cf->pool,
498
+ sizeof(ngx_http_upstream_keepalive_srv_conf_t));
499
+ if (conf == NULL) {
500
+ return NULL;
501
+ }
502
+
503
+ /*
504
+ * set by ngx_pcalloc():
505
+ *
506
+ * conf->original_init_upstream = NULL;
507
+ * conf->original_init_peer = NULL;
508
+ */
509
+
510
+ conf->max_cached = 1;
511
+
512
+ return conf;
513
+ }
514
+
515
+
516
+ static char *
517
+ ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
518
+ {
519
+ ngx_http_upstream_srv_conf_t *uscf;
520
+ ngx_http_upstream_keepalive_srv_conf_t *kcf;
521
+
522
+ ngx_int_t n;
523
+ ngx_str_t *value;
524
+ ngx_uint_t i;
525
+
526
+ uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
527
+
528
+ kcf = ngx_http_conf_upstream_srv_conf(uscf,
529
+ ngx_http_upstream_keepalive_module);
530
+
531
+ kcf->original_init_upstream = uscf->peer.init_upstream
532
+ ? uscf->peer.init_upstream
533
+ : ngx_http_upstream_init_round_robin;
534
+
535
+ uscf->peer.init_upstream = ngx_http_upstream_init_keepalive;
536
+
537
+ /* read options */
538
+
539
+ value = cf->args->elts;
540
+
541
+ n = ngx_atoi(value[1].data, value[1].len);
542
+
543
+ if (n == NGX_ERROR || n == 0) {
544
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
545
+ "invalid value \"%V\" in \"%V\" directive",
546
+ &value[1], &cmd->name);
547
+ return NGX_CONF_ERROR;
548
+ }
549
+
550
+ kcf->max_cached = n;
551
+
552
+ for (i = 2; i < cf->args->nelts; i++) {
553
+
554
+ if (ngx_strcmp(value[i].data, "single") == 0) {
555
+ kcf->single = 1;
556
+ continue;
557
+ }
558
+
559
+ goto invalid;
560
+ }
561
+
562
+ return NGX_CONF_OK;
563
+
564
+ invalid:
565
+
566
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
567
+ "invalid parameter \"%V\"", &value[i]);
568
+
569
+ return NGX_CONF_ERROR;
570
+ }