Mercurial > hg > nginx-quic
annotate src/core/ngx_hash.c @ 7354:1812f1d79d84
Fixed socket leak with "return 444" in error_page (ticket #274).
Socket leak was observed in the following configuration:
error_page 400 = /close;
location = /close {
return 444;
}
The problem is that "return 444" triggers termination of the request,
and due to error_page termination thinks that it needs to use a posted
request to clear stack. But at the early request processing where 400
errors are generated there are no ngx_http_run_posted_requests() calls,
so the request is only terminated after an external event.
Variants of the problem include "error_page 497" instead (ticket #695)
and various other errors generated during early request processing
(405, 414, 421, 494, 495, 496, 501, 505).
The same problem can be also triggered with "return 499" and "return 408"
as both codes trigger ngx_http_terminate_request(), much like "return 444".
To fix this, the patch adds ngx_http_run_posted_requests() calls to
ngx_http_process_request_line() and ngx_http_process_request_headers()
functions, and to ngx_http_v2_run_request() and ngx_http_v2_push_stream()
functions in HTTP/2.
Since the ngx_http_process_request() function is now only called via
other functions which call ngx_http_run_posted_requests(), the call
there is no longer needed and was removed.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 21 Sep 2018 15:59:30 +0300 |
parents | 7fc16ff7ddc4 |
children | c3f60d618c17 |
rev | line source |
---|---|
507 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
507 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 | |
11 | |
589 | 12 void * |
13 ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len) | |
14 { | |
15 ngx_uint_t i; | |
16 ngx_hash_elt_t *elt; | |
17 | |
18 #if 0 | |
2155 | 19 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "hf:\"%*s\"", len, name); |
589 | 20 #endif |
21 | |
22 elt = hash->buckets[key % hash->size]; | |
23 | |
24 if (elt == NULL) { | |
25 return NULL; | |
26 } | |
27 | |
28 while (elt->value) { | |
29 if (len != (size_t) elt->len) { | |
30 goto next; | |
31 } | |
32 | |
33 for (i = 0; i < len; i++) { | |
34 if (name[i] != elt->name[i]) { | |
35 goto next; | |
36 } | |
37 } | |
38 | |
39 return elt->value; | |
40 | |
41 next: | |
42 | |
43 elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len, | |
44 sizeof(void *)); | |
45 continue; | |
46 } | |
47 | |
48 return NULL; | |
49 } | |
50 | |
51 | |
52 void * | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
53 ngx_hash_find_wc_head(ngx_hash_wildcard_t *hwc, u_char *name, size_t len) |
589 | 54 { |
55 void *value; | |
56 ngx_uint_t i, n, key; | |
57 | |
58 #if 0 | |
2155 | 59 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wch:\"%*s\"", len, name); |
589 | 60 #endif |
61 | |
62 n = len; | |
63 | |
64 while (n) { | |
65 if (name[n - 1] == '.') { | |
66 break; | |
67 } | |
68 | |
69 n--; | |
70 } | |
71 | |
72 key = 0; | |
73 | |
74 for (i = n; i < len; i++) { | |
75 key = ngx_hash(key, name[i]); | |
76 } | |
77 | |
78 #if 0 | |
79 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "key:\"%ui\"", key); | |
80 #endif | |
81 | |
82 value = ngx_hash_find(&hwc->hash, key, &name[n], len - n); | |
83 | |
2149 | 84 #if 0 |
85 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "value:\"%p\"", value); | |
86 #endif | |
87 | |
589 | 88 if (value) { |
591 | 89 |
90 /* | |
91 * the 2 low bits of value have the special meaning: | |
2168
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
92 * 00 - value is data pointer for both "example.com" |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
93 * and "*.example.com"; |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
94 * 01 - value is data pointer for "*.example.com" only; |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
95 * 10 - value is pointer to wildcard hash allowing |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
96 * both "example.com" and "*.example.com"; |
591 | 97 * 11 - value is pointer to wildcard hash allowing |
2168
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
98 * "*.example.com" only. |
591 | 99 */ |
100 | |
2168
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
101 if ((uintptr_t) value & 2) { |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
102 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
103 if (n == 0) { |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
104 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
105 /* "example.com" */ |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
106 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
107 if ((uintptr_t) value & 1) { |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
108 return NULL; |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
109 } |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
110 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
111 hwc = (ngx_hash_wildcard_t *) |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
112 ((uintptr_t) value & (uintptr_t) ~3); |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
113 return hwc->value; |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
114 } |
591 | 115 |
116 hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~3); | |
117 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
118 value = ngx_hash_find_wc_head(hwc, name, n - 1); |
589 | 119 |
120 if (value) { | |
121 return value; | |
122 } | |
123 | |
124 return hwc->value; | |
125 } | |
126 | |
2168
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
127 if ((uintptr_t) value & 1) { |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
128 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
129 if (n == 0) { |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
130 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
131 /* "example.com" */ |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
132 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
133 return NULL; |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
134 } |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
135 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
136 return (void *) ((uintptr_t) value & (uintptr_t) ~3); |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
137 } |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
138 |
589 | 139 return value; |
140 } | |
141 | |
142 return hwc->value; | |
143 } | |
144 | |
145 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
146 void * |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
147 ngx_hash_find_wc_tail(ngx_hash_wildcard_t *hwc, u_char *name, size_t len) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
148 { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
149 void *value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
150 ngx_uint_t i, key; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
151 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
152 #if 0 |
2155 | 153 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wct:\"%*s\"", len, name); |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
154 #endif |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
155 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
156 key = 0; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
157 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
158 for (i = 0; i < len; i++) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
159 if (name[i] == '.') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
160 break; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
161 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
162 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
163 key = ngx_hash(key, name[i]); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
164 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
165 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
166 if (i == len) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
167 return NULL; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
168 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
169 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
170 #if 0 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
171 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "key:\"%ui\"", key); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
172 #endif |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
173 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
174 value = ngx_hash_find(&hwc->hash, key, name, i); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
175 |
2155 | 176 #if 0 |
177 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "value:\"%p\"", value); | |
178 #endif | |
179 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
180 if (value) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
181 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
182 /* |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
183 * the 2 low bits of value have the special meaning: |
2168
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
184 * 00 - value is data pointer; |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
185 * 11 - value is pointer to wildcard hash allowing "example.*". |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
186 */ |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
187 |
2168
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
188 if ((uintptr_t) value & 2) { |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
189 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
190 i++; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
191 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
192 hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~3); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
193 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
194 value = ngx_hash_find_wc_tail(hwc, &name[i], len - i); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
195 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
196 if (value) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
197 return value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
198 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
199 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
200 return hwc->value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
201 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
202 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
203 return value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
204 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
205 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
206 return hwc->value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
207 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
208 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
209 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
210 void * |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
211 ngx_hash_find_combined(ngx_hash_combined_t *hash, ngx_uint_t key, u_char *name, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
212 size_t len) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
213 { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
214 void *value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
215 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
216 if (hash->hash.buckets) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
217 value = ngx_hash_find(&hash->hash, key, name, len); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
218 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
219 if (value) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
220 return value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
221 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
222 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
223 |
2195 | 224 if (len == 0) { |
225 return NULL; | |
226 } | |
227 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
228 if (hash->wc_head && hash->wc_head->hash.buckets) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
229 value = ngx_hash_find_wc_head(hash->wc_head, name, len); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
230 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
231 if (value) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
232 return value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
233 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
234 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
235 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
236 if (hash->wc_tail && hash->wc_tail->hash.buckets) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
237 value = ngx_hash_find_wc_tail(hash->wc_tail, name, len); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
238 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
239 if (value) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
240 return value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
241 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
242 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
243 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
244 return NULL; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
245 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
246 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
247 |
589 | 248 #define NGX_HASH_ELT_SIZE(name) \ |
3510
4c70bbdfd076
allow hash key values more than 255 bytes, it does not actually increase mean
Igor Sysoev <igor@sysoev.ru>
parents:
3118
diff
changeset
|
249 (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *))) |
589 | 250 |
507 | 251 ngx_int_t |
589 | 252 ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts) |
253 { | |
254 u_char *elts; | |
595 | 255 size_t len; |
256 u_short *test; | |
589 | 257 ngx_uint_t i, n, key, size, start, bucket_size; |
258 ngx_hash_elt_t *elt, **buckets; | |
259 | |
6225
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
260 if (hinit->max_size == 0) { |
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
261 ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, |
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
262 "could not build %s, you should " |
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
263 "increase %s_max_size: %i", |
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
264 hinit->name, hinit->name, hinit->max_size); |
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
265 return NGX_ERROR; |
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
266 } |
3b6d69857de2
Core: fixed potential division by zero when initializing hash.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6224
diff
changeset
|
267 |
589 | 268 for (n = 0; n < nelts; n++) { |
269 if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) | |
270 { | |
271 ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, | |
6224
ddf35e019a80
Core: fixed style in the error message.
Sergey Kandaurov <pluknet@nginx.com>
parents:
5985
diff
changeset
|
272 "could not build %s, you should " |
589 | 273 "increase %s_bucket_size: %i", |
274 hinit->name, hinit->name, hinit->bucket_size); | |
275 return NGX_ERROR; | |
276 } | |
277 } | |
278 | |
595 | 279 test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log); |
589 | 280 if (test == NULL) { |
281 return NGX_ERROR; | |
282 } | |
283 | |
631 | 284 bucket_size = hinit->bucket_size - sizeof(void *); |
285 | |
746 | 286 start = nelts / (bucket_size / (2 * sizeof(void *))); |
589 | 287 start = start ? start : 1; |
288 | |
4404
840f3e768ef8
Fixed division by zero exception in ngx_hash_init().
Valentin Bartenev <vbart@nginx.com>
parents:
3510
diff
changeset
|
289 if (hinit->max_size > 10000 && nelts && hinit->max_size / nelts < 100) { |
631 | 290 start = hinit->max_size - 1000; |
291 } | |
589 | 292 |
5636
54f847c88cf7
Core: fixed hash to actually try max_size.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5635
diff
changeset
|
293 for (size = start; size <= hinit->max_size; size++) { |
589 | 294 |
595 | 295 ngx_memzero(test, size * sizeof(u_short)); |
589 | 296 |
297 for (n = 0; n < nelts; n++) { | |
298 if (names[n].key.data == NULL) { | |
299 continue; | |
300 } | |
301 | |
302 key = names[n].key_hash % size; | |
595 | 303 test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); |
589 | 304 |
305 #if 0 | |
306 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
307 "%ui: %ui %ui \"%V\"", | |
308 size, key, test[key], &names[n].key); | |
309 #endif | |
310 | |
595 | 311 if (test[key] > (u_short) bucket_size) { |
589 | 312 goto next; |
313 } | |
314 } | |
315 | |
316 goto found; | |
317 | |
318 next: | |
319 | |
320 continue; | |
321 } | |
322 | |
5985
f961c719fb09
Core: fixed potential buffer overrun when initializing hash.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5870
diff
changeset
|
323 size = hinit->max_size; |
5870
5e72578e6503
Core: fixed buffer overrun when hash max_size reached.
Yichun Zhang <agentzh@gmail.com>
parents:
5636
diff
changeset
|
324 |
5635
c348dea081fb
Core: hash now ignores bucket_size if it hits max_size limit.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4689
diff
changeset
|
325 ngx_log_error(NGX_LOG_WARN, hinit->pool->log, 0, |
c348dea081fb
Core: hash now ignores bucket_size if it hits max_size limit.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4689
diff
changeset
|
326 "could not build optimal %s, you should increase " |
c348dea081fb
Core: hash now ignores bucket_size if it hits max_size limit.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4689
diff
changeset
|
327 "either %s_max_size: %i or %s_bucket_size: %i; " |
c348dea081fb
Core: hash now ignores bucket_size if it hits max_size limit.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4689
diff
changeset
|
328 "ignoring %s_bucket_size", |
589 | 329 hinit->name, hinit->name, hinit->max_size, |
5635
c348dea081fb
Core: hash now ignores bucket_size if it hits max_size limit.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4689
diff
changeset
|
330 hinit->name, hinit->bucket_size, hinit->name); |
589 | 331 |
332 found: | |
333 | |
334 for (i = 0; i < size; i++) { | |
335 test[i] = sizeof(void *); | |
336 } | |
337 | |
338 for (n = 0; n < nelts; n++) { | |
339 if (names[n].key.data == NULL) { | |
340 continue; | |
341 } | |
342 | |
343 key = names[n].key_hash % size; | |
595 | 344 test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); |
589 | 345 } |
346 | |
347 len = 0; | |
348 | |
349 for (i = 0; i < size; i++) { | |
350 if (test[i] == sizeof(void *)) { | |
351 continue; | |
352 } | |
353 | |
595 | 354 test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size)); |
589 | 355 |
356 len += test[i]; | |
357 } | |
358 | |
359 if (hinit->hash == NULL) { | |
360 hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t) | |
361 + size * sizeof(ngx_hash_elt_t *)); | |
362 if (hinit->hash == NULL) { | |
363 ngx_free(test); | |
364 return NGX_ERROR; | |
365 } | |
366 | |
367 buckets = (ngx_hash_elt_t **) | |
368 ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t)); | |
369 | |
370 } else { | |
371 buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *)); | |
372 if (buckets == NULL) { | |
373 ngx_free(test); | |
374 return NGX_ERROR; | |
375 } | |
376 } | |
377 | |
378 elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size); | |
379 if (elts == NULL) { | |
380 ngx_free(test); | |
381 return NGX_ERROR; | |
382 } | |
383 | |
384 elts = ngx_align_ptr(elts, ngx_cacheline_size); | |
385 | |
386 for (i = 0; i < size; i++) { | |
387 if (test[i] == sizeof(void *)) { | |
388 continue; | |
389 } | |
390 | |
391 buckets[i] = (ngx_hash_elt_t *) elts; | |
392 elts += test[i]; | |
393 } | |
394 | |
395 for (i = 0; i < size; i++) { | |
396 test[i] = 0; | |
397 } | |
398 | |
399 for (n = 0; n < nelts; n++) { | |
400 if (names[n].key.data == NULL) { | |
401 continue; | |
402 } | |
403 | |
404 key = names[n].key_hash % size; | |
405 elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]); | |
406 | |
407 elt->value = names[n].value; | |
3510
4c70bbdfd076
allow hash key values more than 255 bytes, it does not actually increase mean
Igor Sysoev <igor@sysoev.ru>
parents:
3118
diff
changeset
|
408 elt->len = (u_short) names[n].key.len; |
589 | 409 |
2135 | 410 ngx_strlow(elt->name, names[n].key.data, names[n].key.len); |
589 | 411 |
595 | 412 test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); |
589 | 413 } |
414 | |
415 for (i = 0; i < size; i++) { | |
416 if (buckets[i] == NULL) { | |
417 continue; | |
418 } | |
419 | |
420 elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]); | |
421 | |
422 elt->value = NULL; | |
423 } | |
424 | |
425 ngx_free(test); | |
426 | |
427 hinit->hash->buckets = buckets; | |
428 hinit->hash->size = size; | |
429 | |
430 #if 0 | |
431 | |
432 for (i = 0; i < size; i++) { | |
433 ngx_str_t val; | |
434 ngx_uint_t key; | |
435 | |
436 elt = buckets[i]; | |
437 | |
438 if (elt == NULL) { | |
439 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
440 "%ui: NULL", i); | |
441 continue; | |
442 } | |
443 | |
444 while (elt->value) { | |
445 val.len = elt->len; | |
446 val.data = &elt->name[0]; | |
447 | |
448 key = hinit->key(val.data, val.len); | |
449 | |
450 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
451 "%ui: %p \"%V\" %ui", i, elt, &val, key); | |
452 | |
453 elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len, | |
454 sizeof(void *)); | |
455 } | |
456 } | |
457 | |
458 #endif | |
459 | |
460 return NGX_OK; | |
461 } | |
462 | |
463 | |
464 ngx_int_t | |
465 ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, | |
466 ngx_uint_t nelts) | |
467 { | |
593 | 468 size_t len, dot_len; |
591 | 469 ngx_uint_t i, n, dot; |
589 | 470 ngx_array_t curr_names, next_names; |
471 ngx_hash_key_t *name, *next_name; | |
472 ngx_hash_init_t h; | |
473 ngx_hash_wildcard_t *wdc; | |
474 | |
475 if (ngx_array_init(&curr_names, hinit->temp_pool, nelts, | |
476 sizeof(ngx_hash_key_t)) | |
477 != NGX_OK) | |
478 { | |
479 return NGX_ERROR; | |
480 } | |
481 | |
482 if (ngx_array_init(&next_names, hinit->temp_pool, nelts, | |
483 sizeof(ngx_hash_key_t)) | |
484 != NGX_OK) | |
485 { | |
486 return NGX_ERROR; | |
487 } | |
488 | |
489 for (n = 0; n < nelts; n = i) { | |
490 | |
491 #if 0 | |
492 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
493 "wc0: \"%V\"", &names[n].key); | |
494 #endif | |
495 | |
591 | 496 dot = 0; |
497 | |
589 | 498 for (len = 0; len < names[n].key.len; len++) { |
499 if (names[n].key.data[len] == '.') { | |
591 | 500 dot = 1; |
589 | 501 break; |
502 } | |
503 } | |
504 | |
505 name = ngx_array_push(&curr_names); | |
506 if (name == NULL) { | |
507 return NGX_ERROR; | |
508 } | |
509 | |
591 | 510 name->key.len = len; |
589 | 511 name->key.data = names[n].key.data; |
512 name->key_hash = hinit->key(name->key.data, name->key.len); | |
513 name->value = names[n].value; | |
514 | |
515 #if 0 | |
516 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
593 | 517 "wc1: \"%V\" %ui", &name->key, dot); |
589 | 518 #endif |
519 | |
593 | 520 dot_len = len + 1; |
521 | |
591 | 522 if (dot) { |
523 len++; | |
524 } | |
525 | |
589 | 526 next_names.nelts = 0; |
527 | |
528 if (names[n].key.len != len) { | |
529 next_name = ngx_array_push(&next_names); | |
530 if (next_name == NULL) { | |
531 return NGX_ERROR; | |
532 } | |
533 | |
534 next_name->key.len = names[n].key.len - len; | |
535 next_name->key.data = names[n].key.data + len; | |
3118 | 536 next_name->key_hash = 0; |
589 | 537 next_name->value = names[n].value; |
538 | |
539 #if 0 | |
540 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
541 "wc2: \"%V\"", &next_name->key); | |
542 #endif | |
543 } | |
544 | |
545 for (i = n + 1; i < nelts; i++) { | |
546 if (ngx_strncmp(names[n].key.data, names[i].key.data, len) != 0) { | |
547 break; | |
548 } | |
549 | |
593 | 550 if (!dot |
551 && names[i].key.len > len | |
552 && names[i].key.data[len] != '.') | |
553 { | |
554 break; | |
555 } | |
556 | |
589 | 557 next_name = ngx_array_push(&next_names); |
558 if (next_name == NULL) { | |
559 return NGX_ERROR; | |
560 } | |
561 | |
593 | 562 next_name->key.len = names[i].key.len - dot_len; |
563 next_name->key.data = names[i].key.data + dot_len; | |
3118 | 564 next_name->key_hash = 0; |
589 | 565 next_name->value = names[i].value; |
566 | |
567 #if 0 | |
568 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
591 | 569 "wc3: \"%V\"", &next_name->key); |
589 | 570 #endif |
571 } | |
572 | |
573 if (next_names.nelts) { | |
593 | 574 |
589 | 575 h = *hinit; |
576 h.hash = NULL; | |
577 | |
578 if (ngx_hash_wildcard_init(&h, (ngx_hash_key_t *) next_names.elts, | |
579 next_names.nelts) | |
580 != NGX_OK) | |
581 { | |
582 return NGX_ERROR; | |
583 } | |
584 | |
585 wdc = (ngx_hash_wildcard_t *) h.hash; | |
586 | |
587 if (names[n].key.len == len) { | |
588 wdc->value = names[n].value; | |
589 } | |
590 | |
2502
23706c19fab8
fix r2169 for .def.com and .abc.def.com case
Igor Sysoev <igor@sysoev.ru>
parents:
2195
diff
changeset
|
591 name->value = (void *) ((uintptr_t) wdc | (dot ? 3 : 2)); |
2168
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
592 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
593 } else if (dot) { |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
594 name->value = (void *) ((uintptr_t) name->value | 1); |
589 | 595 } |
596 } | |
597 | |
598 if (ngx_hash_init(hinit, (ngx_hash_key_t *) curr_names.elts, | |
599 curr_names.nelts) | |
600 != NGX_OK) | |
601 { | |
602 return NGX_ERROR; | |
603 } | |
604 | |
605 return NGX_OK; | |
606 } | |
607 | |
608 | |
609 ngx_uint_t | |
610 ngx_hash_key(u_char *data, size_t len) | |
611 { | |
612 ngx_uint_t i, key; | |
613 | |
614 key = 0; | |
615 | |
616 for (i = 0; i < len; i++) { | |
617 key = ngx_hash(key, data[i]); | |
618 } | |
619 | |
620 return key; | |
621 } | |
622 | |
623 | |
624 ngx_uint_t | |
625 ngx_hash_key_lc(u_char *data, size_t len) | |
626 { | |
627 ngx_uint_t i, key; | |
628 | |
629 key = 0; | |
630 | |
631 for (i = 0; i < len; i++) { | |
632 key = ngx_hash(key, ngx_tolower(data[i])); | |
633 } | |
634 | |
635 return key; | |
636 } | |
637 | |
638 | |
2136 | 639 ngx_uint_t |
640 ngx_hash_strlow(u_char *dst, u_char *src, size_t n) | |
641 { | |
642 ngx_uint_t key; | |
643 | |
644 key = 0; | |
645 | |
646 while (n--) { | |
647 *dst = ngx_tolower(*src); | |
648 key = ngx_hash(key, *dst); | |
649 dst++; | |
650 src++; | |
651 } | |
652 | |
653 return key; | |
654 } | |
655 | |
656 | |
589 | 657 ngx_int_t |
593 | 658 ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type) |
659 { | |
660 ngx_uint_t asize; | |
661 | |
662 if (type == NGX_HASH_SMALL) { | |
663 asize = 4; | |
664 ha->hsize = 107; | |
665 | |
666 } else { | |
667 asize = NGX_HASH_LARGE_ASIZE; | |
668 ha->hsize = NGX_HASH_LARGE_HSIZE; | |
669 } | |
670 | |
671 if (ngx_array_init(&ha->keys, ha->temp_pool, asize, sizeof(ngx_hash_key_t)) | |
672 != NGX_OK) | |
673 { | |
674 return NGX_ERROR; | |
675 } | |
676 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
677 if (ngx_array_init(&ha->dns_wc_head, ha->temp_pool, asize, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
678 sizeof(ngx_hash_key_t)) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
679 != NGX_OK) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
680 { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
681 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
682 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
683 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
684 if (ngx_array_init(&ha->dns_wc_tail, ha->temp_pool, asize, |
593 | 685 sizeof(ngx_hash_key_t)) |
686 != NGX_OK) | |
687 { | |
688 return NGX_ERROR; | |
689 } | |
690 | |
691 ha->keys_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize); | |
692 if (ha->keys_hash == NULL) { | |
693 return NGX_ERROR; | |
694 } | |
695 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
696 ha->dns_wc_head_hash = ngx_pcalloc(ha->temp_pool, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
697 sizeof(ngx_array_t) * ha->hsize); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
698 if (ha->dns_wc_head_hash == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
699 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
700 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
701 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
702 ha->dns_wc_tail_hash = ngx_pcalloc(ha->temp_pool, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
703 sizeof(ngx_array_t) * ha->hsize); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
704 if (ha->dns_wc_tail_hash == NULL) { |
593 | 705 return NGX_ERROR; |
706 } | |
707 | |
708 return NGX_OK; | |
709 } | |
710 | |
711 | |
712 ngx_int_t | |
713 ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value, | |
714 ngx_uint_t flags) | |
715 { | |
716 size_t len; | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
717 u_char *p; |
593 | 718 ngx_str_t *name; |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
719 ngx_uint_t i, k, n, skip, last; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
720 ngx_array_t *keys, *hwc; |
593 | 721 ngx_hash_key_t *hk; |
722 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
723 last = key->len; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
724 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
725 if (flags & NGX_HASH_WILDCARD_KEY) { |
593 | 726 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
727 /* |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
728 * supported wildcards: |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
729 * "*.example.com", ".example.com", and "www.example.*" |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
730 */ |
593 | 731 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
732 n = 0; |
593 | 733 |
734 for (i = 0; i < key->len; i++) { | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
735 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
736 if (key->data[i] == '*') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
737 if (++n > 1) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
738 return NGX_DECLINED; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
739 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
740 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
741 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
742 if (key->data[i] == '.' && key->data[i + 1] == '.') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
743 return NGX_DECLINED; |
597 | 744 } |
6245
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
745 |
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
746 if (key->data[i] == '\0') { |
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
747 return NGX_DECLINED; |
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
748 } |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
749 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
750 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
751 if (key->len > 1 && key->data[0] == '.') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
752 skip = 1; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
753 goto wildcard; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
754 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
755 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
756 if (key->len > 2) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
757 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
758 if (key->data[0] == '*' && key->data[1] == '.') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
759 skip = 2; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
760 goto wildcard; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
761 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
762 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
763 if (key->data[i - 2] == '.' && key->data[i - 1] == '*') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
764 skip = 0; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
765 last -= 2; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
766 goto wildcard; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
767 } |
593 | 768 } |
769 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
770 if (n) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
771 return NGX_DECLINED; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
772 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
773 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
774 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
775 /* exact hash */ |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
776 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
777 k = 0; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
778 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
779 for (i = 0; i < last; i++) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
780 if (!(flags & NGX_HASH_READONLY_KEY)) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
781 key->data[i] = ngx_tolower(key->data[i]); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
782 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
783 k = ngx_hash(k, key->data[i]); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
784 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
785 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
786 k %= ha->hsize; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
787 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
788 /* check conflicts in exact hash */ |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
789 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
790 name = ha->keys_hash[k].elts; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
791 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
792 if (name) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
793 for (i = 0; i < ha->keys_hash[k].nelts; i++) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
794 if (last != name[i].len) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
795 continue; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
796 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
797 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
798 if (ngx_strncmp(key->data, name[i].data, last) == 0) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
799 return NGX_BUSY; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
800 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
801 } |
593 | 802 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
803 } else { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
804 if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
805 sizeof(ngx_str_t)) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
806 != NGX_OK) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
807 { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
808 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
809 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
810 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
811 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
812 name = ngx_array_push(&ha->keys_hash[k]); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
813 if (name == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
814 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
815 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
816 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
817 *name = *key; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
818 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
819 hk = ngx_array_push(&ha->keys); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
820 if (hk == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
821 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
822 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
823 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
824 hk->key = *key; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
825 hk->key_hash = ngx_hash_key(key->data, last); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
826 hk->value = value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
827 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
828 return NGX_OK; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
829 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
830 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
831 wildcard: |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
832 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
833 /* wildcard hash */ |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
834 |
2136 | 835 k = ngx_hash_strlow(&key->data[skip], &key->data[skip], last - skip); |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
836 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
837 k %= ha->hsize; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
838 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
839 if (skip == 1) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
840 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
841 /* check conflicts in exact hash for ".example.com" */ |
593 | 842 |
843 name = ha->keys_hash[k].elts; | |
844 | |
845 if (name) { | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
846 len = last - skip; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
847 |
593 | 848 for (i = 0; i < ha->keys_hash[k].nelts; i++) { |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
849 if (len != name[i].len) { |
593 | 850 continue; |
851 } | |
852 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
853 if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) { |
593 | 854 return NGX_BUSY; |
855 } | |
856 } | |
857 | |
858 } else { | |
859 if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4, | |
860 sizeof(ngx_str_t)) | |
861 != NGX_OK) | |
862 { | |
863 return NGX_ERROR; | |
864 } | |
865 } | |
866 | |
867 name = ngx_array_push(&ha->keys_hash[k]); | |
868 if (name == NULL) { | |
869 return NGX_ERROR; | |
870 } | |
871 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
872 name->len = last - 1; |
2049 | 873 name->data = ngx_pnalloc(ha->temp_pool, name->len); |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
874 if (name->data == NULL) { |
593 | 875 return NGX_ERROR; |
876 } | |
877 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
878 ngx_memcpy(name->data, &key->data[1], name->len); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
879 } |
593 | 880 |
881 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
882 if (skip) { |
593 | 883 |
884 /* | |
885 * convert "*.example.com" to "com.example.\0" | |
886 * and ".example.com" to "com.example\0" | |
887 */ | |
888 | |
2049 | 889 p = ngx_pnalloc(ha->temp_pool, last); |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
890 if (p == NULL) { |
619 | 891 return NGX_ERROR; |
892 } | |
893 | |
593 | 894 len = 0; |
895 n = 0; | |
896 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
897 for (i = last - 1; i; i--) { |
593 | 898 if (key->data[i] == '.') { |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
899 ngx_memcpy(&p[n], &key->data[i + 1], len); |
593 | 900 n += len; |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
901 p[n++] = '.'; |
593 | 902 len = 0; |
903 continue; | |
904 } | |
905 | |
906 len++; | |
907 } | |
908 | |
909 if (len) { | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
910 ngx_memcpy(&p[n], &key->data[1], len); |
593 | 911 n += len; |
912 } | |
913 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
914 p[n] = '\0'; |
619 | 915 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
916 hwc = &ha->dns_wc_head; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
917 keys = &ha->dns_wc_head_hash[k]; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
918 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
919 } else { |
619 | 920 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
921 /* convert "www.example.*" to "www.example\0" */ |
619 | 922 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
923 last++; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
924 |
2049 | 925 p = ngx_pnalloc(ha->temp_pool, last); |
1415
d83687d29853
fix trailing wildcard when two or more listen used in one server
Igor Sysoev <igor@sysoev.ru>
parents:
1253
diff
changeset
|
926 if (p == NULL) { |
d83687d29853
fix trailing wildcard when two or more listen used in one server
Igor Sysoev <igor@sysoev.ru>
parents:
1253
diff
changeset
|
927 return NGX_ERROR; |
d83687d29853
fix trailing wildcard when two or more listen used in one server
Igor Sysoev <igor@sysoev.ru>
parents:
1253
diff
changeset
|
928 } |
d83687d29853
fix trailing wildcard when two or more listen used in one server
Igor Sysoev <igor@sysoev.ru>
parents:
1253
diff
changeset
|
929 |
1492 | 930 ngx_cpystrn(p, key->data, last); |
1415
d83687d29853
fix trailing wildcard when two or more listen used in one server
Igor Sysoev <igor@sysoev.ru>
parents:
1253
diff
changeset
|
931 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
932 hwc = &ha->dns_wc_tail; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
933 keys = &ha->dns_wc_tail_hash[k]; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
934 } |
593 | 935 |
936 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
937 /* check conflicts in wildcard hash */ |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
938 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
939 name = keys->elts; |
593 | 940 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
941 if (name) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
942 len = last - skip; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
943 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
944 for (i = 0; i < keys->nelts; i++) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
945 if (len != name[i].len) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
946 continue; |
593 | 947 } |
948 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
949 if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
950 return NGX_BUSY; |
593 | 951 } |
952 } | |
953 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
954 } else { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
955 if (ngx_array_init(keys, ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
956 { |
593 | 957 return NGX_ERROR; |
958 } | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
959 } |
593 | 960 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
961 name = ngx_array_push(keys); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
962 if (name == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
963 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
964 } |
619 | 965 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
966 name->len = last - skip; |
2049 | 967 name->data = ngx_pnalloc(ha->temp_pool, name->len); |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
968 if (name->data == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
969 return NGX_ERROR; |
593 | 970 } |
971 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
972 ngx_memcpy(name->data, key->data + skip, name->len); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
973 |
4689
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
974 |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
975 /* add to wildcard hash */ |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
976 |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
977 hk = ngx_array_push(hwc); |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
978 if (hk == NULL) { |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
979 return NGX_ERROR; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
980 } |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
981 |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
982 hk->key.len = last - 1; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
983 hk->key.data = p; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
984 hk->key_hash = 0; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
985 hk->value = value; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
986 |
593 | 987 return NGX_OK; |
988 } |