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
@@ -7,13 +7,12 @@
7
7
 
8
8
  #include <ngx_config.h>
9
9
  #include <ngx_core.h>
10
- #include <ngx_http.h>
11
10
 
12
11
 
13
12
  static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
14
13
 
15
14
  time_t
16
- ngx_http_parse_time(u_char *value, size_t len)
15
+ ngx_parse_http_time(u_char *value, size_t len)
17
16
  {
18
17
  u_char *p, *end;
19
18
  ngx_int_t month;
@@ -221,7 +220,7 @@ ngx_http_parse_time(u_char *value, size_t len)
221
220
  }
222
221
 
223
222
  if (hour > 23 || min > 59 || sec > 59) {
224
- return NGX_ERROR;
223
+ return NGX_ERROR;
225
224
  }
226
225
 
227
226
  if (day == 29 && month == 1) {
@@ -0,0 +1,22 @@
1
+
2
+ /*
3
+ * Copyright (C) Igor Sysoev
4
+ * Copyright (C) Nginx, Inc.
5
+ */
6
+
7
+
8
+ #ifndef _NGX_PARSE_TIME_H_INCLUDED_
9
+ #define _NGX_PARSE_TIME_H_INCLUDED_
10
+
11
+
12
+ #include <ngx_config.h>
13
+ #include <ngx_core.h>
14
+
15
+
16
+ time_t ngx_parse_http_time(u_char *value, size_t len);
17
+
18
+ /* compatibility */
19
+ #define ngx_http_parse_time(value, len) ngx_parse_http_time(value, len)
20
+
21
+
22
+ #endif /* _NGX_PARSE_TIME_H_INCLUDED_ */
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  u_char *
13
- ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
13
+ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
14
14
  {
15
15
  size_t len;
16
16
  u_char ch, *p, *addr;
@@ -89,3 +89,52 @@ invalid:
89
89
 
90
90
  return NULL;
91
91
  }
92
+
93
+
94
+ u_char *
95
+ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
96
+ {
97
+ ngx_uint_t port, lport;
98
+
99
+ if (last - buf < NGX_PROXY_PROTOCOL_MAX_HEADER) {
100
+ return NULL;
101
+ }
102
+
103
+ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
104
+ return NULL;
105
+ }
106
+
107
+ switch (c->sockaddr->sa_family) {
108
+
109
+ case AF_INET:
110
+ buf = ngx_cpymem(buf, "PROXY TCP4 ", sizeof("PROXY TCP4 ") - 1);
111
+
112
+ port = ntohs(((struct sockaddr_in *) c->sockaddr)->sin_port);
113
+ lport = ntohs(((struct sockaddr_in *) c->local_sockaddr)->sin_port);
114
+
115
+ break;
116
+
117
+ #if (NGX_HAVE_INET6)
118
+ case AF_INET6:
119
+ buf = ngx_cpymem(buf, "PROXY TCP6 ", sizeof("PROXY TCP6 ") - 1);
120
+
121
+ port = ntohs(((struct sockaddr_in6 *) c->sockaddr)->sin6_port);
122
+ lport = ntohs(((struct sockaddr_in6 *) c->local_sockaddr)->sin6_port);
123
+
124
+ break;
125
+ #endif
126
+
127
+ default:
128
+ return ngx_cpymem(buf, "PROXY UNKNOWN" CRLF,
129
+ sizeof("PROXY UNKNOWN" CRLF) - 1);
130
+ }
131
+
132
+ buf += ngx_sock_ntop(c->sockaddr, c->socklen, buf, last - buf, 0);
133
+
134
+ *buf++ = ' ';
135
+
136
+ buf += ngx_sock_ntop(c->local_sockaddr, c->local_socklen, buf, last - buf,
137
+ 0);
138
+
139
+ return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport);
140
+ }
@@ -16,7 +16,9 @@
16
16
  #define NGX_PROXY_PROTOCOL_MAX_HEADER 107
17
17
 
18
18
 
19
- u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf,
19
+ u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
20
+ u_char *last);
21
+ u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
20
22
  u_char *last);
21
23
 
22
24
 
@@ -32,7 +32,7 @@ static ngx_conf_post_t ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };
32
32
  static ngx_command_t ngx_regex_commands[] = {
33
33
 
34
34
  { ngx_string("pcre_jit"),
35
- NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
35
+ NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
36
36
  ngx_conf_set_flag_slot,
37
37
  0,
38
38
  offsetof(ngx_regex_conf_t, pcre_jit),
@@ -80,17 +80,6 @@ ngx_regex_init(void)
80
80
  static ngx_inline void
81
81
  ngx_regex_malloc_init(ngx_pool_t *pool)
82
82
  {
83
- #if (NGX_OLD_THREADS)
84
- ngx_core_tls_t *tls;
85
-
86
- if (ngx_threaded) {
87
- tls = ngx_thread_get_tls(ngx_core_tls_key);
88
- tls->pool = pool;
89
- return;
90
- }
91
-
92
- #endif
93
-
94
83
  ngx_pcre_pool = pool;
95
84
  }
96
85
 
@@ -98,17 +87,6 @@ ngx_regex_malloc_init(ngx_pool_t *pool)
98
87
  static ngx_inline void
99
88
  ngx_regex_malloc_done(void)
100
89
  {
101
- #if (NGX_OLD_THREADS)
102
- ngx_core_tls_t *tls;
103
-
104
- if (ngx_threaded) {
105
- tls = ngx_thread_get_tls(ngx_core_tls_key);
106
- tls->pool = NULL;
107
- return;
108
- }
109
-
110
- #endif
111
-
112
90
  ngx_pcre_pool = NULL;
113
91
  }
114
92
 
@@ -253,23 +231,8 @@ static void * ngx_libc_cdecl
253
231
  ngx_regex_malloc(size_t size)
254
232
  {
255
233
  ngx_pool_t *pool;
256
- #if (NGX_OLD_THREADS)
257
- ngx_core_tls_t *tls;
258
-
259
- if (ngx_threaded) {
260
- tls = ngx_thread_get_tls(ngx_core_tls_key);
261
- pool = tls->pool;
262
-
263
- } else {
264
- pool = ngx_pcre_pool;
265
- }
266
-
267
- #else
268
-
269
234
  pool = ngx_pcre_pool;
270
235
 
271
- #endif
272
-
273
236
  if (pool) {
274
237
  return ngx_palloc(pool, size);
275
238
  }
@@ -12,6 +12,9 @@
12
12
 
13
13
  #define NGX_RESOLVER_UDP_SIZE 4096
14
14
 
15
+ #define NGX_RESOLVER_TCP_RSIZE (2 + 65535)
16
+ #define NGX_RESOLVER_TCP_WSIZE 8192
17
+
15
18
 
16
19
  typedef struct {
17
20
  u_char ident_hi;
@@ -53,7 +56,8 @@ typedef struct {
53
56
  ((u_char *) (n) - offsetof(ngx_resolver_node_t, node))
54
57
 
55
58
 
56
- ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc);
59
+ ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec);
60
+ ngx_int_t ngx_tcp_connect(ngx_resolver_connection_t *rec);
57
61
 
58
62
 
59
63
  static void ngx_resolver_cleanup(void *data);
@@ -64,23 +68,37 @@ static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree,
64
68
  ngx_queue_t *queue);
65
69
  static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r,
66
70
  ngx_resolver_node_t *rn);
71
+ static ngx_int_t ngx_resolver_send_udp_query(ngx_resolver_t *r,
72
+ ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
73
+ static ngx_int_t ngx_resolver_send_tcp_query(ngx_resolver_t *r,
74
+ ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
67
75
  static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r,
68
76
  ngx_resolver_node_t *rn, ngx_str_t *name);
77
+ static ngx_int_t ngx_resolver_create_srv_query(ngx_resolver_t *r,
78
+ ngx_resolver_node_t *rn, ngx_str_t *name);
69
79
  static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r,
70
- ngx_resolver_node_t *rn, ngx_addr_t *addr);
80
+ ngx_resolver_node_t *rn, ngx_resolver_addr_t *addr);
71
81
  static void ngx_resolver_resend_handler(ngx_event_t *ev);
72
82
  static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree,
73
83
  ngx_queue_t *queue);
74
- static void ngx_resolver_read_response(ngx_event_t *rev);
84
+ static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r);
85
+ static void ngx_resolver_udp_read(ngx_event_t *rev);
86
+ static void ngx_resolver_tcp_write(ngx_event_t *wev);
87
+ static void ngx_resolver_tcp_read(ngx_event_t *rev);
75
88
  static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
76
- size_t n);
89
+ size_t n, ngx_uint_t tcp);
77
90
  static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
78
91
  ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
79
- ngx_uint_t nan, ngx_uint_t ans);
92
+ ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans);
93
+ static void ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
94
+ ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
95
+ ngx_uint_t trunc, ngx_uint_t ans);
80
96
  static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
81
97
  ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
82
98
  static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
83
99
  ngx_str_t *name, uint32_t hash);
100
+ static ngx_resolver_node_t *ngx_resolver_lookup_srv(ngx_resolver_t *r,
101
+ ngx_str_t *name, uint32_t hash);
84
102
  static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
85
103
  in_addr_t addr);
86
104
  static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
@@ -94,9 +112,14 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
94
112
  static void ngx_resolver_free(ngx_resolver_t *r, void *p);
95
113
  static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
96
114
  static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
97
- static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r,
115
+ static ngx_resolver_addr_t *ngx_resolver_export(ngx_resolver_t *r,
98
116
  ngx_resolver_node_t *rn, ngx_uint_t rotate);
117
+ static void ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx);
99
118
  static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
119
+ static void ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx,
120
+ ngx_resolver_node_t *rn);
121
+ static void ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *ctx);
122
+ static ngx_int_t ngx_resolver_cmp_srvs(const void *one, const void *two);
100
123
 
101
124
  #if (NGX_HAVE_INET6)
102
125
  static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
@@ -109,12 +132,12 @@ static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
109
132
  ngx_resolver_t *
110
133
  ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
111
134
  {
112
- ngx_str_t s;
113
- ngx_url_t u;
114
- ngx_uint_t i, j;
115
- ngx_resolver_t *r;
116
- ngx_pool_cleanup_t *cln;
117
- ngx_udp_connection_t *uc;
135
+ ngx_str_t s;
136
+ ngx_url_t u;
137
+ ngx_uint_t i, j;
138
+ ngx_resolver_t *r;
139
+ ngx_pool_cleanup_t *cln;
140
+ ngx_resolver_connection_t *rec;
118
141
 
119
142
  cln = ngx_pool_cleanup_add(cf->pool, 0);
120
143
  if (cln == NULL) {
@@ -138,13 +161,18 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
138
161
  ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
139
162
  ngx_resolver_rbtree_insert_value);
140
163
 
164
+ ngx_rbtree_init(&r->srv_rbtree, &r->srv_sentinel,
165
+ ngx_resolver_rbtree_insert_value);
166
+
141
167
  ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,
142
168
  ngx_rbtree_insert_value);
143
169
 
144
170
  ngx_queue_init(&r->name_resend_queue);
171
+ ngx_queue_init(&r->srv_resend_queue);
145
172
  ngx_queue_init(&r->addr_resend_queue);
146
173
 
147
174
  ngx_queue_init(&r->name_expire_queue);
175
+ ngx_queue_init(&r->srv_expire_queue);
148
176
  ngx_queue_init(&r->addr_expire_queue);
149
177
 
150
178
  #if (NGX_HAVE_INET6)
@@ -164,6 +192,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
164
192
  r->ident = -1;
165
193
 
166
194
  r->resend_timeout = 5;
195
+ r->tcp_timeout = 5;
167
196
  r->expire = 30;
168
197
  r->valid = 0;
169
198
 
@@ -171,8 +200,8 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
171
200
  r->log_level = NGX_LOG_ERR;
172
201
 
