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