2018-12-31 20:04:05 +01:00
|
|
|
//
|
2024-01-01 01:07:21 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
2018-12-31 20:04:05 +01:00
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#include "td/net/HttpChunkedByteFlow.h"
|
|
|
|
|
|
|
|
#include "td/utils/find_boundary.h"
|
|
|
|
#include "td/utils/format.h"
|
|
|
|
#include "td/utils/misc.h"
|
2021-05-17 14:21:11 +02:00
|
|
|
#include "td/utils/SliceBuilder.h"
|
2018-12-31 20:04:05 +01:00
|
|
|
#include "td/utils/Status.h"
|
|
|
|
|
|
|
|
namespace td {
|
2018-02-12 11:37:54 +01:00
|
|
|
|
2020-07-22 20:52:00 +02:00
|
|
|
bool HttpChunkedByteFlow::loop() {
|
|
|
|
bool result = false;
|
|
|
|
do {
|
2020-01-19 01:02:56 +01:00
|
|
|
if (state_ == State::ReadChunkLength) {
|
2018-12-31 20:04:05 +01:00
|
|
|
bool ok = find_boundary(input_->clone(), "\r\n", len_);
|
2024-02-29 17:38:57 +01:00
|
|
|
if (len_ > 8) {
|
2020-07-22 20:52:00 +02:00
|
|
|
finish(Status::Error(PSLICE() << "Too long length in chunked "
|
|
|
|
<< input_->cut_head(len_).move_as_buffer_slice().as_slice()));
|
|
|
|
return false;
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
if (!ok) {
|
2020-07-22 20:52:00 +02:00
|
|
|
set_need_size(input_->size() + 1);
|
2018-12-31 20:04:05 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
auto s_len = input_->cut_head(len_).move_as_buffer_slice();
|
|
|
|
input_->advance(2);
|
|
|
|
len_ = hex_to_integer<size_t>(s_len.as_slice());
|
|
|
|
save_len_ = len_;
|
2020-01-19 01:02:56 +01:00
|
|
|
state_ = State::ReadChunkContent;
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
auto size = input_->size();
|
2018-02-12 11:37:54 +01:00
|
|
|
auto ready = min(len_, size);
|
2024-02-29 17:38:57 +01:00
|
|
|
auto need_size = min(MIN_UPDATE_SIZE, len_) + 2;
|
2018-12-31 20:04:05 +01:00
|
|
|
if (size < need_size) {
|
2020-07-22 20:52:00 +02:00
|
|
|
set_need_size(need_size);
|
2018-12-31 20:04:05 +01:00
|
|
|
break;
|
|
|
|
}
|
2022-08-14 12:30:25 +02:00
|
|
|
if (total_size_ > MAX_SIZE - ready) {
|
2020-07-22 20:52:00 +02:00
|
|
|
finish(Status::Error(PSLICE() << "Too big query " << tag("size", input_->size())));
|
|
|
|
return false;
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
2022-08-14 12:30:25 +02:00
|
|
|
total_size_ += ready;
|
2018-12-31 20:04:05 +01:00
|
|
|
|
|
|
|
output_.append(input_->cut_head(ready));
|
2020-07-22 20:52:00 +02:00
|
|
|
result = true;
|
2018-12-31 20:04:05 +01:00
|
|
|
len_ -= ready;
|
|
|
|
|
|
|
|
if (len_ == 0) {
|
|
|
|
if (input_->size() < 2) {
|
2021-10-18 18:26:14 +02:00
|
|
|
set_need_size(2);
|
2018-12-31 20:04:05 +01:00
|
|
|
break;
|
|
|
|
}
|
2018-10-26 16:11:20 +02:00
|
|
|
input_->advance(2);
|
2018-12-31 20:04:05 +01:00
|
|
|
total_size_ += 2;
|
|
|
|
if (save_len_ == 0) {
|
2020-07-22 20:52:00 +02:00
|
|
|
finish(Status::OK());
|
|
|
|
return false;
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
2020-01-19 01:02:56 +01:00
|
|
|
state_ = State::ReadChunkLength;
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
2020-08-13 15:57:28 +02:00
|
|
|
} while (false);
|
2020-07-22 20:52:00 +02:00
|
|
|
if (!is_input_active_ && !result) {
|
|
|
|
finish(Status::Error("Unexpected end of stream"));
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
2020-07-22 20:52:00 +02:00
|
|
|
return result;
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
2018-02-12 11:37:54 +01:00
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
} // namespace td
|