nginxtra 1.8.1.12 → 1.10.1.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (238) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nginxtra +1 -1
  3. data/bin/nginxtra_rails +1 -1
  4. data/lib/nginxtra/version.rb +1 -1
  5. data/vendor/nginx/CHANGES +363 -25
  6. data/vendor/nginx/CHANGES.ru +365 -21
  7. data/vendor/nginx/LICENSE +2 -2
  8. data/vendor/nginx/auto/cc/conf +32 -0
  9. data/vendor/nginx/auto/cc/gcc +1 -1
  10. data/vendor/nginx/auto/cc/icc +2 -2
  11. data/vendor/nginx/auto/cc/msvc +29 -8
  12. data/vendor/nginx/auto/cc/name +2 -25
  13. data/vendor/nginx/auto/cc/sunc +3 -0
  14. data/vendor/nginx/auto/endianness +7 -2
  15. data/vendor/nginx/auto/install +60 -26
  16. data/vendor/nginx/auto/lib/conf +4 -4
  17. data/vendor/nginx/auto/lib/geoip/conf +6 -1
  18. data/vendor/nginx/auto/lib/libgd/conf +6 -1
  19. data/vendor/nginx/auto/lib/libxslt/conf +11 -2
  20. data/vendor/nginx/auto/lib/make +1 -1
  21. data/vendor/nginx/auto/lib/md5/conf +2 -2
  22. data/vendor/nginx/auto/lib/md5/make +2 -2
  23. data/vendor/nginx/auto/lib/openssl/conf +52 -3
  24. data/vendor/nginx/auto/lib/openssl/make +1 -1
  25. data/vendor/nginx/auto/lib/pcre/conf +2 -2
  26. data/vendor/nginx/auto/lib/pcre/make +2 -2
  27. data/vendor/nginx/auto/lib/perl/conf +6 -3
  28. data/vendor/nginx/auto/lib/perl/make +4 -1
  29. data/vendor/nginx/auto/lib/sha1/conf +2 -2
  30. data/vendor/nginx/auto/lib/sha1/make +2 -2
  31. data/vendor/nginx/auto/lib/zlib/conf +2 -2
  32. data/vendor/nginx/auto/lib/zlib/make +2 -2
  33. data/vendor/nginx/auto/make +281 -16
  34. data/vendor/nginx/auto/module +122 -0
  35. data/vendor/nginx/auto/modules +909 -178
  36. data/vendor/nginx/auto/options +81 -19
  37. data/vendor/nginx/auto/os/conf +9 -0
  38. data/vendor/nginx/auto/os/darwin +3 -0
  39. data/vendor/nginx/auto/os/freebsd +0 -20
  40. data/vendor/nginx/auto/os/linux +0 -12
  41. data/vendor/nginx/auto/os/win32 +5 -1
  42. data/vendor/nginx/auto/sources +11 -311
  43. data/vendor/nginx/auto/summary +1 -0
  44. data/vendor/nginx/auto/types/sizeof +5 -3
  45. data/vendor/nginx/auto/types/typedef +9 -4
  46. data/vendor/nginx/auto/types/uintptr_t +7 -2
  47. data/vendor/nginx/auto/unix +72 -12
  48. data/vendor/nginx/conf/fastcgi.conf +1 -0
  49. data/vendor/nginx/conf/fastcgi_params +1 -0
  50. data/vendor/nginx/conf/scgi_params +1 -0
  51. data/vendor/nginx/conf/uwsgi_params +1 -0
  52. data/vendor/nginx/configure +1 -1
  53. data/vendor/nginx/contrib/vim/syntax/nginx.vim +2 -2
  54. data/vendor/nginx/man/nginx.8 +6 -2
  55. data/vendor/nginx/src/core/nginx.c +281 -114
  56. data/vendor/nginx/src/core/nginx.h +2 -2
  57. data/vendor/nginx/src/core/ngx_conf_file.c +54 -13
  58. data/vendor/nginx/src/core/ngx_conf_file.h +8 -52
  59. data/vendor/nginx/src/core/ngx_config.h +0 -5
  60. data/vendor/nginx/src/core/ngx_connection.c +270 -37
  61. data/vendor/nginx/src/core/ngx_connection.h +35 -12
  62. data/vendor/nginx/src/core/ngx_core.h +4 -0
  63. data/vendor/nginx/src/core/ngx_crypt.c +2 -2
  64. data/vendor/nginx/src/core/ngx_cycle.c +72 -25
  65. data/vendor/nginx/src/core/ngx_cycle.h +28 -39
  66. data/vendor/nginx/src/core/ngx_file.c +14 -5
  67. data/vendor/nginx/src/core/ngx_file.h +2 -0
  68. data/vendor/nginx/src/core/ngx_hash.c +13 -1
  69. data/vendor/nginx/src/core/ngx_inet.c +20 -18
  70. data/vendor/nginx/src/core/ngx_log.c +12 -12
  71. data/vendor/nginx/src/core/ngx_log.h +13 -6
  72. data/vendor/nginx/src/core/ngx_module.c +360 -0
  73. data/vendor/nginx/src/core/ngx_module.h +307 -0
  74. data/vendor/nginx/src/core/ngx_open_file_cache.c +2 -2
  75. data/vendor/nginx/src/core/ngx_output_chain.c +8 -4
  76. data/vendor/nginx/src/core/ngx_palloc.c +42 -44
  77. data/vendor/nginx/src/{http/ngx_http_parse_time.c → core/ngx_parse_time.c} +2 -3
  78. data/vendor/nginx/src/core/ngx_parse_time.h +22 -0
  79. data/vendor/nginx/src/core/ngx_proxy_protocol.c +50 -1
  80. data/vendor/nginx/src/core/ngx_proxy_protocol.h +3 -1
  81. data/vendor/nginx/src/core/ngx_regex.c +1 -38
  82. data/vendor/nginx/src/core/ngx_resolver.c +1814 -320
  83. data/vendor/nginx/src/core/ngx_resolver.h +67 -10
  84. data/vendor/nginx/src/core/ngx_rwlock.c +120 -0
  85. data/vendor/nginx/src/core/ngx_rwlock.h +21 -0
  86. data/vendor/nginx/src/core/ngx_slab.c +6 -5
  87. data/vendor/nginx/src/core/ngx_string.c +1 -1
  88. data/vendor/nginx/src/core/ngx_syslog.c +11 -3
  89. data/vendor/nginx/src/core/ngx_syslog.h +2 -1
  90. data/vendor/nginx/src/core/ngx_thread_pool.c +4 -0
  91. data/vendor/nginx/src/core/ngx_times.c +2 -2
  92. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +3 -1
  93. data/vendor/nginx/src/event/modules/ngx_epoll_module.c +5 -2
  94. data/vendor/nginx/src/event/modules/ngx_eventport_module.c +5 -5
  95. data/vendor/nginx/src/event/modules/ngx_kqueue_module.c +15 -8
  96. data/vendor/nginx/src/event/modules/ngx_poll_module.c +0 -10
  97. data/vendor/nginx/src/event/modules/ngx_select_module.c +0 -10
  98. data/vendor/nginx/src/event/ngx_event.c +60 -103
  99. data/vendor/nginx/src/event/ngx_event.h +22 -26
  100. data/vendor/nginx/src/event/ngx_event_accept.c +414 -88
  101. data/vendor/nginx/src/event/ngx_event_connect.c +27 -18
  102. data/vendor/nginx/src/event/ngx_event_connect.h +1 -0
  103. data/vendor/nginx/src/event/ngx_event_openssl.c +65 -25
  104. data/vendor/nginx/src/event/ngx_event_openssl.h +17 -0
  105. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +73 -7
  106. data/vendor/nginx/src/event/ngx_event_pipe.c +85 -27
  107. data/vendor/nginx/src/event/ngx_event_pipe.h +10 -0
  108. data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +1 -1
  109. data/vendor/nginx/src/http/modules/ngx_http_auth_request_module.c +2 -2
  110. data/vendor/nginx/src/http/modules/ngx_http_chunked_filter_module.c +2 -2
  111. data/vendor/nginx/src/http/modules/ngx_http_dav_module.c +6 -6
  112. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +17 -11
  113. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +2 -2
  114. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +9 -9
  115. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +2 -2
  116. data/vendor/nginx/src/http/modules/ngx_http_limit_conn_module.c +2 -2
  117. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +0 -7
  118. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +6 -6
  119. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +2 -1
  120. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +13 -13
  121. data/vendor/nginx/src/http/modules/ngx_http_not_modified_filter_module.c +2 -2
  122. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +26 -21
  123. data/vendor/nginx/src/http/modules/ngx_http_random_index_module.c +1 -1
  124. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +26 -8
  125. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +73 -3
  126. data/vendor/nginx/src/http/modules/ngx_http_referer_module.c +1 -1
  127. data/vendor/nginx/src/http/modules/ngx_http_rewrite_module.c +6 -6
  128. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +5 -3
  129. data/vendor/nginx/src/http/modules/ngx_http_slice_filter_module.c +526 -0
  130. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +7 -7
  131. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +19 -16
  132. data/vendor/nginx/src/http/modules/ngx_http_static_module.c +1 -1
  133. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +1 -1
  134. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +373 -173
  135. data/vendor/nginx/src/http/modules/ngx_http_upstream_hash_module.c +72 -46
  136. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +18 -30
  137. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +50 -39
  138. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +38 -129
  139. data/vendor/nginx/src/http/modules/ngx_http_upstream_zone_module.c +246 -0
  140. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +6 -5
  141. data/vendor/nginx/src/http/modules/perl/nginx.xs +9 -9
  142. data/vendor/nginx/src/http/ngx_http.c +46 -43
  143. data/vendor/nginx/src/http/ngx_http.h +4 -9
  144. data/vendor/nginx/src/http/ngx_http_cache.h +4 -0
  145. data/vendor/nginx/src/http/ngx_http_copy_filter_module.c +13 -5
  146. data/vendor/nginx/src/http/ngx_http_core_module.c +92 -91
  147. data/vendor/nginx/src/http/ngx_http_core_module.h +12 -8
  148. data/vendor/nginx/src/http/ngx_http_file_cache.c +61 -10
  149. data/vendor/nginx/src/http/ngx_http_request.c +37 -50
  150. data/vendor/nginx/src/http/ngx_http_request.h +10 -15
  151. data/vendor/nginx/src/http/ngx_http_request_body.c +64 -88
  152. data/vendor/nginx/src/http/ngx_http_script.c +3 -3
  153. data/vendor/nginx/src/http/ngx_http_special_response.c +1 -4
  154. data/vendor/nginx/src/http/ngx_http_upstream.c +245 -109
  155. data/vendor/nginx/src/http/ngx_http_upstream.h +11 -5
  156. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +212 -65
  157. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.h +66 -5
  158. data/vendor/nginx/src/http/ngx_http_variables.c +28 -15
  159. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +1 -1
  160. data/vendor/nginx/src/http/v2/ngx_http_v2.c +4349 -0
  161. data/vendor/nginx/src/http/v2/ngx_http_v2.h +337 -0
  162. data/vendor/nginx/src/http/v2/ngx_http_v2_filter_module.c +1391 -0
  163. data/vendor/nginx/src/http/v2/ngx_http_v2_huff_decode.c +2714 -0
  164. data/vendor/nginx/src/http/v2/ngx_http_v2_huff_encode.c +254 -0
  165. data/vendor/nginx/src/http/v2/ngx_http_v2_module.c +469 -0
  166. data/vendor/nginx/src/http/{ngx_http_spdy_module.h → v2/ngx_http_v2_module.h} +10 -9
  167. data/vendor/nginx/src/http/v2/ngx_http_v2_table.c +349 -0
  168. data/vendor/nginx/src/mail/ngx_mail.c +49 -82
  169. data/vendor/nginx/src/mail/ngx_mail.h +16 -23
  170. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +1 -1
  171. data/vendor/nginx/src/mail/ngx_mail_core_module.c +60 -34
  172. data/vendor/nginx/src/mail/ngx_mail_handler.c +17 -12
  173. data/vendor/nginx/src/mail/ngx_mail_proxy_module.c +1 -14
  174. data/vendor/nginx/src/mail/ngx_mail_smtp_handler.c +1 -1
  175. data/vendor/nginx/src/mail/ngx_mail_ssl_module.c +5 -5
  176. data/vendor/nginx/src/os/unix/ngx_atomic.h +10 -10
  177. data/vendor/nginx/src/os/unix/ngx_channel.h +4 -4
  178. data/vendor/nginx/src/os/unix/ngx_darwin_config.h +2 -0
  179. data/vendor/nginx/src/os/unix/ngx_darwin_init.c +1 -0
  180. data/vendor/nginx/src/os/unix/ngx_dlopen.c +28 -0
  181. data/vendor/nginx/src/os/unix/ngx_dlopen.h +31 -0
  182. data/vendor/nginx/src/os/unix/ngx_errno.h +1 -0
  183. data/vendor/nginx/src/os/unix/ngx_file_aio_read.c +1 -1
  184. data/vendor/nginx/src/os/unix/ngx_files.c +313 -80
  185. data/vendor/nginx/src/os/unix/ngx_files.h +5 -2
  186. data/vendor/nginx/src/os/unix/ngx_freebsd_config.h +3 -1
  187. data/vendor/nginx/src/os/unix/ngx_freebsd_init.c +1 -0
  188. data/vendor/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +13 -0
  189. data/vendor/nginx/src/os/unix/ngx_linux.h +0 -2
  190. data/vendor/nginx/src/os/unix/ngx_linux_aio_read.c +1 -1
  191. data/vendor/nginx/src/os/unix/ngx_linux_config.h +2 -6
  192. data/vendor/nginx/src/os/unix/ngx_linux_init.c +1 -33
  193. data/vendor/nginx/src/os/unix/ngx_linux_sendfile_chain.c +55 -12
  194. data/vendor/nginx/src/os/unix/ngx_os.h +3 -9
  195. data/vendor/nginx/src/os/unix/ngx_posix_config.h +14 -1
  196. data/vendor/nginx/src/os/unix/ngx_posix_init.c +2 -1
  197. data/vendor/nginx/src/os/unix/ngx_process.c +1 -1
  198. data/vendor/nginx/src/os/unix/ngx_process_cycle.c +25 -51
  199. data/vendor/nginx/src/os/unix/ngx_process_cycle.h +1 -0
  200. data/vendor/nginx/src/os/unix/ngx_readv_chain.c +24 -28
  201. data/vendor/nginx/src/os/unix/ngx_recv.c +30 -79
  202. data/vendor/nginx/src/os/unix/ngx_send.c +1 -1
  203. data/vendor/nginx/src/os/unix/ngx_setaffinity.c +14 -30
  204. data/vendor/nginx/src/os/unix/ngx_setaffinity.h +15 -1
  205. data/vendor/nginx/src/os/unix/ngx_solaris_config.h +2 -0
  206. data/vendor/nginx/src/os/unix/ngx_solaris_init.c +1 -0
  207. data/vendor/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +23 -0
  208. data/vendor/nginx/src/os/unix/ngx_sunpro_amd64.il +3 -3
  209. data/vendor/nginx/src/os/unix/ngx_sunpro_x86.il +3 -3
  210. data/vendor/nginx/src/os/unix/ngx_udp_recv.c +5 -48
  211. data/vendor/nginx/src/os/unix/ngx_udp_send.c +56 -0
  212. data/vendor/nginx/src/stream/ngx_stream.c +564 -0
  213. data/vendor/nginx/src/stream/ngx_stream.h +212 -0
  214. data/vendor/nginx/src/stream/ngx_stream_access_module.c +451 -0
  215. data/vendor/nginx/src/stream/ngx_stream_core_module.c +562 -0
  216. data/vendor/nginx/src/stream/ngx_stream_handler.c +344 -0
  217. data/vendor/nginx/src/stream/ngx_stream_limit_conn_module.c +632 -0
  218. data/vendor/nginx/src/stream/ngx_stream_proxy_module.c +1674 -0
  219. data/vendor/nginx/src/stream/ngx_stream_ssl_module.c +460 -0
  220. data/vendor/nginx/src/stream/ngx_stream_ssl_module.h +49 -0
  221. data/vendor/nginx/src/stream/ngx_stream_upstream.c +464 -0
  222. data/vendor/nginx/src/stream/ngx_stream_upstream.h +107 -0
  223. data/vendor/nginx/src/stream/ngx_stream_upstream_hash_module.c +656 -0
  224. data/vendor/nginx/src/stream/ngx_stream_upstream_least_conn_module.c +307 -0
  225. data/vendor/nginx/src/stream/ngx_stream_upstream_round_robin.c +702 -0
  226. data/vendor/nginx/src/stream/ngx_stream_upstream_round_robin.h +139 -0
  227. data/vendor/nginx/src/stream/ngx_stream_upstream_zone_module.c +242 -0
  228. metadata +39 -15
  229. data/vendor/nginx/src/event/modules/ngx_aio_module.c +0 -171
  230. data/vendor/nginx/src/event/modules/ngx_rtsig_module.c +0 -735
  231. data/vendor/nginx/src/http/ngx_http_spdy.c +0 -3701
  232. data/vendor/nginx/src/http/ngx_http_spdy.h +0 -261
  233. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +0 -1222
  234. data/vendor/nginx/src/http/ngx_http_spdy_module.c +0 -408
  235. data/vendor/nginx/src/os/unix/ngx_aio_read.c +0 -109
  236. data/vendor/nginx/src/os/unix/ngx_aio_read_chain.c +0 -78
  237. data/vendor/nginx/src/os/unix/ngx_aio_write.c +0 -109
  238. data/vendor/nginx/src/os/unix/ngx_aio_write_chain.c +0 -100
