summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/td/telegram/files/FileHashUploader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/td/telegram/files/FileHashUploader.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/td/telegram/files/FileHashUploader.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/protocols/Telegram/tdlib/td/td/telegram/files/FileHashUploader.cpp b/protocols/Telegram/tdlib/td/td/telegram/files/FileHashUploader.cpp
new file mode 100644
index 0000000000..2408e16df4
--- /dev/null
+++ b/protocols/Telegram/tdlib/td/td/telegram/files/FileHashUploader.cpp
@@ -0,0 +1,142 @@
+//
+// 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/telegram/files/FileHashUploader.h"
+
+#include "td/telegram/telegram_api.h"
+
+#include "td/telegram/Global.h"
+#include "td/telegram/net/NetQueryDispatcher.h"
+
+#include "td/utils/buffer.h"
+#include "td/utils/crypto.h"
+#include "td/utils/logging.h"
+#include "td/utils/MimeType.h"
+#include "td/utils/misc.h"
+#include "td/utils/PathView.h"
+#include "td/utils/port/Fd.h"
+#include "td/utils/port/FileFd.h"
+#include "td/utils/Status.h"
+
+namespace td {
+void FileHashUploader::start_up() {
+ auto status = init();
+ if (status.is_error()) {
+ callback_->on_error(std::move(status));
+ stop_flag_ = true;
+ return;
+ }
+}
+Status FileHashUploader::init() {
+ TRY_RESULT(fd, FileFd::open(local_.path_, FileFd::Read));
+ if (fd.get_size() != size_) {
+ return Status::Error("size mismatch");
+ }
+ fd_ = BufferedFd<FileFd>(std::move(fd));
+ sha256_init(&sha256_state_);
+
+ resource_state_.set_unit_size(1024);
+ resource_state_.update_estimated_limit(size_);
+ return Status::OK();
+}
+void FileHashUploader::loop() {
+ if (stop_flag_) {
+ return;
+ }
+
+ auto status = loop_impl();
+ if (status.is_error()) {
+ callback_->on_error(std::move(status));
+ stop_flag_ = true;
+ return;
+ }
+}
+
+Status FileHashUploader::loop_impl() {
+ if (state_ == CalcSha) {
+ TRY_STATUS(loop_sha());
+ }
+ if (state_ == NetRequest) {
+ // messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
+ auto hash = BufferSlice(32);
+ sha256_final(&sha256_state_, hash.as_slice());
+ auto mime_type = MimeType::from_extension(PathView(local_.path_).extension(), "image/gif");
+ auto query =
+ telegram_api::messages_getDocumentByHash(std::move(hash), static_cast<int32>(size_), std::move(mime_type));
+ LOG(INFO) << "Send getDocumentByHash request: " << to_string(query);
+ auto ptr = G()->net_query_creator().create(create_storer(query));
+ G()->net_query_dispatcher().dispatch_with_callback(std::move(ptr), actor_shared(this));
+ state_ = WaitNetResult;
+ }
+ return Status::OK();
+}
+
+Status FileHashUploader::loop_sha() {
+ auto limit = resource_state_.unused();
+ if (limit == 0) {
+ return Status::OK();
+ }
+ if (limit > size_left_) {
+ limit = size_left_;
+ }
+ resource_state_.start_use(limit);
+
+ fd_.update_flags(Fd::Flag::Read);
+ TRY_RESULT(read_size, fd_.flush_read(static_cast<size_t>(limit)));
+ if (read_size != static_cast<size_t>(limit)) {
+ return Status::Error("unexpected end of file");
+ }
+ while (true) {
+ auto ready = fd_.input_buffer().prepare_read();
+ if (ready.empty()) {
+ break;
+ }
+ sha256_update(ready, &sha256_state_);
+ fd_.input_buffer().confirm_read(ready.size());
+ }
+ resource_state_.stop_use(limit);
+
+ size_left_ -= narrow_cast<int64>(read_size);
+ CHECK(size_left_ >= 0);
+ if (size_left_ == 0) {
+ state_ = NetRequest;
+ return Status::OK();
+ }
+ return Status::OK();
+}
+
+void FileHashUploader::on_result(NetQueryPtr net_query) {
+ auto status = on_result_impl(std::move(net_query));
+ if (status.is_error()) {
+ callback_->on_error(std::move(status));
+ stop_flag_ = true;
+ return;
+ }
+}
+
+Status FileHashUploader::on_result_impl(NetQueryPtr net_query) {
+ if (net_query->is_error()) {
+ return net_query->move_as_error();
+ }
+ TRY_RESULT(res, fetch_result<telegram_api::messages_getDocumentByHash>(net_query->ok()));
+
+ switch (res->get_id()) {
+ case telegram_api::documentEmpty::ID:
+ return Status::Error("Document is not found by hash");
+ case telegram_api::document::ID: {
+ auto document = move_tl_object_as<telegram_api::document>(res);
+ callback_->on_ok(FullRemoteFileLocation(FileType::Document, document->id_, document->access_hash_,
+ DcId::internal(document->dc_id_)));
+
+ stop_flag_ = true;
+ return Status::OK();
+ }
+ default:
+ UNREACHABLE();
+ return Status::Error("UNREACHABLE");
+ }
+}
+} // namespace td