this function signals error by assigning a negative value to "chunk_size" the return value indicates whether enough data is available in "buf" to completely parse the chunk header. Returning false means we need more data
| 484 | // the return value indicates whether enough data is available in "buf" to |
| 485 | // completely parse the chunk header. Returning false means we need more data |
| 486 | bool http_parser::parse_chunk_header(span<char const> buf |
| 487 | , std::int64_t* chunk_size, int* header_size) |
| 488 | { |
| 489 | char const* pos = buf.data(); |
| 490 | |
| 491 | // ignore one optional new-line. This is since each chunk |
| 492 | // is terminated by a newline. we're likely to see one |
| 493 | // before the actual header. |
| 494 | |
| 495 | if (pos < buf.end() && pos[0] == '\r') ++pos; |
| 496 | if (pos < buf.end() && pos[0] == '\n') ++pos; |
| 497 | if (pos == buf.end()) return false; |
| 498 | |
| 499 | TORRENT_ASSERT(pos <= buf.end()); |
| 500 | char const* newline = std::find(pos, buf.end(), '\n'); |
| 501 | if (newline == buf.end()) return false; |
| 502 | ++newline; |
| 503 | |
| 504 | // the chunk header is a single line, a hex length of the |
| 505 | // chunk followed by an optional semi-colon with a comment |
| 506 | // in case the length is 0, the stream is terminated and |
| 507 | // there are extra tail headers, which is terminated by an |
| 508 | // empty line |
| 509 | |
| 510 | *header_size = int(newline - buf.data()); |
| 511 | |
| 512 | // first, read the chunk length |
| 513 | std::int64_t size = 0; |
| 514 | for (char const* i = pos; i != newline; ++i) |
| 515 | { |
| 516 | if (*i == '\r') continue; |
| 517 | if (*i == '\n') continue; |
| 518 | if (*i == ';') break; |
| 519 | int const digit = aux::hex_to_int(*i); |
| 520 | if (digit < 0) |
| 521 | { |
| 522 | *chunk_size = -1; |
| 523 | return true; |
| 524 | } |
| 525 | if (size >= std::numeric_limits<std::int64_t>::max() / 16) |
| 526 | { |
| 527 | *chunk_size = -1; |
| 528 | return true; |
| 529 | } |
| 530 | size *= 16; |
| 531 | size += digit; |
| 532 | } |
| 533 | *chunk_size = size; |
| 534 | |
| 535 | if (*chunk_size != 0) |
| 536 | { |
| 537 | // the newline is at least 1 byte, and the length-prefix is at least 1 |
| 538 | // byte |
| 539 | TORRENT_ASSERT(newline - buf.data() >= 2); |
| 540 | return true; |
| 541 | } |
| 542 | |
| 543 | // this is the terminator of the stream. Also read headers |