173
202
  if (n) {
174
- if (ngx_array_init(&r->udp_connections, cf->pool, n,
175
- sizeof(ngx_udp_connection_t))
203
+ if (ngx_array_init(&r->connections, cf->pool, n,
204
+ sizeof(ngx_resolver_connection_t))
176
205
  != NGX_OK)
177
206
  {
178
207
  return NULL;
@@ -229,17 +258,18 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
229
258
  return NULL;
230
259
  }
231
260
 
232
- uc = ngx_array_push_n(&r->udp_connections, u.naddrs);
233
- if (uc == NULL) {
261
+ rec = ngx_array_push_n(&r->connections, u.naddrs);
262
+ if (rec == NULL) {
234
263
  return NULL;
235
264
  }
236
265
 
237
- ngx_memzero(uc, u.naddrs * sizeof(ngx_udp_connection_t));
266
+ ngx_memzero(rec, u.naddrs * sizeof(ngx_resolver_connection_t));
238
267
 
239
268
  for (j = 0; j < u.naddrs; j++) {
240
- uc[j].sockaddr = u.addrs[j].sockaddr;
241
- uc[j].socklen = u.addrs[j].socklen;
242
- uc[j].server = u.addrs[j].name;
269
+ rec[j].sockaddr = u.addrs[j].sockaddr;
270
+ rec[j].socklen = u.addrs[j].socklen;
271
+ rec[j].server = u.addrs[j].name;
272
+ rec[j].resolver = r;
243
273
  }
244
274
  }
245
275
 
@@ -252,8 +282,8 @@ ngx_resolver_cleanup(void *data)
252
282
  {
253
283
  ngx_resolver_t *r = data;
254
284
 
255
- ngx_uint_t i;
256
- ngx_udp_connection_t *uc;
285
+ ngx_uint_t i;
286
+ ngx_resolver_connection_t *rec;
257
287
 
258
288
  if (r) {
259
289
  ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
@@ -261,6 +291,8 @@ ngx_resolver_cleanup(void *data)
261
291
 
262
292
  ngx_resolver_cleanup_tree(r, &r->name_rbtree);
263
293
 
294
+ ngx_resolver_cleanup_tree(r, &r->srv_rbtree);
295
+
264
296
  ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
265
297
 
266
298
  #if (NGX_HAVE_INET6)
@@ -272,11 +304,25 @@ ngx_resolver_cleanup(void *data)
272
304
  }
273
305
 
274
306
 
275
- uc = r->udp_connections.elts;
307
+ rec = r->connections.elts;
308
+
309
+ for (i = 0; i < r->connections.nelts; i++) {
310
+ if (rec[i].udp) {
311
+ ngx_close_connection(rec[i].udp);
312
+ }
313
+
314
+ if (rec[i].tcp) {
315
+ ngx_close_connection(rec[i].tcp);
316
+ }
317
+
318
+ if (rec[i].read_buf) {
319
+ ngx_resolver_free(r, rec[i].read_buf->start);
320
+ ngx_resolver_free(r, rec[i].read_buf);
321
+ }
276
322
 
277
- for (i = 0; i < r->udp_connections.nelts; i++) {
278
- if (uc[i].connection) {
279
- ngx_close_connection(uc[i].connection);
323
+ if (rec[i].write_buf) {
324
+ ngx_resolver_free(r, rec[i].write_buf->start);
325
+ ngx_resolver_free(r, rec[i].write_buf);
280
326
  }
281
327
  }
282
328
 
@@ -339,7 +385,7 @@ ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
339
385
  }
340
386
  }
341
387
 
342
- if (r->udp_connections.nelts == 0) {
388
+ if (r->connections.nelts == 0) {
343
389
  return NGX_NO_RESOLVER;
344
390
  }
345
391
 
@@ -356,7 +402,9 @@ ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
356
402
  ngx_int_t
357
403
  ngx_resolve_name(ngx_resolver_ctx_t *ctx)
358
404
  {
405
+ size_t slen;
359
406
  ngx_int_t rc;
407
+ ngx_str_t name;
360
408
  ngx_resolver_t *r;
361
409
 
362
410
  r = ctx->resolver;
@@ -373,9 +421,41 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx)
373
421
  return NGX_OK;
374
422
  }
375
423
 
376
- /* lock name mutex */
424
+ if (ctx->service.len) {
425
+ slen = ctx->service.len;
426
+
427
+ if (ngx_strlchr(ctx->service.data,
428
+ ctx->service.data + ctx->service.len, '.')
429
+ == NULL)
430
+ {
431
+ slen += sizeof("_._tcp") - 1;
432
+ }
433
+
434
+ name.len = slen + 1 + ctx->name.len;
435
+
436
+ name.data = ngx_resolver_alloc(r, name.len);
437
+ if (name.data == NULL) {
438
+ return NGX_ERROR;
439
+ }
440
+
441
+ if (slen == ctx->service.len) {
442
+ ngx_sprintf(name.data, "%V.%V", &ctx->service, &ctx->name);
443
+
444
+ } else {
445
+ ngx_sprintf(name.data, "_%V._tcp.%V", &ctx->service, &ctx->name);
446
+ }
447
+
448
+ /* lock name mutex */
449
+
450
+ rc = ngx_resolve_name_locked(r, ctx, &name);
451
+
452
+ ngx_resolver_free(r, name.data);
453
+
454
+ } else {
455
+ /* lock name mutex */
377
456
 
378
- rc = ngx_resolve_name_locked(r, ctx, &ctx->name);
457
+ rc = ngx_resolve_name_locked(r, ctx, &ctx->name);
458
+ }
379
459
 
380
460
  if (rc == NGX_OK) {
381
461
  return NGX_OK;
@@ -402,6 +482,7 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx)
402
482
  void
403
483
  ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
404
484
  {
485
+ ngx_uint_t i;
405
486
  ngx_resolver_t *r;
406
487
  ngx_resolver_ctx_t *w, **p;
407
488
  ngx_resolver_node_t *rn;
@@ -421,6 +502,23 @@ ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
421
502
 
422
503
  /* lock name mutex */
423
504
 
505
+ if (ctx->nsrvs) {
506
+ for (i = 0; i < ctx->nsrvs; i++) {
507
+ if (ctx->srvs[i].ctx) {
508
+ ngx_resolve_name_done(ctx->srvs[i].ctx);
509
+ }
510
+
511
+ if (ctx->srvs[i].addrs) {
512
+ ngx_resolver_free(r, ctx->srvs[i].addrs->sockaddr);
513
+ ngx_resolver_free(r, ctx->srvs[i].addrs);
514
+ }
515
+
516
+ ngx_resolver_free(r, ctx->srvs[i].name.data);
517
+ }
518
+
519
+ ngx_resolver_free(r, ctx->srvs);
520
+ }
521
+
424
522
  if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
425
523
 
426
524
  rn = ctx->node;
@@ -439,15 +537,20 @@ ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
439
537
  p = &w->next;
440
538
  w = w->next;
441
539
  }
442
- }
443
540
 
444
- ngx_log_error(NGX_LOG_ALERT, r->log, 0,
445
- "could not cancel %V resolving", &ctx->name);
541
+ ngx_log_error(NGX_LOG_ALERT, r->log, 0,
542
+ "could not cancel %V resolving", &ctx->name);
543
+ }
446
544
  }
447
545
 
448
546
  done:
449
547
 
450
- ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue);
548
+ if (ctx->service.len) {
549
+ ngx_resolver_expire(r, &r->srv_rbtree, &r->srv_expire_queue);
550
+
551
+ } else {
552
+ ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue);
553
+ }
451
554
 
452
555
  /* unlock name mutex */
453
556
 
@@ -460,6 +563,10 @@ done:
460
563
  ngx_resolver_free_locked(r, ctx);
461
564
 
462
565
  /* unlock alloc mutex */
566
+
567
+ if (r->event->timer_set && ngx_resolver_resend_empty(r)) {
568
+ ngx_del_timer(r->event);
569
+ }
463
570
  }
464
571
 
465
572
 
@@ -470,16 +577,31 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
470
577
  uint32_t hash;
471
578
  ngx_int_t rc;
472
579
  ngx_str_t cname;
473
- ngx_uint_t naddrs;
474
- ngx_addr_t *addrs;
580
+ ngx_uint_t i, naddrs;
581
+ ngx_queue_t *resend_queue, *expire_queue;
582
+ ngx_rbtree_t *tree;
475
583
  ngx_resolver_ctx_t *next, *last;
584
+ ngx_resolver_addr_t *addrs;
476
585
  ngx_resolver_node_t *rn;
477
586
 
478
587
  ngx_strlow(name->data, name->data, name->len);
479
588
 
480
589
  hash = ngx_crc32_short(name->data, name->len);
481
590
 
482
- rn = ngx_resolver_lookup_name(r, name, hash);
591
+ if (ctx->service.len) {
592
+ rn = ngx_resolver_lookup_srv(r, name, hash);
593
+
594
+ tree = &r->srv_rbtree;
595
+ resend_queue = &r->srv_resend_queue;
596
+ expire_queue = &r->srv_expire_queue;
597
+
598
+ } else {
599
+ rn = ngx_resolver_lookup_name(r, name, hash);
600
+
601
+ tree = &r->name_rbtree;
602
+ resend_queue = &r->name_resend_queue;
603
+ expire_queue = &r->name_expire_queue;
604
+ }
483
605
 
