| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #pragma once
- #include "mtproto/mtp_instance.h"
- namespace Main {
- class Session;
- } // namespace Main
- namespace MTP {
- class WeakInstance final : private QObject {
- public:
- explicit WeakInstance(base::weak_ptr<Main::Session> session);
- template <typename Request>
- void send(
- const Request &request,
- Fn<void(const typename Request::ResponseType &result)> done,
- Fn<void(const Error &error)> fail,
- ShiftedDcId dcId = 0);
- [[nodiscard]] base::weak_ptr<Main::Session> session() const;
- [[nodiscard]] bool valid() const;
- [[nodiscard]] Instance *instance() const;
- ~WeakInstance();
- private:
- void die();
- bool removeRequest(mtpRequestId requestId);
- void reportUnavailable(Fn<void(const Error &error)> callback);
- base::weak_ptr<Main::Session> _session;
- Instance *_instance = nullptr;
- std::map<mtpRequestId, Fn<void(const Error &)>> _requests;
- rpl::lifetime _lifetime;
- };
- class AbstractDedicatedLoader : public base::has_weak_ptr {
- public:
- AbstractDedicatedLoader(const QString &filepath, int chunkSize);
- static constexpr auto kChunkSize = 128 * 1024;
- static constexpr auto kMaxFileSize = 256 * 1024 * 1024;
- struct Progress {
- int64 already = 0;
- int64 size = 0;
- inline bool operator<(const Progress &other) const {
- return (already < other.already)
- || (already == other.already && size < other.size);
- }
- inline bool operator==(const Progress &other) const {
- return (already == other.already) && (size == other.size);
- }
- };
- void start();
- void wipeFolder();
- void wipeOutput();
- int64 alreadySize() const;
- int64 totalSize() const;
- rpl::producer<Progress> progress() const;
- rpl::producer<QString> ready() const;
- rpl::producer<> failed() const;
- rpl::lifetime &lifetime();
- virtual ~AbstractDedicatedLoader() = default;
- protected:
- void threadSafeFailed();
- // Single threaded.
- void writeChunk(bytes::const_span data, int totalSize);
- private:
- virtual void startLoading() = 0;
- bool validateOutput();
- void threadSafeProgress(Progress progress);
- void threadSafeReady();
- QString _filepath;
- int _chunkSize = 0;
- QFile _output;
- int64 _alreadySize = 0;
- int64 _totalSize = 0;
- mutable QMutex _sizesMutex;
- rpl::event_stream<Progress> _progress;
- rpl::event_stream<QString> _ready;
- rpl::event_stream<> _failed;
- rpl::lifetime _lifetime;
- };
- class DedicatedLoader : public AbstractDedicatedLoader {
- public:
- struct Location {
- QString username;
- int32 postId = 0;
- };
- struct File {
- QString name;
- int64 size = 0;
- DcId dcId = 0;
- MTPInputFileLocation location;
- };
- DedicatedLoader(
- base::weak_ptr<Main::Session> session,
- const QString &folder,
- const File &file);
- private:
- struct Request {
- int64 offset = 0;
- QByteArray bytes;
- };
- void startLoading() override;
- void sendRequest();
- void gotPart(int offset, const MTPupload_File &result);
- Fn<void(const Error &)> failHandler();
- static constexpr auto kRequestsCount = 2;
- static constexpr auto kNextRequestDelay = crl::time(20);
- std::deque<Request> _requests;
- int64 _size = 0;
- int64 _offset = 0;
- DcId _dcId = 0;
- MTPInputFileLocation _location;
- WeakInstance _mtp;
- };
- void ResolveChannel(
- not_null<MTP::WeakInstance*> mtp,
- const QString &username,
- Fn<void(const MTPInputChannel &channel)> done,
- Fn<void()> fail);
- std::optional<MTPMessage> GetMessagesElement(
- const MTPmessages_Messages &list);
- void StartDedicatedLoader(
- not_null<MTP::WeakInstance*> mtp,
- const DedicatedLoader::Location &location,
- const QString &folder,
- Fn<void(std::unique_ptr<DedicatedLoader>)> ready);
- template <typename Request>
- void WeakInstance::send(
- const Request &request,
- Fn<void(const typename Request::ResponseType &result)> done,
- Fn<void(const Error &error)> fail,
- MTP::ShiftedDcId dcId) {
- using Result = typename Request::ResponseType;
- if (!valid()) {
- reportUnavailable(fail);
- return;
- }
- const auto onDone = crl::guard((QObject*)this, [=](
- const Response &response) {
- auto result = Result();
- auto from = response.reply.constData();
- if (!result.read(from, from + response.reply.size())) {
- return false;
- }
- if (removeRequest(response.requestId)) {
- done(result);
- }
- return true;
- });
- const auto onFail = crl::guard((QObject*)this, [=](
- const Error &error,
- const Response &response) {
- if (MTP::IsDefaultHandledError(error)) {
- return false;
- }
- if (removeRequest(response.requestId)) {
- fail(error);
- }
- return true;
- });
- const auto requestId = _instance->send(
- request,
- std::move(onDone),
- std::move(onFail),
- dcId);
- _requests.emplace(requestId, fail);
- }
- } // namespace MTP
|