| 709 | } |
| 710 | |
| 711 | ssize_t |
| 712 | FetchSM::ext_read_data(char *buf, size_t len) |
| 713 | { |
| 714 | const char *start; |
| 715 | IOBufferReader *reader; |
| 716 | IOBufferBlock *blk, *next_blk; |
| 717 | int64_t already, blk_len, need, wavail; |
| 718 | |
| 719 | if (fetch_flags & TS_FETCH_FLAGS_NEWLOCK) { |
| 720 | MUTEX_TRY_LOCK(lock, mutex, this_ethread()); |
| 721 | if (!lock.is_locked()) { |
| 722 | return 0; |
| 723 | } |
| 724 | } |
| 725 | |
| 726 | if (!header_done) { |
| 727 | return 0; |
| 728 | } |
| 729 | |
| 730 | if (check_chunked() && (fetch_flags & TS_FETCH_FLAGS_DECHUNK)) { |
| 731 | reader = chunked_handler.dechunked_reader; |
| 732 | } else { |
| 733 | reader = resp_reader; |
| 734 | } |
| 735 | |
| 736 | already = 0; |
| 737 | if (reader->block) { |
| 738 | reader->skip_empty_blocks(); |
| 739 | } |
| 740 | blk = reader->get_current_block(); |
| 741 | while (blk) { |
| 742 | wavail = len - already; |
| 743 | next_blk = blk->next.get(); |
| 744 | start = blk->start(); |
| 745 | blk_len = blk->read_avail(); |
| 746 | if (reader->block.get() == blk) { |
| 747 | start += reader->start_offset; |
| 748 | blk_len -= reader->start_offset; |
| 749 | if (blk_len < 0) { |
| 750 | blk_len = 0; |
| 751 | } |
| 752 | } |
| 753 | need = blk_len > wavail ? wavail : blk_len; |
| 754 | |
| 755 | memcpy(&buf[already], start, need); |
| 756 | already += need; |
| 757 | |
| 758 | if (already >= static_cast<int64_t>(len)) { |
| 759 | break; |
| 760 | } |
| 761 | |
| 762 | blk = next_blk; |
| 763 | } |
| 764 | |
| 765 | resp_received_body_len += already; |
| 766 | reader->consume(already); |
| 767 | |
| 768 | read_vio->reenable(); |
no test coverage detected