484
606
  if (rn) {
485
607
 
@@ -494,7 +616,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
494
616
 
495
617
  rn->expire = ngx_time() + r->expire;
496
618
 
497
- ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
619
+ ngx_queue_insert_head(expire_queue, &rn->queue);
498
620
 
499
621
  naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
500
622
  #if (NGX_HAVE_INET6)
@@ -520,6 +642,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
520
642
 
521
643
  do {
522
644
  ctx->state = NGX_OK;
645
+ ctx->valid = rn->valid;
523
646
  ctx->naddrs = naddrs;
524
647
 
525
648
  if (addrs == NULL) {
@@ -549,6 +672,23 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
549
672
  return NGX_OK;
550
673
  }
551
674
 
675
+ if (rn->nsrvs) {
676
+ last->next = rn->waiting;
677
+ rn->waiting = NULL;
678
+
679
+ /* unlock name mutex */
680
+
681
+ do {
682
+ next = ctx->next;
683
+
684
+ ngx_resolver_resolve_srv_names(ctx, rn);
685
+
686
+ ctx = next;
687
+ } while (ctx);
688
+
689
+ return NGX_OK;
690
+ }
691
+
552
692
  /* NGX_RESOLVE_CNAME */
553
693
 
554
694
  if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) {
@@ -566,6 +706,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
566
706
 
567
707
  do {
568
708
  ctx->state = NGX_RESOLVE_NXDOMAIN;
709
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
569
710
  next = ctx->next;
570
711
 
571
712
  ctx->handler(ctx);
@@ -578,7 +719,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
578
719
 
579
720
  if (rn->waiting) {
580
721
 
581
- if (ctx->event == NULL) {
722
+ if (ctx->event == NULL && ctx->timeout) {
582
723
  ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
583
724
  if (ctx->event == NULL) {
584
725
  return NGX_ERROR;
@@ -630,6 +771,16 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
630
771
  }
631
772
  #endif
632
773
 
774
+ if (rn->nsrvs) {
775
+ for (i = 0; i < rn->nsrvs; i++) {
776
+ if (rn->u.srvs[i].name.data) {
777
+ ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
778
+ }
779
+ }
780
+
781
+ ngx_resolver_free_locked(r, rn->u.srvs);
782
+ }
783
+
633
784
  /* unlock alloc mutex */
634
785
 
635
786
  } else {
@@ -652,17 +803,22 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
652
803
  rn->query6 = NULL;
653
804
  #endif
654
805
 
655
- ngx_rbtree_insert(&r->name_rbtree, &rn->node);
806
+ ngx_rbtree_insert(tree, &rn->node);
656
807
  }
657
808
 
658
- rc = ngx_resolver_create_name_query(r, rn, name);
809
+ if (ctx->service.len) {
810
+ rc = ngx_resolver_create_srv_query(r, rn, name);
811
+
812
+ } else {
813
+ rc = ngx_resolver_create_name_query(r, rn, name);
814
+ }
659
815
 
660
816
  if (rc == NGX_ERROR) {
661
817
  goto failed;
662
818
  }
663
819
 
664
820
  if (rc == NGX_DECLINED) {
665
- ngx_rbtree_delete(&r->name_rbtree, &rn->node);
821
+ ngx_rbtree_delete(tree, &rn->node);
666
822
 
667
823
  ngx_resolver_free(r, rn->query);
668
824
  ngx_resolver_free(r, rn->name);
@@ -680,16 +836,24 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
680
836
  return NGX_OK;
681
837
  }
682
838
 
839
+ rn->last_connection = r->last_connection++;
840
+ if (r->last_connection == r->connections.nelts) {
841
+ r->last_connection = 0;
842
+ }
843
+
683
844
  rn->naddrs = (u_short) -1;
845
+ rn->tcp = 0;
684
846
  #if (NGX_HAVE_INET6)
685
847
  rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
848
+ rn->tcp6 = 0;
686
849
  #endif
850
+ rn->nsrvs = 0;
687
851
 
688
852
  if (ngx_resolver_send_query(r, rn) != NGX_OK) {
689
853
  goto failed;
690
854
  }
691
855
 
692
- if (ctx->event == NULL) {
856
+ if (ctx->event == NULL && ctx->timeout) {
693
857
  ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
694
858
  if (ctx->event == NULL) {
695
859
  goto failed;
@@ -703,13 +867,13 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
703
867
  ngx_add_timer(ctx->event, ctx->timeout);
704
868
  }
705
869
 
706
- if (ngx_queue_empty(&r->name_resend_queue)) {
870
+ if (ngx_queue_empty(resend_queue)) {
707
871
  ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
708
872
  }
709
873
 
710
874
  rn->expire = ngx_time() + r->resend_timeout;
711
875
 
712
- ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);
876
+ ngx_queue_insert_head(resend_queue, &rn->queue);
713
877
 
714
878
  rn->code = 0;
715
879
  rn->cnlen = 0;
@@ -728,7 +892,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
728
892
 
729
893
  failed:
730
894
 
731
- ngx_rbtree_delete(&r->name_rbtree, &rn->node);
895
+ ngx_rbtree_delete(tree, &rn->node);
732
896
 
733
897
  if (rn->query) {
734
898
  ngx_resolver_free(r, rn->query);
@@ -821,6 +985,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
821
985
  /* unlock addr mutex */
822
986
 
823
987
  ctx->state = NGX_OK;
988
+ ctx->valid = rn->valid;
824
989
 
825
990
  ctx->handler(ctx);
826
991
 
@@ -831,17 +996,19 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
831
996
 
832
997
  if (rn->waiting) {
833
998
 
834
- ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
835
- if (ctx->event == NULL) {
836
- return NGX_ERROR;
837
- }
999
+ if (ctx->event == NULL && ctx->timeout) {
1000
+ ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
1001
+ if (ctx->event == NULL) {
1002
+ return NGX_ERROR;
1003
+ }
838
1004
 
839
- ctx->event->handler = ngx_resolver_timeout_handler;
840
- ctx->event->data = ctx;
841
- ctx->event->log = r->log;
842
- ctx->ident = -1;
1005
+ ctx->event->handler = ngx_resolver_timeout_handler;
1006
+ ctx->event->data = ctx;
1007
+ ctx->event->log = r->log;
1008
+ ctx->ident = -1;
843
1009
 
844
- ngx_add_timer(ctx->event, ctx->timeout);
1010
+ ngx_add_timer(ctx->event, ctx->timeout);
1011
+ }
845
1012
 
846
1013
  ctx->next = rn->waiting;
847
1014
  rn->waiting = ctx;
@@ -892,26 +1059,36 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
892
1059
  goto failed;
893
1060
  }
894
1061
 
1062
+ rn->last_connection = r->last_connection++;
1063
+ if (r->last_connection == r->connections.nelts) {
1064
+ r->last_connection = 0;
1065
+ }
1066
+
895
1067
  rn->naddrs = (u_short) -1;
1068
+ rn->tcp = 0;
896
1069
  #if (NGX_HAVE_INET6)
897
1070
  rn->naddrs6 = (u_short) -1;
1071
+ rn->tcp6 = 0;
898
1072
  #endif
1073
+ rn->nsrvs = 0;
899
1074
 
900
1075
  if (ngx_resolver_send_query(r, rn) != NGX_OK) {
901
1076
  goto failed;
902
1077
  }
903
1078
 
904
- ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
905
- if (ctx->event == NULL) {
906
- goto failed;
907
- }
1079
+ if (ctx->event == NULL && ctx->timeout) {
1080
+ ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
1081
+ if (ctx->event == NULL) {
1082
+ goto failed;
1083
+ }
908
1084
 
909
- ctx->event->handler = ngx_resolver_timeout_handler;
910
- ctx->event->data = ctx;
911
- ctx->event->log = r->log;
912
- ctx->ident = -1;
1085
+ ctx->event->handler = ngx_resolver_timeout_handler;
1086
+ ctx->event->data = ctx;
1087
+ ctx->event->log = r->log;
1088
+ ctx->ident = -1;
913
1089
 
914
- ngx_add_timer(ctx->event, ctx->timeout);
1090
+ ngx_add_timer(ctx->event, ctx->timeout);
1091
+ }
915
1092
 
916
1093
  if (ngx_queue_empty(resend_queue)) {
917
1094
  ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
@@ -1042,6 +1219,10 @@ done:
1042
1219
  ngx_resolver_free_locked(r, ctx);
1043
1220
 
1044
1221
  /* unlock alloc mutex */
1222
+
1223
+ if (r->event->timer_set && ngx_resolver_resend_empty(r)) {
1224
+ ngx_del_timer(r->event);
1225
+ }
1045
1226
  }
1046
1227
 
1047
1228
 
@@ -1085,59 +1266,158 @@ ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
1085
1266
  static ngx_int_t
1086
1267
  ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
1087
1268
  {
1088
- ssize_t n;
1089
- ngx_udp_connection_t *uc;
1269
+ ngx_int_t rc;
1270
+ ngx_resolver_connection_t *rec;
1090
1271
 
1091
- uc = r->udp_connections.elts;
1272
+ rec = r->connections.elts;
1273
+ rec = &rec[rn->last_connection];
1092
1274
 
1093
- uc = &uc[r->last_connection++];
1094
- if (r->last_connection == r->udp_connections.nelts) {
1095
- r->last_connection = 0;
1275
+ if (rec->log.handler == NULL) {
1276
+ rec->log = *r->log;
1277
+ rec->log.handler = ngx_resolver_log_error;
1278
+ rec->log.data = rec;
1279
+ rec->log.action = "resolving";
1096
1280
  }
1097
1281
 
1098
- if (uc->connection == NULL) {
1099
-
1100
- uc->log = *r->log;
1101
- uc->log.handler = ngx_resolver_log_error;
1102
- uc->log.data = uc;
1103
- uc->log.action = "resolving";
1282
+ if (rn->naddrs == (u_short) -1) {
1283
+ rc = rn->tcp ? ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen)
1284
+ : ngx_resolver_send_udp_query(r, rec, rn->query, rn->qlen);
1104
1285
 
1105
- if (ngx_udp_connect(uc) != NGX_OK) {
1106
- return NGX_ERROR;
1286
+ if (rc != NGX_OK) {
1287
+ return rc;
1107
1288
  }
1108
-
1109
- uc->connection->data = r;
1110
- uc->connection->read->handler = ngx_resolver_read_response;
1111
- uc->connection->read->resolver = 1;
1112
1289
  }
1113
1290
 
1114
- if (rn->naddrs == (u_short) -1) {
1115
- n = ngx_send(uc->connection, rn->query, rn->qlen);
1291
+ #if (NGX_HAVE_INET6)
1116
1292
 
1117
- if (n == -1) {
1118
- return NGX_ERROR;
1293
+ if (rn->query6 && rn->naddrs6 == (u_short) -1) {
1294
+ rc = rn->tcp6
1295
+ ? ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen)
1296
+ : ngx_resolver_send_udp_query(r, rec, rn->query6, rn->qlen);
1297
+
1298
+ if (rc != NGX_OK) {
1299
+ return rc;
1119
1300
  }
1301
+ }
1302
+
1303
+ #endif
1304
+
1305
+ return NGX_OK;
1306
+ }
1307
+
1308
+
1309
+ static ngx_int_t
1310
+ ngx_resolver_send_udp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec,
1311
+ u_char *query, u_short qlen)
1312
+ {
1313
+ ssize_t n;
1120
1314
 
1121
- if ((size_t) n != (size_t) rn->qlen) {
1122
- ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1315
+ if (rec->udp == NULL) {
1316
+ if (ngx_udp_connect(rec) != NGX_OK) {
1123
1317
  return NGX_ERROR;
1124
1318
  }
1319
+
1320
+ rec->udp->data = rec;
1321
+ rec->udp->read->handler = ngx_resolver_udp_read;
1322
+ rec->udp->read->resolver = 1;
1125
1323
  }
1126
1324
 
1127
- #if (NGX_HAVE_INET6)
1128
- if (rn->query6 && rn->naddrs6 == (u_short) -1) {
1129
- n = ngx_send(uc->connection, rn->query6, rn->qlen);
1325
+ n = ngx_send(rec->udp, query, qlen);
1130
1326
 
1131
- if (n == -1) {
1132
- return NGX_ERROR;
1327
+ if (n == -1) {
1328
+ return NGX_ERROR;
1329
+ }
1330
+
1331
+ if ((size_t) n != (size_t) qlen) {
1332
+ ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "send() incomplete");
1333
+ return NGX_ERROR;
1334
+ }
1335
+
1336
+ return NGX_OK;
1337
+ }
1338
+
1339
+
1340
+ static ngx_int_t
1341
+ ngx_resolver_send_tcp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec,
1342
+ u_char *query, u_short qlen)
1343
+ {
1344
+ ngx_buf_t *b;
1345
+ ngx_int_t rc;
1346
+
1347
+ rc = NGX_OK;
1348
+
1349
+ if (rec->tcp == NULL) {
1350
+ b = rec->read_buf;
1351
+
1352
+ if (b == NULL) {
1353
+ b = ngx_resolver_calloc(r, sizeof(ngx_buf_t));
1354
+ if (b == NULL) {
1355
+ return NGX_ERROR;
1356
+ }
1357
+
1358
+ b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_RSIZE);
1359
+ if (b->start == NULL) {
1360
+ ngx_resolver_free(r, b);
1361
+ return NGX_ERROR;
1362
+ }
1363
+
1364
+ b->end = b->start + NGX_RESOLVER_TCP_RSIZE;
1365
+
1366
+ rec->read_buf = b;
1367
+ }
1368
+
1369
+ b->pos = b->start;
1370
+ b->last = b->start;
1371
+
1372
+ b = rec->write_buf;
1373
+
1374
+ if (b == NULL) {
1375
+ b = ngx_resolver_calloc(r, sizeof(ngx_buf_t));
1376
+ if (b == NULL) {
1377
+ return NGX_ERROR;
1378
+ }
1379
+
1380
+ b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_WSIZE);
1381
+ if (b->start == NULL) {
1382
+ ngx_resolver_free(r, b);
1383
+ return NGX_ERROR;
1384
+ }
1385
+
1386
+ b->end = b->start + NGX_RESOLVER_TCP_WSIZE;
1387
+
1388
+ rec->write_buf = b;
1133
1389
  }
1134
1390
 
1135
- if ((size_t) n != (size_t) rn->qlen) {
1136
- ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1391
+ b->pos = b->start;
1392
+ b->last = b->start;
1393
+
1394
+ rc = ngx_tcp_connect(rec);
1395
+ if (rc == NGX_ERROR) {
1137
1396
  return NGX_ERROR;
1138
1397
  }
1398
+
1399
+ rec->tcp->data = rec;
1400
+ rec->tcp->write->handler = ngx_resolver_tcp_write;
1401
+ rec->tcp->read->handler = ngx_resolver_tcp_read;
1402
+ rec->tcp->read->resolver = 1;
1403
+
1404
+ ngx_add_timer(rec->tcp->write, (ngx_msec_t) (r->tcp_timeout * 1000));
1405
+ }
1406
+
1407
+ b = rec->write_buf;
1408
+
1409
+ if (b->end - b->last < 2 + qlen) {
1410
+ ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "buffer overflow");
1411
+ return NGX_ERROR;
1412
+ }
1413
+
1414
+ *b->last++ = (u_char) (qlen >> 8);
1415
+ *b->last++ = (u_char) qlen;
1416
+ b->last = ngx_cpymem(b->last, query, qlen);
1417
+
1418
+ if (rc == NGX_OK) {
1419
+ ngx_resolver_tcp_write(rec->tcp->write);
1139
1420
  }
1140
- #endif
1141
1421
 
1142
1422
  return NGX_OK;
1143
1423
  }
@@ -1146,7 +1426,7 @@ ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
1146
1426
  static void
1147
1427
  ngx_resolver_resend_handler(ngx_event_t *ev)
1148
1428
  {
1149
- time_t timer, atimer, ntimer;
1429
+ time_t timer, atimer, stimer, ntimer;
1150
1430
  #if (NGX_HAVE_INET6)
1151
1431
  time_t a6timer;
1152
1432
  #endif
@@ -1161,6 +1441,8 @@ ngx_resolver_resend_handler(ngx_event_t *ev)
1161
1441
 
1162
1442
  ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue);
1163
1443
 
1444
+ stimer = ngx_resolver_resend(r, &r->srv_rbtree, &r->srv_resend_queue);
1445
+
1164
1446
  /* unlock name mutex */
1165
1447
 
1166
1448
  /* lock addr mutex */
@@ -1188,6 +1470,13 @@ ngx_resolver_resend_handler(ngx_event_t *ev)
1188
1470
  timer = ngx_min(timer, atimer);
1189
1471
  }
1190
1472
 
1473
+ if (timer == 0) {
1474
+ timer = stimer;
1475
+
1476
+ } else if (stimer) {
1477
+ timer = ngx_min(timer, stimer);
1478
+ }
1479
+
1191
1480
  #if (NGX_HAVE_INET6)
1192
1481
 
1193
1482
  if (timer == 0) {
@@ -1235,6 +1524,10 @@ ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
1235
1524
 
1236
1525
  if (rn->waiting) {
1237
1526
 
1527
+ if (++rn->last_connection == r->connections.nelts) {
1528
+ rn->last_connection = 0;
1529
+ }
1530
+
1238
1531
  (void) ngx_resolver_send_query(r, rn);
1239
1532
 
1240
1533
  rn->expire = now + r->resend_timeout;
@@ -1251,14 +1544,27 @@ ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
1251
1544
  }
1252
1545
 
1253
1546
 
1547
+ static ngx_uint_t
1548
+ ngx_resolver_resend_empty(ngx_resolver_t *r)
1549
+ {
1550
+ return ngx_queue_empty(&r->name_resend_queue)
1551
+ #if (NGX_HAVE_INET6)
1552
+ && ngx_queue_empty(&r->addr6_resend_queue)
1553
+ #endif
1554
+ && ngx_queue_empty(&r->addr_resend_queue);
1555
+ }
1556
+
1557
+
1254
1558
  static void
1255
- ngx_resolver_read_response(ngx_event_t *rev)
1559
+ ngx_resolver_udp_read(ngx_event_t *rev)
1256
1560
  {
1257
- ssize_t n;
1258
- ngx_connection_t *c;
1259
- u_char buf[NGX_RESOLVER_UDP_SIZE];
1561
+ ssize_t n;
1562
+ ngx_connection_t *c;
1563
+ ngx_resolver_connection_t *rec;
1564
+ u_char buf[NGX_RESOLVER_UDP_SIZE];
1260
1565
 
1261
1566
  c = rev->data;
1567
+ rec = c->data;
1262
1568
 
1263
1569
  do {
1264
1570
  n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE);
@@ -1267,73 +1573,202 @@ ngx_resolver_read_response(ngx_event_t *rev)
1267
1573
  return;
1268
1574
  }
1269
1575
 
1270
- ngx_resolver_process_response(c->data, buf, n);
1576
+ ngx_resolver_process_response(rec->resolver, buf, n, 0);
1271
1577
 
1272
1578
  } while (rev->ready);
1273
1579
  }
1274
1580
 
1275
1581
 
1276
1582
  static void
1277
- ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
1583
+ ngx_resolver_tcp_write(ngx_event_t *wev)
1278
1584
  {
1279
- char *err;
1280
- ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
1281
- qtype, qclass;
1282
- #if (NGX_HAVE_INET6)
1283
- ngx_uint_t qident6;
1284
- #endif
1285
- ngx_queue_t *q;
1286
- ngx_resolver_qs_t *qs;
1287
- ngx_resolver_hdr_t *response;
1288
- ngx_resolver_node_t *rn;
1289
-
1290
- if (n < sizeof(ngx_resolver_hdr_t)) {
1291
- goto short_response;
1585
+ off_t sent;
1586
+ ssize_t n;
1587
+ ngx_buf_t *b;
1588
+ ngx_resolver_t *r;
1589
+ ngx_connection_t *c;
1590
+ ngx_resolver_connection_t *rec;
1591
+
1592
+ c = wev->data;
1593
+ rec = c->data;
1594
+ b = rec->write_buf;
1595
+ r = rec->resolver;
1596
+
1597
+ if (wev->timedout) {
1598
+ goto failed;
1292
1599
  }
1293
1600
 
1294
- response = (ngx_resolver_hdr_t *) buf;
1601
+ sent = c->sent;
1295
1602
 
1296
- ident = (response->ident_hi << 8) + response->ident_lo;
1297
- flags = (response->flags_hi << 8) + response->flags_lo;
1298
- nqs = (response->nqs_hi << 8) + response->nqs_lo;
1299
- nan = (response->nan_hi << 8) + response->nan_lo;
1603
+ while (wev->ready && b->pos < b->last) {
1604
+ n = ngx_send(c, b->pos, b->last - b->pos);
1300
1605
 
1301
- ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
1302
- "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
1303
- ident, flags, nqs, nan,
1304
- (response->nns_hi << 8) + response->nns_lo,
1305
- (response->nar_hi << 8) + response->nar_lo);
1606
+ if (n == NGX_AGAIN) {
1607
+ break;
1608
+ }
1306
1609
 
1307
- /* response to a standard query */
1308
- if ((flags & 0xf870) != 0x8000) {
1309
- ngx_log_error(r->log_level, r->log, 0,
1310
- "invalid DNS response %ui fl:%04Xui", ident, flags);
1311
- return;
1610
+ if (n == NGX_ERROR) {
1611
+ goto failed;
1612
+ }
1613
+
1614
+ b->pos += n;
1312
1615
  }
1313
1616
 
1314
- code = flags & 0xf;
1617
+ if (b->pos != b->start) {
1618
+ b->last = ngx_movemem(b->start, b->pos, b->last - b->pos);
1619
+ b->pos = b->start;
1620
+ }
1315
1621
 
1316
- if (code == NGX_RESOLVE_FORMERR) {
1622
+ if (c->sent != sent) {
1623
+ ngx_add_timer(wev, (ngx_msec_t) (r->tcp_timeout * 1000));
1624
+ }
1317
1625
 
1318
- times = 0;
1626
+ if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1627
+ goto failed;
1628
+ }
1319
1629
 
1320
- for (q = ngx_queue_head(&r->name_resend_queue);
1321
- q != ngx_queue_sentinel(&r->name_resend_queue) && times++ < 100;
1322
- q = ngx_queue_next(q))
1323
- {
1324
- rn = ngx_queue_data(q, ngx_resolver_node_t, queue);
1325
- qident = (rn->query[0] << 8) + rn->query[1];
1630
+ return;
1326
1631
 
1327
- if (qident == ident) {
1328
- goto dns_error_name;
1329
- }
1632
+ failed:
1330
1633
 
1331
- #if (NGX_HAVE_INET6)
1332
- if (rn->query6) {
1333
- qident6 = (rn->query6[0] << 8) + rn->query6[1];
1634
+ ngx_close_connection(c);
1635
+ rec->tcp = NULL;
1636
+ }
1334
1637
 
1335
- if (qident6 == ident) {
1336
- goto dns_error_name;
1638
+
1639
+ static void
1640
+ ngx_resolver_tcp_read(ngx_event_t *rev)
1641
+ {
1642
+ u_char *p;
1643
+ size_t size;
1644
+ ssize_t n;
1645
+ u_short qlen;
1646
+ ngx_buf_t *b;
1647
+ ngx_resolver_t *r;
1648
+ ngx_connection_t *c;
1649
+ ngx_resolver_connection_t *rec;
1650
+
1651
+ c = rev->data;
1652
+ rec = c->data;
1653
+ b = rec->read_buf;
1654
+ r = rec->resolver;
1655
+
1656
+ while (rev->ready) {
1657
+ n = ngx_recv(c, b->last, b->end - b->last);
1658
+
1659
+ if (n == NGX_AGAIN) {
1660
+ break;
1661
+ }
1662
+
1663
+ if (n == NGX_ERROR || n == 0) {
1664
+ goto failed;
1665
+ }
1666
+
1667
+ b->last += n;
1668
+
1669
+ for ( ;; ) {
1670
+ p = b->pos;
1671
+ size = b->last - p;
1672
+
1673
+ if (size < 2) {
1674
+ break;
1675
+ }
1676
+
1677
+ qlen = (u_short) *p++ << 8;
1678
+ qlen += *p++;
1679
+
1680
+ if (size < (size_t) (2 + qlen)) {
1681
+ break;
1682
+ }
1683
+
1684
+ ngx_resolver_process_response(r, p, qlen, 1);
1685
+
1686
+ b->pos += 2 + qlen;
1687
+ }
1688
+
1689
+ if (b->pos != b->start) {
1690
+ b->last = ngx_movemem(b->start, b->pos, b->last - b->pos);
1691
+ b->pos = b->start;
1692
+ }
1693
+ }
1694
+
1695
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1696
+ goto failed;
1697
+ }
1698
+
1699
+ return;
1700
+
1701
+ failed:
1702
+
1703
+ ngx_close_connection(c);
1704
+ rec->tcp = NULL;
1705
+ }
1706
+
1707
+
1708
+ static void
1709
+ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n,
1710
+ ngx_uint_t tcp)
1711
+ {
1712
+ char *err;
1713
+ ngx_uint_t i, times, ident, qident, flags, code, nqs, nan, trunc,
1714
+ qtype, qclass;
1715
+ #if (NGX_HAVE_INET6)
1716
+ ngx_uint_t qident6;
1717
+ #endif
1718
+ ngx_queue_t *q;
1719
+ ngx_resolver_qs_t *qs;
1720
+ ngx_resolver_hdr_t *response;
1721
+ ngx_resolver_node_t *rn;
1722
+
1723
+ if (n < sizeof(ngx_resolver_hdr_t)) {
1724
+ goto short_response;
1725
+ }
1726
+
1727
+ response = (ngx_resolver_hdr_t *) buf;
1728
+
1729
+ ident = (response->ident_hi << 8) + response->ident_lo;
1730
+ flags = (response->flags_hi << 8) + response->flags_lo;
1731
+ nqs = (response->nqs_hi << 8) + response->nqs_lo;
1732
+ nan = (response->nan_hi << 8) + response->nan_lo;
1733
+ trunc = flags & 0x0200;
1734
+
1735
+ ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
1736
+ "resolver DNS response %ui fl:%04Xi %ui/%ui/%ud/%ud",
1737
+ ident, flags, nqs, nan,
1738
+ (response->nns_hi << 8) + response->nns_lo,
1739
+ (response->nar_hi << 8) + response->nar_lo);
1740
+
1741
+ /* response to a standard query */
1742
+ if ((flags & 0xf870) != 0x8000 || (trunc && tcp)) {
1743
+ ngx_log_error(r->log_level, r->log, 0,
1744
+ "invalid %s DNS response %ui fl:%04Xi",
1745
+ tcp ? "TCP" : "UDP", ident, flags);
1746
+ return;
1747
+ }
1748
+
1749
+ code = flags & 0xf;
1750
+
1751
+ if (code == NGX_RESOLVE_FORMERR) {
1752
+
1753
+ times = 0;
1754
+
1755
+ for (q = ngx_queue_head(&r->name_resend_queue);
1756
+ q != ngx_queue_sentinel(&r->name_resend_queue) && times++ < 100;
1757
+ q = ngx_queue_next(q))
1758
+ {
1759
+ rn = ngx_queue_data(q, ngx_resolver_node_t, queue);
1760
+ qident = (rn->query[0] << 8) + rn->query[1];
1761
+
1762
+ if (qident == ident) {
1763
+ goto dns_error_name;
1764
+ }
1765
+
1766
+ #if (NGX_HAVE_INET6)
1767
+ if (rn->query6) {
1768
+ qident6 = (rn->query6[0] << 8) + rn->query6[1];
1769
+
1770
+ if (qident6 == ident) {
1771
+ goto dns_error_name;
1337
1772
  }
1338
1773
  }
1339
1774
  #endif
@@ -1397,11 +1832,18 @@ found:
1397
1832
  case NGX_RESOLVE_AAAA:
1398
1833
  #endif
1399
1834
 
1400
- ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan,
1835
+ ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc,
1401
1836
  i + sizeof(ngx_resolver_qs_t));
1402
1837
 
1403
1838
  break;
1404
1839
 
1840
+ case NGX_RESOLVE_SRV:
1841
+
1842
+ ngx_resolver_process_srv(r, buf, n, ident, code, nan, trunc,
1843
+ i + sizeof(ngx_resolver_qs_t));
1844
+
1845
+ break;
1846
+
1405
1847
  case NGX_RESOLVE_PTR:
1406
1848
 
1407
1849
  ngx_resolver_process_ptr(r, buf, n, ident, code, nan);
@@ -1431,7 +1873,7 @@ dns_error_name:
1431
1873
  ngx_log_error(r->log_level, r->log, 0,
1432
1874
  "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1433
1875
  code, ngx_resolver_strerror(code), ident,
1434
- rn->nlen, rn->name);
1876
+ (size_t) rn->nlen, rn->name);
1435
1877
  return;
1436
1878
 
1437
1879
  dns_error:
@@ -1444,28 +1886,29 @@ dns_error:
1444
1886
 
1445
1887
 
1446
1888
  static void
1447
- ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1889
+ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
1448
1890
  ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
1449
- ngx_uint_t nan, ngx_uint_t ans)
1891
+ ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans)
1450
1892
  {
1451
- char *err;
1452
- u_char *cname;
1453
- size_t len;
1454
- int32_t ttl;
1455
- uint32_t hash;
1456
- in_addr_t *addr;
1457
- ngx_str_t name;
1458
- ngx_addr_t *addrs;
1459
- ngx_uint_t type, class, qident, naddrs, a, i, n, start;
1893
+ char *err;
1894
+ u_char *cname;
1895
+ size_t len;
1896
+ int32_t ttl;
1897
+ uint32_t hash;
1898
+ in_addr_t *addr;
1899
+ ngx_str_t name;
1900
+ ngx_uint_t type, class, qident, naddrs, a, i, j, start;
1460
1901
  #if (NGX_HAVE_INET6)
1461
- struct in6_addr *addr6;
1902
+ struct in6_addr *addr6;
1462
1903
  #endif
1463
- ngx_resolver_an_t *an;
1464
- ngx_resolver_ctx_t *ctx, *next;
1465
- ngx_resolver_node_t *rn;
1904
+ ngx_resolver_an_t *an;
1905
+ ngx_resolver_ctx_t *ctx, *next;
1906
+ ngx_resolver_node_t *rn;
1907
+ ngx_resolver_addr_t *addrs;
1908
+ ngx_resolver_connection_t *rec;
1466
1909
 
1467
1910
  if (ngx_resolver_copy(r, &name, buf,
1468
- buf + sizeof(ngx_resolver_hdr_t), buf + last)
1911
+ buf + sizeof(ngx_resolver_hdr_t), buf + n)
1469
1912
  != NGX_OK)
1470
1913
  {
1471
1914
  return;
@@ -1498,6 +1941,11 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1498
1941
  goto failed;
1499
1942
  }
1500
1943
 
1944
+ if (trunc && rn->tcp6) {
1945
+ ngx_resolver_free(r, name.data);
1946
+ goto failed;
1947
+ }
1948
+
1501
1949
  qident = (rn->query6[0] << 8) + rn->query6[1];
1502
1950
 
1503
1951
  break;
@@ -1512,6 +1960,11 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1512
1960
  goto failed;
1513
1961
  }
1514
1962
 
1963
+ if (trunc && rn->tcp) {
1964
+ ngx_resolver_free(r, name.data);
1965
+ goto failed;
1966
+ }
1967
+
1515
1968
  qident = (rn->query[0] << 8) + rn->query[1];
1516
1969
  }
1517
1970
 
@@ -1525,6 +1978,45 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1525
1978
 
1526
1979
  ngx_resolver_free(r, name.data);
1527
1980
 
1981
+ if (trunc) {
1982
+
1983
+ ngx_queue_remove(&rn->queue);
1984
+
1985
+ if (rn->waiting == NULL) {
1986
+ ngx_rbtree_delete(&r->name_rbtree, &rn->node);
1987
+ ngx_resolver_free_node(r, rn);
1988
+ goto next;
1989
+ }
1990
+
1991
+ rec = r->connections.elts;
1992
+ rec = &rec[rn->last_connection];
1993
+
1994
+ switch (qtype) {
1995
+
1996
+ #if (NGX_HAVE_INET6)
1997
+ case NGX_RESOLVE_AAAA:
1998
+
1999
+ rn->tcp6 = 1;
2000
+
2001
+ (void) ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen);
2002
+
2003
+ break;
2004
+ #endif
2005
+
2006
+ default: /* NGX_RESOLVE_A */
2007
+
2008
+ rn->tcp = 1;
2009
+
2010
+ (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen);
2011
+ }
2012
+
2013
+ rn->expire = ngx_time() + r->resend_timeout;
2014
+
2015
+ ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);
2016
+
2017
+ goto next;
2018
+ }
2019
+
1528
2020
  if (code == 0 && rn->code) {
1529
2021
  code = rn->code;
1530
2022
  }
@@ -1604,6 +2096,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1604
2096
  while (next) {
1605
2097
  ctx = next;
1606
2098
  ctx->state = code;
2099
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
1607
2100
  next = ctx->next;
1608
2101
 
1609
2102
  ctx->handler(ctx);
@@ -1622,7 +2115,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1622
2115
 
1623
2116
  start = i;
1624
2117
 
1625
- while (i < last) {
2118
+ while (i < n) {
1626
2119
 
1627
2120
  if (buf[i] & 0xc0) {
1628
2121
  i += 2;
@@ -1648,7 +2141,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1648
2141
 
1649
2142
  found:
1650
2143
 
1651
- if (i + sizeof(ngx_resolver_an_t) >= last) {
2144
+ if (i + sizeof(ngx_resolver_an_t) >= n) {
1652
2145
  goto short_response;
1653
2146
  }
1654
2147
 
@@ -1688,7 +2181,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1688
2181
  goto invalid;
1689
2182
  }
1690
2183
 
1691
- if (i + 4 > last) {
2184
+ if (i + 4 > n) {
1692
2185
  goto short_response;
1693
2186
  }
1694
2187
 
@@ -1709,7 +2202,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1709
2202
  goto invalid;
1710
2203
  }
1711
2204
 
1712
- if (i + 16 > last) {
2205
+ if (i + 16 > n) {
1713
2206
  goto short_response;
1714
2207
  }
1715
2208
 
@@ -1790,7 +2283,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1790
2283
  #endif
1791
2284
  }
1792
2285
 
1793
- n = 0;
2286
+ j = 0;
1794
2287
  i = ans;
1795
2288
 
1796
2289
  for (a = 0; a < nan; a++) {
@@ -1819,10 +2312,10 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1819
2312
 
1820
2313
  if (type == NGX_RESOLVE_A) {
1821
2314
 
1822
- addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
2315
+ addr[j] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1823
2316
  + (buf[i + 2] << 8) + (buf[i + 3]));
1824
2317
 
1825
- if (++n == naddrs) {
2318
+ if (++j == naddrs) {
1826
2319
 
1827
2320
  #if (NGX_HAVE_INET6)
1828
2321
  if (rn->naddrs6 == (u_short) -1) {
@@ -1837,9 +2330,9 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1837
2330
  #if (NGX_HAVE_INET6)
1838
2331
  else if (type == NGX_RESOLVE_AAAA) {
1839
2332
 
1840
- ngx_memcpy(addr6[n].s6_addr, &buf[i], 16);
2333
+ ngx_memcpy(addr6[j].s6_addr, &buf[i], 16);
1841
2334
 
1842
- if (++n == naddrs) {
2335
+ if (++j == naddrs) {
1843
2336
 
1844
2337
  if (rn->naddrs == (u_short) -1) {
1845
2338
  goto next;
@@ -1918,6 +2411,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1918
2411
  while (next) {
1919
2412
  ctx = next;
1920
2413
  ctx->state = NGX_OK;
2414
+ ctx->valid = rn->valid;
1921
2415
  ctx->naddrs = naddrs;
1922
2416
 
1923
2417
  if (addrs == NULL) {
@@ -1964,7 +2458,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1964
2458
  goto next;
1965
2459
  }
1966
2460
 
1967
- if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
2461
+ if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK) {
1968
2462
  goto failed;
1969
2463
  }
1970
2464
 
@@ -2047,128 +2541,654 @@ next:
2047
2541
 
2048
2542
 
2049
2543
  static void
2050
- ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
2051
- ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
2544
+ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
2545
+ ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
2546
+ ngx_uint_t trunc, ngx_uint_t ans)
2052
2547
  {
2053
- char *err;
2054
- size_t len;
2055
- u_char text[NGX_SOCKADDR_STRLEN];
2056
- in_addr_t addr;
2057
- int32_t ttl;
2058
- ngx_int_t octet;
2059
- ngx_str_t name;
2060
- ngx_uint_t i, mask, qident, class;
2061
- ngx_queue_t *expire_queue;
2062
- ngx_rbtree_t *tree;
2063
- ngx_resolver_an_t *an;
2064
- ngx_resolver_ctx_t *ctx, *next;
2065
- ngx_resolver_node_t *rn;
2066
- #if (NGX_HAVE_INET6)
2067
- uint32_t hash;
2068
- ngx_int_t digit;
2069
- struct in6_addr addr6;
2070
- #endif
2548
+ char *err;
2549
+ u_char *cname;
2550
+ size_t len;
2551
+ int32_t ttl;
2552
+ uint32_t hash;
2553
+ ngx_str_t name;
2554
+ ngx_uint_t type, qident, class, start, nsrvs, a, i, j;
2555
+ ngx_resolver_an_t *an;
2556
+ ngx_resolver_ctx_t *ctx, *next;
2557
+ ngx_resolver_srv_t *srvs;
2558
+ ngx_resolver_node_t *rn;
2559
+ ngx_resolver_connection_t *rec;
2071
2560
 
2072
- if (ngx_resolver_copy(r, NULL, buf,
2561
+ if (ngx_resolver_copy(r, &name, buf,
2073
2562
  buf + sizeof(ngx_resolver_hdr_t), buf + n)
2074
2563
  != NGX_OK)
2075
2564
  {
2076
2565
  return;
2077
2566
  }
2078
2567
 
2079
- /* AF_INET */
2080
-
2081
- addr = 0;
2082
- i = sizeof(ngx_resolver_hdr_t);
2568
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);
2083
2569
 
2084
- for (mask = 0; mask < 32; mask += 8) {
2085
- len = buf[i++];
2570
+ hash = ngx_crc32_short(name.data, name.len);
2086
2571
 
2087
- octet = ngx_atoi(&buf[i], len);
2088
- if (octet == NGX_ERROR || octet > 255) {
2089
- goto invalid_in_addr_arpa;
2090
- }
2572
+ rn = ngx_resolver_lookup_srv(r, &name, hash);
2091
2573
 
2092
- addr += octet << mask;
2093
- i += len;
2574
+ if (rn == NULL || rn->query == NULL) {
2575
+ ngx_log_error(r->log_level, r->log, 0,
2576
+ "unexpected response for %V", &name);
2577
+ ngx_resolver_free(r, name.data);
2578
+ goto failed;
2094
2579
  }
2095
2580
 
2096
- if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
2097
- i += sizeof("\7in-addr\4arpa");
2098
-
2099
- /* lock addr mutex */
2100
-
2101
- rn = ngx_resolver_lookup_addr(r, addr);
2102
-
2103
- tree = &r->addr_rbtree;
2104
- expire_queue = &r->addr_expire_queue;
2581
+ if (trunc && rn->tcp) {
2582
+ ngx_resolver_free(r, name.data);
2583
+ goto failed;
2584
+ }
2105
2585
 
2106
- addr = htonl(addr);
2107
- name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN);
2108
- name.data = text;
2586
+ qident = (rn->query[0] << 8) + rn->query[1];
2109
2587
 
2110
- goto valid;
2588
+ if (ident != qident) {
2589
+ ngx_log_error(r->log_level, r->log, 0,
2590
+ "wrong ident %ui response for %V, expect %ui",
2591
+ ident, &name, qident);
2592
+ ngx_resolver_free(r, name.data);
2593
+ goto failed;
2111
2594
  }
2112
2595
 
2113
- invalid_in_addr_arpa:
2596
+ ngx_resolver_free(r, name.data);
2114
2597
 
2115
- #if (NGX_HAVE_INET6)
2598
+ if (trunc) {
2116
2599
 
2117
- i = sizeof(ngx_resolver_hdr_t);
2600
+ ngx_queue_remove(&rn->queue);
2118
2601
 
2119
- for (octet = 15; octet >= 0; octet--) {
2120
- if (buf[i++] != '\1') {
2121
- goto invalid_ip6_arpa;
2602
+ if (rn->waiting == NULL) {
2603
+ ngx_rbtree_delete(&r->srv_rbtree, &rn->node);
2604
+ ngx_resolver_free_node(r, rn);
2605
+ return;
2122
2606
  }
2123
2607
 
2124
- digit = ngx_hextoi(&buf[i++], 1);
2125
- if (digit == NGX_ERROR) {
2126
- goto invalid_ip6_arpa;
2127
- }
2608
+ rec = r->connections.elts;
2609
+ rec = &rec[rn->last_connection];
2128
2610
 
2129
- addr6.s6_addr[octet] = (u_char) digit;
2611
+ rn->tcp = 1;
2130
2612
 
2131
- if (buf[i++] != '\1') {
2132
- goto invalid_ip6_arpa;
2133
- }
2613
+ (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen);
2134
2614
 
2135
- digit = ngx_hextoi(&buf[i++], 1);
2136
- if (digit == NGX_ERROR) {
2137
- goto invalid_ip6_arpa;
2138
- }
2615
+ rn->expire = ngx_time() + r->resend_timeout;
2139
2616
 
2140
- addr6.s6_addr[octet] += (u_char) (digit * 16);
2617
+ ngx_queue_insert_head(&r->srv_resend_queue, &rn->queue);
2618
+
2619
+ return;
2141
2620
  }
2142
2621
 
2143
- if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
2144
- i += sizeof("\3ip6\4arpa");
2622
+ if (code == 0 && rn->code) {
2623
+ code = rn->code;
2624
+ }
2145
2625
 
2146
- /* lock addr mutex */
2626
+ if (code == 0 && nan == 0) {
2627
+ code = NGX_RESOLVE_NXDOMAIN;
2628
+ }
2147
2629
 
2148
- hash = ngx_crc32_short(addr6.s6_addr, 16);
2149
- rn = ngx_resolver_lookup_addr6(r, &addr6, hash);
2630
+ if (code) {
2631
+ next = rn->waiting;
2632
+ rn->waiting = NULL;
2150
2633
 
2151
- tree = &r->addr6_rbtree;
2152
- expire_queue = &r->addr6_expire_queue;
2634
+ ngx_queue_remove(&rn->queue);
2153
2635
 
2154
- name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN);
2155
- name.data = text;
2636
+ ngx_rbtree_delete(&r->srv_rbtree, &rn->node);
2156
2637
 
2157
- goto valid;
2158
- }
2638
+ while (next) {
2639
+ ctx = next;
2640
+ ctx->state = code;
2641
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
2642
+ next = ctx->next;
2159
2643
 
2160
- invalid_ip6_arpa:
2161
- #endif
2644
+ ctx->handler(ctx);
2645
+ }
2162
2646
 
2163
- ngx_log_error(r->log_level, r->log, 0,
2164
- "invalid in-addr.arpa or ip6.arpa name in DNS response");
2165
- return;
2647
+ ngx_resolver_free_node(r, rn);
2166
2648
 
2167
- valid:
2649
+ return;
2650
+ }
2651
+
2652
+ i = ans;
2653
+ nsrvs = 0;
2654
+ cname = NULL;
2655
+
2656
+ for (a = 0; a < nan; a++) {
2657
+
2658
+ start = i;
2659
+
2660
+ while (i < n) {
2661
+
2662
+ if (buf[i] & 0xc0) {
2663
+ i += 2;
2664
+ goto found;
2665
+ }
2666
+
2667
+ if (buf[i] == 0) {
2668
+ i++;
2669
+ goto test_length;
2670
+ }
2671
+
2672
+ i += 1 + buf[i];
2673
+ }
2674
+
2675
+ goto short_response;
2676
+
2677
+ test_length:
2678
+
2679
+ if (i - start < 2) {
2680
+ err = "invalid name DNS response";
2681
+ goto invalid;
2682
+ }
2683
+
2684
+ found:
2685
+
2686
+ if (i + sizeof(ngx_resolver_an_t) >= n) {
2687
+ goto short_response;
2688
+ }
2689
+
2690
+ an = (ngx_resolver_an_t *) &buf[i];
2691
+
2692
+ type = (an->type_hi << 8) + an->type_lo;
2693
+ class = (an->class_hi << 8) + an->class_lo;
2694
+ len = (an->len_hi << 8) + an->len_lo;
2695
+ ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
2696
+ + (an->ttl[2] << 8) + (an->ttl[3]);
2697
+
2698
+ if (class != 1) {
2699
+ ngx_log_error(r->log_level, r->log, 0,
2700
+ "unexpected RR class %ui", class);
2701
+ goto failed;
2702
+ }
2703
+
2704
+ if (ttl < 0) {
2705
+ ttl = 0;
2706
+ }
2707
+
2708
+ rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);
2709
+
2710
+ i += sizeof(ngx_resolver_an_t);
2711
+
2712
+ switch (type) {
2713
+
2714
+ case NGX_RESOLVE_SRV:
2715
+
2716
+ if (i + 6 > n) {
2717
+ goto short_response;
2718
+ }
2719
+
2720
+ if (ngx_resolver_copy(r, NULL, buf, &buf[i + 6], buf + n)
2721
+ != NGX_OK)
2722
+ {
2723
+ goto failed;
2724
+ }
2725
+
2726
+ nsrvs++;
2727
+
2728
+ break;
2729
+
2730
+ case NGX_RESOLVE_CNAME:
2731
+
2732
+ cname = &buf[i];
2733
+
2734
+ break;
2735
+
2736
+ case NGX_RESOLVE_DNAME:
2737
+
2738
+ break;
2739
+
2740
+ default:
2741
+
2742
+ ngx_log_error(r->log_level, r->log, 0,
2743
+ "unexpected RR type %ui", type);
2744
+ }
2745
+
2746
+ i += len;
2747
+ }
2748
+
2749
+ ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
2750
+ "resolver nsrvs:%ui cname:%p ttl:%uD",
2751
+ nsrvs, cname, rn->ttl);
2752
+
2753
+ if (nsrvs) {
2754
+
2755
+ srvs = ngx_resolver_calloc(r, nsrvs * sizeof(ngx_resolver_srv_t));
2756
+ if (srvs == NULL) {
2757
+ goto failed;
2758
+ }
2759
+
2760
+ rn->u.srvs = srvs;
2761
+ rn->nsrvs = (u_short) nsrvs;
2762
+
2763
+ j = 0;
2764
+ i = ans;
2765
+
2766
+ for (a = 0; a < nan; a++) {
2767
+
2768
+ for ( ;; ) {
2769
+
2770
+ if (buf[i] & 0xc0) {
2771
+ i += 2;
2772
+ break;
2773
+ }
2774
+
2775
+ if (buf[i] == 0) {
2776
+ i++;
2777
+ break;
2778
+ }
2779
+
2780
+ i += 1 + buf[i];
2781
+ }
2782
+
2783
+ an = (ngx_resolver_an_t *) &buf[i];
2784
+
2785
+ type = (an->type_hi << 8) + an->type_lo;
2786
+ len = (an->len_hi << 8) + an->len_lo;
2787
+
2788
+ i += sizeof(ngx_resolver_an_t);
2789
+
2790
+ if (type == NGX_RESOLVE_SRV) {
2791
+
2792
+ srvs[j].priority = (buf[i] << 8) + buf[i + 1];
2793
+ srvs[j].weight = (buf[i + 2] << 8) + buf[i + 3];
2794
+
2795
+ if (srvs[j].weight == 0) {
2796
+ srvs[j].weight = 1;
2797
+ }
2798
+
2799
+ srvs[j].port = (buf[i + 4] << 8) + buf[i + 5];
2800
+
2801
+ if (ngx_resolver_copy(r, &srvs[j].name, buf, &buf[i + 6],
2802
+ buf + n)
2803
+ != NGX_OK)
2804
+ {
2805
+ goto failed;
2806
+ }
2807
+
2808
+ j++;
2809
+ }
2810
+
2811
+ i += len;
2812
+ }
2813
+
2814
+ ngx_sort(srvs, nsrvs, sizeof(ngx_resolver_srv_t),
2815
+ ngx_resolver_cmp_srvs);
2816
+
2817
+ ngx_resolver_free(r, rn->query);
2818
+ rn->query = NULL;
2819
+
2820
+ ngx_queue_remove(&rn->queue);
2821
+
2822
+ rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
2823
+ rn->expire = ngx_time() + r->expire;
2824
+
2825
+ ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue);
2826
+
2827
+ next = rn->waiting;
2828
+ rn->waiting = NULL;
2829
+
2830
+ while (next) {
2831
+ ctx = next;
2832
+ next = ctx->next;
2833
+
2834
+ ngx_resolver_resolve_srv_names(ctx, rn);
2835
+ }
2836
+
2837
+ return;
2838
+ }
2839
+
2840
+ rn->nsrvs = 0;
2841
+
2842
+ if (cname) {
2843
+
2844
+ /* CNAME only */
2845
+
2846
+ if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK) {
2847
+ goto failed;
2848
+ }
2849
+
2850
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
2851
+ "resolver cname:\"%V\"", &name);
2852
+
2853
+ ngx_queue_remove(&rn->queue);
2854
+
2855
+ rn->cnlen = (u_short) name.len;
2856
+ rn->u.cname = name.data;
2857
+
2858
+ rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
2859
+ rn->expire = ngx_time() + r->expire;
2860
+
2861
+ ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue);
2862
+
2863
+ ngx_resolver_free(r, rn->query);
2864
+ rn->query = NULL;
2865
+ #if (NGX_HAVE_INET6)
2866
+ rn->query6 = NULL;
2867
+ #endif
2868
+
2869
+ ctx = rn->waiting;
2870
+ rn->waiting = NULL;
2871
+
2872
+ if (ctx) {
2873
+
2874
+ if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION) {
2875
+
2876
+ /* unlock name mutex */
2877
+
2878
+ do {
2879
+ ctx->state = NGX_RESOLVE_NXDOMAIN;
2880
+ next = ctx->next;
2881
+
2882
+ ctx->handler(ctx);
2883
+
2884
+ ctx = next;
2885
+ } while (ctx);
2886
+
2887
+ return;
2888
+ }
2889
+
2890
+ for (next = ctx; next; next = next->next) {
2891
+ next->node = NULL;
2892
+ }
2893
+
2894
+ (void) ngx_resolve_name_locked(r, ctx, &name);
2895
+ }
2896
+
2897
+ /* unlock name mutex */
2898
+
2899
+ return;
2900
+ }
2901
+
2902
+ ngx_log_error(r->log_level, r->log, 0, "no SRV type in DNS response");
2903
+
2904
+ return;
2905
+
2906
+ short_response:
2907
+
2908
+ err = "short DNS response";
2909
+
2910
+ invalid:
2911
+
2912
+ /* unlock name mutex */
2913
+
2914
+ ngx_log_error(r->log_level, r->log, 0, err);
2915
+
2916
+ return;
2917
+
2918
+ failed:
2919
+
2920
+ /* unlock name mutex */
2921
+
2922
+ return;
2923
+ }
2924
+
2925
+
2926
+ static void
2927
+ ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, ngx_resolver_node_t *rn)
2928
+ {
2929
+ ngx_uint_t i;
2930
+ ngx_resolver_t *r;
2931
+ ngx_resolver_ctx_t *cctx;
2932
+ ngx_resolver_srv_name_t *srvs;
2933
+
2934
+ r = ctx->resolver;
2935
+
2936
+ ctx->node = NULL;
2937
+ ctx->state = NGX_OK;
2938
+ ctx->valid = rn->valid;
2939
+ ctx->count = rn->nsrvs;
2940
+
2941
+ srvs = ngx_resolver_calloc(r, rn->nsrvs * sizeof(ngx_resolver_srv_name_t));
2942
+ if (srvs == NULL) {
2943
+ goto failed;
2944
+ }
2945
+
2946
+ ctx->srvs = srvs;
2947
+ ctx->nsrvs = rn->nsrvs;
2948
+
2949
+ for (i = 0; i < rn->nsrvs; i++) {
2950
+ srvs[i].name.data = ngx_resolver_alloc(r, rn->u.srvs[i].name.len);
2951
+ if (srvs[i].name.data == NULL) {
2952
+ goto failed;
2953
+ }
2954
+
2955
+ srvs[i].name.len = rn->u.srvs[i].name.len;
2956
+ ngx_memcpy(srvs[i].name.data, rn->u.srvs[i].name.data,
2957
+ srvs[i].name.len);
2958
+
2959
+ cctx = ngx_resolve_start(r, NULL);
2960
+ if (cctx == NULL) {
2961
+ goto failed;
2962
+ }
2963
+
2964
+ cctx->name = srvs[i].name;
2965
+ cctx->handler = ngx_resolver_srv_names_handler;
2966
+ cctx->data = ctx;
2967
+ cctx->srvs = &srvs[i];
2968
+ cctx->timeout = 0;
2969
+
2970
+ srvs[i].priority = rn->u.srvs[i].priority;
2971
+ srvs[i].weight = rn->u.srvs[i].weight;
2972
+ srvs[i].port = rn->u.srvs[i].port;
2973
+ srvs[i].ctx = cctx;
2974
+
2975
+ if (ngx_resolve_name(cctx) == NGX_ERROR) {
2976
+ srvs[i].ctx = NULL;
2977
+ goto failed;
2978
+ }
2979
+ }
2980
+
2981
+ return;
2982
+
2983
+ failed:
2984
+
2985
+ ctx->state = NGX_ERROR;
2986
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
2987
+
2988
+ ctx->handler(ctx);
2989
+ }
2990
+
2991
+
2992
+ static void
2993
+ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx)
2994
+ {
2995
+ ngx_uint_t i;
2996
+ u_char (*sockaddr)[NGX_SOCKADDRLEN];
2997
+ ngx_addr_t *addrs;
2998
+ ngx_resolver_t *r;
2999
+ struct sockaddr_in *sin;
3000
+ ngx_resolver_ctx_t *ctx;
3001
+ ngx_resolver_srv_name_t *srv;
3002
+ #if (NGX_HAVE_INET6)
3003
+ struct sockaddr_in6 *sin6;
3004
+ #endif
3005
+
3006
+ r = cctx->resolver;
3007
+ ctx = cctx->data;
3008
+ srv = cctx->srvs;
3009
+
3010
+ ctx->count--;
3011
+
3012
+ srv->ctx = NULL;
3013
+
3014
+ if (cctx->naddrs) {
3015
+
3016
+ ctx->valid = ngx_min(ctx->valid, cctx->valid);
3017
+
3018
+ addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t));
3019
+ if (addrs == NULL) {
3020
+ ngx_resolve_name_done(cctx);
3021
+
3022
+ ctx->state = NGX_ERROR;
3023
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
3024
+
3025
+ ctx->handler(ctx);
3026
+ return;
3027
+ }
3028
+
3029
+ sockaddr = ngx_resolver_alloc(r, cctx->naddrs * NGX_SOCKADDRLEN);
3030
+ if (sockaddr == NULL) {
3031
+ ngx_resolver_free(r, addrs);
3032
+ ngx_resolve_name_done(cctx);
3033
+
3034
+ ctx->state = NGX_ERROR;
3035
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
3036
+
3037
+ ctx->handler(ctx);
3038
+ return;
3039
+ }
3040
+
3041
+ for (i = 0; i < cctx->naddrs; i++) {
3042
+ addrs[i].sockaddr = (struct sockaddr *) sockaddr[i];
3043
+ addrs[i].socklen = cctx->addrs[i].socklen;
3044
+
3045
+ ngx_memcpy(sockaddr[i], cctx->addrs[i].sockaddr,
3046
+ addrs[i].socklen);
3047
+
3048
+ switch (addrs[i].sockaddr->sa_family) {
3049
+ #if (NGX_HAVE_INET6)
3050
+ case AF_INET6:
3051
+ sin6 = (struct sockaddr_in6 *) addrs[i].sockaddr;
3052
+ sin6->sin6_port = htons(srv->port);
3053
+ break;
3054
+ #endif
3055
+ default: /* AF_INET */
3056
+ sin = (struct sockaddr_in *) addrs[i].sockaddr;
3057
+ sin->sin_port = htons(srv->port);
3058
+ }
3059
+ }
3060
+
3061
+ srv->addrs = addrs;
3062
+ srv->naddrs = cctx->naddrs;
3063
+ }
3064
+
3065
+ ngx_resolve_name_done(cctx);
3066
+
3067
+ if (ctx->count == 0) {
3068
+ ngx_resolver_report_srv(r, ctx);
3069
+ }
3070
+ }
3071
+
3072
+
3073
+ static void
3074
+ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
3075
+ ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
3076
+ {
3077
+ char *err;
3078
+ size_t len;
3079
+ in_addr_t addr;
3080
+ int32_t ttl;
3081
+ ngx_int_t octet;
3082
+ ngx_str_t name;
3083
+ ngx_uint_t mask, type, class, qident, a, i, start;
3084
+ ngx_queue_t *expire_queue;
3085
+ ngx_rbtree_t *tree;
3086
+ ngx_resolver_an_t *an;
3087
+ ngx_resolver_ctx_t *ctx, *next;
3088
+ ngx_resolver_node_t *rn;
3089
+ #if (NGX_HAVE_INET6)
3090
+ uint32_t hash;
3091
+ ngx_int_t digit;
3092
+ struct in6_addr addr6;
3093
+ #endif
3094
+
3095
+ if (ngx_resolver_copy(r, &name, buf,
3096
+ buf + sizeof(ngx_resolver_hdr_t), buf + n)
3097
+ != NGX_OK)
3098
+ {
3099
+ return;
3100
+ }
3101
+
3102
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);
3103
+
3104
+ /* AF_INET */
3105
+
3106
+ addr = 0;
3107
+ i = sizeof(ngx_resolver_hdr_t);
3108
+
3109
+ for (mask = 0; mask < 32; mask += 8) {
3110
+ len = buf[i++];
3111
+
3112
+ octet = ngx_atoi(&buf[i], len);
3113
+ if (octet == NGX_ERROR || octet > 255) {
3114
+ goto invalid_in_addr_arpa;
3115
+ }
3116
+
3117
+ addr += octet << mask;
3118
+ i += len;
3119
+ }
3120
+
3121
+ if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
3122
+ i += sizeof("\7in-addr\4arpa");
3123
+
3124
+ /* lock addr mutex */
3125
+
3126
+ rn = ngx_resolver_lookup_addr(r, addr);
3127
+
3128
+ tree = &r->addr_rbtree;
3129
+ expire_queue = &r->addr_expire_queue;
3130
+
3131
+ goto valid;
3132
+ }
3133
+
3134
+ invalid_in_addr_arpa:
3135
+
3136
+ #if (NGX_HAVE_INET6)
3137
+
3138
+ i = sizeof(ngx_resolver_hdr_t);
3139
+
3140
+ for (octet = 15; octet >= 0; octet--) {
3141
+ if (buf[i++] != '\1') {
3142
+ goto invalid_ip6_arpa;
3143
+ }
3144
+
3145
+ digit = ngx_hextoi(&buf[i++], 1);
3146
+ if (digit == NGX_ERROR) {
3147
+ goto invalid_ip6_arpa;
3148
+ }
3149
+
3150
+ addr6.s6_addr[octet] = (u_char) digit;
3151
+
3152
+ if (buf[i++] != '\1') {
3153
+ goto invalid_ip6_arpa;
3154
+ }
3155
+
3156
+ digit = ngx_hextoi(&buf[i++], 1);
3157
+ if (digit == NGX_ERROR) {
3158
+ goto invalid_ip6_arpa;
3159
+ }
3160
+
3161
+ addr6.s6_addr[octet] += (u_char) (digit * 16);
3162
+ }
3163
+
3164
+ if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
3165
+ i += sizeof("\3ip6\4arpa");
3166
+
3167
+ /* lock addr mutex */
3168
+
3169
+ hash = ngx_crc32_short(addr6.s6_addr, 16);
3170
+ rn = ngx_resolver_lookup_addr6(r, &addr6, hash);
3171
+
3172
+ tree = &r->addr6_rbtree;
3173
+ expire_queue = &r->addr6_expire_queue;
3174
+
3175
+ goto valid;
3176
+ }
3177
+
3178
+ invalid_ip6_arpa:
3179
+ #endif
3180
+
3181
+ ngx_log_error(r->log_level, r->log, 0,
3182
+ "invalid in-addr.arpa or ip6.arpa name in DNS response");
3183
+ ngx_resolver_free(r, name.data);
3184
+ return;
3185
+
3186
+ valid:
2168
3187
 
2169
3188
  if (rn == NULL || rn->query == NULL) {
2170
3189
  ngx_log_error(r->log_level, r->log, 0,
2171
3190
  "unexpected response for %V", &name);
3191
+ ngx_resolver_free(r, name.data);
2172
3192
  goto failed;
2173
3193
  }
2174
3194
 
@@ -2178,9 +3198,12 @@ valid:
2178
3198
  ngx_log_error(r->log_level, r->log, 0,
2179
3199
  "wrong ident %ui response for %V, expect %ui",
2180
3200
  ident, &name, qident);
3201
+ ngx_resolver_free(r, name.data);
2181
3202
  goto failed;
2182
3203
  }
2183
3204
 
3205
+ ngx_resolver_free(r, name.data);
3206
+
2184
3207
  if (code == 0 && nan == 0) {
2185
3208
  code = NGX_RESOLVE_NXDOMAIN;
2186
3209
  }
@@ -2198,6 +3221,7 @@ valid:
2198
3221
  while (next) {
2199
3222
  ctx = next;
2200
3223
  ctx->state = code;
3224
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
2201
3225
  next = ctx->next;
2202
3226
 
2203
3227
  ctx->handler(ctx);
@@ -2210,45 +3234,91 @@ valid:
2210
3234
 
2211
3235
  i += sizeof(ngx_resolver_qs_t);
2212
3236
 
2213
- if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
3237
+ for (a = 0; a < nan; a++) {
3238
+
3239
+ start = i;
3240
+
3241
+ while (i < n) {
3242
+
3243
+ if (buf[i] & 0xc0) {
3244
+ i += 2;
3245
+ goto found;
3246
+ }
3247
+
3248
+ if (buf[i] == 0) {
3249
+ i++;
3250
+ goto test_length;
3251
+ }
3252
+
3253
+ i += 1 + buf[i];
3254
+ }
3255
+
2214
3256
  goto short_response;
2215
- }
2216
3257
 
2217
- /* compression pointer to *.arpa */
3258
+ test_length:
2218
3259
 
2219
- if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
2220
- err = "invalid in-addr.arpa or ip6.arpa name in DNS response";
2221
- goto invalid;
2222
- }
3260
+ if (i - start < 2) {
3261
+ err = "invalid name in DNS response";
3262
+ goto invalid;
3263
+ }
2223
3264
 
2224
- an = (ngx_resolver_an_t *) &buf[i + 2];
3265
+ found:
2225
3266
 
2226
- class = (an->class_hi << 8) + an->class_lo;
2227
- len = (an->len_hi << 8) + an->len_lo;
2228
- ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
2229
- + (an->ttl[2] << 8) + (an->ttl[3]);
3267
+ if (i + sizeof(ngx_resolver_an_t) >= n) {
3268
+ goto short_response;
3269
+ }
2230
3270
 
2231
- if (class != 1) {
2232
- ngx_log_error(r->log_level, r->log, 0,
2233
- "unexpected RR class %ui", class);
2234
- goto failed;
2235
- }
3271
+ an = (ngx_resolver_an_t *) &buf[i];
2236
3272
 
2237
- if (ttl < 0) {
2238
- ttl = 0;
2239
- }
3273
+ type = (an->type_hi << 8) + an->type_lo;
3274
+ class = (an->class_hi << 8) + an->class_lo;
3275
+ len = (an->len_hi << 8) + an->len_lo;
3276
+ ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
3277
+ + (an->ttl[2] << 8) + (an->ttl[3]);
2240
3278
 
2241
- ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
2242
- "resolver qt:%ui cl:%ui len:%uz",
2243
- (an->type_hi << 8) + an->type_lo,
2244
- class, len);
3279
+ if (class != 1) {
3280
+ ngx_log_error(r->log_level, r->log, 0,
3281
+ "unexpected RR class %ui", class);
3282
+ goto failed;
3283
+ }
3284
+
3285
+ if (ttl < 0) {
3286
+ ttl = 0;
3287
+ }
2245
3288
 
