/src/h2o/lib/core/headers.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2014 DeNA Co., Ltd. |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | | * of this software and associated documentation files (the "Software"), to |
6 | | * deal in the Software without restriction, including without limitation the |
7 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
8 | | * sell copies of the Software, and to permit persons to whom the Software is |
9 | | * furnished to do so, subject to the following conditions: |
10 | | * |
11 | | * The above copyright notice and this permission notice shall be included in |
12 | | * all copies or substantial portions of the Software. |
13 | | * |
14 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
19 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
20 | | * IN THE SOFTWARE. |
21 | | */ |
22 | | #include <stddef.h> |
23 | | #include <stdio.h> |
24 | | #include "h2o.h" |
25 | | |
26 | | static ssize_t add_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, h2o_iovec_t *name, const char *orig_name, const char *value, |
27 | | size_t value_len, h2o_header_flags_t flags) |
28 | 1.55M | { |
29 | 1.55M | h2o_header_t *slot; |
30 | | |
31 | 1.55M | h2o_vector_reserve(pool, headers, headers->size + 1); |
32 | 1.55M | slot = headers->entries + headers->size++; |
33 | | |
34 | 1.55M | slot->name = name; |
35 | 1.55M | slot->value.base = (char *)value; |
36 | 1.55M | slot->value.len = value_len; |
37 | 1.55M | slot->orig_name = orig_name ? h2o_strdup(pool, orig_name, name->len).base : NULL; |
38 | 1.55M | slot->flags = flags; |
39 | 1.55M | return headers->size - 1; |
40 | 1.55M | } |
41 | | |
42 | | static inline h2o_iovec_t *alloc_and_init_iovec(h2o_mem_pool_t *pool, const char *base, size_t len) |
43 | 228k | { |
44 | 228k | h2o_iovec_t *iov = h2o_mem_alloc_pool(pool, *iov, 1); |
45 | 228k | iov->base = (char *)base; |
46 | 228k | iov->len = len; |
47 | 228k | return iov; |
48 | 228k | } |
49 | | |
50 | | ssize_t h2o_find_header(const h2o_headers_t *headers, const h2o_token_t *token, ssize_t cursor) |
51 | 14.3k | { |
52 | 563k | for (++cursor; cursor < headers->size; ++cursor) { |
53 | 550k | if (headers->entries[cursor].name == &token->buf) { |
54 | 1.13k | return cursor; |
55 | 1.13k | } |
56 | 550k | } |
57 | 13.2k | return -1; |
58 | 14.3k | } |
59 | | |
60 | | ssize_t h2o_find_header_by_str(const h2o_headers_t *headers, const char *name, size_t name_len, ssize_t cursor) |
61 | 0 | { |
62 | 0 | for (++cursor; cursor < headers->size; ++cursor) { |
63 | 0 | h2o_header_t *t = headers->entries + cursor; |
64 | 0 | if (h2o_memis(t->name->base, t->name->len, name, name_len)) { |
65 | 0 | return cursor; |
66 | 0 | } |
67 | 0 | } |
68 | 0 | return -1; |
69 | 0 | } |
70 | | |
71 | | ssize_t h2o_add_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *orig_name, |
72 | | const char *value, size_t value_len) |
73 | 1.32M | { |
74 | 1.32M | return add_header(pool, headers, (h2o_iovec_t *)&token->buf, orig_name, value, value_len, (h2o_header_flags_t){0}); |
75 | 1.32M | } |
76 | | |
77 | | ssize_t h2o_add_header_by_str(h2o_mem_pool_t *pool, h2o_headers_t *headers, const char *lowercase_name, size_t lowercase_name_len, |
78 | | int maybe_token, const char *orig_name, const char *value, size_t value_len) |
79 | 228k | { |
80 | 228k | if (maybe_token) { |
81 | 0 | const h2o_token_t *token = h2o_lookup_token(lowercase_name, lowercase_name_len); |
82 | 0 | if (token != NULL) { |
83 | 0 | return add_header(pool, headers, (h2o_iovec_t *)token, orig_name, value, value_len, (h2o_header_flags_t){0}); |
84 | 0 | } |
85 | 0 | } |
86 | 228k | return add_header(pool, headers, alloc_and_init_iovec(pool, lowercase_name, lowercase_name_len), orig_name, value, value_len, |
87 | 228k | (h2o_header_flags_t){0}); |
88 | 228k | } |
89 | | |
90 | | ssize_t h2o_set_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *value, size_t value_len, |
91 | | int overwrite_if_exists) |
92 | 0 | { |
93 | 0 | ssize_t cursor = h2o_find_header(headers, token, -1); |
94 | 0 | if (cursor != -1) { |
95 | 0 | if (overwrite_if_exists) { |
96 | 0 | headers->entries[cursor].value = h2o_iovec_init(value, value_len); |
97 | 0 | } |
98 | 0 | return cursor; |
99 | 0 | } else { |
100 | 0 | return h2o_add_header(pool, headers, token, NULL, value, value_len); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | ssize_t h2o_set_header_by_str(h2o_mem_pool_t *pool, h2o_headers_t *headers, const char *lowercase_name, size_t lowercase_name_len, |
105 | | int maybe_token, const char *value, size_t value_len, int overwrite_if_exists) |
106 | 0 | { |
107 | 0 | ssize_t cursor; |
108 | |
|
109 | 0 | if (maybe_token) { |
110 | 0 | const h2o_token_t *token = h2o_lookup_token(lowercase_name, lowercase_name_len); |
111 | 0 | if (token != NULL) { |
112 | 0 | return h2o_set_header(pool, headers, token, value, value_len, overwrite_if_exists); |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | 0 | cursor = h2o_find_header_by_str(headers, lowercase_name, lowercase_name_len, -1); |
117 | 0 | if (cursor != -1) { |
118 | 0 | if (overwrite_if_exists) { |
119 | 0 | headers->entries[cursor].value = h2o_iovec_init(value, value_len); |
120 | 0 | } |
121 | 0 | return cursor; |
122 | 0 | } else { |
123 | 0 | return add_header(pool, headers, alloc_and_init_iovec(pool, lowercase_name, lowercase_name_len), NULL, value, value_len, |
124 | 0 | (h2o_header_flags_t){0}); |
125 | 0 | } |
126 | 0 | } |
127 | | |
128 | | ssize_t h2o_set_header_token(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *value, |
129 | | size_t value_len) |
130 | 0 | { |
131 | 0 | ssize_t found = -1; |
132 | 0 | size_t i; |
133 | 0 | for (i = 0; i != headers->size; ++i) { |
134 | 0 | if (headers->entries[i].name == &token->buf) { |
135 | 0 | if (h2o_contains_token(headers->entries[i].value.base, headers->entries[i].value.len, value, value_len, ',')) |
136 | 0 | return -1; |
137 | 0 | found = i; |
138 | 0 | } |
139 | 0 | } |
140 | 0 | if (found != -1) { |
141 | 0 | h2o_header_t *dest = headers->entries + found; |
142 | 0 | dest->value = h2o_concat(pool, dest->value, h2o_iovec_init(H2O_STRLIT(", ")), h2o_iovec_init(value, value_len)); |
143 | 0 | return found; |
144 | 0 | } else { |
145 | 0 | return h2o_add_header(pool, headers, token, NULL, value, value_len); |
146 | 0 | } |
147 | 0 | } |
148 | | |
149 | | ssize_t h2o_delete_header(h2o_headers_t *headers, ssize_t cursor) |
150 | 0 | { |
151 | 0 | assert(cursor != -1); |
152 | | |
153 | 0 | --headers->size; |
154 | 0 | memmove(headers->entries + cursor, headers->entries + cursor + 1, sizeof(h2o_header_t) * (headers->size - cursor)); |
155 | |
|
156 | 0 | return cursor; |
157 | 0 | } |