summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/tdnet/td/net/HttpChunkedByteFlow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/tdnet/td/net/HttpChunkedByteFlow.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/tdnet/td/net/HttpChunkedByteFlow.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/protocols/Telegram/tdlib/td/tdnet/td/net/HttpChunkedByteFlow.cpp b/protocols/Telegram/tdlib/td/tdnet/td/net/HttpChunkedByteFlow.cpp
new file mode 100644
index 0000000000..2edd225bfa
--- /dev/null
+++ b/protocols/Telegram/tdlib/td/tdnet/td/net/HttpChunkedByteFlow.cpp
@@ -0,0 +1,83 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
+//
+// 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/logging.h"
+#include "td/utils/misc.h"
+#include "td/utils/Status.h"
+
+namespace td {
+
+void HttpChunkedByteFlow::loop() {
+ bool was_updated = false;
+ size_t need_size;
+ while (true) {
+ if (state_ == ReadChunkLength) {
+ bool ok = find_boundary(input_->clone(), "\r\n", len_);
+ if (len_ > 10) {
+ return finish(Status::Error(PSLICE() << "Too long length in chunked "
+ << input_->cut_head(len_).move_as_buffer_slice().as_slice()));
+ }
+ if (!ok) {
+ need_size = input_->size() + 1;
+ 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());
+ if (len_ > MAX_CHUNK_SIZE) {
+ return finish(Status::Error(PSLICE() << "Invalid chunk size " << tag("size", len_)));
+ }
+ save_len_ = len_;
+ state_ = ReadChunkContent;
+ }
+
+ auto size = input_->size();
+ auto ready = min(len_, size);
+ need_size = min(MIN_UPDATE_SIZE, len_ + 2);
+ if (size < need_size) {
+ break;
+ }
+ total_size_ += ready;
+ uncommited_size_ += ready;
+ if (total_size_ > MAX_SIZE) {
+ return finish(Status::Error(PSLICE() << "Too big query " << tag("size", input_->size())));
+ }
+
+ output_.append(input_->cut_head(ready));
+ len_ -= ready;
+ if (uncommited_size_ >= MIN_UPDATE_SIZE) {
+ uncommited_size_ = 0;
+ was_updated = true;
+ }
+
+ if (len_ == 0) {
+ if (input_->size() < 2) {
+ need_size = 2;
+ break;
+ }
+ input_->cut_head(2);
+ total_size_ += 2;
+ if (save_len_ == 0) {
+ return finish(Status::OK());
+ }
+ state_ = ReadChunkLength;
+ len_ = 0;
+ }
+ }
+ if (was_updated) {
+ on_output_updated();
+ }
+ if (!is_input_active_) {
+ return finish(Status::Error("Unexpected end of stream"));
+ }
+ set_need_size(need_size);
+}
+
+} // namespace td