2246
- i += 2 + sizeof(ngx_resolver_an_t);
3289
+ ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
3290
+ "resolver qt:%ui cl:%ui len:%uz",
3291
+ type, class, len);
2247
3292
 
2248
- if (i + len > n) {
2249
- goto short_response;
3293
+ i += sizeof(ngx_resolver_an_t);
3294
+
3295
+ switch (type) {
3296
+
3297
+ case NGX_RESOLVE_PTR:
3298
+
3299
+ goto ptr;
3300
+
3301
+ case NGX_RESOLVE_CNAME:
3302
+
3303
+ break;
3304
+
3305
+ default:
3306
+
3307
+ ngx_log_error(r->log_level, r->log, 0,
3308
+ "unexpected RR type %ui", type);
3309
+ }
3310
+
3311
+ i += len;
2250
3312
  }
2251
3313
 
3314
+ /* unlock addr mutex */
3315
+
3316
+ ngx_log_error(r->log_level, r->log, 0,
3317
+ "no PTR type in DNS response");
3318
+ return;
3319
+
3320
+ ptr:
3321
+
2252
3322
  if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
2253
3323
  goto failed;
2254
3324
  }
@@ -2286,6 +3356,7 @@ valid:
2286
3356
  while (next) {
2287
3357
  ctx = next;
2288
3358
  ctx->state = NGX_OK;
3359
+ ctx->valid = rn->valid;
2289
3360
  ctx->name = name;
2290
3361
  next = ctx->next;
2291
3362
 
@@ -2317,14 +3388,55 @@ failed:
2317
3388
 
2318
3389
 
2319
3390
  static ngx_resolver_node_t *
2320
- ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
3391
+ ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
3392
+ {
3393
+ ngx_int_t rc;
3394
+ ngx_rbtree_node_t *node, *sentinel;
3395
+ ngx_resolver_node_t *rn;
3396
+
3397
+ node = r->name_rbtree.root;
3398
+ sentinel = r->name_rbtree.sentinel;
3399
+
3400
+ while (node != sentinel) {
3401
+
3402
+ if (hash < node->key) {
3403
+ node = node->left;
3404
+ continue;
3405
+ }
3406
+
3407
+ if (hash > node->key) {
3408
+ node = node->right;
3409
+ continue;
3410
+ }
3411
+
3412
+ /* hash == node->key */
3413
+
3414
+ rn = ngx_resolver_node(node);
3415
+
3416
+ rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
3417
+
3418
+ if (rc == 0) {
3419
+ return rn;
3420
+ }
3421
+
3422
+ node = (rc < 0) ? node->left : node->right;
3423
+ }
3424
+
3425
+ /* not found */
3426
+
3427
+ return NULL;
3428
+ }
3429
+
3430
+
3431
+ static ngx_resolver_node_t *
3432
+ ngx_resolver_lookup_srv(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
2321
3433
  {
2322
3434
  ngx_int_t rc;
2323
3435
  ngx_rbtree_node_t *node, *sentinel;
2324
3436
  ngx_resolver_node_t *rn;
2325
3437
 
2326
- node = r->name_rbtree.root;
2327
- sentinel = r->name_rbtree.sentinel;
3438
+ node = r->srv_rbtree.root;
3439
+ sentinel = r->srv_rbtree.sentinel;
2328
3440
 
2329
3441
  while (node != sentinel) {
2330
3442
 
@@ -2644,9 +3756,97 @@ ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
2644
3756
  }
2645
3757
 
2646
3758
 
3759
+ static ngx_int_t
3760
+ ngx_resolver_create_srv_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3761
+ ngx_str_t *name)
3762
+ {
3763
+ u_char *p, *s;
3764
+ size_t len, nlen;
3765
+ ngx_uint_t ident;
3766
+ ngx_resolver_qs_t *qs;
3767
+ ngx_resolver_hdr_t *query;
3768
+
3769
+ nlen = name->len ? (1 + name->len + 1) : 1;
3770
+
3771
+ len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
3772
+
3773
+ p = ngx_resolver_alloc(r, len);
3774
+ if (p == NULL) {
3775
+ return NGX_ERROR;
3776
+ }
3777
+
3778
+ rn->qlen = (u_short) len;
3779
+ rn->query = p;
3780
+
3781
+ query = (ngx_resolver_hdr_t *) p;
3782
+
3783
+ ident = ngx_random();
3784
+
3785
+ ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
3786
+ "resolve: \"%V\" SRV %i", name, ident & 0xffff);
3787
+
3788
+ query->ident_hi = (u_char) ((ident >> 8) & 0xff);
3789
+ query->ident_lo = (u_char) (ident & 0xff);
3790
+
3791
+ /* recursion query */
3792
+ query->flags_hi = 1; query->flags_lo = 0;
3793
+
3794
+ /* one question */
3795
+ query->nqs_hi = 0; query->nqs_lo = 1;
3796
+ query->nan_hi = 0; query->nan_lo = 0;
3797
+ query->nns_hi = 0; query->nns_lo = 0;
3798
+ query->nar_hi = 0; query->nar_lo = 0;
3799
+
3800
+ p += sizeof(ngx_resolver_hdr_t) + nlen;
3801
+
3802
+ qs = (ngx_resolver_qs_t *) p;
3803
+
3804
+ /* query type */
3805
+ qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_SRV;
3806
+
3807
+ /* IN query class */
3808
+ qs->class_hi = 0; qs->class_lo = 1;
3809
+
3810
+ /* converts "www.example.com" to "\3www\7example\3com\0" */
3811
+
3812
+ len = 0;
3813
+ p--;
3814
+ *p-- = '\0';
3815
+
3816
+ if (name->len == 0) {
3817
+ return NGX_DECLINED;
3818
+ }
3819
+
3820
+ for (s = name->data + name->len - 1; s >= name->data; s--) {
3821
+ if (*s != '.') {
3822
+ *p = *s;
3823
+ len++;
3824
+
3825
+ } else {
3826
+ if (len == 0 || len > 255) {
3827
+ return NGX_DECLINED;
3828
+ }
3829
+
3830
+ *p = (u_char) len;
3831
+ len = 0;
3832
+ }
3833
+
3834
+ p--;
3835
+ }
3836
+
3837
+ if (len == 0 || len > 255) {
3838
+ return NGX_DECLINED;
3839
+ }
3840
+
3841
+ *p = (u_char) len;
3842
+
3843
+ return NGX_OK;
3844
+ }
3845
+
3846
+
2647
3847
  static ngx_int_t
2648
3848
  ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
2649
- ngx_addr_t *addr)
3849
+ ngx_resolver_addr_t *addr)
2650
3850
  {
2651
3851
  u_char *p, *d;
2652
3852
  size_t len;
@@ -2850,6 +4050,8 @@ ngx_resolver_timeout_handler(ngx_event_t *ev)
2850
4050
  static void
2851
4051
  ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
2852
4052
  {
4053
+ ngx_uint_t i;
4054
+
2853
4055
  /* lock alloc mutex */
2854
4056
 
2855
4057
  if (rn->query) {
@@ -2874,6 +4076,16 @@ ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
2874
4076
  }
2875
4077
  #endif
2876
4078
 
4079
+ if (rn->nsrvs) {
4080
+ for (i = 0; i < rn->nsrvs; i++) {
4081
+ if (rn->u.srvs[i].name.data) {
4082
+ ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
4083
+ }
4084
+ }
4085
+
4086
+ ngx_resolver_free_locked(r, rn->u.srvs);
4087
+ }
4088
+
2877
4089
  ngx_resolver_free_locked(r, rn);
2878
4090
 
2879
4091
  /* unlock alloc mutex */
@@ -2945,15 +4157,15 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
2945
4157
  }
2946
4158
 
2947
4159
 
2948
- static ngx_addr_t *
4160
+ static ngx_resolver_addr_t *
2949
4161
  ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
2950
4162
  ngx_uint_t rotate)
