Mercurial > hg > nginx-quic
annotate src/core/ngx_hash.c @ 8457:6a81d96d3733
Mail: fixed handling of invalid SMTP commands split between reads.
Previously, if an invalid SMTP command was split between reads, nginx failed
to wait for LF before returning an error, and interpreted the rest of the
command received later as a separate command.
The sw_invalid state in ngx_mail_smtp_parse_command(), introduced in
04e43d03e153, did not work, since ngx_mail_smtp_auth_state() clears
s->state when returning an error due to NGX_MAIL_PARSE_INVALID_COMMAND.
And not clearing s->state will introduce another problem: the rest
of the command would trigger duplicate error when rest of the command is
received.
Fix is to return NGX_AGAIN from ngx_mail_smtp_parse_command() until full
command is received.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 19 May 2021 03:13:15 +0300 |
parents | eb9c7fb796d5 |
children | 2a7155733855 |
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 |
7536
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
268 if (hinit->bucket_size > 65536 - ngx_cacheline_size) { |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
269 ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
270 "could not build %s, too large " |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
271 "%s_bucket_size: %i", |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
272 hinit->name, hinit->name, hinit->bucket_size); |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
273 return NGX_ERROR; |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
274 } |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
275 |
589 | 276 for (n = 0; n < nelts; n++) { |
277 if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) | |
278 { | |
279 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
|
280 "could not build %s, you should " |
589 | 281 "increase %s_bucket_size: %i", |
282 hinit->name, hinit->name, hinit->bucket_size); | |
283 return NGX_ERROR; | |
284 } | |
285 } | |
286 | |
595 | 287 test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log); |
589 | 288 if (test == NULL) { |
289 return NGX_ERROR; | |
290 } | |
291 | |
631 | 292 bucket_size = hinit->bucket_size - sizeof(void *); |
293 | |
746 | 294 start = nelts / (bucket_size / (2 * sizeof(void *))); |
589 | 295 start = start ? start : 1; |
296 | |
4404
840f3e768ef8
Fixed division by zero exception in ngx_hash_init().
Valentin Bartenev <vbart@nginx.com>
parents:
3510
diff
changeset
|
297 if (hinit->max_size > 10000 && nelts && hinit->max_size / nelts < 100) { |
631 | 298 start = hinit->max_size - 1000; |
299 } | |
589 | 300 |
5636
54f847c88cf7
Core: fixed hash to actually try max_size.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5635
diff
changeset
|
301 for (size = start; size <= hinit->max_size; size++) { |
589 | 302 |
595 | 303 ngx_memzero(test, size * sizeof(u_short)); |
589 | 304 |
305 for (n = 0; n < nelts; n++) { | |
306 if (names[n].key.data == NULL) { | |
307 continue; | |
308 } | |
309 | |
310 key = names[n].key_hash % size; | |
7536
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
311 len = test[key] + NGX_HASH_ELT_SIZE(&names[n]); |
589 | 312 |
313 #if 0 | |
314 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
7536
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
315 "%ui: %ui %uz \"%V\"", |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
316 size, key, len, &names[n].key); |
589 | 317 #endif |
318 | |
7536
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
319 if (len > bucket_size) { |
589 | 320 goto next; |
321 } | |
7536
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
322 |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
323 test[key] = (u_short) len; |
589 | 324 } |
325 | |
326 goto found; | |
327 | |
328 next: | |
329 | |
330 continue; | |
331 } | |
332 | |
5985
f961c719fb09
Core: fixed potential buffer overrun when initializing hash.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5870
diff
changeset
|
333 size = hinit->max_size; |
5870
5e72578e6503
Core: fixed buffer overrun when hash max_size reached.
Yichun Zhang <agentzh@gmail.com>
parents:
5636
diff
changeset
|
334 |
5635
c348dea081fb
Core: hash now ignores bucket_size if it hits max_size limit.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4689
diff
changeset
|
335 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
|
336 "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
|
337 "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
|
338 "ignoring %s_bucket_size", |
589 | 339 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
|
340 hinit->name, hinit->bucket_size, hinit->name); |
589 | 341 |
342 found: | |
343 | |
344 for (i = 0; i < size; i++) { | |
345 test[i] = sizeof(void *); | |
346 } | |
347 | |
348 for (n = 0; n < nelts; n++) { | |
349 if (names[n].key.data == NULL) { | |
350 continue; | |
351 } | |
352 | |
353 key = names[n].key_hash % size; | |
7536
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
354 len = test[key] + NGX_HASH_ELT_SIZE(&names[n]); |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
355 |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
356 if (len > 65536 - ngx_cacheline_size) { |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
357 ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
358 "could not build %s, you should " |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
359 "increase %s_max_size: %i", |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
360 hinit->name, hinit->name, hinit->max_size); |
7541
eb9c7fb796d5
Core: fixed memory leak on error, missed in c3f60d618c17.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7536
diff
changeset
|
361 ngx_free(test); |
7536
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
362 return NGX_ERROR; |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
363 } |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
364 |
c3f60d618c17
Core: fixed segfault with too large bucket sizes (ticket #1806).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6743
diff
changeset
|
365 test[key] = (u_short) len; |
589 | 366 } |
367 | |
368 len = 0; | |
369 | |
370 for (i = 0; i < size; i++) { | |
371 if (test[i] == sizeof(void *)) { | |
372 continue; | |
373 } | |
374 | |
595 | 375 test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size)); |
589 | 376 |
377 len += test[i]; | |
378 } | |
379 | |
380 if (hinit->hash == NULL) { | |
381 hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t) | |
382 + size * sizeof(ngx_hash_elt_t *)); | |
383 if (hinit->hash == NULL) { | |
384 ngx_free(test); | |
385 return NGX_ERROR; | |
386 } | |
387 | |
388 buckets = (ngx_hash_elt_t **) | |
389 ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t)); | |
390 | |
391 } else { | |
392 buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *)); | |
393 if (buckets == NULL) { | |
394 ngx_free(test); | |
395 return NGX_ERROR; | |
396 } | |
397 } | |
398 | |
399 elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size); | |
400 if (elts == NULL) { | |
401 ngx_free(test); | |
402 return NGX_ERROR; | |
403 } | |
404 | |
405 elts = ngx_align_ptr(elts, ngx_cacheline_size); | |
406 | |
407 for (i = 0; i < size; i++) { | |
408 if (test[i] == sizeof(void *)) { | |
409 continue; | |
410 } | |
411 | |
412 buckets[i] = (ngx_hash_elt_t *) elts; | |
413 elts += test[i]; | |
414 } | |
415 | |
416 for (i = 0; i < size; i++) { | |
417 test[i] = 0; | |
418 } | |
419 | |
420 for (n = 0; n < nelts; n++) { | |
421 if (names[n].key.data == NULL) { | |
422 continue; | |
423 } | |
424 | |
425 key = names[n].key_hash % size; | |
426 elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]); | |
427 | |
428 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
|
429 elt->len = (u_short) names[n].key.len; |
589 | 430 |
2135 | 431 ngx_strlow(elt->name, names[n].key.data, names[n].key.len); |
589 | 432 |
595 | 433 test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); |
589 | 434 } |
435 | |
436 for (i = 0; i < size; i++) { | |
437 if (buckets[i] == NULL) { | |
438 continue; | |
439 } | |
440 | |
441 elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]); | |
442 | |
443 elt->value = NULL; | |
444 } | |
445 | |
446 ngx_free(test); | |
447 | |
448 hinit->hash->buckets = buckets; | |
449 hinit->hash->size = size; | |
450 | |
451 #if 0 | |
452 | |
453 for (i = 0; i < size; i++) { | |
454 ngx_str_t val; | |
455 ngx_uint_t key; | |
456 | |
457 elt = buckets[i]; | |
458 | |
459 if (elt == NULL) { | |
460 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
461 "%ui: NULL", i); | |
462 continue; | |
463 } | |
464 | |
465 while (elt->value) { | |
466 val.len = elt->len; | |
467 val.data = &elt->name[0]; | |
468 | |
469 key = hinit->key(val.data, val.len); | |
470 | |
471 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
472 "%ui: %p \"%V\" %ui", i, elt, &val, key); | |
473 | |
474 elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len, | |
475 sizeof(void *)); | |
476 } | |
477 } | |
478 | |
479 #endif | |
480 | |
481 return NGX_OK; | |
482 } | |
483 | |
484 | |
485 ngx_int_t | |
486 ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, | |
487 ngx_uint_t nelts) | |
488 { | |
593 | 489 size_t len, dot_len; |
591 | 490 ngx_uint_t i, n, dot; |
589 | 491 ngx_array_t curr_names, next_names; |
492 ngx_hash_key_t *name, *next_name; | |
493 ngx_hash_init_t h; | |
494 ngx_hash_wildcard_t *wdc; | |
495 | |
496 if (ngx_array_init(&curr_names, hinit->temp_pool, nelts, | |
497 sizeof(ngx_hash_key_t)) | |
498 != NGX_OK) | |
499 { | |
500 return NGX_ERROR; | |
501 } | |
502 | |
503 if (ngx_array_init(&next_names, hinit->temp_pool, nelts, | |
504 sizeof(ngx_hash_key_t)) | |
505 != NGX_OK) | |
506 { | |
507 return NGX_ERROR; | |
508 } | |
509 | |
510 for (n = 0; n < nelts; n = i) { | |
511 | |
512 #if 0 | |
513 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
514 "wc0: \"%V\"", &names[n].key); | |
515 #endif | |
516 | |
591 | 517 dot = 0; |
518 | |
589 | 519 for (len = 0; len < names[n].key.len; len++) { |
520 if (names[n].key.data[len] == '.') { | |
591 | 521 dot = 1; |
589 | 522 break; |
523 } | |
524 } | |
525 | |
526 name = ngx_array_push(&curr_names); | |
527 if (name == NULL) { | |
528 return NGX_ERROR; | |
529 } | |
530 | |
591 | 531 name->key.len = len; |
589 | 532 name->key.data = names[n].key.data; |
533 name->key_hash = hinit->key(name->key.data, name->key.len); | |
534 name->value = names[n].value; | |
535 | |
536 #if 0 | |
537 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
593 | 538 "wc1: \"%V\" %ui", &name->key, dot); |
589 | 539 #endif |
540 | |
593 | 541 dot_len = len + 1; |
542 | |
591 | 543 if (dot) { |
544 len++; | |
545 } | |
546 | |
589 | 547 next_names.nelts = 0; |
548 | |
549 if (names[n].key.len != len) { | |
550 next_name = ngx_array_push(&next_names); | |
551 if (next_name == NULL) { | |
552 return NGX_ERROR; | |
553 } | |
554 | |
555 next_name->key.len = names[n].key.len - len; | |
556 next_name->key.data = names[n].key.data + len; | |
3118 | 557 next_name->key_hash = 0; |
589 | 558 next_name->value = names[n].value; |
559 | |
560 #if 0 | |
561 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
562 "wc2: \"%V\"", &next_name->key); | |
563 #endif | |
564 } | |
565 | |
566 for (i = n + 1; i < nelts; i++) { | |
567 if (ngx_strncmp(names[n].key.data, names[i].key.data, len) != 0) { | |
568 break; | |
569 } | |
570 | |
593 | 571 if (!dot |
572 && names[i].key.len > len | |
573 && names[i].key.data[len] != '.') | |
574 { | |
575 break; | |
576 } | |
577 | |
589 | 578 next_name = ngx_array_push(&next_names); |
579 if (next_name == NULL) { | |
580 return NGX_ERROR; | |
581 } | |
582 | |
593 | 583 next_name->key.len = names[i].key.len - dot_len; |
584 next_name->key.data = names[i].key.data + dot_len; | |
3118 | 585 next_name->key_hash = 0; |
589 | 586 next_name->value = names[i].value; |
587 | |
588 #if 0 | |
589 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, | |
591 | 590 "wc3: \"%V\"", &next_name->key); |
589 | 591 #endif |
592 } | |
593 | |
594 if (next_names.nelts) { | |
593 | 595 |
589 | 596 h = *hinit; |
597 h.hash = NULL; | |
598 | |
599 if (ngx_hash_wildcard_init(&h, (ngx_hash_key_t *) next_names.elts, | |
600 next_names.nelts) | |
601 != NGX_OK) | |
602 { | |
603 return NGX_ERROR; | |
604 } | |
605 | |
606 wdc = (ngx_hash_wildcard_t *) h.hash; | |
607 | |
608 if (names[n].key.len == len) { | |
609 wdc->value = names[n].value; | |
610 } | |
611 | |
2502
23706c19fab8
fix r2169 for .def.com and .abc.def.com case
Igor Sysoev <igor@sysoev.ru>
parents:
2195
diff
changeset
|
612 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
|
613 |
80924319ba05
fix the case when unset domain.tld was matched by *.domain.tld
Igor Sysoev <igor@sysoev.ru>
parents:
2155
diff
changeset
|
614 } 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
|
615 name->value = (void *) ((uintptr_t) name->value | 1); |
589 | 616 } |
617 } | |
618 | |
619 if (ngx_hash_init(hinit, (ngx_hash_key_t *) curr_names.elts, | |
620 curr_names.nelts) | |
621 != NGX_OK) | |
622 { | |
623 return NGX_ERROR; | |
624 } | |
625 | |
626 return NGX_OK; | |
627 } | |
628 | |
629 | |
630 ngx_uint_t | |
631 ngx_hash_key(u_char *data, size_t len) | |
632 { | |
633 ngx_uint_t i, key; | |
634 | |
635 key = 0; | |
636 | |
637 for (i = 0; i < len; i++) { | |
638 key = ngx_hash(key, data[i]); | |
639 } | |
640 | |
641 return key; | |
642 } | |
643 | |
644 | |
645 ngx_uint_t | |
646 ngx_hash_key_lc(u_char *data, size_t len) | |
647 { | |
648 ngx_uint_t i, key; | |
649 | |
650 key = 0; | |
651 | |
652 for (i = 0; i < len; i++) { | |
653 key = ngx_hash(key, ngx_tolower(data[i])); | |
654 } | |
655 | |
656 return key; | |
657 } | |
658 | |
659 | |
2136 | 660 ngx_uint_t |
661 ngx_hash_strlow(u_char *dst, u_char *src, size_t n) | |
662 { | |
663 ngx_uint_t key; | |
664 | |
665 key = 0; | |
666 | |
667 while (n--) { | |
668 *dst = ngx_tolower(*src); | |
669 key = ngx_hash(key, *dst); | |
670 dst++; | |
671 src++; | |
672 } | |
673 | |
674 return key; | |
675 } | |
676 | |
677 | |
589 | 678 ngx_int_t |
593 | 679 ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type) |
680 { | |
681 ngx_uint_t asize; | |
682 | |
683 if (type == NGX_HASH_SMALL) { | |
684 asize = 4; | |
685 ha->hsize = 107; | |
686 | |
687 } else { | |
688 asize = NGX_HASH_LARGE_ASIZE; | |
689 ha->hsize = NGX_HASH_LARGE_HSIZE; | |
690 } | |
691 | |
692 if (ngx_array_init(&ha->keys, ha->temp_pool, asize, sizeof(ngx_hash_key_t)) | |
693 != NGX_OK) | |
694 { | |
695 return NGX_ERROR; | |
696 } | |
697 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
698 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
|
699 sizeof(ngx_hash_key_t)) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
700 != NGX_OK) |
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 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
703 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
704 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
705 if (ngx_array_init(&ha->dns_wc_tail, ha->temp_pool, asize, |
593 | 706 sizeof(ngx_hash_key_t)) |
707 != NGX_OK) | |
708 { | |
709 return NGX_ERROR; | |
710 } | |
711 | |
712 ha->keys_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize); | |
713 if (ha->keys_hash == NULL) { | |
714 return NGX_ERROR; | |
715 } | |
716 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
717 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
|
718 sizeof(ngx_array_t) * ha->hsize); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
719 if (ha->dns_wc_head_hash == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
720 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
721 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
722 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
723 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
|
724 sizeof(ngx_array_t) * ha->hsize); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
725 if (ha->dns_wc_tail_hash == NULL) { |
593 | 726 return NGX_ERROR; |
727 } | |
728 | |
729 return NGX_OK; | |
730 } | |
731 | |
732 | |
733 ngx_int_t | |
734 ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value, | |
735 ngx_uint_t flags) | |
736 { | |
737 size_t len; | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
738 u_char *p; |
593 | 739 ngx_str_t *name; |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
740 ngx_uint_t i, k, n, skip, last; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
741 ngx_array_t *keys, *hwc; |
593 | 742 ngx_hash_key_t *hk; |
743 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
744 last = key->len; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
745 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
746 if (flags & NGX_HASH_WILDCARD_KEY) { |
593 | 747 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
748 /* |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
749 * supported wildcards: |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
750 * "*.example.com", ".example.com", and "www.example.*" |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
751 */ |
593 | 752 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
753 n = 0; |
593 | 754 |
755 for (i = 0; i < key->len; i++) { | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
756 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
757 if (key->data[i] == '*') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
758 if (++n > 1) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
759 return NGX_DECLINED; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
760 } |
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] == '.' && key->data[i + 1] == '.') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
764 return NGX_DECLINED; |
597 | 765 } |
6245
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
766 |
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
767 if (key->data[i] == '\0') { |
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
768 return NGX_DECLINED; |
3cf25d33886a
Core: fixed segfault with null in wildcard hash names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6225
diff
changeset
|
769 } |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
770 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
771 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
772 if (key->len > 1 && key->data[0] == '.') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
773 skip = 1; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
774 goto wildcard; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
775 } |
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 if (key->len > 2) { |
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 if (key->data[0] == '*' && key->data[1] == '.') { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
780 skip = 2; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
781 goto wildcard; |
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 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
784 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
|
785 skip = 0; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
786 last -= 2; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
787 goto wildcard; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
788 } |
593 | 789 } |
790 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
791 if (n) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
792 return NGX_DECLINED; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
793 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
794 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
795 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
796 /* exact hash */ |
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 k = 0; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
799 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
800 for (i = 0; i < last; i++) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
801 if (!(flags & NGX_HASH_READONLY_KEY)) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
802 key->data[i] = ngx_tolower(key->data[i]); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
803 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
804 k = ngx_hash(k, key->data[i]); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
805 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
806 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
807 k %= ha->hsize; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
808 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
809 /* check conflicts in exact hash */ |
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 name = ha->keys_hash[k].elts; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
812 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
813 if (name) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
814 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
|
815 if (last != name[i].len) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
816 continue; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
817 } |
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 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
|
820 return NGX_BUSY; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
821 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
822 } |
593 | 823 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
824 } else { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
825 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
|
826 sizeof(ngx_str_t)) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
827 != NGX_OK) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
828 { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
829 return NGX_ERROR; |
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 } |
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 name = ngx_array_push(&ha->keys_hash[k]); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
834 if (name == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
835 return NGX_ERROR; |
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 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
838 *name = *key; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
839 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
840 hk = ngx_array_push(&ha->keys); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
841 if (hk == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
842 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
843 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
844 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
845 hk->key = *key; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
846 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
|
847 hk->value = value; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
848 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
849 return NGX_OK; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
850 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
851 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
852 wildcard: |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
853 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
854 /* wildcard hash */ |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
855 |
2136 | 856 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
|
857 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
858 k %= ha->hsize; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
859 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
860 if (skip == 1) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
861 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
862 /* check conflicts in exact hash for ".example.com" */ |
593 | 863 |
864 name = ha->keys_hash[k].elts; | |
865 | |
866 if (name) { | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
867 len = last - skip; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
868 |
593 | 869 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
|
870 if (len != name[i].len) { |
593 | 871 continue; |
872 } | |
873 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
874 if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) { |
593 | 875 return NGX_BUSY; |
876 } | |
877 } | |
878 | |
879 } else { | |
880 if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4, | |
881 sizeof(ngx_str_t)) | |
882 != NGX_OK) | |
883 { | |
884 return NGX_ERROR; | |
885 } | |
886 } | |
887 | |
888 name = ngx_array_push(&ha->keys_hash[k]); | |
889 if (name == NULL) { | |
890 return NGX_ERROR; | |
891 } | |
892 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
893 name->len = last - 1; |
2049 | 894 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
|
895 if (name->data == NULL) { |
593 | 896 return NGX_ERROR; |
897 } | |
898 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
899 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
|
900 } |
593 | 901 |
902 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
903 if (skip) { |
593 | 904 |
905 /* | |
906 * convert "*.example.com" to "com.example.\0" | |
907 * and ".example.com" to "com.example\0" | |
908 */ | |
909 | |
2049 | 910 p = ngx_pnalloc(ha->temp_pool, last); |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
911 if (p == NULL) { |
619 | 912 return NGX_ERROR; |
913 } | |
914 | |
593 | 915 len = 0; |
916 n = 0; | |
917 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
918 for (i = last - 1; i; i--) { |
593 | 919 if (key->data[i] == '.') { |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
920 ngx_memcpy(&p[n], &key->data[i + 1], len); |
593 | 921 n += len; |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
922 p[n++] = '.'; |
593 | 923 len = 0; |
924 continue; | |
925 } | |
926 | |
927 len++; | |
928 } | |
929 | |
930 if (len) { | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
931 ngx_memcpy(&p[n], &key->data[1], len); |
593 | 932 n += len; |
933 } | |
934 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
935 p[n] = '\0'; |
619 | 936 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
937 hwc = &ha->dns_wc_head; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
938 keys = &ha->dns_wc_head_hash[k]; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
939 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
940 } else { |
619 | 941 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
942 /* convert "www.example.*" to "www.example\0" */ |
619 | 943 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
944 last++; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
945 |
2049 | 946 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
|
947 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
|
948 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
|
949 } |
d83687d29853
fix trailing wildcard when two or more listen used in one server
Igor Sysoev <igor@sysoev.ru>
parents:
1253
diff
changeset
|
950 |
1492 | 951 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
|
952 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
953 hwc = &ha->dns_wc_tail; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
954 keys = &ha->dns_wc_tail_hash[k]; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
955 } |
593 | 956 |
957 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
958 /* check conflicts in wildcard hash */ |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
959 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
960 name = keys->elts; |
593 | 961 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
962 if (name) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
963 len = last - skip; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
964 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
965 for (i = 0; i < keys->nelts; i++) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
966 if (len != name[i].len) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
967 continue; |
593 | 968 } |
969 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
970 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
|
971 return NGX_BUSY; |
593 | 972 } |
973 } | |
974 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
975 } else { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
976 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
|
977 { |
593 | 978 return NGX_ERROR; |
979 } | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
980 } |
593 | 981 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
982 name = ngx_array_push(keys); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
983 if (name == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
984 return NGX_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
985 } |
619 | 986 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
987 name->len = last - skip; |
2049 | 988 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
|
989 if (name->data == NULL) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
990 return NGX_ERROR; |
593 | 991 } |
992 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
746
diff
changeset
|
993 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
|
994 |
4689
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
995 |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
996 /* add to wildcard hash */ |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
997 |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
998 hk = ngx_array_push(hwc); |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
999 if (hk == NULL) { |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1000 return NGX_ERROR; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1001 } |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1002 |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1003 hk->key.len = last - 1; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1004 hk->key.data = p; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1005 hk->key_hash = 0; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1006 hk->value = value; |
d2ed9fee092b
Fixed handling of conflicting wildcard server names.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
1007 |
593 | 1008 return NGX_OK; |
1009 } |