diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp index 2b9cd94cb..f3a1a442c 100644 --- a/Telegram/SourceFiles/boxes/connection_box.cpp +++ b/Telegram/SourceFiles/boxes/connection_box.cpp @@ -1059,7 +1059,7 @@ void ProxiesBoxController::refreshChecker(Item &item) { item.state = ItemState::Checking; const auto setup = [&](Checker &checker, const bytes::vector &secret) { - checker = MTP::internal::AbstractConnection::Create( + checker = MTP::details::AbstractConnection::Create( mtproto, type, QThread::currentThread(), @@ -1107,7 +1107,7 @@ void ProxiesBoxController::refreshChecker(Item &item) { } void ProxiesBoxController::setupChecker(int id, const Checker &checker) { - using Connection = MTP::internal::AbstractConnection; + using Connection = MTP::details::AbstractConnection; const auto pointer = checker.get(); pointer->connect(pointer, &Connection::connected, [=] { const auto item = findById(id); diff --git a/Telegram/SourceFiles/boxes/connection_box.h b/Telegram/SourceFiles/boxes/connection_box.h index 21d79f9ad..fbefdacb5 100644 --- a/Telegram/SourceFiles/boxes/connection_box.h +++ b/Telegram/SourceFiles/boxes/connection_box.h @@ -75,7 +75,7 @@ public: ~ProxiesBoxController(); private: - using Checker = MTP::internal::ConnectionPointer; + using Checker = MTP::details::ConnectionPointer; struct Item { int id = 0; ProxyData data; diff --git a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py index 1193e6afd..ff0e91d47 100644 --- a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py +++ b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py @@ -14,7 +14,7 @@ from generate_tl import generate generate({ 'namespaces': { - 'creator': 'MTP::internal', + 'creator': 'MTP::details', }, 'prefixes': { 'type': 'MTP', diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index 04a167751..9954a1faa 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -184,9 +184,9 @@ void Application::run() { style::ShortAnimationPlaying( ) | rpl::start_with_next([=](bool playing) { if (playing) { - MTP::internal::pause(); + MTP::details::pause(); } else { - MTP::internal::unpause(); + MTP::details::unpause(); } }, _lifetime); diff --git a/Telegram/SourceFiles/export/export_api_wrap.h b/Telegram/SourceFiles/export/export_api_wrap.h index 6f3016ab6..0e47e9be3 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.h +++ b/Telegram/SourceFiles/export/export_api_wrap.h @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "mtproto/concurrent_sender.h" +#include "mtproto/mtproto_concurrent_sender.h" namespace Export { namespace Data { diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index bfa29df18..9c4f41615 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/type_traits.h" #include "base/observer.h" #include "base/call_delayed.h" -#include "ui/effects/animation_value.h" #include "mtproto/mtproto_proxy_data.h" class History; diff --git a/Telegram/SourceFiles/mtproto/config_loader.cpp b/Telegram/SourceFiles/mtproto/config_loader.cpp index 3f60590a5..fc847c855 100644 --- a/Telegram/SourceFiles/mtproto/config_loader.cpp +++ b/Telegram/SourceFiles/mtproto/config_loader.cpp @@ -7,14 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/config_loader.h" +#include "mtproto/special_config_request.h" #include "mtproto/facade.h" #include "mtproto/dc_options.h" #include "mtproto/mtp_instance.h" -#include "mtproto/special_config_request.h" #include "facades.h" namespace MTP { -namespace internal { +namespace details { namespace { constexpr auto kEnumerateDcTimeout = 8000; // 8 seconds timeout for help_getConfig to work (then move to other dc) @@ -215,5 +215,5 @@ void ConfigLoader::specialConfigLoaded(const MTPConfig &result) { _instance->dcOptions()->setFromList(data.vdc_options()); } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/config_loader.h b/Telegram/SourceFiles/mtproto/config_loader.h index 476e8f164..39b7bc214 100644 --- a/Telegram/SourceFiles/mtproto/config_loader.h +++ b/Telegram/SourceFiles/mtproto/config_loader.h @@ -14,10 +14,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace MTP { -class SpecialConfigRequest; class Instance; -namespace internal { +namespace details { + +class SpecialConfigRequest; class ConfigLoader : public base::has_weak_ptr { public: @@ -76,5 +77,5 @@ inline bool operator==(const ConfigLoader::SpecialEndpoint &a, const ConfigLoade return (a.dcId == b.dcId) && (a.ip == b.ip) && (a.port == b.port); } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_abstract.cpp b/Telegram/SourceFiles/mtproto/connection_abstract.cpp index 831141c29..cf2f3bdb0 100644 --- a/Telegram/SourceFiles/mtproto/connection_abstract.cpp +++ b/Telegram/SourceFiles/mtproto/connection_abstract.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/openssl_help.h" namespace MTP { -namespace internal { +namespace details { ConnectionPointer::ConnectionPointer() = default; @@ -194,5 +194,5 @@ uint32 AbstractConnection::extendedNotSecurePadding() const { : 0; } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_abstract.h b/Telegram/SourceFiles/mtproto/connection_abstract.h index b84ae0d08..695d83694 100644 --- a/Telegram/SourceFiles/mtproto/connection_abstract.h +++ b/Telegram/SourceFiles/mtproto/connection_abstract.h @@ -18,7 +18,7 @@ namespace MTP { class Instance; -namespace internal { +namespace details { struct ConnectionOptions; @@ -195,5 +195,5 @@ mtpBuffer AbstractConnection::prepareNotSecurePacket( return result; } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_http.cpp b/Telegram/SourceFiles/mtproto/connection_http.cpp index f7d6a81f7..3f9d005b7 100644 --- a/Telegram/SourceFiles/mtproto/connection_http.cpp +++ b/Telegram/SourceFiles/mtproto/connection_http.cpp @@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/qthelp_url.h" namespace MTP { -namespace internal { +namespace details { namespace { constexpr auto kForceHttpPort = 80; @@ -246,5 +246,5 @@ QUrl HttpConnection::url() const { return QUrl(pattern.arg(_address).arg(kForceHttpPort)); } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_http.h b/Telegram/SourceFiles/mtproto/connection_http.h index 57fffb875..8fb867aa5 100644 --- a/Telegram/SourceFiles/mtproto/connection_http.h +++ b/Telegram/SourceFiles/mtproto/connection_http.h @@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include namespace MTP { -namespace internal { +namespace details { class HttpConnection : public AbstractConnection { public: @@ -64,5 +64,5 @@ private: }; -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_resolving.cpp b/Telegram/SourceFiles/mtproto/connection_resolving.cpp index 171b8885b..7590db6a3 100644 --- a/Telegram/SourceFiles/mtproto/connection_resolving.cpp +++ b/Telegram/SourceFiles/mtproto/connection_resolving.cpp @@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/mtp_instance.h" namespace MTP { -namespace internal { +namespace details { namespace { constexpr auto kOneConnectionTimeout = 4000; @@ -256,5 +256,5 @@ QString ResolvingConnection::tag() const { return _child ? _child->tag() : QString(); } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_resolving.h b/Telegram/SourceFiles/mtproto/connection_resolving.h index ceb9c474e..eeb137113 100644 --- a/Telegram/SourceFiles/mtproto/connection_resolving.h +++ b/Telegram/SourceFiles/mtproto/connection_resolving.h @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" namespace MTP { -namespace internal { +namespace details { class ResolvingConnection : public AbstractConnection { public: @@ -67,5 +67,5 @@ private: }; -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_tcp.cpp b/Telegram/SourceFiles/mtproto/connection_tcp.cpp index f46e16c26..f195c7c44 100644 --- a/Telegram/SourceFiles/mtproto/connection_tcp.cpp +++ b/Telegram/SourceFiles/mtproto/connection_tcp.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/connection_tcp.h" -#include "mtproto/mtproto_abstract_socket.h" +#include "mtproto/details/mtproto_abstract_socket.h" #include "base/bytes.h" #include "base/openssl_help.h" #include "base/qthelp_url.h" @@ -17,7 +17,7 @@ extern "C" { } // extern "C" namespace MTP { -namespace internal { +namespace details { namespace { constexpr auto kPacketSizeMax = int(0x01000000 * sizeof(mtpPrime)); @@ -665,5 +665,5 @@ void TcpConnection::socketError() { TcpConnection::~TcpConnection() = default; -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection_tcp.h b/Telegram/SourceFiles/mtproto/connection_tcp.h index 07134f14f..1fc5319a1 100644 --- a/Telegram/SourceFiles/mtproto/connection_tcp.h +++ b/Telegram/SourceFiles/mtproto/connection_tcp.h @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/mtproto_auth_key.h" namespace MTP { -namespace internal { +namespace details { class AbstractSocket; @@ -98,5 +98,5 @@ private: }; -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/dc_options.cpp b/Telegram/SourceFiles/mtproto/dc_options.cpp index 34dfd0cbe..d82d60e10 100644 --- a/Telegram/SourceFiles/mtproto/dc_options.cpp +++ b/Telegram/SourceFiles/mtproto/dc_options.cpp @@ -7,13 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/dc_options.h" +#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/facade.h" -#include "storage/serialize_common.h" #include "mtproto/connection_tcp.h" +#include "storage/serialize_common.h" namespace MTP { namespace { +using namespace details; + const char *(PublicRSAKeys[]) = { "\ -----BEGIN RSA PUBLIC KEY-----\n\ MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n\ @@ -102,6 +105,8 @@ DcOptions::DcOptions() { constructFromBuiltIn(); } +DcOptions::~DcOptions() = default; + bool DcOptions::ValidateSecret(bytes::const_span secret) { // See also TcpConnection::Protocol::Create. return (secret.size() >= 21 && secret[0] == bytes::type(0xEE)) @@ -113,7 +118,7 @@ bool DcOptions::ValidateSecret(bytes::const_span secret) { void DcOptions::readBuiltInPublicKeys() { for (const auto key : PublicRSAKeys) { const auto keyBytes = bytes::make_span(key, strlen(key)); - auto parsed = internal::RSAPublicKey(keyBytes); + auto parsed = RSAPublicKey(keyBytes); if (parsed.valid()) { _publicKeys.emplace(parsed.fingerprint(), std::move(parsed)); } else { @@ -512,7 +517,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) { return; } - auto key = internal::RSAPublicKey(n, e); + auto key = RSAPublicKey(n, e); if (key.valid()) { _cdnPublicKeys[dcId].emplace(key.fingerprint(), std::move(key)); } else { @@ -569,7 +574,7 @@ void DcOptions::setCDNConfig(const MTPDcdnConfig &config) { for (const auto &key : config.vpublic_keys().v) { key.match([&](const MTPDcdnPublicKey &data) { const auto keyBytes = bytes::make_span(data.vpublic_key().v); - auto key = internal::RSAPublicKey(keyBytes); + auto key = RSAPublicKey(keyBytes); if (key.valid()) { _cdnPublicKeys[data.vdc_id().v].emplace( key.fingerprint(), @@ -590,18 +595,17 @@ bool DcOptions::hasCDNKeysForDc(DcId dcId) const { return _cdnPublicKeys.find(dcId) != _cdnPublicKeys.cend(); } -internal::RSAPublicKey DcOptions::getDcRSAKey( +RSAPublicKey DcOptions::getDcRSAKey( DcId dcId, const QVector &fingerprints) const { - const auto findKey = [&]( - const std::map &keys) { + const auto findKey = [&](const std::map &keys) { for (const auto &fingerprint : fingerprints) { const auto it = keys.find(static_cast(fingerprint.v)); if (it != keys.cend()) { return it->second; } } - return internal::RSAPublicKey(); + return RSAPublicKey(); }; { ReadLocker lock(this); diff --git a/Telegram/SourceFiles/mtproto/dc_options.h b/Telegram/SourceFiles/mtproto/dc_options.h index ca0293b9c..11449d3ea 100644 --- a/Telegram/SourceFiles/mtproto/dc_options.h +++ b/Telegram/SourceFiles/mtproto/dc_options.h @@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/observer.h" #include "base/bytes.h" -#include "mtproto/mtproto_rsa_public_key.h" #include #include @@ -18,6 +17,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include namespace MTP { +namespace details { +class RSAPublicKey; +} // namespace details enum class DcType { Regular, @@ -52,6 +54,7 @@ public: }; DcOptions(); + ~DcOptions(); [[nodiscard]] static bool ValidateSecret(bytes::const_span secret); @@ -95,7 +98,7 @@ public: void setCDNConfig(const MTPDcdnConfig &config); [[nodiscard]] bool hasCDNKeysForDc(DcId dcId) const; - [[nodiscard]] internal::RSAPublicKey getDcRSAKey( + [[nodiscard]] details::RSAPublicKey getDcRSAKey( DcId dcId, const QVector &fingerprints) const; @@ -137,8 +140,8 @@ private: std::map> _data; std::set _cdnDcIds; - std::map _publicKeys; - std::map> _cdnPublicKeys; + std::map _publicKeys; + std::map> _cdnPublicKeys; mutable QReadWriteLock _useThroughLockers; rpl::event_stream _changed; diff --git a/Telegram/SourceFiles/mtproto/mtproto_abstract_socket.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_abstract_socket.cpp similarity index 73% rename from Telegram/SourceFiles/mtproto/mtproto_abstract_socket.cpp rename to Telegram/SourceFiles/mtproto/details/mtproto_abstract_socket.cpp index 2f77cd144..2ad0a44a6 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_abstract_socket.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_abstract_socket.cpp @@ -5,13 +5,12 @@ 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 */ -#include "mtproto/mtproto_abstract_socket.h" +#include "mtproto/details/mtproto_abstract_socket.h" -#include "mtproto/mtproto_tcp_socket.h" -#include "mtproto/mtproto_tls_socket.h" +#include "mtproto/details/mtproto_tcp_socket.h" +#include "mtproto/details/mtproto_tls_socket.h" -namespace MTP { -namespace internal { +namespace MTP::details { std::unique_ptr AbstractSocket::Create( not_null thread, @@ -24,5 +23,4 @@ std::unique_ptr AbstractSocket::Create( } } -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/mtproto_abstract_socket.h b/Telegram/SourceFiles/mtproto/details/mtproto_abstract_socket.h similarity index 95% rename from Telegram/SourceFiles/mtproto/mtproto_abstract_socket.h rename to Telegram/SourceFiles/mtproto/details/mtproto_abstract_socket.h index 4d5c35108..61da8b5e3 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_abstract_socket.h +++ b/Telegram/SourceFiles/mtproto/details/mtproto_abstract_socket.h @@ -10,8 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/bytes.h" #include "base/basic_types.h" -namespace MTP { -namespace internal { +namespace MTP::details { class AbstractSocket : protected QObject { public: @@ -62,5 +61,4 @@ protected: }; -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.cpp index 6b90e1b6a..d1da9f591 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/details/mtproto_dc_key_creator.h" +#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/connection_abstract.h" #include "mtproto/mtproto_dh_utils.h" #include "base/openssl_help.h" diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.h b/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.h index 756044444..f62bb8f41 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.h +++ b/Telegram/SourceFiles/mtproto/details/mtproto_dc_key_creator.h @@ -19,8 +19,6 @@ class DcOptions; namespace MTP::details { -using namespace ::MTP::internal; - struct DcKeyRequest { TimeId temporaryExpiresIn = 0; bool persistentNeeded = false; diff --git a/Telegram/SourceFiles/mtproto/dcenter.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_dcenter.cpp similarity index 97% rename from Telegram/SourceFiles/mtproto/dcenter.cpp rename to Telegram/SourceFiles/mtproto/details/mtproto_dcenter.cpp index 663d72897..43ece30f4 100644 --- a/Telegram/SourceFiles/mtproto/dcenter.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_dcenter.cpp @@ -5,17 +5,16 @@ 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 */ -#include "mtproto/dcenter.h" +#include "mtproto/details/mtproto_dcenter.h" #include "mtproto/facade.h" #include "mtproto/mtproto_auth_key.h" #include "mtproto/dc_options.h" #include "mtproto/mtp_instance.h" #include "mtproto/special_config_request.h" -#include "storage/localstorage.h" namespace MTP { -namespace internal { +namespace details { namespace { constexpr auto kEnumerateDcTimeout = 8000; // 8 seconds timeout for help_getConfig to work (then move to other dc) @@ -165,5 +164,5 @@ void Dcenter::releaseKeyCreationOnFail(CreatingKeyType type) { _creatingKeys[IndexByType(type)] = false; } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/dcenter.h b/Telegram/SourceFiles/mtproto/details/mtproto_dcenter.h similarity index 95% rename from Telegram/SourceFiles/mtproto/dcenter.h rename to Telegram/SourceFiles/mtproto/details/mtproto_dcenter.h index 0b4636014..0418e09e4 100644 --- a/Telegram/SourceFiles/mtproto/dcenter.h +++ b/Telegram/SourceFiles/mtproto/details/mtproto_dcenter.h @@ -7,13 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include + namespace MTP { class Instance; class AuthKey; using AuthKeyPtr = std::shared_ptr; -namespace internal { +namespace details { enum class TemporaryKeyType { Regular, @@ -61,5 +63,5 @@ private: }; -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp new file mode 100644 index 000000000..b26308978 --- /dev/null +++ b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp @@ -0,0 +1,362 @@ +/* +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 +*/ +#include "mtproto/details/mtproto_domain_resolver.h" + +#include "base/openssl_help.h" +#include "base/invoke_queued.h" +#include "base/call_delayed.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace MTP::details { +namespace { + +constexpr auto kSendNextTimeout = crl::time(800); +constexpr auto kMinTimeToLive = 10 * crl::time(1000); +constexpr auto kMaxTimeToLive = 300 * crl::time(1000); + +} // namespace + +const std::vector &DnsDomains() { + static const auto kResult = std::vector{ + "google.com", + "www.google.com", + "google.ru", + "www.google.ru", + }; + return kResult; +} + +QString GenerateDnsRandomPadding() { + constexpr char kValid[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + auto result = QString(); + const auto count = [&] { + constexpr auto kMinPadding = 13; + constexpr auto kMaxPadding = 128; + while (true) { + const auto result = 1 + (openssl::RandomValue() / 2); + Assert(result <= kMaxPadding); + if (result >= kMinPadding) { + return result; + } + } + }(); + result.resize(count); + for (auto &ch : result) { + ch = kValid[openssl::RandomValue() % (sizeof(kValid) - 1)]; + } + return result; +} + +QByteArray DnsUserAgent() { + static const auto kResult = QByteArray( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/77.0.3865.90 Safari/537.36"); + return kResult; +} + +std::vector ParseDnsResponse( + const QByteArray &bytes, + std::optional typeRestriction) { + // Read and store to "result" all the data bytes from the response: + // { .., + // "Answer": [ + // { .., "data": "bytes1", "TTL": int, .. }, + // { .., "data": "bytes2", "TTL": int, .. } + // ], + // .. } + auto error = QJsonParseError{ 0, QJsonParseError::NoError }; + const auto document = QJsonDocument::fromJson(bytes, &error); + if (error.error != QJsonParseError::NoError) { + LOG(("Config Error: Failed to parse dns response JSON, error: %1" + ).arg(error.errorString())); + return {}; + } else if (!document.isObject()) { + LOG(("Config Error: Not an object received in dns response JSON.")); + return {}; + } + const auto response = document.object(); + const auto answerIt = response.find("Answer"); + if (answerIt == response.constEnd()) { + LOG(("Config Error: Could not find Answer in dns response JSON.")); + return {}; + } else if (!(*answerIt).isArray()) { + LOG(("Config Error: Not an array received " + "in Answer in dns response JSON.")); + return {}; + } + + auto result = std::vector(); + for (const auto elem : (*answerIt).toArray()) { + if (!elem.isObject()) { + LOG(("Config Error: Not an object found " + "in Answer array in dns response JSON.")); + continue; + } + const auto object = elem.toObject(); + if (typeRestriction) { + const auto typeIt = object.find("type"); + const auto type = int(std::round((*typeIt).toDouble())); + if (!(*typeIt).isDouble()) { + LOG(("Config Error: Not a number in type field " + "in Answer array in dns response JSON.")); + continue; + } else if (type != *typeRestriction) { + continue; + } + } + const auto dataIt = object.find("data"); + if (dataIt == object.constEnd()) { + LOG(("Config Error: Could not find data " + "in Answer array entry in dns response JSON.")); + continue; + } else if (!(*dataIt).isString()) { + LOG(("Config Error: Not a string data found " + "in Answer array entry in dns response JSON.")); + continue; + } + + const auto ttlIt = object.find("TTL"); + const auto ttl = (ttlIt != object.constEnd()) + ? crl::time(std::round((*ttlIt).toDouble())) + : crl::time(0); + result.push_back({ (*dataIt).toString(), ttl }); + } + return result; +} + +ServiceWebRequest::ServiceWebRequest(not_null reply) +: reply(reply.get()) { +} + +ServiceWebRequest::ServiceWebRequest(ServiceWebRequest &&other) +: reply(base::take(other.reply)) { +} + +ServiceWebRequest &ServiceWebRequest::operator=(ServiceWebRequest &&other) { + if (reply != other.reply) { + destroy(); + reply = base::take(other.reply); + } + return *this; +} + +void ServiceWebRequest::destroy() { + if (const auto value = base::take(reply)) { + value->disconnect( + value, + &QNetworkReply::finished, + nullptr, + nullptr); + value->abort(); + value->deleteLater(); + } +} + +ServiceWebRequest::~ServiceWebRequest() { + if (reply) { + reply->deleteLater(); + } +} + +DomainResolver::DomainResolver(Fn callback) +: _callback(std::move(callback)) { + _manager.setProxy(QNetworkProxy::NoProxy); +} + +void DomainResolver::resolve(const QString &domain) { + resolve({ domain, false }); + resolve({ domain, true }); +} + +void DomainResolver::resolve(const AttemptKey &key) { + if (_attempts.find(key) != end(_attempts)) { + return; + } else if (_requests.find(key) != end(_requests)) { + return; + } + const auto i = _cache.find(key); + _lastTimestamp = crl::now(); + if (i != end(_cache) && i->second.expireAt > _lastTimestamp) { + checkExpireAndPushResult(key.domain); + return; + } + + auto attempts = std::vector(); + auto domains = DnsDomains(); + std::random_device rd; + ranges::shuffle(domains, std::mt19937(rd())); + const auto takeDomain = [&] { + const auto result = domains.back(); + domains.pop_back(); + return result; + }; + const auto shuffle = [&](int from, int till) { + Expects(till > from); + + ranges::shuffle( + begin(attempts) + from, + begin(attempts) + till, + std::mt19937(rd())); + }; + + attempts.push_back({ Type::Google, "dns.google.com" }); + attempts.push_back({ Type::Google, takeDomain(), "dns" }); + attempts.push_back({ Type::Mozilla, "mozilla.cloudflare-dns.com" }); + while (!domains.empty()) { + attempts.push_back({ Type::Google, takeDomain(), "dns" }); + } + + shuffle(0, 2); + + ranges::reverse(attempts); // We go from last to first. + + _attempts.emplace(key, Attempts{ std::move(attempts) }); + sendNextRequest(key); +} + +void DomainResolver::checkExpireAndPushResult(const QString &domain) { + const auto ipv4 = _cache.find({ domain, false }); + if (ipv4 == end(_cache) || ipv4->second.expireAt <= _lastTimestamp) { + return; + } + auto result = ipv4->second; + const auto ipv6 = _cache.find({ domain, true }); + if (ipv6 != end(_cache) && ipv6->second.expireAt > _lastTimestamp) { + result.ips.append(ipv6->second.ips); + accumulate_min(result.expireAt, ipv6->second.expireAt); + } + InvokeQueued(this, [=] { + _callback(domain, result.ips, result.expireAt); + }); +} + +void DomainResolver::sendNextRequest(const AttemptKey &key) { + auto i = _attempts.find(key); + if (i == end(_attempts)) { + return; + } + auto &attempts = i->second; + auto &list = attempts.list; + const auto attempt = list.back(); + list.pop_back(); + + if (!list.empty()) { + base::call_delayed(kSendNextTimeout, &attempts.guard, [=] { + sendNextRequest(key); + }); + } + performRequest(key, attempt); +} + +void DomainResolver::performRequest( + const AttemptKey &key, + const Attempt &attempt) { + auto url = QUrl(); + url.setScheme("https"); + auto request = QNetworkRequest(); + switch (attempt.type) { + case Type::Mozilla: { + url.setHost(attempt.data); + url.setPath("/dns-query"); + url.setQuery(QStringLiteral("name=%1&type=%2&random_padding=%3" + ).arg(key.domain + ).arg(key.ipv6 ? 28 : 1 + ).arg(GenerateDnsRandomPadding())); + request.setRawHeader("accept", "application/dns-json"); + } break; + case Type::Google: { + url.setHost(attempt.data); + url.setPath("/resolve"); + url.setQuery(QStringLiteral("name=%1&type=%2&random_padding=%3" + ).arg(key.domain + ).arg(key.ipv6 ? 28 : 1 + ).arg(GenerateDnsRandomPadding())); + if (!attempt.host.isEmpty()) { + const auto host = attempt.host + ".google.com"; + request.setRawHeader("Host", host.toLatin1()); + } + } break; + default: Unexpected("Type in SpecialConfigRequest::performRequest."); + } + request.setUrl(url); + request.setRawHeader("User-Agent", DnsUserAgent()); + const auto i = _requests.emplace( + key, + std::vector()).first; + const auto reply = i->second.emplace_back( + _manager.get(request) + ).reply; + connect(reply, &QNetworkReply::finished, this, [=] { + requestFinished(key, reply); + }); +} + +void DomainResolver::requestFinished( + const AttemptKey &key, + not_null reply) { + const auto result = finalizeRequest(key, reply); + const auto response = ParseDnsResponse(result); + if (response.empty()) { + return; + } + _requests.erase(key); + _attempts.erase(key); + + auto entry = CacheEntry(); + auto ttl = kMaxTimeToLive; + for (const auto &item : response) { + entry.ips.push_back(item.data); + ttl = std::min( + ttl, + std::max(item.TTL * crl::time(1000), kMinTimeToLive)); + } + _lastTimestamp = crl::now(); + entry.expireAt = _lastTimestamp + ttl; + _cache[key] = std::move(entry); + + checkExpireAndPushResult(key.domain); +} + +QByteArray DomainResolver::finalizeRequest( + const AttemptKey &key, + not_null reply) { + if (reply->error() != QNetworkReply::NoError) { + LOG(("Resolve Error: Failed to get response, error: %2 (%3)" + ).arg(reply->errorString() + ).arg(reply->error())); + } + const auto result = reply->readAll(); + const auto i = _requests.find(key); + if (i != end(_requests)) { + auto &requests = i->second; + const auto from = ranges::remove( + requests, + reply, + [](const ServiceWebRequest &request) { return request.reply; }); + requests.erase(from, end(requests)); + if (requests.empty()) { + _requests.erase(i); + } + } + return result; +} + +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.h b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.h new file mode 100644 index 000000000..cb1979bbb --- /dev/null +++ b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.h @@ -0,0 +1,106 @@ +/* +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 "base/weak_ptr.h" + +#include +#include +#include + +namespace MTP::details { + +[[nodiscard]] const std::vector &DnsDomains(); +[[nodiscard]] QString GenerateDnsRandomPadding(); +[[nodiscard]] QByteArray DnsUserAgent(); + +struct DnsEntry { + QString data; + crl::time TTL = 0; +}; + +[[nodiscard]] std::vector ParseDnsResponse( + const QByteArray &bytes, + std::optional typeRestriction = std::nullopt); + +struct ServiceWebRequest { + ServiceWebRequest(not_null reply); + ServiceWebRequest(ServiceWebRequest &&other); + ServiceWebRequest &operator=(ServiceWebRequest &&other); + ~ServiceWebRequest(); + + void destroy(); + + QPointer reply; +}; + +class DomainResolver : public QObject { +public: + DomainResolver(Fn callback); + + void resolve(const QString &domain); + +private: + enum class Type { + Mozilla, + Google, + }; + struct Attempt { + Type type; + QString data; + QString host; + }; + struct AttemptKey { + QString domain; + bool ipv6 = false; + + inline bool operator<(const AttemptKey &other) const { + return (domain < other.domain) + || (domain == other.domain && !ipv6 && other.ipv6); + } + inline bool operator==(const AttemptKey &other) const { + return (domain == other.domain) && (ipv6 == other.ipv6); + } + }; + struct CacheEntry { + QStringList ips; + crl::time expireAt = 0; + }; + struct Attempts { + std::vector list; + base::has_weak_ptr guard; + }; + + void resolve(const AttemptKey &key); + void sendNextRequest(const AttemptKey &key); + void performRequest(const AttemptKey &key, const Attempt &attempt); + void checkExpireAndPushResult(const QString &domain); + void requestFinished( + const AttemptKey &key, + not_null reply); + QByteArray finalizeRequest( + const AttemptKey &key, + not_null reply); + + Fn _callback; + + QNetworkAccessManager _manager; + std::map _attempts; + std::map> _requests; + std::map _cache; + crl::time _lastTimestamp = 0; + +}; + +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/mtproto_rsa_public_key.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.cpp similarity index 98% rename from Telegram/SourceFiles/mtproto/mtproto_rsa_public_key.cpp rename to Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.cpp index ca10f0a29..8d47ed822 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_rsa_public_key.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.cpp @@ -5,12 +5,11 @@ 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 */ -#include "mtproto/mtproto_rsa_public_key.h" +#include "mtproto/details/mtproto_rsa_public_key.h" #include "base/openssl_help.h" -namespace MTP { -namespace internal { +namespace MTP::details { namespace { #if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) @@ -292,5 +291,4 @@ bytes::vector RSAPublicKey::encryptOAEPpadding( return _private->encryptOAEPpadding(data); } -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/mtproto_rsa_public_key.h b/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.h similarity index 94% rename from Telegram/SourceFiles/mtproto/mtproto_rsa_public_key.h rename to Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.h index 402b17426..86978061d 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_rsa_public_key.h +++ b/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.h @@ -9,8 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/bytes.h" -namespace MTP { -namespace internal { +namespace MTP::details { // this class holds an RSA public key and can encrypt fixed-size messages with it class RSAPublicKey final { @@ -47,5 +46,4 @@ private: }; -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_serialized_request.h b/Telegram/SourceFiles/mtproto/details/mtproto_serialized_request.h index 61dd8e6c7..ad9901b2b 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_serialized_request.h +++ b/Telegram/SourceFiles/mtproto/details/mtproto_serialized_request.h @@ -11,7 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include -namespace MTP::details { +namespace MTP { +namespace details { class RequestData; class SerializedRequest; @@ -44,7 +45,7 @@ public: template < typename Request, typename = std::enable_if_t>> - static SerializedRequest Serialize(const Request &request); + static SerializedRequest Serialize(const Request &request); // For template MTP requests and MTPBoxed instantiation. template @@ -102,4 +103,5 @@ SerializedRequest SerializedRequest::Serialize(const Request &request) { return serialized; } -} // namespace MTP::details +} // namespace details +} // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/mtproto_tcp_socket.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_tcp_socket.cpp similarity index 97% rename from Telegram/SourceFiles/mtproto/mtproto_tcp_socket.cpp rename to Telegram/SourceFiles/mtproto/details/mtproto_tcp_socket.cpp index d2fbd6ad9..53680461a 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_tcp_socket.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_tcp_socket.cpp @@ -5,12 +5,11 @@ 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 */ -#include "mtproto/mtproto_tcp_socket.h" +#include "mtproto/details/mtproto_tcp_socket.h" #include "base/invoke_queued.h" -namespace MTP { -namespace internal { +namespace MTP::details { TcpSocket::TcpSocket(not_null thread, const QNetworkProxy &proxy) : AbstractSocket(thread) { @@ -153,5 +152,4 @@ void TcpSocket::handleError(int errorCode) { _error.fire({}); } -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/mtproto_tcp_socket.h b/Telegram/SourceFiles/mtproto/details/mtproto_tcp_socket.h similarity index 87% rename from Telegram/SourceFiles/mtproto/mtproto_tcp_socket.h rename to Telegram/SourceFiles/mtproto/details/mtproto_tcp_socket.h index c8919fce2..6c8bac882 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_tcp_socket.h +++ b/Telegram/SourceFiles/mtproto/details/mtproto_tcp_socket.h @@ -7,10 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "mtproto/mtproto_abstract_socket.h" +#include "mtproto/details/mtproto_abstract_socket.h" -namespace MTP { -namespace internal { +namespace MTP::details { class TcpSocket final : public AbstractSocket { public: @@ -35,5 +34,4 @@ private: }; -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/mtproto_tls_socket.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_tls_socket.cpp similarity index 99% rename from Telegram/SourceFiles/mtproto/mtproto_tls_socket.cpp rename to Telegram/SourceFiles/mtproto/details/mtproto_tls_socket.cpp index 8aa38f523..385dff13a 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_tls_socket.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_tls_socket.cpp @@ -5,9 +5,9 @@ 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 */ -#include "mtproto/mtproto_tls_socket.h" +#include "mtproto/details/mtproto_tls_socket.h" -#include "mtproto/mtproto_tcp_socket.h" +#include "mtproto/details/mtproto_tcp_socket.h" #include "base/openssl_help.h" #include "base/bytes.h" #include "base/invoke_queued.h" @@ -16,8 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -namespace MTP { -namespace internal { +namespace MTP::details { namespace { constexpr auto kMaxGrease = 8; @@ -778,5 +777,4 @@ void TlsSocket::handleError(int errorCode) { _error.fire({}); } -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/mtproto_tls_socket.h b/Telegram/SourceFiles/mtproto/details/mtproto_tls_socket.h similarity index 92% rename from Telegram/SourceFiles/mtproto/mtproto_tls_socket.h rename to Telegram/SourceFiles/mtproto/details/mtproto_tls_socket.h index a93ef4014..01848230a 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_tls_socket.h +++ b/Telegram/SourceFiles/mtproto/details/mtproto_tls_socket.h @@ -7,10 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "mtproto/mtproto_abstract_socket.h" +#include "mtproto/details/mtproto_abstract_socket.h" -namespace MTP { -namespace internal { +namespace MTP::details { class TlsSocket final : public AbstractSocket { public: @@ -64,5 +63,4 @@ private: }; -} // namespace internal -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/facade.cpp b/Telegram/SourceFiles/mtproto/facade.cpp index 920a2c723..a776a958e 100644 --- a/Telegram/SourceFiles/mtproto/facade.cpp +++ b/Telegram/SourceFiles/mtproto/facade.cpp @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_account.h" namespace MTP { -namespace internal { +namespace details { namespace { int PauseLevel = 0; @@ -36,7 +36,7 @@ void unpause() { } } -} // namespace internal +} // namespace details Instance *MainInstance() { return Core::IsAppLaunched() diff --git a/Telegram/SourceFiles/mtproto/facade.h b/Telegram/SourceFiles/mtproto/facade.h index cffb33584..75868ce83 100644 --- a/Telegram/SourceFiles/mtproto/facade.h +++ b/Telegram/SourceFiles/mtproto/facade.h @@ -11,13 +11,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/mtp_instance.h" namespace MTP { -namespace internal { +namespace details { [[nodiscard]] bool paused(); void pause(); void unpause(); -} // namespace internal +} // namespace details // send(MTPhelp_GetConfig(), MTP::configDcId(dc)) - for dc enumeration constexpr ShiftedDcId configDcId(DcId dcId) { @@ -37,23 +37,24 @@ constexpr ShiftedDcId updaterDcId(DcId dcId) { constexpr auto kDownloadSessionsCount = 2; constexpr auto kUploadSessionsCount = 2; -namespace internal { +namespace details { constexpr ShiftedDcId downloadDcId(DcId dcId, int index) { static_assert(kDownloadSessionsCount < kMaxMediaDcCount, "Too large MTPDownloadSessionsCount!"); return ShiftDcId(dcId, kBaseDownloadDcShift + index); }; -} // namespace internal +} // namespace details // send(req, callbacks, MTP::downloadDcId(dc, index)) - for download shifted dc id inline ShiftedDcId downloadDcId(DcId dcId, int index) { Expects(index >= 0 && index < kDownloadSessionsCount); - return internal::downloadDcId(dcId, index); + return details::downloadDcId(dcId, index); } inline constexpr bool isDownloadDcId(ShiftedDcId shiftedDcId) { - return (shiftedDcId >= internal::downloadDcId(0, 0)) && (shiftedDcId < internal::downloadDcId(0, kDownloadSessionsCount - 1) + kDcShift); + return (shiftedDcId >= details::downloadDcId(0, 0)) + && (shiftedDcId < details::downloadDcId(0, kDownloadSessionsCount - 1) + kDcShift); } inline bool isCdnDc(MTPDdcOption::Flags flags) { @@ -75,25 +76,26 @@ inline DcId getTemporaryIdFromRealDcId(ShiftedDcId shiftedDcId) { return (dcId < Instance::Config::kTemporaryMainDc) ? (dcId + Instance::Config::kTemporaryMainDc) : 0; } -namespace internal { +namespace details { constexpr ShiftedDcId uploadDcId(DcId dcId, int index) { static_assert(kUploadSessionsCount < kMaxMediaDcCount, "Too large MTPUploadSessionsCount!"); return ShiftDcId(dcId, kBaseUploadDcShift + index); }; -} // namespace internal +} // namespace details // send(req, callbacks, MTP::uploadDcId(index)) - for upload shifted dc id // uploading always to the main dc so BareDcId(result) == 0 inline ShiftedDcId uploadDcId(int index) { Expects(index >= 0 && index < kUploadSessionsCount); - return internal::uploadDcId(0, index); + return details::uploadDcId(0, index); }; constexpr bool isUploadDcId(ShiftedDcId shiftedDcId) { - return (shiftedDcId >= internal::uploadDcId(0, 0)) && (shiftedDcId < internal::uploadDcId(0, kUploadSessionsCount - 1) + kDcShift); + return (shiftedDcId >= details::uploadDcId(0, 0)) + && (shiftedDcId < details::uploadDcId(0, kUploadSessionsCount - 1) + kDcShift); } inline ShiftedDcId destroyKeyNextDcId(ShiftedDcId shiftedDcId) { diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 2af0788f0..b48ddf734 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -7,14 +7,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/mtp_instance.h" +#include "mtproto/details/mtproto_dcenter.h" +#include "mtproto/details/mtproto_rsa_public_key.h" +#include "mtproto/special_config_request.h" #include "mtproto/session.h" #include "mtproto/dc_options.h" -#include "mtproto/dcenter.h" #include "mtproto/config_loader.h" -#include "mtproto/special_config_request.h" -#include "mtproto/connection.h" #include "mtproto/sender.h" -#include "mtproto/mtproto_rsa_public_key.h" #include "storage/localstorage.h" #include "calls/calls_instance.h" #include "main/main_session.h" // Session::Exists. @@ -35,14 +34,13 @@ constexpr auto kConfigBecomesOldIn = 2 * 60 * crl::time(1000); constexpr auto kConfigBecomesOldForBlockedIn = 8 * crl::time(1000); constexpr auto kCheckKeyEach = 60 * crl::time(1000); -using namespace internal; using namespace details; std::atomic GlobalAtomicRequestId = 0; } // namespace -namespace internal { +namespace details { int GetNextRequestId() { const auto result = ++GlobalAtomicRequestId; @@ -52,7 +50,7 @@ int GetNextRequestId() { return result; } -} // namespace internal +} // namespace details class Instance::Private : private Sender { public: diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.h b/Telegram/SourceFiles/mtproto/mtp_instance.h index 7f6d7f463..834ef947d 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.h +++ b/Telegram/SourceFiles/mtproto/mtp_instance.h @@ -11,14 +11,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/details/mtproto_serialized_request.h" namespace MTP { -namespace internal { +namespace details { class Dcenter; class Session; [[nodiscard]] int GetNextRequestId(); -} // namespace internal +} // namespace details class DcOptions; class AuthKey; @@ -131,7 +131,7 @@ public: ShiftedDcId shiftedDcId = 0, crl::time msCanWait = 0, mtpRequestId afterRequestId = 0) { - const auto requestId = internal::GetNextRequestId(); + const auto requestId = details::GetNextRequestId(); sendSerialized( requestId, details::SerializedRequest::Serialize(request), @@ -162,7 +162,7 @@ public: mtpRequestId sendProtocolMessage( ShiftedDcId shiftedDcId, const Request &request) { - const auto requestId = internal::GetNextRequestId(); + const auto requestId = details::GetNextRequestId(); sendRequest( requestId, details::SerializedRequest::Serialize(request), diff --git a/Telegram/SourceFiles/mtproto/concurrent_sender.cpp b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.cpp similarity index 98% rename from Telegram/SourceFiles/mtproto/concurrent_sender.cpp rename to Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.cpp index 3d484296a..b211cda30 100644 --- a/Telegram/SourceFiles/mtproto/concurrent_sender.cpp +++ b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.cpp @@ -5,7 +5,7 @@ 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 */ -#include "mtproto/concurrent_sender.h" +#include "mtproto/mtproto_concurrent_sender.h" #include "mtproto/mtp_instance.h" #include "mtproto/mtproto_rpc_sender.h" @@ -135,7 +135,7 @@ void ConcurrentSender::RequestBuilder::setAfter( } mtpRequestId ConcurrentSender::RequestBuilder::send() { - const auto requestId = internal::GetNextRequestId(); + const auto requestId = details::GetNextRequestId(); const auto dcId = _dcId; const auto msCanWait = _canWait; const auto afterRequestId = _afterRequestId; diff --git a/Telegram/SourceFiles/mtproto/concurrent_sender.h b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.h similarity index 99% rename from Telegram/SourceFiles/mtproto/concurrent_sender.h rename to Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.h index 68fb22781..74c1c4482 100644 --- a/Telegram/SourceFiles/mtproto/concurrent_sender.h +++ b/Telegram/SourceFiles/mtproto/mtproto_concurrent_sender.h @@ -7,13 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include #include "base/bytes.h" #include "base/weak_ptr.h" #include "base/flat_map.h" #include "mtproto/core_types.h" #include "mtproto/details/mtproto_serialized_request.h" +#include + #ifndef _DEBUG #define MTP_SENDER_USE_GENERIC_HANDLERS #endif // !_DEBUG diff --git a/Telegram/SourceFiles/mtproto/session.cpp b/Telegram/SourceFiles/mtproto/session.cpp index b81859c27..563f8de2f 100644 --- a/Telegram/SourceFiles/mtproto/session.cpp +++ b/Telegram/SourceFiles/mtproto/session.cpp @@ -7,18 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/session.h" -#include "mtproto/connection.h" -#include "mtproto/dcenter.h" +#include "mtproto/details/mtproto_dcenter.h" +#include "mtproto/session_private.h" #include "mtproto/mtproto_auth_key.h" #include "base/unixtime.h" #include "base/openssl_help.h" -#include "core/crash_reports.h" #include "facades.h" namespace MTP { -namespace internal { +namespace details { -ConnectionOptions::ConnectionOptions( +SessionOptions::SessionOptions( const QString &systemLangCode, const QString &cloudLangCode, const QString &langPackName, @@ -50,9 +49,9 @@ void SessionData::withSession(Callback &&callback) { } } -void SessionData::notifyConnectionInited(const ConnectionOptions &options) { +void SessionData::notifyConnectionInited(const SessionOptions &options) { // #TODO race - const auto current = connectionOptions(); + const auto current = this->options(); if (current.cloudLangCode == _options.cloudLangCode && current.systemLangCode == _options.systemLangCode && current.langPackName == _options.langPackName @@ -163,7 +162,7 @@ Session::Session( } Session::~Session() { - Expects(!_connection); + Expects(!_private); if (_myKeyCreation != CreatingKeyType::None) { releaseKeyCreationOnFail(); @@ -177,11 +176,11 @@ void Session::watchDcKeyChanges() { }) | rpl::start_with_next([=] { DEBUG_LOG(("AuthKey Info: dcTemporaryKeyChanged in Session %1" ).arg(_shiftedDcId)); - if (const auto connection = _connection) { - InvokeQueued(connection, [=] { + if (const auto captured = _private) { + InvokeQueued(captured, [=] { DEBUG_LOG(("AuthKey Info: calling Connection::updateAuthKey in Session %1" ).arg(_shiftedDcId)); - connection->updateAuthKey(); + captured->updateAuthKey(); }); } }, _lifetime); @@ -190,20 +189,20 @@ void Session::watchDcKeyChanges() { void Session::watchDcOptionsChanges() { _instance->dcOptions()->changed( ) | rpl::filter([=](DcId dcId) { - return (BareDcId(_shiftedDcId) == dcId) && (_connection != nullptr); + return (BareDcId(_shiftedDcId) == dcId) && (_private != nullptr); }) | rpl::start_with_next([=] { - InvokeQueued(_connection, [connection = _connection] { - connection->dcOptionsChanged(); + InvokeQueued(_private, [captured = _private] { + captured->dcOptionsChanged(); }); }, _lifetime); if (_instance->dcOptions()->dcType(_shiftedDcId) == DcType::Cdn) { _instance->dcOptions()->cdnConfigChanged( ) | rpl::filter([=] { - return (_connection != nullptr); + return (_private != nullptr); }) | rpl::start_with_next([=] { - InvokeQueued(_connection, [connection = _connection] { - connection->cdnConfigChanged(); + InvokeQueued(_private, [captured = _private] { + captured->cdnConfigChanged(); }); }, _lifetime); } @@ -211,7 +210,7 @@ void Session::watchDcOptionsChanges() { void Session::start() { killConnection(); - _connection = new Connection( + _private = new SessionPrivate( _instance, _thread.get(), _data, @@ -231,9 +230,9 @@ void Session::restart() { return; } refreshOptions(); - if (const auto connection = _connection) { - InvokeQueued(connection, [=] { - connection->restartNow(); + if (const auto captured = _private) { + InvokeQueued(captured, [=] { + captured->restartNow(); }); } } @@ -248,7 +247,7 @@ void Session::refreshOptions() { const auto useHttp = (proxyType != ProxyData::Type::Mtproto); const auto useIPv4 = true; const auto useIPv6 = Global::TryIPv6(); - _data->setConnectionOptions(ConnectionOptions( + _data->setOptions(SessionOptions( _instance->systemLangCode(), _instance->cloudLangCode(), _instance->langPackName(), @@ -326,17 +325,17 @@ void Session::needToResumeAndSend() { DEBUG_LOG(("Session Info: can't resume a killed session")); return; } - if (!_connection) { + if (!_private) { DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(_shiftedDcId)); start(); } - const auto connection = _connection; + const auto captured = _private; const auto ping = base::take(_ping); - InvokeQueued(connection, [=] { + InvokeQueued(captured, [=] { if (ping) { - connection->sendPingForce(); + captured->sendPingForce(); } else { - connection->tryToSend(); + captured->tryToSend(); } }); } @@ -369,8 +368,8 @@ int32 Session::requestState(mtpRequestId requestId) const { int32 result = MTP::RequestSent; bool connected = false; - if (_connection) { - const auto s = _connection->getState(); + if (_private) { + const auto s = _private->getState(); if (s == ConnectedState) { connected = true; } else if (s == ConnectingState || s == DisconnectedState) { @@ -398,8 +397,8 @@ int32 Session::requestState(mtpRequestId requestId) const { int32 Session::getState() const { int32 result = -86400000; - if (_connection) { - const auto s = _connection->getState(); + if (_private) { + const auto s = _private->getState(); if (s == ConnectedState) { return s; } else if (s == ConnectingState || s == DisconnectedState) { @@ -419,11 +418,11 @@ int32 Session::getState() const { } QString Session::transport() const { - return _connection ? _connection->transport() : QString(); + return _private ? _private->transport() : QString(); } void Session::sendPrepared( - const details::SerializedRequest &request, + const SerializedRequest &request, crl::time msCanWait) { DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1" ).arg(msCanWait)); @@ -563,14 +562,14 @@ void Session::tryToReceive() { } void Session::killConnection() { - if (!_connection) { + if (!_private) { return; } - base::take(_connection)->deleteLater(); + base::take(_private)->deleteLater(); - Ensures(_connection == nullptr); + Ensures(_private == nullptr); } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/session.h b/Telegram/SourceFiles/mtproto/session.h index 81b484afe..0e9169834 100644 --- a/Telegram/SourceFiles/mtproto/session.h +++ b/Telegram/SourceFiles/mtproto/session.h @@ -20,17 +20,17 @@ class Instance; class AuthKey; using AuthKeyPtr = std::shared_ptr; -namespace internal { +namespace details { class Dcenter; -class Connection; +class SessionPrivate; enum class TemporaryKeyType; enum class CreatingKeyType; -struct ConnectionOptions { - ConnectionOptions() = default; - ConnectionOptions( +struct SessionOptions { + SessionOptions() = default; + SessionOptions( const QString &systemLangCode, const QString &cloudLangCode, const QString &langPackName, @@ -39,8 +39,6 @@ struct ConnectionOptions { bool useIPv6, bool useHttp, bool useTcp); - ConnectionOptions(const ConnectionOptions &other) = default; - ConnectionOptions &operator=(const ConnectionOptions &other) = default; QString systemLangCode; QString cloudLangCode; @@ -54,17 +52,17 @@ struct ConnectionOptions { }; class Session; -class SessionData { +class SessionData final { public: explicit SessionData(not_null creator) : _owner(creator) { } - void notifyConnectionInited(const ConnectionOptions &options); - void setConnectionOptions(ConnectionOptions options) { + void notifyConnectionInited(const SessionOptions &options); + void setOptions(SessionOptions options) { QWriteLocker locker(&_optionsLock); _options = options; } - [[nodiscard]] ConnectionOptions connectionOptions() const { + [[nodiscard]] SessionOptions options() const { QReadLocker locker(&_optionsLock); return _options; } @@ -79,10 +77,10 @@ public: return &_haveReceivedLock; } - base::flat_map &toSendMap() { + base::flat_map &toSendMap() { return _toSend; } - base::flat_map &haveSentMap() { + base::flat_map &haveSentMap() { return _haveSent; } base::flat_map &haveReceivedResponses() { @@ -92,7 +90,7 @@ public: return _receivedUpdates; } - // Connection -> Session interface. + // SessionPrivate -> Session interface. void queueTryToReceive(); void queueNeedToResumeAndSend(); void queueConnectionStateChange(int newState); @@ -118,13 +116,13 @@ private: Session *_owner = nullptr; mutable QMutex _ownerMutex; - ConnectionOptions _options; + SessionOptions _options; mutable QReadWriteLock _optionsLock; - base::flat_map _toSend; // map of request_id -> request, that is waiting to be sent + base::flat_map _toSend; // map of request_id -> request, that is waiting to be sent QReadWriteLock _toSendLock; - base::flat_map _haveSent; // map of msg_id -> request, that was sent + base::flat_map _haveSent; // map of msg_id -> request, that was sent QReadWriteLock _haveSentLock; base::flat_map _receivedResponses; // map of request_id -> response that should be processed in the main thread @@ -133,7 +131,7 @@ private: }; -class Session : public QObject { +class Session final : public QObject { public: // Main thread. Session( @@ -159,10 +157,10 @@ public: [[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const; [[nodiscard]] bool connectionInited() const; void sendPrepared( - const details::SerializedRequest &request, + const SerializedRequest &request, crl::time msCanWait = 0); - // Connection thread. + // SessionPrivate thread. [[nodiscard]] CreatingKeyType acquireKeyCreation(TemporaryKeyType type); [[nodiscard]] bool releaseKeyCreationOnDone( const AuthKeyPtr &temporaryKey, @@ -201,7 +199,7 @@ private: const std::shared_ptr _data; const not_null _thread; - Connection *_connection = nullptr; + SessionPrivate *_private = nullptr; bool _killed = false; bool _needToReceive = false; @@ -221,5 +219,5 @@ private: }; -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection.cpp b/Telegram/SourceFiles/mtproto/session_private.cpp similarity index 94% rename from Telegram/SourceFiles/mtproto/connection.cpp rename to Telegram/SourceFiles/mtproto/session_private.cpp index f8b4a9bb5..ba718f8c2 100644 --- a/Telegram/SourceFiles/mtproto/connection.cpp +++ b/Telegram/SourceFiles/mtproto/session_private.cpp @@ -5,26 +5,23 @@ 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 */ -#include "mtproto/connection.h" +#include "mtproto/session_private.h" #include "mtproto/details/mtproto_bound_key_creator.h" +#include "mtproto/details/mtproto_dcenter.h" #include "mtproto/details/mtproto_dump_to_text.h" +#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/session.h" -#include "mtproto/mtproto_rsa_public_key.h" #include "mtproto/mtproto_rpc_sender.h" #include "mtproto/dc_options.h" -#include "mtproto/dcenter.h" #include "mtproto/connection_abstract.h" -#include "zlib.h" -#include "core/application.h" -#include "core/launcher.h" -#include "lang/lang_keys.h" #include "base/openssl_help.h" #include "base/qthelp_url.h" #include "base/unixtime.h" +#include "zlib.h" namespace MTP { -namespace internal { +namespace details { namespace { constexpr auto kIntSize = static_cast(sizeof(mtpPrime)); @@ -42,6 +39,7 @@ constexpr auto kBindKeyAdditionalExpiresTimeout = TimeId(30); constexpr auto kTestModeDcIdShift = 10000; constexpr auto kCheckSentRequestsEach = 1 * crl::time(1000); constexpr auto kKeyOldEnoughForDestroy = 60 * crl::time(1000); +constexpr auto kSentContainerLives = 600 * crl::time(1000); // If we can't connect for this time we will ask _instance to update config. constexpr auto kRequestConfigTimeout = 8 * crl::time(1000); @@ -56,7 +54,8 @@ constexpr auto kCheckSentRequestTimeout = 10 * crl::time(1000); // when resending request or checking its state. constexpr auto kSendStateRequestWaiting = crl::time(1000); -constexpr auto kSentContainerLives = 600 * crl::time(1000); +// How much time to wait for some more requests, when sending msg acks. +constexpr auto kAckSendWaiting = 10 * crl::time(1000); using namespace details; @@ -113,7 +112,7 @@ void WrapInvokeAfter( } // namespace -Connection::Connection( +SessionPrivate::SessionPrivate( not_null instance, not_null thread, std::shared_ptr data, @@ -144,7 +143,7 @@ Connection::Connection( }); } -Connection::~Connection() { +SessionPrivate::~SessionPrivate() { releaseKeyCreationOnFail(); doDisconnect(); @@ -152,7 +151,7 @@ Connection::~Connection() { Expects(_testConnections.empty()); } -void Connection::appendTestConnection( +void SessionPrivate::appendTestConnection( DcOptions::Variants::Protocol protocol, const QString &ip, int port, @@ -168,7 +167,7 @@ void Connection::appendTestConnection( protocol, thread(), protocolSecret, - _connectionOptions->proxy), + _options->proxy), priority }); const auto weak = _testConnections.back().data.get(); @@ -201,7 +200,7 @@ void Connection::appendTestConnection( }); } -int16 Connection::getProtocolDcId() const { +int16 SessionPrivate::getProtocolDcId() const { const auto dcId = BareDcId(_shiftedDcId); const auto simpleDcId = isTemporaryDcId(dcId) ? getRealIdFromTemporaryDcId(dcId) @@ -214,7 +213,7 @@ int16 Connection::getProtocolDcId() const { : testedDcId; } -void Connection::checkSentRequests() { +void SessionPrivate::checkSentRequests() { clearOldContainers(); auto restarting = false; @@ -246,7 +245,7 @@ void Connection::checkSentRequests() { } } -void Connection::clearOldContainers() { +void SessionPrivate::clearOldContainers() { auto resent = false; const auto now = crl::now(); for (auto i = _sentContainers.begin(); i != _sentContainers.end();) { @@ -274,7 +273,7 @@ void Connection::clearOldContainers() { } } -void Connection::destroyAllConnections() { +void SessionPrivate::destroyAllConnections() { clearUnboundKeyCreator(); _waitForBetterTimer.cancel(); _waitForReceivedTimer.cancel(); @@ -283,20 +282,20 @@ void Connection::destroyAllConnections() { _connection = nullptr; } -void Connection::cdnConfigChanged() { +void SessionPrivate::cdnConfigChanged() { connectToServer(true); } -int32 Connection::getShiftedDcId() const { +int32 SessionPrivate::getShiftedDcId() const { return _shiftedDcId; } -void Connection::dcOptionsChanged() { +void SessionPrivate::dcOptionsChanged() { _retryTimeout = 1; connectToServer(true); } -int32 Connection::getState() const { +int32 SessionPrivate::getState() const { QReadLocker lock(&_stateMutex); int32 result = _state; if (_state < 0) { @@ -310,17 +309,17 @@ int32 Connection::getState() const { return result; } -QString Connection::transport() const { +QString SessionPrivate::transport() const { QReadLocker lock(&_stateMutex); if (!_connection || (_state < 0)) { return QString(); } - Assert(_connectionOptions != nullptr); + Assert(_options != nullptr); return _connection->transport(); } -bool Connection::setState(int state, int ifState) { +bool SessionPrivate::setState(int state, int ifState) { if (ifState != kUpdateStateAlways) { QReadLocker lock(&_stateMutex); if (_state != ifState) { @@ -344,7 +343,7 @@ bool Connection::setState(int state, int ifState) { return true; } -void Connection::resetSession() { +void SessionPrivate::resetSession() { MTP_LOG(_shiftedDcId, ("Resetting session!")); _needSessionReset = false; @@ -354,7 +353,7 @@ void Connection::resetSession() { _sessionData->queueResetDone(); } -void Connection::changeSessionId() { +void SessionPrivate::changeSessionId() { auto sessionId = _sessionId; do { sessionId = openssl::RandomValue(); @@ -371,13 +370,13 @@ void Connection::changeSessionId() { _receivedMessageIds.clear(); } -uint32 Connection::nextRequestSeqNumber(bool needAck) { +uint32 SessionPrivate::nextRequestSeqNumber(bool needAck) { const auto result = _messagesCounter; _messagesCounter += (needAck ? 1 : 0); return result * 2 + (needAck ? 1 : 0); } -bool Connection::realDcTypeChanged() { +bool SessionPrivate::realDcTypeChanged() { const auto now = _instance->dcOptions()->dcType(_shiftedDcId); if (_realDcType == now) { return false; @@ -386,7 +385,7 @@ bool Connection::realDcTypeChanged() { return true; } -bool Connection::markSessionAsStarted() { +bool SessionPrivate::markSessionAsStarted() { if (_sessionMarkedAsStarted) { return false; } @@ -394,7 +393,7 @@ bool Connection::markSessionAsStarted() { return true; } -mtpMsgId Connection::prepareToSend( +mtpMsgId SessionPrivate::prepareToSend( SerializedRequest &request, mtpMsgId currentLastId, bool forceNewMsgId) { @@ -419,7 +418,7 @@ mtpMsgId Connection::prepareToSend( return currentLastId; } -mtpMsgId Connection::replaceMsgId(SerializedRequest &request, mtpMsgId newId) { +mtpMsgId SessionPrivate::replaceMsgId(SerializedRequest &request, mtpMsgId newId) { Expects(request->size() > 8); const auto oldMsgId = request.getMsgId(); @@ -472,7 +471,7 @@ mtpMsgId Connection::replaceMsgId(SerializedRequest &request, mtpMsgId newId) { return newId; } -mtpMsgId Connection::placeToContainer( +mtpMsgId SessionPrivate::placeToContainer( SerializedRequest &toSendRequest, mtpMsgId &bigMsgId, bool forceNewMsgId, @@ -489,7 +488,7 @@ mtpMsgId Connection::placeToContainer( return msgId; } -void Connection::tryToSend() { +void SessionPrivate::tryToSend() { DEBUG_LOG(("MTP Info: tryToSend for dc %1.").arg(_shiftedDcId)); if (!_connection) { DEBUG_LOG(("MTP Info: not yet connected in dc %1.").arg(_shiftedDcId)); @@ -591,10 +590,10 @@ void Connection::tryToSend() { MTPInitConnection initWrapper; int32 initSize = 0, initSizeInInts = 0; if (needsLayer) { - Assert(_connectionOptions != nullptr); - const auto systemLangCode = _connectionOptions->systemLangCode; - const auto cloudLangCode = _connectionOptions->cloudLangCode; - const auto langPackName = _connectionOptions->langPackName; + Assert(_options != nullptr); + const auto systemLangCode = _options->systemLangCode; + const auto cloudLangCode = _options->cloudLangCode; + const auto langPackName = _options->langPackName; const auto deviceModel = (_currentDcType == DcType::Cdn) ? "n/a" : _instance->deviceModel(); @@ -610,12 +609,12 @@ void Connection::tryToSend() { #else // OS_MAC_STORE || OS_WIN_STORE const auto appVersion = QString::fromLatin1(AppVersionStr); #endif // OS_MAC_STORE || OS_WIN_STORE - const auto proxyType = _connectionOptions->proxy.type; + const auto proxyType = _options->proxy.type; const auto mtprotoProxy = (proxyType == ProxyData::Type::Mtproto); const auto clientProxyFields = mtprotoProxy ? MTP_inputClientProxy( - MTP_string(_connectionOptions->proxy.host), - MTP_int(_connectionOptions->proxy.port)) + MTP_string(_options->proxy.host), + MTP_int(_options->proxy.port)) : MTPInputClientProxy(); using Flag = MTPInitConnection::Flag; initWrapper = MTPInitConnection( @@ -720,7 +719,7 @@ void Connection::tryToSend() { auto wrappedRequest = SerializedRequest::Prepare(toSendSize); memcpy(wrappedRequest->data(), toSendRequest->constData(), 7 * sizeof(mtpPrime)); // all except length wrappedRequest->push_back(mtpc_invokeWithLayer); - wrappedRequest->push_back(internal::CurrentLayer); + wrappedRequest->push_back(kCurrentLayer); initWrapper.write(*wrappedRequest); wrappedRequest->resize(wrappedRequest->size() + noWrapSize); memcpy(wrappedRequest->data() + wrappedRequest->size() - noWrapSize, toSendRequest->constData() + 8, noWrapSize * sizeof(mtpPrime)); @@ -752,7 +751,7 @@ void Connection::tryToSend() { if (willNeedInit) { initSerialized.reserve(initSizeInInts); initSerialized.push_back(mtpc_invokeWithLayer); - initSerialized.push_back(internal::CurrentLayer); + initSerialized.push_back(kCurrentLayer); initWrapper.write(initSerialized); } // prepare container + each in invoke after @@ -879,7 +878,7 @@ void Connection::tryToSend() { sendSecureRequest(std::move(toSendRequest), needAnyResponse); } -void Connection::retryByTimer() { +void SessionPrivate::retryByTimer() { if (_retryTimeout < 3) { ++_retryTimeout; } else if (_retryTimeout == 3) { @@ -890,13 +889,13 @@ void Connection::retryByTimer() { connectToServer(); } -void Connection::restartNow() { +void SessionPrivate::restartNow() { _retryTimeout = 1; _retryTimer.cancel(); restart(); } -void Connection::connectToServer(bool afterConfig) { +void SessionPrivate::connectToServer(bool afterConfig) { if (afterConfig && (!_testConnections.empty() || _connection)) { return; } @@ -908,8 +907,7 @@ void Connection::connectToServer(bool afterConfig) { return; } - _connectionOptions = std::make_unique( - _sessionData->connectionOptions()); + _options = std::make_unique(_sessionData->options()); const auto bareDc = BareDcId(_shiftedDcId); @@ -920,7 +918,7 @@ void Connection::connectToServer(bool afterConfig) { return; } } - if (_connectionOptions->proxy.type == ProxyData::Type::Mtproto) { + if (_options->proxy.type == ProxyData::Type::Mtproto) { // host, port, secret for mtproto proxy are taken from proxy. appendTestConnection(DcOptions::Variants::Tcp, {}, 0, {}); } else { @@ -929,11 +927,11 @@ void Connection::connectToServer(bool afterConfig) { const auto variants = _instance->dcOptions()->lookup( bareDc, _currentDcType, - _connectionOptions->proxy.type != ProxyData::Type::None); - const auto useIPv4 = special ? true : _connectionOptions->useIPv4; - const auto useIPv6 = special ? false : _connectionOptions->useIPv6; - const auto useTcp = special ? true : _connectionOptions->useTcp; - const auto useHttp = special ? false : _connectionOptions->useHttp; + _options->proxy.type != ProxyData::Type::None); + const auto useIPv4 = special ? true : _options->useIPv4; + const auto useIPv6 = special ? false : _options->useIPv6; + const auto useTcp = special ? true : _options->useTcp; + const auto useHttp = special ? false : _options->useHttp; const auto skipAddress = !useIPv4 ? Variants::IPv4 : !useIPv6 @@ -1001,7 +999,7 @@ void Connection::connectToServer(bool afterConfig) { _waitForConnectedTimer.callOnce(_waitForConnected); } -void Connection::restart() { +void SessionPrivate::restart() { DEBUG_LOG(("MTP Info: restarting Connection")); _waitForReceivedTimer.cancel(); @@ -1021,7 +1019,7 @@ void Connection::restart() { setState(-_retryTimeout); } -void Connection::onSentSome(uint64 size) { +void SessionPrivate::onSentSome(uint64 size) { if (!_waitForReceivedTimer.isActive()) { auto remain = static_cast(_waitForReceived); if (!_oldConnection) { @@ -1042,7 +1040,7 @@ void Connection::onSentSome(uint64 size) { if (!_firstSentAt) _firstSentAt = crl::now(); } -void Connection::onReceivedSome() { +void SessionPrivate::onReceivedSome() { if (_oldConnection) { _oldConnection = false; DEBUG_LOG(("This connection marked as not old!")); @@ -1060,13 +1058,13 @@ void Connection::onReceivedSome() { } } -void Connection::markConnectionOld() { +void SessionPrivate::markConnectionOld() { _oldConnection = true; _waitForReceived = kMinReceiveTimeout; DEBUG_LOG(("This connection marked as old! _waitForReceived now %1ms").arg(_waitForReceived)); } -void Connection::sendPingByTimer() { +void SessionPrivate::sendPingByTimer() { if (_pingId) { // _pingSendAt: when to send next ping (lastPingAt + kPingSendAfter) // could be equal to zero. @@ -1085,7 +1083,7 @@ void Connection::sendPingByTimer() { } } -void Connection::sendPingForce() { +void SessionPrivate::sendPingForce() { DEBUG_LOG(("MTP Info: send ping force for dcWithShift %1.").arg(_shiftedDcId)); if (!_pingId) { _pingSendAt = 0; @@ -1094,10 +1092,10 @@ void Connection::sendPingForce() { } } -void Connection::waitReceivedFailed() { - Expects(_connectionOptions != nullptr); +void SessionPrivate::waitReceivedFailed() { + Expects(_options != nullptr); - if (!_connectionOptions->useTcp) { + if (!_options->useTcp) { return; } @@ -1114,7 +1112,7 @@ void Connection::waitReceivedFailed() { InvokeQueued(this, [=] { connectToServer(); }); } -void Connection::waitConnectedFailed() { +void SessionPrivate::waitConnectedFailed() { DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(_waitForConnected)); auto maxTimeout = kMaxConnectedTimeout; for (const auto &connection : _testConnections) { @@ -1130,29 +1128,29 @@ void Connection::waitConnectedFailed() { InvokeQueued(this, [=] { connectToServer(); }); } -void Connection::waitBetterFailed() { +void SessionPrivate::waitBetterFailed() { confirmBestConnection(); } -void Connection::connectingTimedOut() { +void SessionPrivate::connectingTimedOut() { for (const auto &connection : _testConnections) { connection.data->timedOut(); } doDisconnect(); } -void Connection::doDisconnect() { +void SessionPrivate::doDisconnect() { destroyAllConnections(); setState(DisconnectedState); } -void Connection::requestCDNConfig() { +void SessionPrivate::requestCDNConfig() { InvokeQueued(_instance, [instance = _instance] { instance->requestCDNConfig(); }); } -void Connection::handleReceived() { +void SessionPrivate::handleReceived() { Expects(_encryptionKey != nullptr); onReceivedSome(); @@ -1303,7 +1301,7 @@ void Connection::handleReceived() { auto end = from + (messageLength / kIntSize); auto sfrom = decryptedInts + 4U; // msg_id + seq_no + length + message MTP_LOG(_shiftedDcId, ("Recv: ") - + details::DumpToText(sfrom, end) + + DumpToText(sfrom, end) + QString(" (protocolDcId:%1,key:%2)" ).arg(getProtocolDcId() ).arg(_encryptionKey->keyId())); @@ -1352,7 +1350,7 @@ void Connection::handleReceived() { } } -Connection::HandleResult Connection::handleOneReceived( +SessionPrivate::HandleResult SessionPrivate::handleOneReceived( const mtpPrime *from, const mtpPrime *end, uint64 msgId, @@ -1733,7 +1731,7 @@ Connection::HandleResult Connection::handleOneReceived( // the initConnection, so we're not sure yet that it was inited. // Wait till a good response is received. } else { - _sessionData->notifyConnectionInited(*_connectionOptions); + _sessionData->notifyConnectionInited(*_options); } requestsAcked(ids, true); @@ -1850,7 +1848,7 @@ Connection::HandleResult Connection::handleOneReceived( return HandleResult::Success; } -Connection::HandleResult Connection::handleBindResponse( +SessionPrivate::HandleResult SessionPrivate::handleBindResponse( mtpMsgId requestMsgId, const mtpBuffer &response) { if (!_keyCreator || !_bindMsgId || _bindMsgId != requestMsgId) { @@ -1878,7 +1876,7 @@ Connection::HandleResult Connection::handleBindResponse( Unexpected("Result of BoundKeyCreator::handleBindResponse."); } -mtpBuffer Connection::ungzip(const mtpPrime *from, const mtpPrime *end) const { +mtpBuffer SessionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) const { mtpBuffer result; // * 4 because of mtpPrime type result.resize(0); @@ -1930,7 +1928,7 @@ mtpBuffer Connection::ungzip(const mtpPrime *from, const mtpPrime *end) const { return result; } -bool Connection::requestsFixTimeSalt(const QVector &ids, int32 serverTime, uint64 serverSalt) { +bool SessionPrivate::requestsFixTimeSalt(const QVector &ids, int32 serverTime, uint64 serverSalt) { uint32 idsCount = ids.size(); for (uint32 i = 0; i < idsCount; ++i) { @@ -1945,7 +1943,7 @@ bool Connection::requestsFixTimeSalt(const QVector &ids, int32 serverTi return false; } -void Connection::requestsAcked(const QVector &ids, bool byResponse) { +void SessionPrivate::requestsAcked(const QVector &ids, bool byResponse) { uint32 idsCount = ids.size(); DEBUG_LOG(("Message Info: requests acked, ids %1").arg(LogIdsVector(ids))); @@ -2027,7 +2025,7 @@ void Connection::requestsAcked(const QVector &ids, bool byResponse) { } } -void Connection::handleMsgsStates(const QVector &ids, const QByteArray &states) { +void SessionPrivate::handleMsgsStates(const QVector &ids, const QByteArray &states) { const auto idsCount = ids.size(); if (!idsCount) { DEBUG_LOG(("Message Info: void ids vector in handleMsgsStates()")); @@ -2072,7 +2070,7 @@ void Connection::handleMsgsStates(const QVector &ids, const QByteArray requestsAcked(acked); } -void Connection::clearSpecialMsgId(mtpMsgId msgId) { +void SessionPrivate::clearSpecialMsgId(mtpMsgId msgId) { if (msgId == _pingMsgId) { _pingMsgId = 0; _pingId = 0; @@ -2081,7 +2079,7 @@ void Connection::clearSpecialMsgId(mtpMsgId msgId) { } } -void Connection::resend( +void SessionPrivate::resend( mtpMsgId msgId, crl::time msCanWait, bool forceContainer) { @@ -2121,7 +2119,7 @@ void Connection::resend( } } -void Connection::resendAll() { +void SessionPrivate::resendAll() { auto lock = QWriteLocker(_sessionData->haveSentMutex()); auto haveSent = base::take(_sessionData->haveSentMap()); lock.unlock(); @@ -2141,7 +2139,7 @@ void Connection::resendAll() { _sessionData->queueSendAnything(); } -void Connection::onConnected( +void SessionPrivate::onConnected( not_null connection) { disconnect(connection, &AbstractConnection::connected, nullptr, nullptr); if (!connection->isConnected()) { @@ -2175,7 +2173,7 @@ void Connection::onConnected( } } -void Connection::onDisconnected( +void SessionPrivate::onDisconnected( not_null connection) { removeTestConnection(connection); @@ -2187,7 +2185,7 @@ void Connection::onDisconnected( } } -void Connection::confirmBestConnection() { +void SessionPrivate::confirmBestConnection() { if (_waitForBetterTimer.isActive()) { return; } @@ -2211,7 +2209,7 @@ void Connection::confirmBestConnection() { checkAuthKey(); } -void Connection::removeTestConnection( +void SessionPrivate::removeTestConnection( not_null connection) { _testConnections.erase( ranges::remove( @@ -2221,7 +2219,7 @@ void Connection::removeTestConnection( end(_testConnections)); } -void Connection::checkAuthKey() { +void SessionPrivate::checkAuthKey() { if (_keyId) { authKeyChecked(); } else if (_instance->isKeysDestroyer()) { @@ -2232,7 +2230,7 @@ void Connection::checkAuthKey() { } } -void Connection::updateAuthKey() { +void SessionPrivate::updateAuthKey() { if (_instance->isKeysDestroyer() || _keyCreator || !_connection) { return; } @@ -2250,7 +2248,7 @@ void Connection::updateAuthKey() { } } -void Connection::setCurrentKeyId(uint64 newKeyId) { +void SessionPrivate::setCurrentKeyId(uint64 newKeyId) { if (_keyId == newKeyId) { return; } @@ -2260,7 +2258,7 @@ void Connection::setCurrentKeyId(uint64 newKeyId) { changeSessionId(); } -void Connection::applyAuthKey(AuthKeyPtr &&encryptionKey) { +void SessionPrivate::applyAuthKey(AuthKeyPtr &&encryptionKey) { _encryptionKey = std::move(encryptionKey); const auto newKeyId = _encryptionKey ? _encryptionKey->keyId() : 0; if (_keyId) { @@ -2302,7 +2300,7 @@ void Connection::applyAuthKey(AuthKeyPtr &&encryptionKey) { } } -bool Connection::destroyOldEnoughPersistentKey() { +bool SessionPrivate::destroyOldEnoughPersistentKey() { Expects(_keyCreator != nullptr); const auto key = _keyCreator->bindPersistentKey(); @@ -2321,7 +2319,7 @@ bool Connection::destroyOldEnoughPersistentKey() { return true; } -DcType Connection::tryAcquireKeyCreation() { +DcType SessionPrivate::tryAcquireKeyCreation() { if (_keyCreator) { return _currentDcType; } else if (_instance->isKeysDestroyer()) { @@ -2395,7 +2393,7 @@ DcType Connection::tryAcquireKeyCreation() { return forceUseRegular ? DcType::Regular : _realDcType; } -void Connection::authKeyChecked() { +void SessionPrivate::authKeyChecked() { connect(_connection, &AbstractConnection::receivedData, [=] { handleReceived(); }); @@ -2408,7 +2406,7 @@ void Connection::authKeyChecked() { _sessionData->queueNeedToResumeAndSend(); } -void Connection::onError( +void SessionPrivate::onError( not_null connection, qint32 errorCode) { if (errorCode == -429) { @@ -2428,7 +2426,7 @@ void Connection::onError( } } -void Connection::handleError(int errorCode) { +void SessionPrivate::handleError(int errorCode) { destroyAllConnections(); _waitForConnectedTimer.cancel(); @@ -2440,7 +2438,7 @@ void Connection::handleError(int errorCode) { } } -void Connection::destroyTemporaryKey() { +void SessionPrivate::destroyTemporaryKey() { if (_instance->isKeysDestroyer()) { LOG(("MTP Info: -404 error received in destroyer %1, assuming key was destroyed.").arg(_shiftedDcId)); _instance->keyWasPossiblyDestroyed(_shiftedDcId); @@ -2455,7 +2453,7 @@ void Connection::destroyTemporaryKey() { restart(); } -bool Connection::sendSecureRequest( +bool SessionPrivate::sendSecureRequest( SerializedRequest &&request, bool needAnyResponse) { #ifdef TDESKTOP_MTPROTO_OLD @@ -2480,7 +2478,7 @@ bool Connection::sendSecureRequest( auto from = request->constData() + 4; MTP_LOG(_shiftedDcId, ("Send: ") - + details::DumpToText(from, from + messageSize) + + DumpToText(from, from + messageSize) + QString(" (protocolDcId:%1,key:%2)" ).arg(getProtocolDcId() ).arg(_encryptionKey->keyId())); @@ -2539,7 +2537,7 @@ bool Connection::sendSecureRequest( return true; } -mtpRequestId Connection::wasSent(mtpMsgId msgId) const { +mtpRequestId SessionPrivate::wasSent(mtpMsgId msgId) const { if (msgId == _pingMsgId || msgId == _bindMsgId) { return mtpRequestId(0xFFFFFFFF); } @@ -2566,13 +2564,13 @@ mtpRequestId Connection::wasSent(mtpMsgId msgId) const { return 0; } -void Connection::clearUnboundKeyCreator() { +void SessionPrivate::clearUnboundKeyCreator() { if (_keyCreator) { _keyCreator->stop(); } } -void Connection::releaseKeyCreationOnFail() { +void SessionPrivate::releaseKeyCreationOnFail() { if (!_keyCreator) { return; } @@ -2580,5 +2578,5 @@ void Connection::releaseKeyCreationOnFail() { _sessionData->releaseKeyCreationOnFail(); } -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/connection.h b/Telegram/SourceFiles/mtproto/session_private.h similarity index 89% rename from Telegram/SourceFiles/mtproto/connection.h rename to Telegram/SourceFiles/mtproto/session_private.h index 67b898f48..fcc32c704 100644 --- a/Telegram/SourceFiles/mtproto/connection.h +++ b/Telegram/SourceFiles/mtproto/session_private.h @@ -21,26 +21,23 @@ namespace details { class BoundKeyCreator; } // namespace details -// How much time to wait for some more requests, when sending msg acks. -constexpr auto kAckSendWaiting = 10 * crl::time(1000); - class Instance; -namespace internal { +namespace details { class AbstractConnection; class SessionData; class RSAPublicKey; -struct ConnectionOptions; +struct SessionOptions; -class Connection : public QObject { +class SessionPrivate final : public QObject { public: - Connection( + SessionPrivate( not_null instance, not_null thread, std::shared_ptr data, ShiftedDcId shiftedDcId); - ~Connection(); + ~SessionPrivate(); [[nodiscard]] int32 getShiftedDcId() const; void dcOptionsChanged(); @@ -106,20 +103,20 @@ private: void clearOldContainers(); mtpMsgId placeToContainer( - details::SerializedRequest &toSendRequest, + SerializedRequest &toSendRequest, mtpMsgId &bigMsgId, bool forceNewMsgId, - details::SerializedRequest &req); + SerializedRequest &req); mtpMsgId prepareToSend( - details::SerializedRequest &request, + SerializedRequest &request, mtpMsgId currentLastId, bool forceNewMsgId); mtpMsgId replaceMsgId( - details::SerializedRequest &request, + SerializedRequest &request, mtpMsgId newId); bool sendSecureRequest( - details::SerializedRequest &&request, + SerializedRequest &&request, bool needAnyResponse); mtpRequestId wasSent(mtpMsgId msgId) const; @@ -205,7 +202,7 @@ private: base::Timer _checkSentRequestsTimer; std::shared_ptr _sessionData; - std::unique_ptr _connectionOptions; + std::unique_ptr _options; AuthKeyPtr _encryptionKey; uint64 _keyId = 0; uint64 _sessionId = 0; @@ -216,16 +213,16 @@ private: QVector _ackRequestData; QVector _resendRequestData; base::flat_set _stateRequestData; - details::ReceivedIdsManager _receivedMessageIds; + ReceivedIdsManager _receivedMessageIds; base::flat_map _resendingIds; base::flat_map _ackedIds; - base::flat_map _stateAndResendRequests; + base::flat_map _stateAndResendRequests; base::flat_map _sentContainers; - std::unique_ptr _keyCreator; + std::unique_ptr _keyCreator; mtpMsgId _bindMsgId = 0; }; -} // namespace internal +} // namespace details } // namespace MTP diff --git a/Telegram/SourceFiles/mtproto/special_config_request.cpp b/Telegram/SourceFiles/mtproto/special_config_request.cpp index 992c436c6..29f0fc7ee 100644 --- a/Telegram/SourceFiles/mtproto/special_config_request.cpp +++ b/Telegram/SourceFiles/mtproto/special_config_request.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/special_config_request.h" -#include "mtproto/mtproto_rsa_public_key.h" +#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/dc_options.h" #include "mtproto/mtproto_auth_key.h" #include "base/unixtime.h" @@ -19,16 +19,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -extern "C" { -#include -} // extern "C" - -namespace MTP { +namespace MTP::details { namespace { constexpr auto kSendNextTimeout = crl::time(800); -constexpr auto kMinTimeToLive = 10 * crl::time(1000); -constexpr auto kMaxTimeToLive = 300 * crl::time(1000); constexpr auto kPublicKey = str_const("\ -----BEGIN RSA PUBLIC KEY-----\n\ @@ -41,9 +35,6 @@ Y1hZCxdv6cs5UnW9+PWvS+WIbkh+GaWYxwIDAQAB\n\ -----END RSA PUBLIC KEY-----\ "); -constexpr auto kUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " -"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"; - const auto kRemoteProject = "peak-vista-421"; const auto kFireProject = "reserve-5a846"; const auto kConfigKey = "ipconfig"; @@ -51,21 +42,6 @@ const auto kConfigSubKey = "v3"; const auto kApiKey = "AIzaSyC2-kAkpDsroixRXw-sTw-Wfqo4NxjMwwM"; const auto kAppId = "1:560508485281:web:4ee13a6af4e84d49e67ae0"; -struct DnsEntry { - QString data; - crl::time TTL = 0; -}; - -const std::vector &DnsDomains() { - static auto result = std::vector{ - qsl("google.com"), - qsl("www.google.com"), - qsl("google.ru"), - qsl("www.google.ru"), - }; - return result; -} - QString ApiDomain(const QString &service) { return service + ".googleapis.com"; } @@ -103,99 +79,6 @@ bool CheckPhoneByPrefixesRules(const QString &phone, const QString &rules) { return result; } -QString GenerateRandomPadding() { - constexpr char kValid[] = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - - auto result = QString(); - const auto count = [&] { - constexpr auto kMinPadding = 13; - constexpr auto kMaxPadding = 128; - while (true) { - const auto result = 1 + (rand_value() / 2); - Assert(result <= kMaxPadding); - if (result >= kMinPadding) { - return result; - } - } - }(); - result.resize(count); - for (auto &ch : result) { - ch = kValid[rand_value() % (sizeof(kValid) - 1)]; - } - return result; -} - -std::vector ParseDnsResponse( - const QByteArray &bytes, - std::optional typeRestriction = std::nullopt) { - // Read and store to "result" all the data bytes from the response: - // { .., - // "Answer": [ - // { .., "data": "bytes1", "TTL": int, .. }, - // { .., "data": "bytes2", "TTL": int, .. } - // ], - // .. } - auto error = QJsonParseError{ 0, QJsonParseError::NoError }; - const auto document = QJsonDocument::fromJson(bytes, &error); - if (error.error != QJsonParseError::NoError) { - LOG(("Config Error: Failed to parse dns response JSON, error: %1" - ).arg(error.errorString())); - return {}; - } else if (!document.isObject()) { - LOG(("Config Error: Not an object received in dns response JSON.")); - return {}; - } - const auto response = document.object(); - const auto answerIt = response.find(qsl("Answer")); - if (answerIt == response.constEnd()) { - LOG(("Config Error: Could not find Answer in dns response JSON.")); - return {}; - } else if (!(*answerIt).isArray()) { - LOG(("Config Error: Not an array received " - "in Answer in dns response JSON.")); - return {}; - } - - auto result = std::vector(); - for (const auto elem : (*answerIt).toArray()) { - if (!elem.isObject()) { - LOG(("Config Error: Not an object found " - "in Answer array in dns response JSON.")); - continue; - } - const auto object = elem.toObject(); - if (typeRestriction) { - const auto typeIt = object.find(qsl("type")); - const auto type = int(std::round((*typeIt).toDouble())); - if (!(*typeIt).isDouble()) { - LOG(("Config Error: Not a number in type field " - "in Answer array in dns response JSON.")); - continue; - } else if (type != *typeRestriction) { - continue; - } - } - const auto dataIt = object.find(qsl("data")); - if (dataIt == object.constEnd()) { - LOG(("Config Error: Could not find data " - "in Answer array entry in dns response JSON.")); - continue; - } else if (!(*dataIt).isString()) { - LOG(("Config Error: Not a string data found " - "in Answer array entry in dns response JSON.")); - continue; - } - - const auto ttlIt = object.find(qsl("TTL")); - const auto ttl = (ttlIt != object.constEnd()) - ? crl::time(std::round((*ttlIt).toDouble())) - : crl::time(0); - result.push_back({ (*dataIt).toString(), ttl }); - } - return result; -} - QByteArray ConcatenateDnsTxtFields(const std::vector &response) { auto entries = QMap(); for (const auto &entry : response) { @@ -299,40 +182,6 @@ QByteArray ParseRealtimeResponse(const QByteArray &bytes) { } // namespace -ServiceWebRequest::ServiceWebRequest(not_null reply) -: reply(reply.get()) { -} - -ServiceWebRequest::ServiceWebRequest(ServiceWebRequest &&other) -: reply(base::take(other.reply)) { -} - -ServiceWebRequest &ServiceWebRequest::operator=(ServiceWebRequest &&other) { - if (reply != other.reply) { - destroy(); - reply = base::take(other.reply); - } - return *this; -} - -void ServiceWebRequest::destroy() { - if (const auto value = base::take(reply)) { - value->disconnect( - value, - &QNetworkReply::finished, - nullptr, - nullptr); - value->abort(); - value->deleteLater(); - } -} - -ServiceWebRequest::~ServiceWebRequest() { - if (reply) { - reply->deleteLater(); - } -} - SpecialConfigRequest::SpecialConfigRequest( Fn callback) -: _callback(std::move(callback)) { - _manager.setProxy(QNetworkProxy::NoProxy); -} - -void DomainResolver::resolve(const QString &domain) { - resolve({ domain, false }); - resolve({ domain, true }); -} - -void DomainResolver::resolve(const AttemptKey &key) { - if (_attempts.find(key) != end(_attempts)) { - return; - } else if (_requests.find(key) != end(_requests)) { - return; - } - const auto i = _cache.find(key); - _lastTimestamp = crl::now(); - if (i != end(_cache) && i->second.expireAt > _lastTimestamp) { - checkExpireAndPushResult(key.domain); - return; - } - - auto attempts = std::vector(); - auto domains = DnsDomains(); - std::random_device rd; - ranges::shuffle(domains, std::mt19937(rd())); - const auto takeDomain = [&] { - const auto result = domains.back(); - domains.pop_back(); - return result; - }; - const auto shuffle = [&](int from, int till) { - Expects(till > from); - - ranges::shuffle( - begin(attempts) + from, - begin(attempts) + till, - std::mt19937(rd())); - }; - - attempts.push_back({ Type::Google, "dns.google.com" }); - attempts.push_back({ Type::Google, takeDomain(), "dns" }); - attempts.push_back({ Type::Mozilla, "mozilla.cloudflare-dns.com" }); - while (!domains.empty()) { - attempts.push_back({ Type::Google, takeDomain(), "dns" }); - } - - shuffle(0, 2); - - ranges::reverse(attempts); // We go from last to first. - - _attempts.emplace(key, Attempts{ std::move(attempts) }); - sendNextRequest(key); -} - -void DomainResolver::checkExpireAndPushResult(const QString &domain) { - const auto ipv4 = _cache.find({ domain, false }); - if (ipv4 == end(_cache) || ipv4->second.expireAt <= _lastTimestamp) { - return; - } - auto result = ipv4->second; - const auto ipv6 = _cache.find({ domain, true }); - if (ipv6 != end(_cache) && ipv6->second.expireAt > _lastTimestamp) { - result.ips.append(ipv6->second.ips); - accumulate_min(result.expireAt, ipv6->second.expireAt); - } - InvokeQueued(this, [=] { - _callback(domain, result.ips, result.expireAt); - }); -} - -void DomainResolver::sendNextRequest(const AttemptKey &key) { - auto i = _attempts.find(key); - if (i == end(_attempts)) { - return; - } - auto &attempts = i->second; - auto &list = attempts.list; - const auto attempt = list.back(); - list.pop_back(); - - if (!list.empty()) { - base::call_delayed(kSendNextTimeout, &attempts.guard, [=] { - sendNextRequest(key); - }); - } - performRequest(key, attempt); -} - -void DomainResolver::performRequest( - const AttemptKey &key, - const Attempt &attempt) { - auto url = QUrl(); - url.setScheme(qsl("https")); - auto request = QNetworkRequest(); - switch (attempt.type) { - case Type::Mozilla: { - url.setHost(attempt.data); - url.setPath(qsl("/dns-query")); - url.setQuery(qsl("name=%1&type=%2&random_padding=%3" - ).arg(key.domain - ).arg(key.ipv6 ? 28 : 1 - ).arg(GenerateRandomPadding())); - request.setRawHeader("accept", "application/dns-json"); - } break; - case Type::Google: { - url.setHost(attempt.data); - url.setPath(qsl("/resolve")); - url.setQuery(qsl("name=%1&type=%2&random_padding=%3" - ).arg(key.domain - ).arg(key.ipv6 ? 28 : 1 - ).arg(GenerateRandomPadding())); - if (!attempt.host.isEmpty()) { - const auto host = attempt.host + ".google.com"; - request.setRawHeader("Host", host.toLatin1()); - } - } break; - default: Unexpected("Type in SpecialConfigRequest::performRequest."); - } - request.setUrl(url); - request.setRawHeader("User-Agent", kUserAgent); - const auto i = _requests.emplace( - key, - std::vector()).first; - const auto reply = i->second.emplace_back( - _manager.get(request) - ).reply; - connect(reply, &QNetworkReply::finished, this, [=] { - requestFinished(key, reply); - }); -} - -void DomainResolver::requestFinished( - const AttemptKey &key, - not_null reply) { - const auto result = finalizeRequest(key, reply); - const auto response = ParseDnsResponse(result); - if (response.empty()) { - return; - } - _requests.erase(key); - _attempts.erase(key); - - auto entry = CacheEntry(); - auto ttl = kMaxTimeToLive; - for (const auto &item : response) { - entry.ips.push_back(item.data); - accumulate_min(ttl, std::max( - item.TTL * crl::time(1000), - kMinTimeToLive)); - } - _lastTimestamp = crl::now(); - entry.expireAt = _lastTimestamp + ttl; - _cache[key] = std::move(entry); - - checkExpireAndPushResult(key.domain); -} - -QByteArray DomainResolver::finalizeRequest( - const AttemptKey &key, - not_null reply) { - if (reply->error() != QNetworkReply::NoError) { - LOG(("Resolve Error: Failed to get response, error: %2 (%3)" - ).arg(reply->errorString() - ).arg(reply->error())); - } - const auto result = reply->readAll(); - const auto i = _requests.find(key); - if (i != end(_requests)) { - auto &requests = i->second; - const auto from = ranges::remove( - requests, - reply, - [](const ServiceWebRequest &request) { return request.reply; }); - requests.erase(from, end(requests)); - if (requests.empty()) { - _requests.erase(i); - } - } - return result; -} - -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/mtproto/special_config_request.h b/Telegram/SourceFiles/mtproto/special_config_request.h index 7826c66b1..da4d27f4d 100644 --- a/Telegram/SourceFiles/mtproto/special_config_request.h +++ b/Telegram/SourceFiles/mtproto/special_config_request.h @@ -7,24 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "mtproto/details/mtproto_domain_resolver.h" #include "base/bytes.h" +#include "base/weak_ptr.h" +#include #include #include -namespace MTP { - -struct ServiceWebRequest { - ServiceWebRequest(not_null reply); - ServiceWebRequest(ServiceWebRequest &&other); - ServiceWebRequest &operator=(ServiceWebRequest &&other); - ~ServiceWebRequest(); - - void destroy(); - - QPointer reply; - -}; +namespace MTP::details { class SpecialConfigRequest : public QObject { public: @@ -83,71 +74,4 @@ private: }; -class DomainResolver : public QObject { -public: - DomainResolver(Fn callback); - - void resolve(const QString &domain); - -private: - enum class Type { - Mozilla, - Google, - }; - struct Attempt { - Type type; - QString data; - QString host; - }; - struct AttemptKey { - QString domain; - bool ipv6 = false; - - inline bool operator<(const AttemptKey &other) const { - return (domain < other.domain) - || (domain == other.domain && !ipv6 && other.ipv6); - } - inline bool operator==(const AttemptKey &other) const { - return (domain == other.domain) && (ipv6 == other.ipv6); - } - - }; - struct CacheEntry { - QStringList ips; - crl::time expireAt = 0; - - }; - struct Attempts { - std::vector list; - base::has_weak_ptr guard; - - }; - - void resolve(const AttemptKey &key); - void sendNextRequest(const AttemptKey &key); - void performRequest(const AttemptKey &key, const Attempt &attempt); - void checkExpireAndPushResult(const QString &domain); - void requestFinished( - const AttemptKey &key, - not_null reply); - QByteArray finalizeRequest( - const AttemptKey &key, - not_null reply); - - Fn _callback; - - QNetworkAccessManager _manager; - std::map _attempts; - std::map> _requests; - std::map _cache; - crl::time _lastTimestamp = 0; - -}; - -} // namespace MTP +} // namespace MTP::details diff --git a/Telegram/SourceFiles/passport/passport_encryption.cpp b/Telegram/SourceFiles/passport/passport_encryption.cpp index ce83fa5d8..4d9b3520e 100644 --- a/Telegram/SourceFiles/passport/passport_encryption.cpp +++ b/Telegram/SourceFiles/passport/passport_encryption.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "passport/passport_encryption.h" #include "base/openssl_help.h" -#include "mtproto/mtproto_rsa_public_key.h" +#include "mtproto/details/mtproto_rsa_public_key.h" #include #include @@ -429,7 +429,7 @@ uint64 CountSecureSecretId(bytes::const_span secret) { bytes::vector EncryptCredentialsSecret( bytes::const_span secret, bytes::const_span publicKey) { - const auto key = MTP::internal::RSAPublicKey(publicKey); + const auto key = MTP::details::RSAPublicKey(publicKey); return key.encryptOAEPpadding(secret); } diff --git a/Telegram/SourceFiles/storage/file_download.cpp b/Telegram/SourceFiles/storage/file_download.cpp index ae046b0d4..e56544935 100644 --- a/Telegram/SourceFiles/storage/file_download.cpp +++ b/Telegram/SourceFiles/storage/file_download.cpp @@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "storage/localstorage.h" #include "platform/platform_file_utilities.h" -#include "mtproto/connection.h" // for MTP::kAckSendWaiting #include "main/main_session.h" #include "apiwrap.h" #include "core/crash_reports.h" @@ -28,7 +27,7 @@ namespace Storage { namespace { // How much time without download causes additional session kill. -constexpr auto kKillSessionTimeout = crl::time(5000); +constexpr auto kKillSessionTimeout = 15 * crl::time(1000); // Max 16 file parts downloaded at the same time, 128 KB each. constexpr auto kMaxFileQueries = 16; @@ -75,11 +74,10 @@ void Downloader::killDownloadSessionsStart(MTP::DcId dcId) { if (!_killDownloadSessionTimes.contains(dcId)) { _killDownloadSessionTimes.emplace( dcId, - crl::now() + MTP::kAckSendWaiting + kKillSessionTimeout); + crl::now() + kKillSessionTimeout); } if (!_killDownloadSessionsTimer.isActive()) { - _killDownloadSessionsTimer.callOnce( - MTP::kAckSendWaiting + kKillSessionTimeout + 5); + _killDownloadSessionsTimer.callOnce(kKillSessionTimeout + 5); } } @@ -92,16 +90,17 @@ void Downloader::killDownloadSessionsStop(MTP::DcId dcId) { } void Downloader::killDownloadSessions() { - auto ms = crl::now(), left = MTP::kAckSendWaiting + kKillSessionTimeout; + const auto now = crl::now(); + auto left = kKillSessionTimeout; for (auto i = _killDownloadSessionTimes.begin(); i != _killDownloadSessionTimes.end(); ) { - if (i->second <= ms) { + if (i->second <= now) { for (int j = 0; j < MTP::kDownloadSessionsCount; ++j) { MTP::stopSession(MTP::downloadDcId(i->first, j)); } i = _killDownloadSessionTimes.erase(i); } else { - if (i->second - ms < left) { - left = i->second - ms; + if (i->second - now < left) { + left = i->second - now; } ++i; } diff --git a/Telegram/SourceFiles/storage/file_upload.cpp b/Telegram/SourceFiles/storage/file_upload.cpp index 6d852cdb9..4263328fd 100644 --- a/Telegram/SourceFiles/storage/file_upload.cpp +++ b/Telegram/SourceFiles/storage/file_upload.cpp @@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/localimageloader.h" #include "storage/file_download.h" -#include "mtproto/connection.h" // for MTP::kAckSendWaiting #include "data/data_document.h" #include "data/data_photo.h" #include "data/data_session.h" @@ -42,7 +41,7 @@ constexpr auto kDocumentUploadPartSize4 = 512 * 1024; constexpr auto kUploadRequestInterval = crl::time(500); // How much time without upload causes additional session kill. -constexpr auto kKillSessionTimeout = crl::time(5000); +constexpr auto kKillSessionTimeout = 15 * crl::time(000); } // namespace @@ -256,8 +255,7 @@ void Uploader::sendNext() { bool stopping = stopSessionsTimer.isActive(); if (queue.empty()) { if (!stopping) { - stopSessionsTimer.start( - MTP::kAckSendWaiting + kKillSessionTimeout); + stopSessionsTimer.start(kKillSessionTimeout); } return; } diff --git a/Telegram/gyp/lib_mtproto.gyp b/Telegram/gyp/lib_mtproto.gyp index f95b4310d..5ca1ad191 100644 --- a/Telegram/gyp/lib_mtproto.gyp +++ b/Telegram/gyp/lib_mtproto.gyp @@ -34,34 +34,40 @@ '<(src_loc)', ], 'sources': [ + '<(src_loc)/mtproto/details/mtproto_abstract_socket.cpp', + '<(src_loc)/mtproto/details/mtproto_abstract_socket.h', '<(src_loc)/mtproto/details/mtproto_bound_key_creator.cpp', '<(src_loc)/mtproto/details/mtproto_bound_key_creator.h', '<(src_loc)/mtproto/details/mtproto_dc_key_binder.cpp', '<(src_loc)/mtproto/details/mtproto_dc_key_binder.h', '<(src_loc)/mtproto/details/mtproto_dc_key_creator.cpp', '<(src_loc)/mtproto/details/mtproto_dc_key_creator.h', + '<(src_loc)/mtproto/details/mtproto_dcenter.cpp', + '<(src_loc)/mtproto/details/mtproto_dcenter.h', + '<(src_loc)/mtproto/details/mtproto_domain_resolver.cpp', + '<(src_loc)/mtproto/details/mtproto_domain_resolver.h', '<(src_loc)/mtproto/details/mtproto_dump_to_text.cpp', '<(src_loc)/mtproto/details/mtproto_dump_to_text.h', '<(src_loc)/mtproto/details/mtproto_received_ids_manager.cpp', '<(src_loc)/mtproto/details/mtproto_received_ids_manager.h', + '<(src_loc)/mtproto/details/mtproto_rsa_public_key.cpp', + '<(src_loc)/mtproto/details/mtproto_rsa_public_key.h', '<(src_loc)/mtproto/details/mtproto_serialized_request.cpp', '<(src_loc)/mtproto/details/mtproto_serialized_request.h', - '<(src_loc)/mtproto/mtproto_abstract_socket.cpp', - '<(src_loc)/mtproto/mtproto_abstract_socket.h', + '<(src_loc)/mtproto/details/mtproto_tcp_socket.cpp', + '<(src_loc)/mtproto/details/mtproto_tcp_socket.h', + '<(src_loc)/mtproto/details/mtproto_tls_socket.cpp', + '<(src_loc)/mtproto/details/mtproto_tls_socket.h', '<(src_loc)/mtproto/mtproto_auth_key.cpp', '<(src_loc)/mtproto/mtproto_auth_key.h', + '<(src_loc)/mtproto/mtproto_concurrent_sender.cpp', + '<(src_loc)/mtproto/mtproto_concurrent_sender.h', '<(src_loc)/mtproto/mtproto_dh_utils.cpp', '<(src_loc)/mtproto/mtproto_dh_utils.h', '<(src_loc)/mtproto/mtproto_proxy_data.cpp', '<(src_loc)/mtproto/mtproto_proxy_data.h', - '<(src_loc)/mtproto/mtproto_rsa_public_key.cpp', - '<(src_loc)/mtproto/mtproto_rsa_public_key.h', '<(src_loc)/mtproto/mtproto_rpc_sender.cpp', '<(src_loc)/mtproto/mtproto_rpc_sender.h', - '<(src_loc)/mtproto/mtproto_tcp_socket.cpp', - '<(src_loc)/mtproto/mtproto_tcp_socket.h', - '<(src_loc)/mtproto/mtproto_tls_socket.cpp', - '<(src_loc)/mtproto/mtproto_tls_socket.h', ], }], } diff --git a/Telegram/gyp/telegram/sources.txt b/Telegram/gyp/telegram/sources.txt index c4d81714e..6276efafc 100644 --- a/Telegram/gyp/telegram/sources.txt +++ b/Telegram/gyp/telegram/sources.txt @@ -537,12 +537,8 @@ <(src_loc)/media/view/media_view_group_thumbs.h <(src_loc)/media/view/media_view_overlay_widget.cpp <(src_loc)/media/view/media_view_overlay_widget.h -<(src_loc)/mtproto/concurrent_sender.cpp -<(src_loc)/mtproto/concurrent_sender.h <(src_loc)/mtproto/config_loader.cpp <(src_loc)/mtproto/config_loader.h -<(src_loc)/mtproto/connection.cpp -<(src_loc)/mtproto/connection.h <(src_loc)/mtproto/connection_abstract.cpp <(src_loc)/mtproto/connection_abstract.h <(src_loc)/mtproto/connection_http.cpp @@ -552,8 +548,6 @@ <(src_loc)/mtproto/connection_tcp.cpp <(src_loc)/mtproto/connection_tcp.h <(src_loc)/mtproto/core_types.h -<(src_loc)/mtproto/dcenter.cpp -<(src_loc)/mtproto/dcenter.h <(src_loc)/mtproto/dc_options.cpp <(src_loc)/mtproto/dc_options.h <(src_loc)/mtproto/dedicated_file_loader.cpp @@ -565,6 +559,8 @@ <(src_loc)/mtproto/sender.h <(src_loc)/mtproto/session.cpp <(src_loc)/mtproto/session.h +<(src_loc)/mtproto/session_private.cpp +<(src_loc)/mtproto/session_private.h <(src_loc)/mtproto/special_config_request.cpp <(src_loc)/mtproto/special_config_request.h <(src_loc)/mtproto/type_utils.h diff --git a/Telegram/lib_tl b/Telegram/lib_tl index 13918d5b5..10cddc61a 160000 --- a/Telegram/lib_tl +++ b/Telegram/lib_tl @@ -1 +1 @@ -Subproject commit 13918d5b5c4611ef1563a13ac1daf4d2c77c5f49 +Subproject commit 10cddc61a6c5b6cd896ba014fc187d15f5267be3