2951
4163
  {
2952
- ngx_addr_t *dst;
2953
4164
  ngx_uint_t d, i, j, n;
2954
4165
  u_char (*sockaddr)[NGX_SOCKADDRLEN];
2955
4166
  in_addr_t *addr;
2956
4167
  struct sockaddr_in *sin;
4168
+ ngx_resolver_addr_t *dst;
2957
4169
  #if (NGX_HAVE_INET6)
2958
4170
  struct in6_addr *addr6;
2959
4171
  struct sockaddr_in6 *sin6;
@@ -2964,7 +4176,7 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
2964
4176
  n += rn->naddrs6;
2965
4177
  #endif
2966
4178
 
2967
- dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t));
4179
+ dst = ngx_resolver_calloc(r, n * sizeof(ngx_resolver_addr_t));
2968
4180
  if (dst == NULL) {
2969
4181
  return NULL;
2970
4182
  }
@@ -3028,6 +4240,99 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3028
4240
  }
3029
4241
 
3030
4242
 
4243
+ static void
4244
+ ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
4245
+ {
4246
+ ngx_uint_t naddrs, nsrvs, nw, i, j, k, l, m, n, w;
4247
+ ngx_resolver_addr_t *addrs;
4248
+ ngx_resolver_srv_name_t *srvs;
4249
+
4250
+ naddrs = 0;
4251
+
4252
+ for (i = 0; i < ctx->nsrvs; i++) {
4253
+ naddrs += ctx->srvs[i].naddrs;
4254
+ }
4255
+
4256
+ if (naddrs == 0) {
4257
+ ctx->state = NGX_RESOLVE_NXDOMAIN;
4258
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
4259
+
4260
+ ctx->handler(ctx);
4261
+ return;
4262
+ }
4263
+
4264
+ addrs = ngx_resolver_calloc(r, naddrs * sizeof(ngx_resolver_addr_t));
4265
+ if (addrs == NULL) {
4266
+ ctx->state = NGX_ERROR;
4267
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
4268
+
4269
+ ctx->handler(ctx);
4270
+ return;
4271
+ }
4272
+
4273
+ srvs = ctx->srvs;
4274
+ nsrvs = ctx->nsrvs;
4275
+
4276
+ i = 0;
4277
+ n = 0;
4278
+
4279
+ do {
4280
+ nw = 0;
4281
+
4282
+ for (j = i; j < nsrvs; j++) {
4283
+ if (srvs[j].priority != srvs[i].priority) {
4284
+ break;
4285
+ }
4286
+
4287
+ nw += srvs[j].naddrs * srvs[j].weight;
4288
+ }
4289
+
4290
+ if (nw == 0) {
4291
+ goto next_srv;
4292
+ }
4293
+
4294
+ w = ngx_random() % nw;
4295
+
4296
+ for (k = i; k < j; k++) {
4297
+ if (w < srvs[k].naddrs * srvs[k].weight) {
4298
+ break;
4299
+ }
4300
+
4301
+ w -= srvs[k].naddrs * srvs[k].weight;
4302
+ }
4303
+
4304
+ for (l = i; l < j; l++) {
4305
+
4306
+ for (m = 0; m < srvs[k].naddrs; m++) {
4307
+ addrs[n].socklen = srvs[k].addrs[m].socklen;
4308
+ addrs[n].sockaddr = srvs[k].addrs[m].sockaddr;
4309
+ addrs[n].name = srvs[k].name;
4310
+ addrs[n].priority = srvs[k].priority;
4311
+ addrs[n].weight = srvs[k].weight;
4312
+ n++;
4313
+ }
4314
+
4315
+ if (++k == j) {
4316
+ k = i;
4317
+ }
4318
+ }
4319
+
4320
+ next_srv:
4321
+
4322
+ i = j;
4323
+
4324
+ } while (i < ctx->nsrvs);
4325
+
4326
+ ctx->state = NGX_OK;
4327
+ ctx->addrs = addrs;
4328
+ ctx->naddrs = naddrs;
4329
+
4330
+ ctx->handler(ctx);
4331
+
4332
+ ngx_resolver_free(r, addrs);
4333
+ }
4334
+
4335
+
3031
4336
  char *
