Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) | ||
3 | // | ||
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
6 | // | ||
7 | // Official repository: https://github.com/cppalliance/http_proto | ||
8 | // | ||
9 | |||
10 | #include <boost/http_proto/message_base.hpp> | ||
11 | #include <boost/http_proto/rfc/list_rule.hpp> | ||
12 | #include <boost/http_proto/rfc/token_rule.hpp> | ||
13 | #include <boost/http_proto/detail/except.hpp> | ||
14 | #include "detail/number_string.hpp" | ||
15 | #include <boost/url/grammar/parse.hpp> | ||
16 | #include <boost/url/grammar/ci_string.hpp> | ||
17 | |||
18 | namespace boost { | ||
19 | namespace http_proto { | ||
20 | |||
21 | void | ||
22 | ✗ | message_base:: | |
23 | set_payload_size( | ||
24 | std::uint64_t n) | ||
25 | { | ||
26 | //if(! is_head_response()) | ||
27 | if(true) | ||
28 | { | ||
29 | // comes first for exception safety | ||
30 | ✗ | set_content_length(n); | |
31 | |||
32 | ✗ | set_chunked(false); | |
33 | } | ||
34 | else | ||
35 | { | ||
36 | // VFALCO ? | ||
37 | } | ||
38 | ✗ | } | |
39 | |||
40 | void | ||
41 | ✗ | message_base:: | |
42 | set_content_length( | ||
43 | std::uint64_t n) | ||
44 | { | ||
45 | ✗ | set(field::content_length, | |
46 | ✗ | detail::number_string(n)); | |
47 | ✗ | } | |
48 | |||
49 | void | ||
50 | ✗ | message_base:: | |
51 | set_chunked(bool value) | ||
52 | { | ||
53 | ✗ | if(value) | |
54 | { | ||
55 | // set chunked | ||
56 | ✗ | if(! h_.md.transfer_encoding.is_chunked ) | |
57 | { | ||
58 | ✗ | append( | |
59 | field::transfer_encoding, | ||
60 | ✗ | "chunked"); | |
61 | ✗ | return; | |
62 | } | ||
63 | } | ||
64 | else | ||
65 | { | ||
66 | // clear chunked | ||
67 | // VFALCO ? | ||
68 | } | ||
69 | } | ||
70 | |||
71 | void | ||
72 | 12 | message_base:: | |
73 | set_keep_alive(bool value) | ||
74 | { | ||
75 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | if(ph_->md.connection.ec.failed()) |
76 | { | ||
77 | // throw? return false? | ||
78 | 5 | return; | |
79 | } | ||
80 | |||
81 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
|
12 | if(ph_->md.connection.count == 0) |
82 | { | ||
83 | // no Connection field | ||
84 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | switch(ph_->version) |
85 | { | ||
86 | 3 | default: | |
87 | case version::http_1_1: | ||
88 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if(! value) |
89 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | set(field::connection, "close"); |
90 | 3 | break; | |
91 | |||
92 | 2 | case version::http_1_0: | |
93 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(value) |
94 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | set(field::connection, "keep-alive"); |
95 | 2 | break; | |
96 | } | ||
97 | 5 | return; | |
98 | } | ||
99 | |||
100 | // VFALCO TODO iterate in reverse order, | ||
101 | // and cache the last iterator to use | ||
102 | // for appending | ||
103 | |||
104 | // one or more Connection fields | ||
105 | 7 | auto it = begin(); | |
106 | auto const erase_token = | ||
107 | 14 | [&](core::string_view token) | |
108 | { | ||
109 |
2/2✓ Branch 2 taken 8 times.
✓ Branch 3 taken 6 times.
|
14 | while(it != end()) |
110 | { | ||
111 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if(it->id != field::connection) |
112 | { | ||
113 | ✗ | ++it; | |
114 | 4 | continue; | |
115 | } | ||
116 | auto rv = grammar::parse( | ||
117 | 8 | it->value, | |
118 |
1/2✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
16 | list_rule(token_rule, 1)); |
119 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | BOOST_ASSERT(! rv.has_error()); |
120 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | BOOST_ASSERT(! rv->empty()); |
121 | 8 | auto itv = rv->begin(); | |
122 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
|
8 | if(urls::grammar::ci_is_equal( |
123 | 8 | *itv, token)) | |
124 | { | ||
125 |
2/2✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
|
4 | if(rv->size() == 1) |
126 | { | ||
127 | // only one token | ||
128 | 3 | it = erase(it); | |
129 | } | ||
130 | else | ||
131 | { | ||
132 | // first token matches | ||
133 | 1 | ++itv; | |
134 | 1 | set(it, | |
135 | 1 | it->value.substr( | |
136 | 1 | (*itv).data() - | |
137 |
2/4✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
|
3 | it->value.data())); |
138 | 1 | ++it; | |
139 | } | ||
140 | 4 | continue; | |
141 | } | ||
142 | // search remaining tokens | ||
143 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
8 | std::string s = *itv++; |
144 |
2/2✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
|
7 | while(itv != rv->end()) |
145 | { | ||
146 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | if(! urls::grammar::ci_is_equal( |
147 | 3 | *itv, token)) | |
148 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | s += ", " + std::string(*itv); |
149 | 3 | ++itv; | |
150 | } | ||
151 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | set(it, s); |
152 | 4 | ++it; | |
153 | } | ||
154 | 6 | }; | |
155 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
|
7 | if(value) |
156 | { | ||
157 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | if(ph_->md.connection.close) |
158 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | erase_token("close"); |
159 | } | ||
160 | else | ||
161 | { | ||
162 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if(ph_->md.connection.keep_alive) |
163 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | erase_token("keep-alive"); |
164 | } | ||
165 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
|
7 | switch(ph_->version) |
166 | { | ||
167 | 5 | default: | |
168 | case version::http_1_1: | ||
169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if(! value) |
170 | { | ||
171 | // add one "close" token if needed | ||
172 | ✗ | if(! ph_->md.connection.close) | |
173 | ✗ | append(field::connection, "close"); | |
174 | } | ||
175 | 5 | break; | |
176 | |||
177 | 2 | case version::http_1_0: | |
178 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if(value) |
179 | { | ||
180 | // add one "keep-alive" token if needed | ||
181 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(! ph_->md.connection.keep_alive) |
182 | ✗ | append(field::connection, "keep-alive"); | |
183 | } | ||
184 | 2 | break; | |
185 | } | ||
186 | } | ||
187 | |||
188 | //------------------------------------------------ | ||
189 | |||
190 | char* | ||
191 | 25 | message_base:: | |
192 | set_prefix_impl( | ||
193 | std::size_t n) | ||
194 | { | ||
195 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 21 times.
|
25 | if( n > h_.prefix || |
196 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | h_.buf == nullptr) |
197 | { | ||
198 | // allocate or grow | ||
199 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2 times.
|
23 | if( n > h_.prefix && |
200 | static_cast<std::size_t>( | ||
201 | 21 | n - h_.prefix) > | |
202 | 21 | static_cast<std::size_t>( | |
203 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
|
21 | max_offset - h_.size)) |
204 | 1 | detail::throw_length_error(); | |
205 | |||
206 | 22 | auto n0 = detail::header::bytes_needed( | |
207 | 22 | n + h_.size - h_.prefix, | |
208 | 22 | h_.count); | |
209 | 22 | auto buf = new char[n0]; | |
210 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 19 times.
|
22 | if(h_.buf != nullptr) |
211 | { | ||
212 | 3 | std::memcpy( | |
213 | 3 | buf + n, | |
214 | 3 | h_.buf + h_.prefix, | |
215 | 3 | h_.size - h_.prefix); | |
216 | detail::header::table ft( | ||
217 | 3 | h_.buf + h_.cap); | |
218 | 3 | h_.copy_table(buf + n0); | |
219 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | delete[] h_.buf; |
220 | } | ||
221 | else | ||
222 | { | ||
223 | 19 | std::memcpy( | |
224 | 19 | buf + n, | |
225 | 19 | h_.cbuf + h_.prefix, | |
226 | 19 | h_.size - h_.prefix); | |
227 | } | ||
228 | 22 | h_.buf = buf; | |
229 | 22 | h_.cbuf = buf; | |
230 | 22 | h_.size = static_cast< | |
231 | 22 | offset_type>(h_.size + | |
232 | 22 | n - h_.prefix); | |
233 | 22 | h_.prefix = static_cast< | |
234 | offset_type>(n); | ||
235 | 22 | h_.cap = n0; | |
236 | 22 | return h_.buf; | |
237 | } | ||
238 | |||
239 | // shrink | ||
240 | 2 | std::memmove( | |
241 | 2 | h_.buf + n, | |
242 | 2 | h_.buf + h_.prefix, | |
243 | 2 | h_.size - h_.prefix); | |
244 | 2 | h_.size = static_cast< | |
245 | 2 | offset_type>(h_.size - | |
246 | 2 | h_.prefix + n); | |
247 | 2 | h_.prefix = static_cast< | |
248 | offset_type>(n); | ||
249 | 2 | return h_.buf; | |
250 | } | ||
251 | |||
252 | } // http_proto | ||
253 | } // boost | ||
254 |