@@ -0,0 +1,344 @@
1
+
2
+ /*
3
+ * Copyright (C) Roman Arutyunyan
4
+ * Copyright (C) Nginx, Inc.
5
+ */
6
+
7
+
8
+ #include <ngx_config.h>
9
+ #include <ngx_core.h>
10
+ #include <ngx_event.h>
11
+ #include <ngx_stream.h>
12
+
13
+
14
+ static u_char *ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len);
15
+ static void ngx_stream_init_session(ngx_connection_t *c);
16
+
17
+ #if (NGX_STREAM_SSL)
18
+ static void ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
19
+ static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
20
+ #endif
21
+
22
+
23
+ void
24
+ ngx_stream_init_connection(ngx_connection_t *c)
25
+ {
26
+ int tcp_nodelay;
27
+ u_char text[NGX_SOCKADDR_STRLEN];
28
+ size_t len;
29
+ ngx_int_t rc;
30
+ ngx_uint_t i;
31
+ struct sockaddr *sa;
32
+ ngx_stream_port_t *port;
33
+ struct sockaddr_in *sin;
34
+ ngx_stream_in_addr_t *addr;
35
+ ngx_stream_session_t *s;
36
+ ngx_stream_addr_conf_t *addr_conf;
37
+ #if (NGX_HAVE_INET6)
38
+ struct sockaddr_in6 *sin6;
39
+ ngx_stream_in6_addr_t *addr6;
40
+ #endif
41
+ ngx_stream_core_srv_conf_t *cscf;
42
+ ngx_stream_core_main_conf_t *cmcf;
43
+
44
+ /* find the server configuration for the address:port */
45
+
46
+ port = c->listening->servers;
47
+
48
+ if (port->naddrs > 1) {
49
+
50
+ /*
51
+ * There are several addresses on this port and one of them
52
+ * is the "*:port" wildcard so getsockname() is needed to determine
53
+ * the server address.
54
+ *
55
+ * AcceptEx() and recvmsg() already gave this address.
56
+ */
57
+
58
+ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
59
+ ngx_stream_close_connection(c);
60
+ return;
61
+ }
62
+
63
+ sa = c->local_sockaddr;
64
+
65
+ switch (sa->sa_family) {
66
+
67
+ #if (NGX_HAVE_INET6)
68
+ case AF_INET6:
69
+ sin6 = (struct sockaddr_in6 *) sa;
70
+
71
+ addr6 = port->addrs;
72
+
73
+ /* the last address is "*" */
74
+
75
+ for (i = 0; i < port->naddrs - 1; i++) {
76
+ if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
77
+ break;
78
+ }
79
+ }
80
+
81
+ addr_conf = &addr6[i].conf;
82
+
83
+ break;
84
+ #endif
85
+
86
+ default: /* AF_INET */
87
+ sin = (struct sockaddr_in *) sa;
88
+
89
+ addr = port->addrs;
90
+
91
+ /* the last address is "*" */
92
+
93
+ for (i = 0; i < port->naddrs - 1; i++) {
94
+ if (addr[i].addr == sin->sin_addr.s_addr) {
95
+ break;
96
+ }
97
+ }
98
+
99
+ addr_conf = &addr[i].conf;
100
+
101
+ break;
102
+ }
103
+
104
+ } else {
105
+ switch (c->local_sockaddr->sa_family) {
106
+
107
+ #if (NGX_HAVE_INET6)
108
+ case AF_INET6:
109
+ addr6 = port->addrs;
110
+ addr_conf = &addr6[0].conf;
111
+ break;
112
+ #endif
113
+
114
+ default: /* AF_INET */
115
+ addr = port->addrs;
116
+ addr_conf = &addr[0].conf;
117
+ break;
118
+ }
119
+ }
120
+
121
+ s = ngx_pcalloc(c->pool, sizeof(ngx_stream_session_t));
122
+ if (s == NULL) {
123
+ ngx_stream_close_connection(c);
124
+ return;
125
+ }
126
+
127
+ s->signature = NGX_STREAM_MODULE;
128
+ s->main_conf = addr_conf->ctx->main_conf;
129
+ s->srv_conf = addr_conf->ctx->srv_conf;
130
+
131
+ s->connection = c;
132
+ c->data = s;
133
+
134
+ cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
135
+
136
+ ngx_set_connection_log(c, cscf->error_log);
137
+
138
+ len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1);
139
+
140
+ ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA %sclient %*s connected to %V",
141
+ c->number, c->type == SOCK_DGRAM ? "udp " : "",
142
+ len, text, &addr_conf->addr_text);
143
+
144
+ c->log->connection = c->number;
145
+ c->log->handler = ngx_stream_log_error;
146
+ c->log->data = s;
147
+ c->log->action = "initializing connection";
148
+ c->log_error = NGX_ERROR_INFO;
149
+
150
+ cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
151
+
152
+ if (cmcf->limit_conn_handler) {
153
+ rc = cmcf->limit_conn_handler(s);
154
+
155
+ if (rc != NGX_DECLINED) {
156
+ ngx_stream_close_connection(c);
157
+ return;
158
+ }
159
+ }
160
+
161
+ if (cmcf->access_handler) {
162
+ rc = cmcf->access_handler(s);
163
+
164
+ if (rc != NGX_OK && rc != NGX_DECLINED) {
165
+ ngx_stream_close_connection(c);
166
+ return;
167
+ }
168
+ }
169
+
170
+ if (c->type == SOCK_STREAM
171
+ && cscf->tcp_nodelay
172
+ && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
173
+ {
174
+ ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay");
175
+
176
+ tcp_nodelay = 1;
177
+
178
+ if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
179
+ (const void *) &tcp_nodelay, sizeof(int)) == -1)
180
+ {
181
+ ngx_connection_error(c, ngx_socket_errno,
182
+ "setsockopt(TCP_NODELAY) failed");
183
+ ngx_stream_close_connection(c);
184
+ return;
185
+ }
186
+
187
+ c->tcp_nodelay = NGX_TCP_NODELAY_SET;
188
+ }
189
+
190
+
191
+ #if (NGX_STREAM_SSL)
192
+ {
193
+ ngx_stream_ssl_conf_t *sslcf;
194
+
195
+ sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
196
+
197
+ if (addr_conf->ssl) {
198
+ c->log->action = "SSL handshaking";
199
+
200
+ if (sslcf->ssl.ctx == NULL) {
201
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
202
+ "no \"ssl_certificate\" is defined "
203
+ "in server listening on SSL port");
204
+ ngx_stream_close_connection(c);
205
+ return;
206
+ }
207
+
208
+ ngx_stream_ssl_init_connection(&sslcf->ssl, c);
209
+ return;
210
+ }
211
+ }
212
+ #endif
213
+
214
+ ngx_stream_init_session(c);
215
+ }
216
+
217
+
218
+ static void
219
+ ngx_stream_init_session(ngx_connection_t *c)
220
+ {
221
+ ngx_stream_session_t *s;
222
+ ngx_stream_core_srv_conf_t *cscf;
223
+
224
+ s = c->data;
225
+ c->log->action = "handling client connection";
226
+
227
+ cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
228
+
229
+ s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_stream_max_module);
230
+ if (s->ctx == NULL) {
231
+ ngx_stream_close_connection(c);
232
+ return;
233
+ }
234
+
235
+ cscf->handler(s);
236
+ }
237
+
238
+
239
+ #if (NGX_STREAM_SSL)
240
+
241
+ static void
242
+ ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
243
+ {
244
+ ngx_stream_session_t *s;
245
+ ngx_stream_ssl_conf_t *sslcf;
246
+
247
+ if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
248
+ ngx_stream_close_connection(c);
249
+ return;
250
+ }
251
+
252
+ if (ngx_ssl_handshake(c) == NGX_AGAIN) {
253
+
254
+ s = c->data;
255
+
256
+ sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
257
+
258
+ ngx_add_timer(c->read, sslcf->handshake_timeout);
259
+
260
+ c->ssl->handler = ngx_stream_ssl_handshake_handler;
261
+
262
+ return;
263
+ }
264
+
265
+ ngx_stream_ssl_handshake_handler(c);
266
+ }
267
+
268
+
269
+ static void
270
+ ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
271
+ {
272
+ if (!c->ssl->handshaked) {
273
+ ngx_stream_close_connection(c);
274
+ return;
275
+ }
276
+
277
+ if (c->read->timer_set) {
278
+ ngx_del_timer(c->read);
279
+ }
280
+
281
+ ngx_stream_init_session(c);
282
+ }
283
+
284
+ #endif
285
+
286
+
287
+ void
288
+ ngx_stream_close_connection(ngx_connection_t *c)
289
+ {
290
+ ngx_pool_t *pool;
291
+
292
+ ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
293
+ "close stream connection: %d", c->fd);
294
+
295
+ #if (NGX_STREAM_SSL)
296
+
297
+ if (c->ssl) {
298
+ if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
299
+ c->ssl->handler = ngx_stream_close_connection;
300
+ return;
301
+ }
302
+ }
303
+
304
+ #endif
305
+
306
+ #if (NGX_STAT_STUB)
307
+ (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
308
+ #endif
309
+
310
+ pool = c->pool;
311
+
312
+ ngx_close_connection(c);
313
+
314
+ ngx_destroy_pool(pool);
315
+ }
316
+
317
+
318
+ static u_char *
319
+ ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len)
320
+ {
321
+ u_char *p;
322
+ ngx_stream_session_t *s;
323
+
324
+ if (log->action) {
325
+ p = ngx_snprintf(buf, len, " while %s", log->action);
326
+ len -= p - buf;
327
+ buf = p;
328
+ }
329
+
330
+ s = log->data;
331
+
332
+ p = ngx_snprintf(buf, len, ", %sclient: %V, server: %V",
333
+ s->connection->type == SOCK_DGRAM ? "udp " : "",
334
+ &s->connection->addr_text,
335
+ &s->connection->listening->addr_text);
336
+ len -= p - buf;
337
+ buf = p;
338
+
339
+ if (s->log_handler) {
340
+ p = s->log_handler(log, buf, len);
341
+ }
342
+
343
+ return p;
344
+ }
@@ -0,0 +1,632 @@
1
+
2
+ /*
3
+ * Copyright (C) Igor Sysoev
4
+ * Copyright (C) Nginx, Inc.
5
+ */
6
+
7
+
8
+ #include <ngx_config.h>
9
+ #include <ngx_core.h>
10
+ #include <ngx_stream.h>
11
+
12
+
13
+ typedef struct {
14
+ u_char color;
15
+ u_char len;
16
+ u_short conn;
17
+ u_char data[1];
18
+ } ngx_stream_limit_conn_node_t;
19
+
20
+
21
+ typedef struct {
22
+ ngx_shm_zone_t *shm_zone;
23
+ ngx_rbtree_node_t *node;
24
+ } ngx_stream_limit_conn_cleanup_t;
25
+
26
+
27
+ typedef struct {
28
+ ngx_rbtree_t *rbtree;
29
+ } ngx_stream_limit_conn_ctx_t;
30
+
31
+
32
+ typedef struct {
33
+ ngx_shm_zone_t *shm_zone;
34
+ ngx_uint_t conn;
35
+ } ngx_stream_limit_conn_limit_t;
36
+
37
+
38
+ typedef struct {
39
+ ngx_array_t limits;
40
+ ngx_uint_t log_level;
41
+ } ngx_stream_limit_conn_conf_t;
42
+
43
+
44
+ static ngx_rbtree_node_t *ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree,
45
+ ngx_str_t *key, uint32_t hash);
46
+ static void ngx_stream_limit_conn_cleanup(void *data);
47
+ static ngx_inline void ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool);
48
+
49
+ static void *ngx_stream_limit_conn_create_conf(ngx_conf_t *cf);
50
+ static char *ngx_stream_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
51
+ void *child);
52
+ static char *ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd,
53
+ void *conf);
54
+ static char *ngx_stream_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
55
+ void *conf);
56
+ static ngx_int_t ngx_stream_limit_conn_init(ngx_conf_t *cf);
57
+
58
+
59
+ static ngx_conf_enum_t ngx_stream_limit_conn_log_levels[] = {
60
+ { ngx_string("info"), NGX_LOG_INFO },
61
+ { ngx_string("notice"), NGX_LOG_NOTICE },
62
+ { ngx_string("warn"), NGX_LOG_WARN },
63
+ { ngx_string("error"), NGX_LOG_ERR },
64
+ { ngx_null_string, 0 }
65
+ };
66
+
67
+
68
+ static ngx_command_t ngx_stream_limit_conn_commands[] = {
69
+
70
+ { ngx_string("limit_conn_zone"),
71
+ NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE2,
72
+ ngx_stream_limit_conn_zone,
73
+ 0,
74
+ 0,
75
+ NULL },
76
+
77
+ { ngx_string("limit_conn"),
78
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
79
+ ngx_stream_limit_conn,
80
+ NGX_STREAM_SRV_CONF_OFFSET,
81
+ 0,
82
+ NULL },
83
+
84
+ { ngx_string("limit_conn_log_level"),
85
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
86
+ ngx_conf_set_enum_slot,
87
+ NGX_STREAM_SRV_CONF_OFFSET,
88
+ offsetof(ngx_stream_limit_conn_conf_t, log_level),
89
+ &ngx_stream_limit_conn_log_levels },
90
+
91
+ ngx_null_command
92
+ };
93
+
94
+
95
+ static ngx_stream_module_t ngx_stream_limit_conn_module_ctx = {
96
+ ngx_stream_limit_conn_init, /* postconfiguration */
97
+
98
+ NULL, /* create main configuration */
99
+ NULL, /* init main configuration */
100
+
101
+ ngx_stream_limit_conn_create_conf, /* create server configuration */
102
+ ngx_stream_limit_conn_merge_conf, /* merge server configuration */
103
+ };
104
+
105
+
106
+ ngx_module_t ngx_stream_limit_conn_module = {
107
+ NGX_MODULE_V1,
108
+ &ngx_stream_limit_conn_module_ctx, /* module context */
109
+ ngx_stream_limit_conn_commands, /* module directives */
110
+ NGX_STREAM_MODULE, /* module type */
111
+ NULL, /* init master */
112
+ NULL, /* init module */
113
+ NULL, /* init process */
114
+ NULL, /* init thread */
115
+ NULL, /* exit thread */
116
+ NULL, /* exit process */
117
+ NULL, /* exit master */
118
+ NGX_MODULE_V1_PADDING
119
+ };
120
+
121
+
122
+ static ngx_int_t
123
+ ngx_stream_limit_conn_handler(ngx_stream_session_t *s)
124
+ {
125
+ size_t n;
126
+ uint32_t hash;
127
+ ngx_str_t key;
128
+ ngx_uint_t i;
129
+ ngx_slab_pool_t *shpool;
130
+ ngx_rbtree_node_t *node;
131
+ ngx_pool_cleanup_t *cln;
132
+ struct sockaddr_in *sin;
133
+ #if (NGX_HAVE_INET6)
134
+ struct sockaddr_in6 *sin6;
135
+ #endif
136
+ ngx_stream_limit_conn_ctx_t *ctx;
137
+ ngx_stream_limit_conn_node_t *lc;
138
+ ngx_stream_limit_conn_conf_t *lccf;
139
+ ngx_stream_limit_conn_limit_t *limits;
140
+ ngx_stream_limit_conn_cleanup_t *lccln;
141
+
142
+ switch (s->connection->sockaddr->sa_family) {
143
+
144
+ case AF_INET:
145
+ sin = (struct sockaddr_in *) s->connection->sockaddr;
146
+
147
+ key.len = sizeof(in_addr_t);
148
+ key.data = (u_char *) &sin->sin_addr;
149
+
150
+ break;
151
+
152
+ #if (NGX_HAVE_INET6)
153
+ case AF_INET6:
154
+ sin6 = (struct sockaddr_in6 *) s->connection->sockaddr;
155
+
156
+ key.len = sizeof(struct in6_addr);
157
+ key.data = sin6->sin6_addr.s6_addr;
158
+
159
+ break;
160
+ #endif
161
+
162
+ default:
163
+ return NGX_DECLINED;
164
+ }
165
+
166
+ hash = ngx_crc32_short(key.data, key.len);
167
+
168
+ lccf = ngx_stream_get_module_srv_conf(s, ngx_stream_limit_conn_module);
169
+ limits = lccf->limits.elts;
170
+
171
+ for (i = 0; i < lccf->limits.nelts; i++) {
172
+ ctx = limits[i].shm_zone->data;
173
+
174
+ shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
175
+
176
+ ngx_shmtx_lock(&shpool->mutex);
177
+
178
+ node = ngx_stream_limit_conn_lookup(ctx->rbtree, &key, hash);
179
+
180
+ if (node == NULL) {
181
+
182
+ n = offsetof(ngx_rbtree_node_t, color)
183
+ + offsetof(ngx_stream_limit_conn_node_t, data)
184
+ + key.len;
185
+
186
+ node = ngx_slab_alloc_locked(shpool, n);
187
+
188
+ if (node == NULL) {
189
+ ngx_shmtx_unlock(&shpool->mutex);
190
+ ngx_stream_limit_conn_cleanup_all(s->connection->pool);
191
+ return NGX_ABORT;
192
+ }
193
+
194
+ lc = (ngx_stream_limit_conn_node_t *) &node->color;
195
+
196
+ node->key = hash;
197
+ lc->len = (u_char) key.len;
198
+ lc->conn = 1;
199
+ ngx_memcpy(lc->data, key.data, key.len);
200
+
201
+ ngx_rbtree_insert(ctx->rbtree, node);
202
+
203
+ } else {
204
+
205
+ lc = (ngx_stream_limit_conn_node_t *) &node->color;
206
+
207
+ if ((ngx_uint_t) lc->conn >= limits[i].conn) {
208
+
209
+ ngx_shmtx_unlock(&shpool->mutex);
210
+
211
+ ngx_log_error(lccf->log_level, s->connection->log, 0,
212
+ "limiting connections by zone \"%V\"",
213
+ &limits[i].shm_zone->shm.name);
214
+
215
+ ngx_stream_limit_conn_cleanup_all(s->connection->pool);
216
+ return NGX_ABORT;
217
+ }
218
+
219
+ lc->conn++;
220
+ }
221
+
222
+ ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
223
+ "limit conn: %08Xi %d", node->key, lc->conn);
224
+
225
+ ngx_shmtx_unlock(&shpool->mutex);
226
+
227
+ cln = ngx_pool_cleanup_add(s->connection->pool,
228
+ sizeof(ngx_stream_limit_conn_cleanup_t));
229
+ if (cln == NULL) {
230
+ return NGX_ERROR;
231
+ }
232
+
233
+ cln->handler = ngx_stream_limit_conn_cleanup;
234
+ lccln = cln->data;
235
+
236
+ lccln->shm_zone = limits[i].shm_zone;
237
+ lccln->node = node;
238
+ }
239
+
240
+ return NGX_DECLINED;
241
+ }
242
+
243
+
244
+ static void
245
+ ngx_stream_limit_conn_rbtree_insert_value(ngx_rbtree_node_t *temp,
246
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
247
+ {
248
+ ngx_rbtree_node_t **p;
249
+ ngx_stream_limit_conn_node_t *lcn, *lcnt;
250
+
251
+ for ( ;; ) {
252
+
253
+ if (node->key < temp->key) {
254
+
255
+ p = &temp->left;
256
+
257
+ } else if (node->key > temp->key) {
258
+
259
+ p = &temp->right;
260
+
261
+ } else { /* node->key == temp->key */
262
+
263
+ lcn = (ngx_stream_limit_conn_node_t *) &node->color;
264
+ lcnt = (ngx_stream_limit_conn_node_t *) &temp->color;
265
+
266
+ p = (ngx_memn2cmp(lcn->data, lcnt->data, lcn->len, lcnt->len) < 0)
267
+ ? &temp->left : &temp->right;
268
+ }
269
+
270
+ if (*p == sentinel) {
271
+ break;
272
+ }
273
+
274
+ temp = *p;
275
+ }
276
+
277
+ *p = node;
278
+ node->parent = temp;
279
+ node->left = sentinel;
280
+ node->right = sentinel;
281
+ ngx_rbt_red(node);
282
+ }
283
+
284
+
285
+ static ngx_rbtree_node_t *
286
+ ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_str_t *key,
287
+ uint32_t hash)
288
+ {
289
+ ngx_int_t rc;
290
+ ngx_rbtree_node_t *node, *sentinel;
291
+ ngx_stream_limit_conn_node_t *lcn;
292
+
293
+ node = rbtree->root;
294
+ sentinel = rbtree->sentinel;
295
+
296
+ while (node != sentinel) {
297
+
298
+ if (hash < node->key) {
299
+ node = node->left;
300
+ continue;
301
+ }
302
+
303
+ if (hash > node->key) {
304
+ node = node->right;
305
+ continue;
306
+ }
307
+
308
+ /* hash == node->key */
309
+
310
+ lcn = (ngx_stream_limit_conn_node_t *) &node->color;
311
+
312
+ rc = ngx_memn2cmp(key->data, lcn->data, key->len, (size_t) lcn->len);
313
+
314
+ if (rc == 0) {
315
+ return node;
316
+ }
317
+
318
+ node = (rc < 0) ? node->left : node->right;
319
+ }
320
+
321
+ return NULL;
322
+ }
323
+
324
+
325
+ static void
326
+ ngx_stream_limit_conn_cleanup(void *data)
327
+ {
328
+ ngx_stream_limit_conn_cleanup_t *lccln = data;
329
+
330
+ ngx_slab_pool_t *shpool;
331
+ ngx_rbtree_node_t *node;
332
+ ngx_stream_limit_conn_ctx_t *ctx;
333
+ ngx_stream_limit_conn_node_t *lc;
334
+
335
+ ctx = lccln->shm_zone->data;
336
+ shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
337
+ node = lccln->node;
338
+ lc = (ngx_stream_limit_conn_node_t *) &node->color;
339
+
340
+ ngx_shmtx_lock(&shpool->mutex);
341
+
342
+ ngx_log_debug2(NGX_LOG_DEBUG_STREAM, lccln->shm_zone->shm.log, 0,
343
+ "limit conn cleanup: %08Xi %d", node->key, lc->conn);
344
+
345
+ lc->conn--;
346
+
347
+ if (lc->conn == 0) {
348
+ ngx_rbtree_delete(ctx->rbtree, node);
349
+ ngx_slab_free_locked(shpool, node);
350
+ }
351
+
352
+ ngx_shmtx_unlock(&shpool->mutex);
353
+ }
354
+
355
+
356
+ static ngx_inline void
357
+ ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool)
358
+ {
359
+ ngx_pool_cleanup_t *cln;
360
+
361
+ cln = pool->cleanup;
362
+
363
+ while (cln && cln->handler == ngx_stream_limit_conn_cleanup) {
364
+ ngx_stream_limit_conn_cleanup(cln->data);
365
+ cln = cln->next;
366
+ }
367
+
368
+ pool->cleanup = cln;
369
+ }
370
+
371
+
372
+ static ngx_int_t
373
+ ngx_stream_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
374
+ {
375
+ ngx_stream_limit_conn_ctx_t *octx = data;
376
+
377
+ size_t len;
378
+ ngx_slab_pool_t *shpool;
379
+ ngx_rbtree_node_t *sentinel;
380
+ ngx_stream_limit_conn_ctx_t *ctx;
381
+
382
+ ctx = shm_zone->data;
383
+
384
+ if (octx) {
385
+ ctx->rbtree = octx->rbtree;
386
+
387
+ return NGX_OK;
388
+ }
389
+
390
+ shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
391
+
392
+ if (shm_zone->shm.exists) {
393
+ ctx->rbtree = shpool->data;
394
+
395
+ return NGX_OK;
396
+ }
397
+
398
+ ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
399
+ if (ctx->rbtree == NULL) {
400
+ return NGX_ERROR;
401
+ }
402
+
403
+ shpool->data = ctx->rbtree;
404
+
405
+ sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
406
+ if (sentinel == NULL) {
407
+ return NGX_ERROR;
408
+ }
409
+
410
+ ngx_rbtree_init(ctx->rbtree, sentinel,
411
+ ngx_stream_limit_conn_rbtree_insert_value);
412
+
413
+ len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
414
+
415
+ shpool->log_ctx = ngx_slab_alloc(shpool, len);
416
+ if (shpool->log_ctx == NULL) {
417
+ return NGX_ERROR;
418
+ }
419
+
420
+ ngx_sprintf(shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
421
+ &shm_zone->shm.name);
422
+
423
+ return NGX_OK;
424
+ }
425
+
426
+
427
+ static void *
428
+ ngx_stream_limit_conn_create_conf(ngx_conf_t *cf)
429
+ {
430
+ ngx_stream_limit_conn_conf_t *conf;
431
+
432
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_limit_conn_conf_t));
433
+ if (conf == NULL) {
434
+ return NULL;
435
+ }
436
+
437
+ /*
438
+ * set by ngx_pcalloc():
439
+ *
440
+ * conf->limits.elts = NULL;
441
+ */
442
+
443
+ conf->log_level = NGX_CONF_UNSET_UINT;
444
+
445
+ return conf;
446
+ }
447
+
448
+
449
+ static char *
450
+ ngx_stream_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child)
451
+ {
452
+ ngx_stream_limit_conn_conf_t *prev = parent;
453
+ ngx_stream_limit_conn_conf_t *conf = child;
454
+
455
+ if (conf->limits.elts == NULL) {
456
+ conf->limits = prev->limits;
457
+ }
458
+
459
+ ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR);
460
+
461
+ return NGX_CONF_OK;
462
+ }
463
+
464
+
465
+ static char *
466
+ ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
467
+ {
468
+ u_char *p;
469
+ ssize_t size;
470
+ ngx_str_t *value, name, s;
471
+ ngx_uint_t i;
472
+ ngx_shm_zone_t *shm_zone;
473
+ ngx_stream_limit_conn_ctx_t *ctx;
474
+
475
+ value = cf->args->elts;
476
+
477
+ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_limit_conn_ctx_t));
478
+ if (ctx == NULL) {
479
+ return NGX_CONF_ERROR;
480
+ }
481
+
482
+ size = 0;
483
+ name.len = 0;
484
+
485
+ for (i = 2; i < cf->args->nelts; i++) {
486
+
487
+ if (ngx_strncmp(value[i].data, "zone=", 5) == 0) {
488
+
489
+ name.data = value[i].data + 5;
490
+
491
+ p = (u_char *) ngx_strchr(name.data, ':');
492
+
493
+ if (p == NULL) {
494
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
495
+ "invalid zone size \"%V\"", &value[i]);
496
+ return NGX_CONF_ERROR;
497
+ }
498
+
499
+ name.len = p - name.data;
500
+
501
+ s.data = p + 1;
502
+ s.len = value[i].data + value[i].len - s.data;
503
+
504
+ size = ngx_parse_size(&s);
505
+
506
+ if (size == NGX_ERROR) {
507
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
508
+ "invalid zone size \"%V\"", &value[i]);
509
+ return NGX_CONF_ERROR;
510
+ }
511
+
512
+ if (size < (ssize_t) (8 * ngx_pagesize)) {
513
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
514
+ "zone \"%V\" is too small", &value[i]);
515
+ return NGX_CONF_ERROR;
516
+ }
517
+
518
+ continue;
519
+ }
520
+
521
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
522
+ "invalid parameter \"%V\"", &value[i]);
523
+ return NGX_CONF_ERROR;
524
+ }
525
+
526
+ if (name.len == 0) {
527
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
528
+ "\"%V\" must have \"zone\" parameter",
529
+ &cmd->name);
530
+ return NGX_CONF_ERROR;
531
+ }
532
+
533
+ shm_zone = ngx_shared_memory_add(cf, &name, size,
534
+ &ngx_stream_limit_conn_module);
535
+ if (shm_zone == NULL) {
536
+ return NGX_CONF_ERROR;
537
+ }
538
+
539
+ if (shm_zone->data) {
540
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
541
+ "%V \"%V\" is already bound to key "
542
+ "\"$binary_remote_addr\"",
543
+ &cmd->name, &name);
544
+ return NGX_CONF_ERROR;
545
+ }
546
+
547
+ if (ngx_strcmp(value[1].data, "$binary_remote_addr") != 0) {
548
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
549
+ "unsupported key \"%V\", use "
550
+ "$binary_remote_addr", &value[1]);
551
+ return NGX_CONF_ERROR;
552
+ }
553
+
554
+ shm_zone->init = ngx_stream_limit_conn_init_zone;
555
+ shm_zone->data = ctx;
556
+
557
+ return NGX_CONF_OK;
558
+ }
559
+
560
+
561
+ static char *
562
+ ngx_stream_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
563
+ {
564
+ ngx_shm_zone_t *shm_zone;
565
+ ngx_stream_limit_conn_conf_t *lccf = conf;
566
+ ngx_stream_limit_conn_limit_t *limit, *limits;
567
+
568
+ ngx_str_t *value;
569
+ ngx_int_t n;
570
+ ngx_uint_t i;
571
+
572
+ value = cf->args->elts;
573
+
574
+ shm_zone = ngx_shared_memory_add(cf, &value[1], 0,
575
+ &ngx_stream_limit_conn_module);
576
+ if (shm_zone == NULL) {
577
+ return NGX_CONF_ERROR;
578
+ }
579
+
580
+ limits = lccf->limits.elts;
581
+
582
+ if (limits == NULL) {
583
+ if (ngx_array_init(&lccf->limits, cf->pool, 1,
584
+ sizeof(ngx_stream_limit_conn_limit_t))
585
+ != NGX_OK)
586
+ {
587
+ return NGX_CONF_ERROR;
588
+ }
589
+ }
590
+
591
+ for (i = 0; i < lccf->limits.nelts; i++) {
592
+ if (shm_zone == limits[i].shm_zone) {
593
+ return "is duplicate";
594
+ }
595
+ }
596
+
597
+ n = ngx_atoi(value[2].data, value[2].len);
598
+ if (n <= 0) {
599
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
600
+ "invalid number of connections \"%V\"", &value[2]);
601
+ return NGX_CONF_ERROR;
602
+ }
603
+
604
+ if (n > 65535) {
605
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
606
+ "connection limit must be less 65536");
607
+ return NGX_CONF_ERROR;
608
+ }
609
+
610
+ limit = ngx_array_push(&lccf->limits);
611
+ if (limit == NULL) {
612
+ return NGX_CONF_ERROR;
613
+ }
614
+
615
+ limit->conn = n;
616
+ limit->shm_zone = shm_zone;
617
+
618
+ return NGX_CONF_OK;
619
+ }
620
+
621
+
622
+ static ngx_int_t
623
+ ngx_stream_limit_conn_init(ngx_conf_t *cf)
624
+ {
625
+ ngx_stream_core_main_conf_t *cmcf;
626
+
627
+ cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
628
+
629
+ cmcf->limit_conn_handler = ngx_stream_limit_conn_handler;
630
+
631
+ return NGX_OK;
632
+ }