3032
4337
  ngx_resolver_strerror(ngx_int_t err)
3033
4338
  {
@@ -3054,8 +4359,8 @@ ngx_resolver_strerror(ngx_int_t err)
3054
4359
  static u_char *
3055
4360
  ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
3056
4361
  {
3057
- u_char *p;
3058
- ngx_udp_connection_t *uc;
4362
+ u_char *p;
4363
+ ngx_resolver_connection_t *rec;
3059
4364
 
3060
4365
  p = buf;
3061
4366
 
@@ -3064,10 +4369,10 @@ ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
3064
4369
  len -= p - buf;
3065
4370
  }
3066
4371
 
3067
- uc = log->data;
4372
+ rec = log->data;
3068
4373
 
3069
- if (uc) {
3070
- p = ngx_snprintf(p, len, ", resolver: %V", &uc->server);
4374
+ if (rec) {
4375
+ p = ngx_snprintf(p, len, ", resolver: %V", &rec->server);
3071
4376
  }
3072
4377
 
3073
4378
  return p;
@@ -3075,7 +4380,7 @@ ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
3075
4380
 
3076
4381
 
3077
4382
  ngx_int_t
3078
- ngx_udp_connect(ngx_udp_connection_t *uc)
4383
+ ngx_udp_connect(ngx_resolver_connection_t *rec)
3079
4384
  {
3080
4385
  int rc;
3081
4386
  ngx_int_t event;
@@ -3083,21 +4388,21 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
3083
4388
  ngx_socket_t s;
3084
4389
  ngx_connection_t *c;
3085
4390
 
3086
- s = ngx_socket(uc->sockaddr->sa_family, SOCK_DGRAM, 0);
4391
+ s = ngx_socket(rec->sockaddr->sa_family, SOCK_DGRAM, 0);
3087
4392
 
3088
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);
4393
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "UDP socket %d", s);
3089
4394
 
3090
4395
  if (s == (ngx_socket_t) -1) {
3091
- ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
4396
+ ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
3092
4397
  ngx_socket_n " failed");
3093
4398
  return NGX_ERROR;
3094
4399
  }
