| 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/rfc/detail/rules.hpp> | ||
| 11 | |||
| 12 | #include <boost/http_proto/error.hpp> | ||
| 13 | #include <boost/http_proto/detail/config.hpp> | ||
| 14 | #include <boost/http_proto/rfc/token_rule.hpp> | ||
| 15 | |||
| 16 | #include <boost/core/detail/string_view.hpp> | ||
| 17 | #include <boost/url/grammar/delim_rule.hpp> | ||
| 18 | #include <boost/url/grammar/digit_chars.hpp> | ||
| 19 | #include <boost/url/grammar/error.hpp> | ||
| 20 | #include <boost/url/grammar/hexdig_chars.hpp> | ||
| 21 | #include <boost/url/grammar/lut_chars.hpp> | ||
| 22 | #include <boost/url/grammar/parse.hpp> | ||
| 23 | #include <boost/url/grammar/tuple_rule.hpp> | ||
| 24 | |||
| 25 | #include "rules.hpp" | ||
| 26 | |||
| 27 | namespace boost { | ||
| 28 | namespace http_proto { | ||
| 29 | namespace detail { | ||
| 30 | |||
| 31 | auto | ||
| 32 | 6287 | crlf_rule_t:: | |
| 33 | parse( | ||
| 34 | char const*& it, | ||
| 35 | char const* end) const noexcept -> | ||
| 36 | system::result<value_type> | ||
| 37 | { | ||
| 38 |
2/2✓ Branch 0 taken 1006 times.
✓ Branch 1 taken 5281 times.
|
6287 | if(it == end) |
| 39 | 1006 | return grammar::error::need_more; | |
| 40 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 5250 times.
|
5281 | if(*it != '\r') |
| 41 | 31 | return grammar::error::mismatch; | |
| 42 | 5250 | ++it; | |
| 43 |
2/2✓ Branch 0 taken 163 times.
✓ Branch 1 taken 5087 times.
|
5250 | if(it == end) |
| 44 | 163 | return grammar::error::need_more; | |
| 45 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 5035 times.
|
5087 | if(*it != '\n') |
| 46 | 52 | return grammar::error::mismatch; | |
| 47 | 5035 | ++it; | |
| 48 | 5035 | return {}; | |
| 49 | } | ||
| 50 | |||
| 51 | //------------------------------------------------ | ||
| 52 | |||
| 53 | auto | ||
| 54 | 3594 | version_rule_t:: | |
| 55 | parse( | ||
| 56 | char const*& it, | ||
| 57 | char const* end) const noexcept -> | ||
| 58 | system::result<value_type> | ||
| 59 | { | ||
| 60 | 3594 | value_type v = 0; | |
| 61 |
2/2✓ Branch 0 taken 171 times.
✓ Branch 1 taken 3423 times.
|
3594 | if(it == end) |
| 62 | { | ||
| 63 | // expected "HTTP/" | ||
| 64 | 171 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 65 | grammar::error::need_more); | ||
| 66 | } | ||
| 67 |
2/2✓ Branch 0 taken 2883 times.
✓ Branch 1 taken 540 times.
|
3423 | if(end - it >= 5) |
| 68 | { | ||
| 69 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2883 times.
|
2883 | if(std::memcmp( |
| 70 | it, "HTTP/", 5) != 0) | ||
| 71 | { | ||
| 72 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
| 73 | grammar::error::mismatch); | ||
| 74 | } | ||
| 75 | 2883 | it += 5; | |
| 76 | } | ||
| 77 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 3333 times.
|
3423 | if(it == end) |
| 78 | { | ||
| 79 | // expected DIGIT | ||
| 80 | 90 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 81 | grammar::error::need_more); | ||
| 82 | } | ||
| 83 |
2/2✓ Branch 1 taken 540 times.
✓ Branch 2 taken 2793 times.
|
3333 | if(! grammar::digit_chars(*it)) |
| 84 | { | ||
| 85 | // expected DIGIT | ||
| 86 | 540 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 87 | grammar::error::need_more); | ||
| 88 | } | ||
| 89 | 2793 | v = 10 * (*it++ - '0'); | |
| 90 |
2/2✓ Branch 0 taken 234 times.
✓ Branch 1 taken 2559 times.
|
2793 | if(it == end) |
| 91 | { | ||
| 92 | // expected "." | ||
| 93 | 234 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 94 | grammar::error::need_more); | ||
| 95 | } | ||
| 96 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2559 times.
|
2559 | if(*it != '.') |
| 97 | { | ||
| 98 | // expected "." | ||
| 99 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
| 100 | grammar::error::need_more); | ||
| 101 | } | ||
| 102 | 2559 | ++it; | |
| 103 |
2/2✓ Branch 0 taken 89 times.
✓ Branch 1 taken 2470 times.
|
2559 | if(it == end) |
| 104 | { | ||
| 105 | // expected DIGIT | ||
| 106 | 89 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 107 | grammar::error::need_more); | ||
| 108 | } | ||
| 109 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2470 times.
|
2470 | if(! grammar::digit_chars(*it)) |
| 110 | { | ||
| 111 | // expected DIGIT | ||
| 112 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
| 113 | grammar::error::need_more); | ||
| 114 | } | ||
| 115 | 2470 | v += *it++ - '0'; | |
| 116 | 2470 | return v; | |
| 117 | } | ||
| 118 | |||
| 119 | //------------------------------------------------ | ||
| 120 | |||
| 121 | auto | ||
| 122 | 608 | status_code_rule_t:: | |
| 123 | parse( | ||
| 124 | char const*& it, | ||
| 125 | char const* end) const noexcept -> | ||
| 126 | system::result<value_type> | ||
| 127 | { | ||
| 128 | auto const dig = | ||
| 129 | 1773 | [](char c) -> int | |
| 130 | { | ||
| 131 | 1773 | unsigned char uc(c - '0'); | |
| 132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1773 times.
|
1773 | if(uc > 9) |
| 133 | ✗ | return -1; | |
| 134 | 1773 | return uc; | |
| 135 | }; | ||
| 136 | |||
| 137 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 599 times.
|
608 | if(it == end) |
| 138 | { | ||
| 139 | // end | ||
| 140 | 9 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 141 | grammar::error::need_more); | ||
| 142 | } | ||
| 143 | 599 | auto it0 = it; | |
| 144 | 599 | int v = dig(*it); | |
| 145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
|
599 | if(v == -1) |
| 146 | { | ||
| 147 | // expected DIGIT | ||
| 148 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
| 149 | grammar::error::mismatch); | ||
| 150 | } | ||
| 151 | 599 | value_type t; | |
| 152 | 599 | t.v = 100 * v; | |
| 153 | 599 | ++it; | |
| 154 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 591 times.
|
599 | if(it == end) |
| 155 | { | ||
| 156 | // end | ||
| 157 | 8 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 158 | grammar::error::need_more); | ||
| 159 | } | ||
| 160 | 591 | v = dig(*it); | |
| 161 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 591 times.
|
591 | if(v == -1) |
| 162 | { | ||
| 163 | // expected DIGIT | ||
| 164 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
| 165 | grammar::error::mismatch); | ||
| 166 | } | ||
| 167 | 591 | t.v = t.v + (10 * v); | |
| 168 | 591 | ++it; | |
| 169 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 583 times.
|
591 | if(it == end) |
| 170 | { | ||
| 171 | // end | ||
| 172 | 8 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 173 | grammar::error::need_more); | ||
| 174 | } | ||
| 175 | 583 | v = dig(*it); | |
| 176 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 583 times.
|
583 | if(v == -1) |
| 177 | { | ||
| 178 | // expected DIGIT | ||
| 179 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
| 180 | grammar::error::need_more); | ||
| 181 | } | ||
| 182 | 583 | t.v = t.v + v; | |
| 183 | 583 | ++it; | |
| 184 | |||
| 185 | 583 | t.s = core::string_view(it0, it - it0); | |
| 186 | 583 | t.st = int_to_status(t.v); | |
| 187 | 583 | return t; | |
| 188 | } | ||
| 189 | |||
| 190 | //------------------------------------------------ | ||
| 191 | |||
| 192 | auto | ||
| 193 | 4841 | field_name_rule_t:: | |
| 194 | parse( | ||
| 195 | char const*& it, | ||
| 196 | char const* end) const noexcept -> | ||
| 197 | system::result<value_type> | ||
| 198 | { | ||
| 199 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4840 times.
|
4841 | if( it == end ) |
| 200 | 1 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 201 | grammar::error::need_more); | ||
| 202 | |||
| 203 | 4840 | value_type v; | |
| 204 | |||
| 205 | 4840 | auto begin = it; | |
| 206 | 4840 | auto rv = grammar::parse( | |
| 207 | it, end, token_rule); | ||
| 208 |
6/6✓ Branch 1 taken 4775 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 4172 times.
✓ Branch 4 taken 603 times.
✓ Branch 5 taken 4237 times.
✓ Branch 6 taken 603 times.
|
4840 | if( rv.has_error() || (it != end) ) |
| 209 | { | ||
| 210 |
2/2✓ Branch 0 taken 4172 times.
✓ Branch 1 taken 65 times.
|
4237 | if( it != begin ) |
| 211 | { | ||
| 212 | 4172 | v = core::string_view(begin, it - begin); | |
| 213 | 4172 | return v; | |
| 214 | } | ||
| 215 | 65 | return error::bad_field_name; | |
| 216 | } | ||
| 217 | |||
| 218 | 603 | v = core::string_view(begin, end - begin); | |
| 219 | 603 | return v; | |
| 220 | } | ||
| 221 | |||
| 222 | auto | ||
| 223 | 4419 | field_value_rule_t:: | |
| 224 | parse( | ||
| 225 | char const*& it, | ||
| 226 | char const* end) const noexcept -> | ||
| 227 | system::result<value_type> | ||
| 228 | { | ||
| 229 | 4419 | value_type v; | |
| 230 |
2/2✓ Branch 0 taken 199 times.
✓ Branch 1 taken 4220 times.
|
4419 | if( it == end ) |
| 231 | { | ||
| 232 | 199 | v.value = core::string_view(it, 0); | |
| 233 | 199 | return v; | |
| 234 | } | ||
| 235 | |||
| 236 | // field-line = field-name ":" OWS field-value OWS | ||
| 237 | // field-value = *field-content | ||
| 238 | // field-content = field-vchar | ||
| 239 | // [ 1*( SP / HTAB / field-vchar ) field-vchar ] | ||
| 240 | // field-vchar = VCHAR / obs-text | ||
| 241 | // obs-text = %x80-FF | ||
| 242 | // VCHAR = %x21-7E | ||
| 243 | // ; visible (printing) characters | ||
| 244 | |||
| 245 | 15877 | auto is_field_vchar = [](unsigned char ch) | |
| 246 | { | ||
| 247 |
6/6✓ Branch 0 taken 15843 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 15831 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 34 times.
|
15877 | return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80; |
| 248 | }; | ||
| 249 | |||
| 250 | 4220 | char const* s0 = nullptr; | |
| 251 | 4220 | char const* s1 = nullptr; | |
| 252 | |||
| 253 | 4220 | bool has_crlf = false; | |
| 254 | 4220 | bool has_obs_fold = false; | |
| 255 | |||
| 256 |
2/2✓ Branch 0 taken 25952 times.
✓ Branch 1 taken 958 times.
|
26910 | while( it < end ) |
| 257 | { | ||
| 258 | 25952 | auto ch = *it; | |
| 259 |
2/2✓ Branch 1 taken 6131 times.
✓ Branch 2 taken 19821 times.
|
25952 | if( ws(ch) ) |
| 260 | { | ||
| 261 | 6131 | ++it; | |
| 262 | 6131 | continue; | |
| 263 | } | ||
| 264 | |||
| 265 |
2/2✓ Branch 0 taken 3944 times.
✓ Branch 1 taken 15877 times.
|
19821 | if( ch == '\r' ) |
| 266 | { | ||
| 267 | // too short to know if we have a potential obs-fold | ||
| 268 | // occurrence | ||
| 269 |
2/2✓ Branch 0 taken 200 times.
✓ Branch 1 taken 3744 times.
|
3944 | if( end - it < 2 ) |
| 270 | 200 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 271 | grammar::error::need_more); | ||
| 272 | |||
| 273 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 3691 times.
|
3744 | if( it[1] != '\n' ) |
| 274 | 53 | goto done; | |
| 275 | |||
| 276 |
2/2✓ Branch 0 taken 171 times.
✓ Branch 1 taken 3520 times.
|
3691 | if( end - it < 3 ) |
| 277 | 171 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 278 | grammar::error::need_more); | ||
| 279 | |||
| 280 |
2/2✓ Branch 1 taken 2804 times.
✓ Branch 2 taken 716 times.
|
3520 | if(! ws(it[2]) ) |
| 281 | { | ||
| 282 | 2804 | has_crlf = true; | |
| 283 | 2804 | goto done; | |
| 284 | } | ||
| 285 | |||
| 286 | 716 | has_obs_fold = true; | |
| 287 | 716 | it = it + 3; | |
| 288 | 716 | continue; | |
| 289 | 716 | } | |
| 290 | |||
| 291 |
2/2✓ Branch 1 taken 34 times.
✓ Branch 2 taken 15843 times.
|
15877 | if(! is_field_vchar(ch) ) |
| 292 | { | ||
| 293 | 34 | goto done; | |
| 294 | } | ||
| 295 | |||
| 296 |
2/2✓ Branch 0 taken 3595 times.
✓ Branch 1 taken 12248 times.
|
15843 | if(! s0 ) |
| 297 | 3595 | s0 = it; | |
| 298 | |||
| 299 | 15843 | ++it; | |
| 300 | 15843 | s1 = it; | |
| 301 | } | ||
| 302 | |||
| 303 | 958 | done: | |
| 304 | // later routines wind up doing pointer | ||
| 305 | // subtraction using the .data() member | ||
| 306 | // of the value so we need a valid 0-len range | ||
| 307 |
2/2✓ Branch 0 taken 462 times.
✓ Branch 1 taken 3387 times.
|
3849 | if(! s0 ) |
| 308 | { | ||
| 309 | 462 | s0 = it; | |
| 310 | 462 | s1 = s0; | |
| 311 | } | ||
| 312 | |||
| 313 | 3849 | v.value = core::string_view(s0, s1 - s0); | |
| 314 | 3849 | v.has_crlf = has_crlf; | |
| 315 | 3849 | v.has_obs_fold = has_obs_fold; | |
| 316 | 3849 | return v; | |
| 317 | } | ||
| 318 | |||
| 319 | auto | ||
| 320 | 6957 | field_rule_t:: | |
| 321 | parse( | ||
| 322 | char const*& it, | ||
| 323 | char const* end) const noexcept -> | ||
| 324 | system::result<value_type> | ||
| 325 | { | ||
| 326 |
2/2✓ Branch 0 taken 197 times.
✓ Branch 1 taken 6760 times.
|
6957 | if(it == end) |
| 327 | { | ||
| 328 | 197 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 329 | grammar::error::need_more); | ||
| 330 | } | ||
| 331 | // check for leading CRLF | ||
| 332 |
2/2✓ Branch 0 taken 2224 times.
✓ Branch 1 taken 4536 times.
|
6760 | if(it[0] == '\r') |
| 333 | { | ||
| 334 | 2224 | ++it; | |
| 335 |
2/2✓ Branch 0 taken 134 times.
✓ Branch 1 taken 2090 times.
|
2224 | if(it == end) |
| 336 | { | ||
| 337 | 134 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 338 | grammar::error::need_more); | ||
| 339 | } | ||
| 340 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2069 times.
|
2090 | if(*it != '\n') |
| 341 | { | ||
| 342 | 21 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 343 | grammar::error::mismatch); | ||
| 344 | } | ||
| 345 | // end of fields | ||
| 346 | 2069 | ++it; | |
| 347 | 2069 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 348 | grammar::error::end_of_range); | ||
| 349 | } | ||
| 350 | |||
| 351 | 4536 | value_type v; | |
| 352 | auto rv = grammar::parse( | ||
| 353 | 4536 | it, end, grammar::tuple_rule( | |
| 354 | field_name_rule, | ||
| 355 | 4536 | grammar::delim_rule(':'), | |
| 356 | field_value_rule, | ||
| 357 | 4536 | crlf_rule)); | |
| 358 | |||
| 359 |
2/2✓ Branch 1 taken 1739 times.
✓ Branch 2 taken 2797 times.
|
4536 | if( rv.has_error() ) |
| 360 | 1739 | return rv.error(); | |
| 361 | |||
| 362 | 2797 | auto val = rv.value(); | |
| 363 | 2797 | v.name = std::get<0>(val); | |
| 364 | 2797 | v.value = std::get<2>(val).value; | |
| 365 | 2797 | v.has_obs_fold = std::get<2>(val).has_obs_fold; | |
| 366 | |||
| 367 | 2797 | return v; | |
| 368 | } | ||
| 369 | |||
| 370 | //------------------------------------------------ | ||
| 371 | |||
| 372 | void | ||
| 373 | 241 | remove_obs_fold( | |
| 374 | char* it, | ||
| 375 | char const* const end) noexcept | ||
| 376 | { | ||
| 377 |
2/2✓ Branch 0 taken 2224 times.
✓ Branch 1 taken 23 times.
|
2247 | while(it != end) |
| 378 | { | ||
| 379 |
2/2✓ Branch 0 taken 1628 times.
✓ Branch 1 taken 596 times.
|
2224 | if(*it != '\r') |
| 380 | { | ||
| 381 | 1628 | ++it; | |
| 382 | 1628 | continue; | |
| 383 | } | ||
| 384 |
2/2✓ Branch 0 taken 218 times.
✓ Branch 1 taken 378 times.
|
596 | if(end - it < 3) |
| 385 | 218 | break; | |
| 386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
|
378 | BOOST_ASSERT(it[1] == '\n'); |
| 387 |
5/6✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 375 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 375 times.
✓ Branch 5 taken 3 times.
|
756 | if( it[1] == '\n' && |
| 388 | 378 | ws(it[2])) | |
| 389 | { | ||
| 390 | 375 | it[0] = ' '; | |
| 391 | 375 | it[1] = ' '; | |
| 392 | 375 | it += 3; | |
| 393 | } | ||
| 394 | else | ||
| 395 | { | ||
| 396 | 3 | ++it; | |
| 397 | } | ||
| 398 | } | ||
| 399 | 241 | } | |
| 400 | |||
| 401 | //------------------------------------------------ | ||
| 402 | |||
| 403 | system::result<hex_rule_t::value_type> | ||
| 404 | 244 | hex_rule_t:: | |
| 405 | parse( | ||
| 406 | char const*& it, | ||
| 407 | char const* end) const noexcept | ||
| 408 | { | ||
| 409 | 244 | value_type v; | |
| 410 | |||
| 411 | constexpr | ||
| 412 | 244 | auto const max_size = | |
| 413 | (std::numeric_limits<std::size_t>::max)() >> 4; | ||
| 414 | |||
| 415 | 244 | auto const begin = it; | |
| 416 |
2/2✓ Branch 0 taken 493 times.
✓ Branch 1 taken 4 times.
|
497 | for( ; it < end; ++it ) |
| 417 | { | ||
| 418 | 493 | auto n = grammar::hexdig_value(*it); | |
| 419 |
2/2✓ Branch 0 taken 239 times.
✓ Branch 1 taken 254 times.
|
493 | if(n < 0) |
| 420 | { | ||
| 421 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 155 times.
|
239 | if( it == begin ) |
| 422 | 84 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 423 | grammar::error::mismatch); | ||
| 424 | |||
| 425 | 155 | return v; | |
| 426 | } | ||
| 427 | |||
| 428 | // we know that so long as we can shift the current | ||
| 429 | // value up 4 bits, we'll be able to fit the hex | ||
| 430 | // digit we've just parsed | ||
| 431 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 253 times.
|
254 | if( v.v > max_size ) |
| 432 | 1 | BOOST_HTTP_PROTO_RETURN_EC( | |
| 433 | grammar::error::invalid); | ||
| 434 | |||
| 435 | 253 | v.v = (v.v << 4) | (std::size_t)n; | |
| 436 | } | ||
| 437 | 4 | return v; | |
| 438 | } | ||
| 439 | |||
| 440 | system::result<void> | ||
| 441 | ✗ | last_chunk_rule_t:: | |
| 442 | parse( | ||
| 443 | char const*& it, | ||
| 444 | char const* end) const noexcept | ||
| 445 | { | ||
| 446 | constexpr | ||
| 447 | ✗ | std::size_t const last_chunk_len = 5; // 0\r\n\r\n | |
| 448 | |||
| 449 | ✗ | if( static_cast<std::size_t>(end - it) < | |
| 450 | last_chunk_len ) | ||
| 451 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
| 452 | grammar::error::need_more); | ||
| 453 | |||
| 454 | ✗ | core::string_view str(it, end - it); | |
| 455 | ✗ | if( str != "0\r\n\r\n" ) | |
| 456 | ✗ | BOOST_HTTP_PROTO_RETURN_EC(grammar::error::invalid); | |
| 457 | |||
| 458 | ✗ | it += last_chunk_len; | |
| 459 | |||
| 460 | ✗ | return {}; | |
| 461 | } | ||
| 462 | |||
| 463 | } // detail | ||
| 464 | } // http_proto | ||
| 465 | } // boost | ||
| 466 |