3095
4400
 
3096
- c = ngx_get_connection(s, &uc->log);
4401
+ c = ngx_get_connection(s, &rec->log);
3097
4402
 
3098
4403
  if (c == NULL) {
3099
4404
  if (ngx_close_socket(s) == -1) {
3100
- ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
4405
+ ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
3101
4406
  ngx_close_socket_n "failed");
3102
4407
  }
3103
4408
 
@@ -3105,7 +4410,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
3105
4410
  }
3106
4411
 
3107
4412
  if (ngx_nonblocking(s) == -1) {
3108
- ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
4413
+ ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
3109
4414
  ngx_nonblocking_n " failed");
3110
4415
 
3111
4416
  goto failed;
@@ -3114,22 +4419,22 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
3114
4419
  rev = c->read;
3115
4420
  wev = c->write;
3116
4421
 
3117
- rev->log = &uc->log;
3118
- wev->log = &uc->log;
4422
+ rev->log = &rec->log;
4423
+ wev->log = &rec->log;
3119
4424
 
3120
- uc->connection = c;
4425
+ rec->udp = c;
3121
4426
 
3122
4427
  c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
3123
4428
 
3124
- ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
3125
- "connect to %V, fd:%d #%uA", &uc->server, s, c->number);
4429
+ ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0,
4430
+ "connect to %V, fd:%d #%uA", &rec->server, s, c->number);
3126
4431
 
3127
- rc = connect(s, uc->sockaddr, uc->socklen);
4432
+ rc = connect(s, rec->sockaddr, rec->socklen);
3128
4433
 
3129
- /* TODO: aio, iocp */
4434
+ /* TODO: iocp */
3130
4435
 
3131
4436
  if (rc == -1) {
3132
- ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
4437
+ ngx_log_error(NGX_LOG_CRIT, &rec->log, ngx_socket_errno,
3133
4438
  "connect() failed");
3134
4439
 
3135
4440
  goto failed;
@@ -3138,31 +4443,220 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
3138
4443
  /* UDP sockets are always ready to write */
3139
4444
  wev->ready = 1;
3140
4445
 
3141
- if (ngx_add_event) {
4446
+ event = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ?
4447
+ /* kqueue, epoll */ NGX_CLEAR_EVENT:
4448
+ /* select, poll, /dev/poll */ NGX_LEVEL_EVENT;
4449
+ /* eventport event type has no meaning: oneshot only */
4450
+
4451
+ if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
4452
+ goto failed;
4453
+ }
4454
+
4455
+ return NGX_OK;
4456
+
4457
+ failed:
4458
+
4459
+ ngx_close_connection(c);
4460
+ rec->udp = NULL;
4461
+
4462
+ return NGX_ERROR;
4463
+ }
4464
+
4465
+
4466
+ ngx_int_t
4467
+ ngx_tcp_connect(ngx_resolver_connection_t *rec)
4468
+ {
4469
+ int rc;
4470
+ ngx_int_t event;
4471
+ ngx_err_t err;
4472
+ ngx_uint_t level;
4473
+ ngx_socket_t s;
4474
+ ngx_event_t *rev, *wev;
4475
+ ngx_connection_t *c;
4476
+
4477
+ s = ngx_socket(rec->sockaddr->sa_family, SOCK_STREAM, 0);
4478
+
4479
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "TCP socket %d", s);
4480
+
4481
+ if (s == (ngx_socket_t) -1) {
4482
+ ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
4483
+ ngx_socket_n " failed");
4484
+ return NGX_ERROR;
4485
+ }
4486
+
4487
+ c = ngx_get_connection(s, &rec->log);
4488
+
4489
+ if (c == NULL) {
4490
+ if (ngx_close_socket(s) == -1) {
4491
+ ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
4492
+ ngx_close_socket_n "failed");
4493
+ }
4494
+
4495
+ return NGX_ERROR;
4496
+ }
4497
+
4498
+ if (ngx_nonblocking(s) == -1) {
4499
+ ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
4500
+ ngx_nonblocking_n " failed");
4501
+
4502
+ goto failed;
4503
+ }
4504
+
4505
+ rev = c->read;
4506
+ wev = c->write;
4507
+
4508
+ rev->log = &rec->log;
4509
+ wev->log = &rec->log;
4510
+
4511
+ rec->tcp = c;
4512
+
4513
+ c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
4514
+
4515
+ if (ngx_add_conn) {
4516
+ if (ngx_add_conn(c) == NGX_ERROR) {
4517
+ goto failed;
4518
+ }
4519
+ }
4520
+
4521
+ ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0,
4522
+ "connect to %V, fd:%d #%uA", &rec->server, s, c->number);
4523
+
4524
+ rc = connect(s, rec->sockaddr, rec->socklen);
4525
+
4526
+ if (rc == -1) {
4527
+ err = ngx_socket_errno;
4528
+
4529
+
4530
+ if (err != NGX_EINPROGRESS
4531
+ #if (NGX_WIN32)
4532
+ /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
4533
+ && err != NGX_EAGAIN
4534
+ #endif
4535
+ )
4536
+ {
4537
+ if (err == NGX_ECONNREFUSED
4538
+ #if (NGX_LINUX)
4539
+ /*
4540
+ * Linux returns EAGAIN instead of ECONNREFUSED
4541
+ * for unix sockets if listen queue is full
4542
+ */
4543
+ || err == NGX_EAGAIN
4544
+ #endif
4545
+ || err == NGX_ECONNRESET
4546
+ || err == NGX_ENETDOWN
4547
+ || err == NGX_ENETUNREACH
4548
+ || err == NGX_EHOSTDOWN
4549
+ || err == NGX_EHOSTUNREACH)
4550
+ {
4551
+ level = NGX_LOG_ERR;
4552
+
4553
+ } else {
4554
+ level = NGX_LOG_CRIT;
4555
+ }
4556
+
4557
+ ngx_log_error(level, c->log, err, "connect() to %V failed",
4558
+ &rec->server);
4559
+
4560
+ ngx_close_connection(c);
4561
+ rec->tcp = NULL;
4562
+
4563
+ return NGX_ERROR;
4564
+ }
4565
+ }
4566
+
4567
+ if (ngx_add_conn) {
4568
+ if (rc == -1) {
4569
+
4570
+ /* NGX_EINPROGRESS */
4571
+
4572
+ return NGX_AGAIN;
4573
+ }
4574
+
4575
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected");
4576
+
4577
+ wev->ready = 1;
4578
+
4579
+ return NGX_OK;
4580
+ }
4581
+
4582
+ if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
3142
4583
 
3143
- event = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ?
3144
- /* kqueue, epoll */ NGX_CLEAR_EVENT:
3145
- /* select, poll, /dev/poll */ NGX_LEVEL_EVENT;
3146
- /* eventport event type has no meaning: oneshot only */
4584
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, ngx_socket_errno,
4585
+ "connect(): %d", rc);
3147
4586
 
3148
- if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
4587
+ if (ngx_blocking(s) == -1) {
4588
+ ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
4589
+ ngx_blocking_n " failed");
3149
4590
  goto failed;
3150
4591
  }
3151
4592
 
4593
+ /*
4594
+ * FreeBSD's aio allows to post an operation on non-connected socket.
4595
+ * NT does not support it.
4596
+ *
4597
+ * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT
4598
+ */
4599
+
4600
+ rev->ready = 1;
4601
+ wev->ready = 1;
4602
+
4603
+ return NGX_OK;
4604
+ }
4605
+
4606
+ if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
4607
+
4608
+ /* kqueue */
4609
+
4610
+ event = NGX_CLEAR_EVENT;
4611
+
3152
4612
  } else {
3153
- /* rtsig */
3154
4613
 
3155
- if (ngx_add_conn(c) == NGX_ERROR) {
4614
+ /* select, poll, /dev/poll */
4615
+
4616
+ event = NGX_LEVEL_EVENT;
4617
+ }
4618
+
4619
+ if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
4620
+ goto failed;
4621
+ }
4622
+
4623
+ if (rc == -1) {
4624
+
4625
+ /* NGX_EINPROGRESS */
4626
+
4627
+ if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
3156
4628
  goto failed;
3157
4629
  }
4630
+
4631
+ return NGX_AGAIN;
3158
4632
  }
3159
4633
 
4634
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected");
4635
+
4636
+ wev->ready = 1;
4637
+
3160
4638
  return NGX_OK;
3161
4639
 
3162
4640
  failed:
3163
4641
 
3164
4642
  ngx_close_connection(c);
3165
- uc->connection = NULL;
4643
+ rec->tcp = NULL;
3166
4644
 
3167
4645
  return NGX_ERROR;
3168
4646
  }
4647
+
4648
+
4649
+ static ngx_int_t
4650
+ ngx_resolver_cmp_srvs(const void *one, const void *two)
4651
+ {
4652
+ ngx_int_t p1, p2;
4653
+ ngx_resolver_srv_t *first, *second;
4654
+
4655
+ first = (ngx_resolver_srv_t *) one;
4656
+ second = (ngx_resolver_srv_t *) two;
4657
+
4658
+ p1 = first->priority;
4659
+ p2 = second->priority;
4660
+
4661
+ return p1 - p2;
4662
+ }