Move some more code to lib_mtproto.

This commit is contained in:
John Preston 2019-12-02 16:10:19 +03:00
parent 718de09aa6
commit 91f50e8bdc
51 changed files with 792 additions and 752 deletions

View File

@ -1059,7 +1059,7 @@ void ProxiesBoxController::refreshChecker(Item &item) {
item.state = ItemState::Checking; item.state = ItemState::Checking;
const auto setup = [&](Checker &checker, const bytes::vector &secret) { const auto setup = [&](Checker &checker, const bytes::vector &secret) {
checker = MTP::internal::AbstractConnection::Create( checker = MTP::details::AbstractConnection::Create(
mtproto, mtproto,
type, type,
QThread::currentThread(), QThread::currentThread(),
@ -1107,7 +1107,7 @@ void ProxiesBoxController::refreshChecker(Item &item) {
} }
void ProxiesBoxController::setupChecker(int id, const Checker &checker) { void ProxiesBoxController::setupChecker(int id, const Checker &checker) {
using Connection = MTP::internal::AbstractConnection; using Connection = MTP::details::AbstractConnection;
const auto pointer = checker.get(); const auto pointer = checker.get();
pointer->connect(pointer, &Connection::connected, [=] { pointer->connect(pointer, &Connection::connected, [=] {
const auto item = findById(id); const auto item = findById(id);

View File

@ -75,7 +75,7 @@ public:
~ProxiesBoxController(); ~ProxiesBoxController();
private: private:
using Checker = MTP::internal::ConnectionPointer; using Checker = MTP::details::ConnectionPointer;
struct Item { struct Item {
int id = 0; int id = 0;
ProxyData data; ProxyData data;

View File

@ -14,7 +14,7 @@ from generate_tl import generate
generate({ generate({
'namespaces': { 'namespaces': {
'creator': 'MTP::internal', 'creator': 'MTP::details',
}, },
'prefixes': { 'prefixes': {
'type': 'MTP', 'type': 'MTP',

View File

@ -184,9 +184,9 @@ void Application::run() {
style::ShortAnimationPlaying( style::ShortAnimationPlaying(
) | rpl::start_with_next([=](bool playing) { ) | rpl::start_with_next([=](bool playing) {
if (playing) { if (playing) {
MTP::internal::pause(); MTP::details::pause();
} else { } else {
MTP::internal::unpause(); MTP::details::unpause();
} }
}, _lifetime); }, _lifetime);

View File

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "mtproto/concurrent_sender.h" #include "mtproto/mtproto_concurrent_sender.h"
namespace Export { namespace Export {
namespace Data { namespace Data {

View File

@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/type_traits.h" #include "base/type_traits.h"
#include "base/observer.h" #include "base/observer.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "ui/effects/animation_value.h"
#include "mtproto/mtproto_proxy_data.h" #include "mtproto/mtproto_proxy_data.h"
class History; class History;

View File

@ -7,14 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/config_loader.h" #include "mtproto/config_loader.h"
#include "mtproto/special_config_request.h"
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "mtproto/dc_options.h" #include "mtproto/dc_options.h"
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
#include "mtproto/special_config_request.h"
#include "facades.h" #include "facades.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
namespace { namespace {
constexpr auto kEnumerateDcTimeout = 8000; // 8 seconds timeout for help_getConfig to work (then move to other dc) 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()); _instance->dcOptions()->setFromList(data.vdc_options());
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -14,10 +14,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace MTP { namespace MTP {
class SpecialConfigRequest;
class Instance; class Instance;
namespace internal { namespace details {
class SpecialConfigRequest;
class ConfigLoader : public base::has_weak_ptr { class ConfigLoader : public base::has_weak_ptr {
public: 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); return (a.dcId == b.dcId) && (a.ip == b.ip) && (a.port == b.port);
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/openssl_help.h" #include "base/openssl_help.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
ConnectionPointer::ConnectionPointer() = default; ConnectionPointer::ConnectionPointer() = default;
@ -194,5 +194,5 @@ uint32 AbstractConnection::extendedNotSecurePadding() const {
: 0; : 0;
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -18,7 +18,7 @@ namespace MTP {
class Instance; class Instance;
namespace internal { namespace details {
struct ConnectionOptions; struct ConnectionOptions;
@ -195,5 +195,5 @@ mtpBuffer AbstractConnection::prepareNotSecurePacket(
return result; return result;
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/qthelp_url.h" #include "base/qthelp_url.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
namespace { namespace {
constexpr auto kForceHttpPort = 80; constexpr auto kForceHttpPort = 80;
@ -246,5 +246,5 @@ QUrl HttpConnection::url() const {
return QUrl(pattern.arg(_address).arg(kForceHttpPort)); return QUrl(pattern.arg(_address).arg(kForceHttpPort));
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
namespace MTP { namespace MTP {
namespace internal { namespace details {
class HttpConnection : public AbstractConnection { class HttpConnection : public AbstractConnection {
public: public:
@ -64,5 +64,5 @@ private:
}; };
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
namespace { namespace {
constexpr auto kOneConnectionTimeout = 4000; constexpr auto kOneConnectionTimeout = 4000;
@ -256,5 +256,5 @@ QString ResolvingConnection::tag() const {
return _child ? _child->tag() : QString(); return _child ? _child->tag() : QString();
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h" #include "base/timer.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
class ResolvingConnection : public AbstractConnection { class ResolvingConnection : public AbstractConnection {
public: public:
@ -67,5 +67,5 @@ private:
}; };
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/connection_tcp.h" #include "mtproto/connection_tcp.h"
#include "mtproto/mtproto_abstract_socket.h" #include "mtproto/details/mtproto_abstract_socket.h"
#include "base/bytes.h" #include "base/bytes.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"
#include "base/qthelp_url.h" #include "base/qthelp_url.h"
@ -17,7 +17,7 @@ extern "C" {
} // extern "C" } // extern "C"
namespace MTP { namespace MTP {
namespace internal { namespace details {
namespace { namespace {
constexpr auto kPacketSizeMax = int(0x01000000 * sizeof(mtpPrime)); constexpr auto kPacketSizeMax = int(0x01000000 * sizeof(mtpPrime));
@ -665,5 +665,5 @@ void TcpConnection::socketError() {
TcpConnection::~TcpConnection() = default; TcpConnection::~TcpConnection() = default;
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtproto_auth_key.h" #include "mtproto/mtproto_auth_key.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
class AbstractSocket; class AbstractSocket;
@ -98,5 +98,5 @@ private:
}; };
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -7,13 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/dc_options.h" #include "mtproto/dc_options.h"
#include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "storage/serialize_common.h"
#include "mtproto/connection_tcp.h" #include "mtproto/connection_tcp.h"
#include "storage/serialize_common.h"
namespace MTP { namespace MTP {
namespace { namespace {
using namespace details;
const char *(PublicRSAKeys[]) = { "\ const char *(PublicRSAKeys[]) = { "\
-----BEGIN RSA PUBLIC KEY-----\n\ -----BEGIN RSA PUBLIC KEY-----\n\
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n\ MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n\
@ -102,6 +105,8 @@ DcOptions::DcOptions() {
constructFromBuiltIn(); constructFromBuiltIn();
} }
DcOptions::~DcOptions() = default;
bool DcOptions::ValidateSecret(bytes::const_span secret) { bool DcOptions::ValidateSecret(bytes::const_span secret) {
// See also TcpConnection::Protocol::Create. // See also TcpConnection::Protocol::Create.
return (secret.size() >= 21 && secret[0] == bytes::type(0xEE)) return (secret.size() >= 21 && secret[0] == bytes::type(0xEE))
@ -113,7 +118,7 @@ bool DcOptions::ValidateSecret(bytes::const_span secret) {
void DcOptions::readBuiltInPublicKeys() { void DcOptions::readBuiltInPublicKeys() {
for (const auto key : PublicRSAKeys) { for (const auto key : PublicRSAKeys) {
const auto keyBytes = bytes::make_span(key, strlen(key)); const auto keyBytes = bytes::make_span(key, strlen(key));
auto parsed = internal::RSAPublicKey(keyBytes); auto parsed = RSAPublicKey(keyBytes);
if (parsed.valid()) { if (parsed.valid()) {
_publicKeys.emplace(parsed.fingerprint(), std::move(parsed)); _publicKeys.emplace(parsed.fingerprint(), std::move(parsed));
} else { } else {
@ -512,7 +517,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
return; return;
} }
auto key = internal::RSAPublicKey(n, e); auto key = RSAPublicKey(n, e);
if (key.valid()) { if (key.valid()) {
_cdnPublicKeys[dcId].emplace(key.fingerprint(), std::move(key)); _cdnPublicKeys[dcId].emplace(key.fingerprint(), std::move(key));
} else { } else {
@ -569,7 +574,7 @@ void DcOptions::setCDNConfig(const MTPDcdnConfig &config) {
for (const auto &key : config.vpublic_keys().v) { for (const auto &key : config.vpublic_keys().v) {
key.match([&](const MTPDcdnPublicKey &data) { key.match([&](const MTPDcdnPublicKey &data) {
const auto keyBytes = bytes::make_span(data.vpublic_key().v); const auto keyBytes = bytes::make_span(data.vpublic_key().v);
auto key = internal::RSAPublicKey(keyBytes); auto key = RSAPublicKey(keyBytes);
if (key.valid()) { if (key.valid()) {
_cdnPublicKeys[data.vdc_id().v].emplace( _cdnPublicKeys[data.vdc_id().v].emplace(
key.fingerprint(), key.fingerprint(),
@ -590,18 +595,17 @@ bool DcOptions::hasCDNKeysForDc(DcId dcId) const {
return _cdnPublicKeys.find(dcId) != _cdnPublicKeys.cend(); return _cdnPublicKeys.find(dcId) != _cdnPublicKeys.cend();
} }
internal::RSAPublicKey DcOptions::getDcRSAKey( RSAPublicKey DcOptions::getDcRSAKey(
DcId dcId, DcId dcId,
const QVector<MTPlong> &fingerprints) const { const QVector<MTPlong> &fingerprints) const {
const auto findKey = [&]( const auto findKey = [&](const std::map<uint64, RSAPublicKey> &keys) {
const std::map<uint64, internal::RSAPublicKey> &keys) {
for (const auto &fingerprint : fingerprints) { for (const auto &fingerprint : fingerprints) {
const auto it = keys.find(static_cast<uint64>(fingerprint.v)); const auto it = keys.find(static_cast<uint64>(fingerprint.v));
if (it != keys.cend()) { if (it != keys.cend()) {
return it->second; return it->second;
} }
} }
return internal::RSAPublicKey(); return RSAPublicKey();
}; };
{ {
ReadLocker lock(this); ReadLocker lock(this);

View File

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/observer.h" #include "base/observer.h"
#include "base/bytes.h" #include "base/bytes.h"
#include "mtproto/mtproto_rsa_public_key.h"
#include <QtCore/QReadWriteLock> #include <QtCore/QReadWriteLock>
#include <string> #include <string>
@ -18,6 +17,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <set> #include <set>
namespace MTP { namespace MTP {
namespace details {
class RSAPublicKey;
} // namespace details
enum class DcType { enum class DcType {
Regular, Regular,
@ -52,6 +54,7 @@ public:
}; };
DcOptions(); DcOptions();
~DcOptions();
[[nodiscard]] static bool ValidateSecret(bytes::const_span secret); [[nodiscard]] static bool ValidateSecret(bytes::const_span secret);
@ -95,7 +98,7 @@ public:
void setCDNConfig(const MTPDcdnConfig &config); void setCDNConfig(const MTPDcdnConfig &config);
[[nodiscard]] bool hasCDNKeysForDc(DcId dcId) const; [[nodiscard]] bool hasCDNKeysForDc(DcId dcId) const;
[[nodiscard]] internal::RSAPublicKey getDcRSAKey( [[nodiscard]] details::RSAPublicKey getDcRSAKey(
DcId dcId, DcId dcId,
const QVector<MTPlong> &fingerprints) const; const QVector<MTPlong> &fingerprints) const;
@ -137,8 +140,8 @@ private:
std::map<DcId, std::vector<Endpoint>> _data; std::map<DcId, std::vector<Endpoint>> _data;
std::set<DcId> _cdnDcIds; std::set<DcId> _cdnDcIds;
std::map<uint64, internal::RSAPublicKey> _publicKeys; std::map<uint64, details::RSAPublicKey> _publicKeys;
std::map<DcId, std::map<uint64, internal::RSAPublicKey>> _cdnPublicKeys; std::map<DcId, std::map<uint64, details::RSAPublicKey>> _cdnPublicKeys;
mutable QReadWriteLock _useThroughLockers; mutable QReadWriteLock _useThroughLockers;
rpl::event_stream<DcId> _changed; rpl::event_stream<DcId> _changed;

View File

@ -5,13 +5,12 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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/details/mtproto_tcp_socket.h"
#include "mtproto/mtproto_tls_socket.h" #include "mtproto/details/mtproto_tls_socket.h"
namespace MTP { namespace MTP::details {
namespace internal {
std::unique_ptr<AbstractSocket> AbstractSocket::Create( std::unique_ptr<AbstractSocket> AbstractSocket::Create(
not_null<QThread*> thread, not_null<QThread*> thread,
@ -24,5 +23,4 @@ std::unique_ptr<AbstractSocket> AbstractSocket::Create(
} }
} }
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -10,8 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/bytes.h" #include "base/bytes.h"
#include "base/basic_types.h" #include "base/basic_types.h"
namespace MTP { namespace MTP::details {
namespace internal {
class AbstractSocket : protected QObject { class AbstractSocket : protected QObject {
public: public:
@ -62,5 +61,4 @@ protected:
}; };
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/details/mtproto_dc_key_creator.h" #include "mtproto/details/mtproto_dc_key_creator.h"
#include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/connection_abstract.h" #include "mtproto/connection_abstract.h"
#include "mtproto/mtproto_dh_utils.h" #include "mtproto/mtproto_dh_utils.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"

View File

@ -19,8 +19,6 @@ class DcOptions;
namespace MTP::details { namespace MTP::details {
using namespace ::MTP::internal;
struct DcKeyRequest { struct DcKeyRequest {
TimeId temporaryExpiresIn = 0; TimeId temporaryExpiresIn = 0;
bool persistentNeeded = false; bool persistentNeeded = false;

View File

@ -5,17 +5,16 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/dcenter.h" #include "mtproto/details/mtproto_dcenter.h"
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "mtproto/mtproto_auth_key.h" #include "mtproto/mtproto_auth_key.h"
#include "mtproto/dc_options.h" #include "mtproto/dc_options.h"
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
#include "mtproto/special_config_request.h" #include "mtproto/special_config_request.h"
#include "storage/localstorage.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
namespace { namespace {
constexpr auto kEnumerateDcTimeout = 8000; // 8 seconds timeout for help_getConfig to work (then move to other dc) 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; _creatingKeys[IndexByType(type)] = false;
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -7,13 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include <QtCore/QReadWriteLock>
namespace MTP { namespace MTP {
class Instance; class Instance;
class AuthKey; class AuthKey;
using AuthKeyPtr = std::shared_ptr<AuthKey>; using AuthKeyPtr = std::shared_ptr<AuthKey>;
namespace internal { namespace details {
enum class TemporaryKeyType { enum class TemporaryKeyType {
Regular, Regular,
@ -61,5 +63,5 @@ private:
}; };
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -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 <QtCore/QJsonDocument>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonObject>
#include <range/v3/algorithm/shuffle.hpp>
#include <range/v3/algorithm/reverse.hpp>
#include <range/v3/algorithm/remove.hpp>
#include <random>
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<QString> &DnsDomains() {
static const auto kResult = std::vector<QString>{
"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<uchar>() / 2);
Assert(result <= kMaxPadding);
if (result >= kMinPadding) {
return result;
}
}
}();
result.resize(count);
for (auto &ch : result) {
ch = kValid[openssl::RandomValue<uchar>() % (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<DnsEntry> ParseDnsResponse(
const QByteArray &bytes,
std::optional<int> 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<DnsEntry>();
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<QNetworkReply*> 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<void(
const QString &host,
const QStringList &ips,
crl::time expireAt)> 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<Attempt>();
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<ServiceWebRequest>()).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<QNetworkReply*> 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<QNetworkReply*> 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

View File

@ -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 <QtCore/QPointer>
#include <QtNetwork/QNetworkReply>
#include <optional>
namespace MTP::details {
[[nodiscard]] const std::vector<QString> &DnsDomains();
[[nodiscard]] QString GenerateDnsRandomPadding();
[[nodiscard]] QByteArray DnsUserAgent();
struct DnsEntry {
QString data;
crl::time TTL = 0;
};
[[nodiscard]] std::vector<DnsEntry> ParseDnsResponse(
const QByteArray &bytes,
std::optional<int> typeRestriction = std::nullopt);
struct ServiceWebRequest {
ServiceWebRequest(not_null<QNetworkReply*> reply);
ServiceWebRequest(ServiceWebRequest &&other);
ServiceWebRequest &operator=(ServiceWebRequest &&other);
~ServiceWebRequest();
void destroy();
QPointer<QNetworkReply> reply;
};
class DomainResolver : public QObject {
public:
DomainResolver(Fn<void(
const QString &domain,
const QStringList &ips,
crl::time expireAt)> 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<Attempt> 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<QNetworkReply*> reply);
QByteArray finalizeRequest(
const AttemptKey &key,
not_null<QNetworkReply*> reply);
Fn<void(
const QString &domain,
const QStringList &ips,
crl::time expireAt)> _callback;
QNetworkAccessManager _manager;
std::map<AttemptKey, Attempts> _attempts;
std::map<AttemptKey, std::vector<ServiceWebRequest>> _requests;
std::map<AttemptKey, CacheEntry> _cache;
crl::time _lastTimestamp = 0;
};
} // namespace MTP::details

View File

@ -5,12 +5,11 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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" #include "base/openssl_help.h"
namespace MTP { namespace MTP::details {
namespace internal {
namespace { namespace {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) #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); return _private->encryptOAEPpadding(data);
} }
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -9,8 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/bytes.h" #include "base/bytes.h"
namespace MTP { namespace MTP::details {
namespace internal {
// this class holds an RSA public key and can encrypt fixed-size messages with it // this class holds an RSA public key and can encrypt fixed-size messages with it
class RSAPublicKey final { class RSAPublicKey final {
@ -47,5 +46,4 @@ private:
}; };
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -11,7 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <crl/crl_time.h> #include <crl/crl_time.h>
namespace MTP::details { namespace MTP {
namespace details {
class RequestData; class RequestData;
class SerializedRequest; class SerializedRequest;
@ -44,7 +45,7 @@ public:
template < template <
typename Request, typename Request,
typename = std::enable_if_t<tl::is_boxed_v<Request>>> typename = std::enable_if_t<tl::is_boxed_v<Request>>>
static SerializedRequest Serialize(const Request &request); static SerializedRequest Serialize(const Request &request);
// For template MTP requests and MTPBoxed instantiation. // For template MTP requests and MTPBoxed instantiation.
template <typename Accumulator> template <typename Accumulator>
@ -102,4 +103,5 @@ SerializedRequest SerializedRequest::Serialize(const Request &request) {
return serialized; return serialized;
} }
} // namespace MTP::details } // namespace details
} // namespace MTP

View File

@ -5,12 +5,11 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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" #include "base/invoke_queued.h"
namespace MTP { namespace MTP::details {
namespace internal {
TcpSocket::TcpSocket(not_null<QThread*> thread, const QNetworkProxy &proxy) TcpSocket::TcpSocket(not_null<QThread*> thread, const QNetworkProxy &proxy)
: AbstractSocket(thread) { : AbstractSocket(thread) {
@ -153,5 +152,4 @@ void TcpSocket::handleError(int errorCode) {
_error.fire({}); _error.fire({});
} }
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -7,10 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "mtproto/mtproto_abstract_socket.h" #include "mtproto/details/mtproto_abstract_socket.h"
namespace MTP { namespace MTP::details {
namespace internal {
class TcpSocket final : public AbstractSocket { class TcpSocket final : public AbstractSocket {
public: public:
@ -35,5 +34,4 @@ private:
}; };
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -5,9 +5,9 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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/openssl_help.h"
#include "base/bytes.h" #include "base/bytes.h"
#include "base/invoke_queued.h" #include "base/invoke_queued.h"
@ -16,8 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QtEndian> #include <QtCore/QtEndian>
#include <range/v3/algorithm/reverse.hpp> #include <range/v3/algorithm/reverse.hpp>
namespace MTP { namespace MTP::details {
namespace internal {
namespace { namespace {
constexpr auto kMaxGrease = 8; constexpr auto kMaxGrease = 8;
@ -778,5 +777,4 @@ void TlsSocket::handleError(int errorCode) {
_error.fire({}); _error.fire({});
} }
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -7,10 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "mtproto/mtproto_abstract_socket.h" #include "mtproto/details/mtproto_abstract_socket.h"
namespace MTP { namespace MTP::details {
namespace internal {
class TlsSocket final : public AbstractSocket { class TlsSocket final : public AbstractSocket {
public: public:
@ -64,5 +63,4 @@ private:
}; };
} // namespace internal } // namespace MTP::details
} // namespace MTP

View File

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_account.h" #include "main/main_account.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
namespace { namespace {
int PauseLevel = 0; int PauseLevel = 0;
@ -36,7 +36,7 @@ void unpause() {
} }
} }
} // namespace internal } // namespace details
Instance *MainInstance() { Instance *MainInstance() {
return Core::IsAppLaunched() return Core::IsAppLaunched()

View File

@ -11,13 +11,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
[[nodiscard]] bool paused(); [[nodiscard]] bool paused();
void pause(); void pause();
void unpause(); void unpause();
} // namespace internal } // namespace details
// send(MTPhelp_GetConfig(), MTP::configDcId(dc)) - for dc enumeration // send(MTPhelp_GetConfig(), MTP::configDcId(dc)) - for dc enumeration
constexpr ShiftedDcId configDcId(DcId dcId) { constexpr ShiftedDcId configDcId(DcId dcId) {
@ -37,23 +37,24 @@ constexpr ShiftedDcId updaterDcId(DcId dcId) {
constexpr auto kDownloadSessionsCount = 2; constexpr auto kDownloadSessionsCount = 2;
constexpr auto kUploadSessionsCount = 2; constexpr auto kUploadSessionsCount = 2;
namespace internal { namespace details {
constexpr ShiftedDcId downloadDcId(DcId dcId, int index) { constexpr ShiftedDcId downloadDcId(DcId dcId, int index) {
static_assert(kDownloadSessionsCount < kMaxMediaDcCount, "Too large MTPDownloadSessionsCount!"); static_assert(kDownloadSessionsCount < kMaxMediaDcCount, "Too large MTPDownloadSessionsCount!");
return ShiftDcId(dcId, kBaseDownloadDcShift + index); return ShiftDcId(dcId, kBaseDownloadDcShift + index);
}; };
} // namespace internal } // namespace details
// send(req, callbacks, MTP::downloadDcId(dc, index)) - for download shifted dc id // send(req, callbacks, MTP::downloadDcId(dc, index)) - for download shifted dc id
inline ShiftedDcId downloadDcId(DcId dcId, int index) { inline ShiftedDcId downloadDcId(DcId dcId, int index) {
Expects(index >= 0 && index < kDownloadSessionsCount); Expects(index >= 0 && index < kDownloadSessionsCount);
return internal::downloadDcId(dcId, index); return details::downloadDcId(dcId, index);
} }
inline constexpr bool isDownloadDcId(ShiftedDcId shiftedDcId) { 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) { 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; return (dcId < Instance::Config::kTemporaryMainDc) ? (dcId + Instance::Config::kTemporaryMainDc) : 0;
} }
namespace internal { namespace details {
constexpr ShiftedDcId uploadDcId(DcId dcId, int index) { constexpr ShiftedDcId uploadDcId(DcId dcId, int index) {
static_assert(kUploadSessionsCount < kMaxMediaDcCount, "Too large MTPUploadSessionsCount!"); static_assert(kUploadSessionsCount < kMaxMediaDcCount, "Too large MTPUploadSessionsCount!");
return ShiftDcId(dcId, kBaseUploadDcShift + index); return ShiftDcId(dcId, kBaseUploadDcShift + index);
}; };
} // namespace internal } // namespace details
// send(req, callbacks, MTP::uploadDcId(index)) - for upload shifted dc id // send(req, callbacks, MTP::uploadDcId(index)) - for upload shifted dc id
// uploading always to the main dc so BareDcId(result) == 0 // uploading always to the main dc so BareDcId(result) == 0
inline ShiftedDcId uploadDcId(int index) { inline ShiftedDcId uploadDcId(int index) {
Expects(index >= 0 && index < kUploadSessionsCount); Expects(index >= 0 && index < kUploadSessionsCount);
return internal::uploadDcId(0, index); return details::uploadDcId(0, index);
}; };
constexpr bool isUploadDcId(ShiftedDcId shiftedDcId) { 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) { inline ShiftedDcId destroyKeyNextDcId(ShiftedDcId shiftedDcId) {

View File

@ -7,14 +7,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/mtp_instance.h" #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/session.h"
#include "mtproto/dc_options.h" #include "mtproto/dc_options.h"
#include "mtproto/dcenter.h"
#include "mtproto/config_loader.h" #include "mtproto/config_loader.h"
#include "mtproto/special_config_request.h"
#include "mtproto/connection.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "mtproto/mtproto_rsa_public_key.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
#include "main/main_session.h" // Session::Exists. #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 kConfigBecomesOldForBlockedIn = 8 * crl::time(1000);
constexpr auto kCheckKeyEach = 60 * crl::time(1000); constexpr auto kCheckKeyEach = 60 * crl::time(1000);
using namespace internal;
using namespace details; using namespace details;
std::atomic<int> GlobalAtomicRequestId = 0; std::atomic<int> GlobalAtomicRequestId = 0;
} // namespace } // namespace
namespace internal { namespace details {
int GetNextRequestId() { int GetNextRequestId() {
const auto result = ++GlobalAtomicRequestId; const auto result = ++GlobalAtomicRequestId;
@ -52,7 +50,7 @@ int GetNextRequestId() {
return result; return result;
} }
} // namespace internal } // namespace details
class Instance::Private : private Sender { class Instance::Private : private Sender {
public: public:

View File

@ -11,14 +11,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/details/mtproto_serialized_request.h" #include "mtproto/details/mtproto_serialized_request.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
class Dcenter; class Dcenter;
class Session; class Session;
[[nodiscard]] int GetNextRequestId(); [[nodiscard]] int GetNextRequestId();
} // namespace internal } // namespace details
class DcOptions; class DcOptions;
class AuthKey; class AuthKey;
@ -131,7 +131,7 @@ public:
ShiftedDcId shiftedDcId = 0, ShiftedDcId shiftedDcId = 0,
crl::time msCanWait = 0, crl::time msCanWait = 0,
mtpRequestId afterRequestId = 0) { mtpRequestId afterRequestId = 0) {
const auto requestId = internal::GetNextRequestId(); const auto requestId = details::GetNextRequestId();
sendSerialized( sendSerialized(
requestId, requestId,
details::SerializedRequest::Serialize(request), details::SerializedRequest::Serialize(request),
@ -162,7 +162,7 @@ public:
mtpRequestId sendProtocolMessage( mtpRequestId sendProtocolMessage(
ShiftedDcId shiftedDcId, ShiftedDcId shiftedDcId,
const Request &request) { const Request &request) {
const auto requestId = internal::GetNextRequestId(); const auto requestId = details::GetNextRequestId();
sendRequest( sendRequest(
requestId, requestId,
details::SerializedRequest::Serialize(request), details::SerializedRequest::Serialize(request),

View File

@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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/mtp_instance.h"
#include "mtproto/mtproto_rpc_sender.h" #include "mtproto/mtproto_rpc_sender.h"
@ -135,7 +135,7 @@ void ConcurrentSender::RequestBuilder::setAfter(
} }
mtpRequestId ConcurrentSender::RequestBuilder::send() { mtpRequestId ConcurrentSender::RequestBuilder::send() {
const auto requestId = internal::GetNextRequestId(); const auto requestId = details::GetNextRequestId();
const auto dcId = _dcId; const auto dcId = _dcId;
const auto msCanWait = _canWait; const auto msCanWait = _canWait;
const auto afterRequestId = _afterRequestId; const auto afterRequestId = _afterRequestId;

View File

@ -7,13 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include <rpl/details/callable.h>
#include "base/bytes.h" #include "base/bytes.h"
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#include "base/flat_map.h" #include "base/flat_map.h"
#include "mtproto/core_types.h" #include "mtproto/core_types.h"
#include "mtproto/details/mtproto_serialized_request.h" #include "mtproto/details/mtproto_serialized_request.h"
#include <rpl/details/callable.h>
#ifndef _DEBUG #ifndef _DEBUG
#define MTP_SENDER_USE_GENERIC_HANDLERS #define MTP_SENDER_USE_GENERIC_HANDLERS
#endif // !_DEBUG #endif // !_DEBUG

View File

@ -7,18 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/session.h" #include "mtproto/session.h"
#include "mtproto/connection.h" #include "mtproto/details/mtproto_dcenter.h"
#include "mtproto/dcenter.h" #include "mtproto/session_private.h"
#include "mtproto/mtproto_auth_key.h" #include "mtproto/mtproto_auth_key.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"
#include "core/crash_reports.h"
#include "facades.h" #include "facades.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
ConnectionOptions::ConnectionOptions( SessionOptions::SessionOptions(
const QString &systemLangCode, const QString &systemLangCode,
const QString &cloudLangCode, const QString &cloudLangCode,
const QString &langPackName, 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 // #TODO race
const auto current = connectionOptions(); const auto current = this->options();
if (current.cloudLangCode == _options.cloudLangCode if (current.cloudLangCode == _options.cloudLangCode
&& current.systemLangCode == _options.systemLangCode && current.systemLangCode == _options.systemLangCode
&& current.langPackName == _options.langPackName && current.langPackName == _options.langPackName
@ -163,7 +162,7 @@ Session::Session(
} }
Session::~Session() { Session::~Session() {
Expects(!_connection); Expects(!_private);
if (_myKeyCreation != CreatingKeyType::None) { if (_myKeyCreation != CreatingKeyType::None) {
releaseKeyCreationOnFail(); releaseKeyCreationOnFail();
@ -177,11 +176,11 @@ void Session::watchDcKeyChanges() {
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
DEBUG_LOG(("AuthKey Info: dcTemporaryKeyChanged in Session %1" DEBUG_LOG(("AuthKey Info: dcTemporaryKeyChanged in Session %1"
).arg(_shiftedDcId)); ).arg(_shiftedDcId));
if (const auto connection = _connection) { if (const auto captured = _private) {
InvokeQueued(connection, [=] { InvokeQueued(captured, [=] {
DEBUG_LOG(("AuthKey Info: calling Connection::updateAuthKey in Session %1" DEBUG_LOG(("AuthKey Info: calling Connection::updateAuthKey in Session %1"
).arg(_shiftedDcId)); ).arg(_shiftedDcId));
connection->updateAuthKey(); captured->updateAuthKey();
}); });
} }
}, _lifetime); }, _lifetime);
@ -190,20 +189,20 @@ void Session::watchDcKeyChanges() {
void Session::watchDcOptionsChanges() { void Session::watchDcOptionsChanges() {
_instance->dcOptions()->changed( _instance->dcOptions()->changed(
) | rpl::filter([=](DcId dcId) { ) | rpl::filter([=](DcId dcId) {
return (BareDcId(_shiftedDcId) == dcId) && (_connection != nullptr); return (BareDcId(_shiftedDcId) == dcId) && (_private != nullptr);
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
InvokeQueued(_connection, [connection = _connection] { InvokeQueued(_private, [captured = _private] {
connection->dcOptionsChanged(); captured->dcOptionsChanged();
}); });
}, _lifetime); }, _lifetime);
if (_instance->dcOptions()->dcType(_shiftedDcId) == DcType::Cdn) { if (_instance->dcOptions()->dcType(_shiftedDcId) == DcType::Cdn) {
_instance->dcOptions()->cdnConfigChanged( _instance->dcOptions()->cdnConfigChanged(
) | rpl::filter([=] { ) | rpl::filter([=] {
return (_connection != nullptr); return (_private != nullptr);
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
InvokeQueued(_connection, [connection = _connection] { InvokeQueued(_private, [captured = _private] {
connection->cdnConfigChanged(); captured->cdnConfigChanged();
}); });
}, _lifetime); }, _lifetime);
} }
@ -211,7 +210,7 @@ void Session::watchDcOptionsChanges() {
void Session::start() { void Session::start() {
killConnection(); killConnection();
_connection = new Connection( _private = new SessionPrivate(
_instance, _instance,
_thread.get(), _thread.get(),
_data, _data,
@ -231,9 +230,9 @@ void Session::restart() {
return; return;
} }
refreshOptions(); refreshOptions();
if (const auto connection = _connection) { if (const auto captured = _private) {
InvokeQueued(connection, [=] { InvokeQueued(captured, [=] {
connection->restartNow(); captured->restartNow();
}); });
} }
} }
@ -248,7 +247,7 @@ void Session::refreshOptions() {
const auto useHttp = (proxyType != ProxyData::Type::Mtproto); const auto useHttp = (proxyType != ProxyData::Type::Mtproto);
const auto useIPv4 = true; const auto useIPv4 = true;
const auto useIPv6 = Global::TryIPv6(); const auto useIPv6 = Global::TryIPv6();
_data->setConnectionOptions(ConnectionOptions( _data->setOptions(SessionOptions(
_instance->systemLangCode(), _instance->systemLangCode(),
_instance->cloudLangCode(), _instance->cloudLangCode(),
_instance->langPackName(), _instance->langPackName(),
@ -326,17 +325,17 @@ void Session::needToResumeAndSend() {
DEBUG_LOG(("Session Info: can't resume a killed session")); DEBUG_LOG(("Session Info: can't resume a killed session"));
return; return;
} }
if (!_connection) { if (!_private) {
DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(_shiftedDcId)); DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(_shiftedDcId));
start(); start();
} }
const auto connection = _connection; const auto captured = _private;
const auto ping = base::take(_ping); const auto ping = base::take(_ping);
InvokeQueued(connection, [=] { InvokeQueued(captured, [=] {
if (ping) { if (ping) {
connection->sendPingForce(); captured->sendPingForce();
} else { } else {
connection->tryToSend(); captured->tryToSend();
} }
}); });
} }
@ -369,8 +368,8 @@ int32 Session::requestState(mtpRequestId requestId) const {
int32 result = MTP::RequestSent; int32 result = MTP::RequestSent;
bool connected = false; bool connected = false;
if (_connection) { if (_private) {
const auto s = _connection->getState(); const auto s = _private->getState();
if (s == ConnectedState) { if (s == ConnectedState) {
connected = true; connected = true;
} else if (s == ConnectingState || s == DisconnectedState) { } else if (s == ConnectingState || s == DisconnectedState) {
@ -398,8 +397,8 @@ int32 Session::requestState(mtpRequestId requestId) const {
int32 Session::getState() const { int32 Session::getState() const {
int32 result = -86400000; int32 result = -86400000;
if (_connection) { if (_private) {
const auto s = _connection->getState(); const auto s = _private->getState();
if (s == ConnectedState) { if (s == ConnectedState) {
return s; return s;
} else if (s == ConnectingState || s == DisconnectedState) { } else if (s == ConnectingState || s == DisconnectedState) {
@ -419,11 +418,11 @@ int32 Session::getState() const {
} }
QString Session::transport() const { QString Session::transport() const {
return _connection ? _connection->transport() : QString(); return _private ? _private->transport() : QString();
} }
void Session::sendPrepared( void Session::sendPrepared(
const details::SerializedRequest &request, const SerializedRequest &request,
crl::time msCanWait) { crl::time msCanWait) {
DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1" DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1"
).arg(msCanWait)); ).arg(msCanWait));
@ -563,14 +562,14 @@ void Session::tryToReceive() {
} }
void Session::killConnection() { void Session::killConnection() {
if (!_connection) { if (!_private) {
return; return;
} }
base::take(_connection)->deleteLater(); base::take(_private)->deleteLater();
Ensures(_connection == nullptr); Ensures(_private == nullptr);
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -20,17 +20,17 @@ class Instance;
class AuthKey; class AuthKey;
using AuthKeyPtr = std::shared_ptr<AuthKey>; using AuthKeyPtr = std::shared_ptr<AuthKey>;
namespace internal { namespace details {
class Dcenter; class Dcenter;
class Connection; class SessionPrivate;
enum class TemporaryKeyType; enum class TemporaryKeyType;
enum class CreatingKeyType; enum class CreatingKeyType;
struct ConnectionOptions { struct SessionOptions {
ConnectionOptions() = default; SessionOptions() = default;
ConnectionOptions( SessionOptions(
const QString &systemLangCode, const QString &systemLangCode,
const QString &cloudLangCode, const QString &cloudLangCode,
const QString &langPackName, const QString &langPackName,
@ -39,8 +39,6 @@ struct ConnectionOptions {
bool useIPv6, bool useIPv6,
bool useHttp, bool useHttp,
bool useTcp); bool useTcp);
ConnectionOptions(const ConnectionOptions &other) = default;
ConnectionOptions &operator=(const ConnectionOptions &other) = default;
QString systemLangCode; QString systemLangCode;
QString cloudLangCode; QString cloudLangCode;
@ -54,17 +52,17 @@ struct ConnectionOptions {
}; };
class Session; class Session;
class SessionData { class SessionData final {
public: public:
explicit SessionData(not_null<Session*> creator) : _owner(creator) { explicit SessionData(not_null<Session*> creator) : _owner(creator) {
} }
void notifyConnectionInited(const ConnectionOptions &options); void notifyConnectionInited(const SessionOptions &options);
void setConnectionOptions(ConnectionOptions options) { void setOptions(SessionOptions options) {
QWriteLocker locker(&_optionsLock); QWriteLocker locker(&_optionsLock);
_options = options; _options = options;
} }
[[nodiscard]] ConnectionOptions connectionOptions() const { [[nodiscard]] SessionOptions options() const {
QReadLocker locker(&_optionsLock); QReadLocker locker(&_optionsLock);
return _options; return _options;
} }
@ -79,10 +77,10 @@ public:
return &_haveReceivedLock; return &_haveReceivedLock;
} }
base::flat_map<mtpRequestId, details::SerializedRequest> &toSendMap() { base::flat_map<mtpRequestId, SerializedRequest> &toSendMap() {
return _toSend; return _toSend;
} }
base::flat_map<mtpMsgId, details::SerializedRequest> &haveSentMap() { base::flat_map<mtpMsgId, SerializedRequest> &haveSentMap() {
return _haveSent; return _haveSent;
} }
base::flat_map<mtpRequestId, mtpBuffer> &haveReceivedResponses() { base::flat_map<mtpRequestId, mtpBuffer> &haveReceivedResponses() {
@ -92,7 +90,7 @@ public:
return _receivedUpdates; return _receivedUpdates;
} }
// Connection -> Session interface. // SessionPrivate -> Session interface.
void queueTryToReceive(); void queueTryToReceive();
void queueNeedToResumeAndSend(); void queueNeedToResumeAndSend();
void queueConnectionStateChange(int newState); void queueConnectionStateChange(int newState);
@ -118,13 +116,13 @@ private:
Session *_owner = nullptr; Session *_owner = nullptr;
mutable QMutex _ownerMutex; mutable QMutex _ownerMutex;
ConnectionOptions _options; SessionOptions _options;
mutable QReadWriteLock _optionsLock; mutable QReadWriteLock _optionsLock;
base::flat_map<mtpRequestId, details::SerializedRequest> _toSend; // map of request_id -> request, that is waiting to be sent base::flat_map<mtpRequestId, SerializedRequest> _toSend; // map of request_id -> request, that is waiting to be sent
QReadWriteLock _toSendLock; QReadWriteLock _toSendLock;
base::flat_map<mtpMsgId, details::SerializedRequest> _haveSent; // map of msg_id -> request, that was sent base::flat_map<mtpMsgId, SerializedRequest> _haveSent; // map of msg_id -> request, that was sent
QReadWriteLock _haveSentLock; QReadWriteLock _haveSentLock;
base::flat_map<mtpRequestId, mtpBuffer> _receivedResponses; // map of request_id -> response that should be processed in the main thread base::flat_map<mtpRequestId, mtpBuffer> _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: public:
// Main thread. // Main thread.
Session( Session(
@ -159,10 +157,10 @@ public:
[[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const; [[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const;
[[nodiscard]] bool connectionInited() const; [[nodiscard]] bool connectionInited() const;
void sendPrepared( void sendPrepared(
const details::SerializedRequest &request, const SerializedRequest &request,
crl::time msCanWait = 0); crl::time msCanWait = 0);
// Connection thread. // SessionPrivate thread.
[[nodiscard]] CreatingKeyType acquireKeyCreation(TemporaryKeyType type); [[nodiscard]] CreatingKeyType acquireKeyCreation(TemporaryKeyType type);
[[nodiscard]] bool releaseKeyCreationOnDone( [[nodiscard]] bool releaseKeyCreationOnDone(
const AuthKeyPtr &temporaryKey, const AuthKeyPtr &temporaryKey,
@ -201,7 +199,7 @@ private:
const std::shared_ptr<SessionData> _data; const std::shared_ptr<SessionData> _data;
const not_null<QThread*> _thread; const not_null<QThread*> _thread;
Connection *_connection = nullptr; SessionPrivate *_private = nullptr;
bool _killed = false; bool _killed = false;
bool _needToReceive = false; bool _needToReceive = false;
@ -221,5 +219,5 @@ private:
}; };
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -5,26 +5,23 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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_bound_key_creator.h"
#include "mtproto/details/mtproto_dcenter.h"
#include "mtproto/details/mtproto_dump_to_text.h" #include "mtproto/details/mtproto_dump_to_text.h"
#include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/session.h" #include "mtproto/session.h"
#include "mtproto/mtproto_rsa_public_key.h"
#include "mtproto/mtproto_rpc_sender.h" #include "mtproto/mtproto_rpc_sender.h"
#include "mtproto/dc_options.h" #include "mtproto/dc_options.h"
#include "mtproto/dcenter.h"
#include "mtproto/connection_abstract.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/openssl_help.h"
#include "base/qthelp_url.h" #include "base/qthelp_url.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "zlib.h"
namespace MTP { namespace MTP {
namespace internal { namespace details {
namespace { namespace {
constexpr auto kIntSize = static_cast<int>(sizeof(mtpPrime)); constexpr auto kIntSize = static_cast<int>(sizeof(mtpPrime));
@ -42,6 +39,7 @@ constexpr auto kBindKeyAdditionalExpiresTimeout = TimeId(30);
constexpr auto kTestModeDcIdShift = 10000; constexpr auto kTestModeDcIdShift = 10000;
constexpr auto kCheckSentRequestsEach = 1 * crl::time(1000); constexpr auto kCheckSentRequestsEach = 1 * crl::time(1000);
constexpr auto kKeyOldEnoughForDestroy = 60 * 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. // If we can't connect for this time we will ask _instance to update config.
constexpr auto kRequestConfigTimeout = 8 * crl::time(1000); 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. // when resending request or checking its state.
constexpr auto kSendStateRequestWaiting = crl::time(1000); 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; using namespace details;
@ -113,7 +112,7 @@ void WrapInvokeAfter(
} // namespace } // namespace
Connection::Connection( SessionPrivate::SessionPrivate(
not_null<Instance*> instance, not_null<Instance*> instance,
not_null<QThread*> thread, not_null<QThread*> thread,
std::shared_ptr<SessionData> data, std::shared_ptr<SessionData> data,
@ -144,7 +143,7 @@ Connection::Connection(
}); });
} }
Connection::~Connection() { SessionPrivate::~SessionPrivate() {
releaseKeyCreationOnFail(); releaseKeyCreationOnFail();
doDisconnect(); doDisconnect();
@ -152,7 +151,7 @@ Connection::~Connection() {
Expects(_testConnections.empty()); Expects(_testConnections.empty());
} }
void Connection::appendTestConnection( void SessionPrivate::appendTestConnection(
DcOptions::Variants::Protocol protocol, DcOptions::Variants::Protocol protocol,
const QString &ip, const QString &ip,
int port, int port,
@ -168,7 +167,7 @@ void Connection::appendTestConnection(
protocol, protocol,
thread(), thread(),
protocolSecret, protocolSecret,
_connectionOptions->proxy), _options->proxy),
priority priority
}); });
const auto weak = _testConnections.back().data.get(); 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 dcId = BareDcId(_shiftedDcId);
const auto simpleDcId = isTemporaryDcId(dcId) const auto simpleDcId = isTemporaryDcId(dcId)
? getRealIdFromTemporaryDcId(dcId) ? getRealIdFromTemporaryDcId(dcId)
@ -214,7 +213,7 @@ int16 Connection::getProtocolDcId() const {
: testedDcId; : testedDcId;
} }
void Connection::checkSentRequests() { void SessionPrivate::checkSentRequests() {
clearOldContainers(); clearOldContainers();
auto restarting = false; auto restarting = false;
@ -246,7 +245,7 @@ void Connection::checkSentRequests() {
} }
} }
void Connection::clearOldContainers() { void SessionPrivate::clearOldContainers() {
auto resent = false; auto resent = false;
const auto now = crl::now(); const auto now = crl::now();
for (auto i = _sentContainers.begin(); i != _sentContainers.end();) { for (auto i = _sentContainers.begin(); i != _sentContainers.end();) {
@ -274,7 +273,7 @@ void Connection::clearOldContainers() {
} }
} }
void Connection::destroyAllConnections() { void SessionPrivate::destroyAllConnections() {
clearUnboundKeyCreator(); clearUnboundKeyCreator();
_waitForBetterTimer.cancel(); _waitForBetterTimer.cancel();
_waitForReceivedTimer.cancel(); _waitForReceivedTimer.cancel();
@ -283,20 +282,20 @@ void Connection::destroyAllConnections() {
_connection = nullptr; _connection = nullptr;
} }
void Connection::cdnConfigChanged() { void SessionPrivate::cdnConfigChanged() {
connectToServer(true); connectToServer(true);
} }
int32 Connection::getShiftedDcId() const { int32 SessionPrivate::getShiftedDcId() const {
return _shiftedDcId; return _shiftedDcId;
} }
void Connection::dcOptionsChanged() { void SessionPrivate::dcOptionsChanged() {
_retryTimeout = 1; _retryTimeout = 1;
connectToServer(true); connectToServer(true);
} }
int32 Connection::getState() const { int32 SessionPrivate::getState() const {
QReadLocker lock(&_stateMutex); QReadLocker lock(&_stateMutex);
int32 result = _state; int32 result = _state;
if (_state < 0) { if (_state < 0) {
@ -310,17 +309,17 @@ int32 Connection::getState() const {
return result; return result;
} }
QString Connection::transport() const { QString SessionPrivate::transport() const {
QReadLocker lock(&_stateMutex); QReadLocker lock(&_stateMutex);
if (!_connection || (_state < 0)) { if (!_connection || (_state < 0)) {
return QString(); return QString();
} }
Assert(_connectionOptions != nullptr); Assert(_options != nullptr);
return _connection->transport(); return _connection->transport();
} }
bool Connection::setState(int state, int ifState) { bool SessionPrivate::setState(int state, int ifState) {
if (ifState != kUpdateStateAlways) { if (ifState != kUpdateStateAlways) {
QReadLocker lock(&_stateMutex); QReadLocker lock(&_stateMutex);
if (_state != ifState) { if (_state != ifState) {
@ -344,7 +343,7 @@ bool Connection::setState(int state, int ifState) {
return true; return true;
} }
void Connection::resetSession() { void SessionPrivate::resetSession() {
MTP_LOG(_shiftedDcId, ("Resetting session!")); MTP_LOG(_shiftedDcId, ("Resetting session!"));
_needSessionReset = false; _needSessionReset = false;
@ -354,7 +353,7 @@ void Connection::resetSession() {
_sessionData->queueResetDone(); _sessionData->queueResetDone();
} }
void Connection::changeSessionId() { void SessionPrivate::changeSessionId() {
auto sessionId = _sessionId; auto sessionId = _sessionId;
do { do {
sessionId = openssl::RandomValue<uint64>(); sessionId = openssl::RandomValue<uint64>();
@ -371,13 +370,13 @@ void Connection::changeSessionId() {
_receivedMessageIds.clear(); _receivedMessageIds.clear();
} }
uint32 Connection::nextRequestSeqNumber(bool needAck) { uint32 SessionPrivate::nextRequestSeqNumber(bool needAck) {
const auto result = _messagesCounter; const auto result = _messagesCounter;
_messagesCounter += (needAck ? 1 : 0); _messagesCounter += (needAck ? 1 : 0);
return result * 2 + (needAck ? 1 : 0); return result * 2 + (needAck ? 1 : 0);
} }
bool Connection::realDcTypeChanged() { bool SessionPrivate::realDcTypeChanged() {
const auto now = _instance->dcOptions()->dcType(_shiftedDcId); const auto now = _instance->dcOptions()->dcType(_shiftedDcId);
if (_realDcType == now) { if (_realDcType == now) {
return false; return false;
@ -386,7 +385,7 @@ bool Connection::realDcTypeChanged() {
return true; return true;
} }
bool Connection::markSessionAsStarted() { bool SessionPrivate::markSessionAsStarted() {
if (_sessionMarkedAsStarted) { if (_sessionMarkedAsStarted) {
return false; return false;
} }
@ -394,7 +393,7 @@ bool Connection::markSessionAsStarted() {
return true; return true;
} }
mtpMsgId Connection::prepareToSend( mtpMsgId SessionPrivate::prepareToSend(
SerializedRequest &request, SerializedRequest &request,
mtpMsgId currentLastId, mtpMsgId currentLastId,
bool forceNewMsgId) { bool forceNewMsgId) {
@ -419,7 +418,7 @@ mtpMsgId Connection::prepareToSend(
return currentLastId; return currentLastId;
} }
mtpMsgId Connection::replaceMsgId(SerializedRequest &request, mtpMsgId newId) { mtpMsgId SessionPrivate::replaceMsgId(SerializedRequest &request, mtpMsgId newId) {
Expects(request->size() > 8); Expects(request->size() > 8);
const auto oldMsgId = request.getMsgId(); const auto oldMsgId = request.getMsgId();
@ -472,7 +471,7 @@ mtpMsgId Connection::replaceMsgId(SerializedRequest &request, mtpMsgId newId) {
return newId; return newId;
} }
mtpMsgId Connection::placeToContainer( mtpMsgId SessionPrivate::placeToContainer(
SerializedRequest &toSendRequest, SerializedRequest &toSendRequest,
mtpMsgId &bigMsgId, mtpMsgId &bigMsgId,
bool forceNewMsgId, bool forceNewMsgId,
@ -489,7 +488,7 @@ mtpMsgId Connection::placeToContainer(
return msgId; return msgId;
} }
void Connection::tryToSend() { void SessionPrivate::tryToSend() {
DEBUG_LOG(("MTP Info: tryToSend for dc %1.").arg(_shiftedDcId)); DEBUG_LOG(("MTP Info: tryToSend for dc %1.").arg(_shiftedDcId));
if (!_connection) { if (!_connection) {
DEBUG_LOG(("MTP Info: not yet connected in dc %1.").arg(_shiftedDcId)); DEBUG_LOG(("MTP Info: not yet connected in dc %1.").arg(_shiftedDcId));
@ -591,10 +590,10 @@ void Connection::tryToSend() {
MTPInitConnection<SerializedRequest> initWrapper; MTPInitConnection<SerializedRequest> initWrapper;
int32 initSize = 0, initSizeInInts = 0; int32 initSize = 0, initSizeInInts = 0;
if (needsLayer) { if (needsLayer) {
Assert(_connectionOptions != nullptr); Assert(_options != nullptr);
const auto systemLangCode = _connectionOptions->systemLangCode; const auto systemLangCode = _options->systemLangCode;
const auto cloudLangCode = _connectionOptions->cloudLangCode; const auto cloudLangCode = _options->cloudLangCode;
const auto langPackName = _connectionOptions->langPackName; const auto langPackName = _options->langPackName;
const auto deviceModel = (_currentDcType == DcType::Cdn) const auto deviceModel = (_currentDcType == DcType::Cdn)
? "n/a" ? "n/a"
: _instance->deviceModel(); : _instance->deviceModel();
@ -610,12 +609,12 @@ void Connection::tryToSend() {
#else // OS_MAC_STORE || OS_WIN_STORE #else // OS_MAC_STORE || OS_WIN_STORE
const auto appVersion = QString::fromLatin1(AppVersionStr); const auto appVersion = QString::fromLatin1(AppVersionStr);
#endif // OS_MAC_STORE || OS_WIN_STORE #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 mtprotoProxy = (proxyType == ProxyData::Type::Mtproto);
const auto clientProxyFields = mtprotoProxy const auto clientProxyFields = mtprotoProxy
? MTP_inputClientProxy( ? MTP_inputClientProxy(
MTP_string(_connectionOptions->proxy.host), MTP_string(_options->proxy.host),
MTP_int(_connectionOptions->proxy.port)) MTP_int(_options->proxy.port))
: MTPInputClientProxy(); : MTPInputClientProxy();
using Flag = MTPInitConnection<SerializedRequest>::Flag; using Flag = MTPInitConnection<SerializedRequest>::Flag;
initWrapper = MTPInitConnection<SerializedRequest>( initWrapper = MTPInitConnection<SerializedRequest>(
@ -720,7 +719,7 @@ void Connection::tryToSend() {
auto wrappedRequest = SerializedRequest::Prepare(toSendSize); auto wrappedRequest = SerializedRequest::Prepare(toSendSize);
memcpy(wrappedRequest->data(), toSendRequest->constData(), 7 * sizeof(mtpPrime)); // all except length memcpy(wrappedRequest->data(), toSendRequest->constData(), 7 * sizeof(mtpPrime)); // all except length
wrappedRequest->push_back(mtpc_invokeWithLayer); wrappedRequest->push_back(mtpc_invokeWithLayer);
wrappedRequest->push_back(internal::CurrentLayer); wrappedRequest->push_back(kCurrentLayer);
initWrapper.write<mtpBuffer>(*wrappedRequest); initWrapper.write<mtpBuffer>(*wrappedRequest);
wrappedRequest->resize(wrappedRequest->size() + noWrapSize); wrappedRequest->resize(wrappedRequest->size() + noWrapSize);
memcpy(wrappedRequest->data() + wrappedRequest->size() - noWrapSize, toSendRequest->constData() + 8, noWrapSize * sizeof(mtpPrime)); memcpy(wrappedRequest->data() + wrappedRequest->size() - noWrapSize, toSendRequest->constData() + 8, noWrapSize * sizeof(mtpPrime));
@ -752,7 +751,7 @@ void Connection::tryToSend() {
if (willNeedInit) { if (willNeedInit) {
initSerialized.reserve(initSizeInInts); initSerialized.reserve(initSizeInInts);
initSerialized.push_back(mtpc_invokeWithLayer); initSerialized.push_back(mtpc_invokeWithLayer);
initSerialized.push_back(internal::CurrentLayer); initSerialized.push_back(kCurrentLayer);
initWrapper.write<mtpBuffer>(initSerialized); initWrapper.write<mtpBuffer>(initSerialized);
} }
// prepare container + each in invoke after // prepare container + each in invoke after
@ -879,7 +878,7 @@ void Connection::tryToSend() {
sendSecureRequest(std::move(toSendRequest), needAnyResponse); sendSecureRequest(std::move(toSendRequest), needAnyResponse);
} }
void Connection::retryByTimer() { void SessionPrivate::retryByTimer() {
if (_retryTimeout < 3) { if (_retryTimeout < 3) {
++_retryTimeout; ++_retryTimeout;
} else if (_retryTimeout == 3) { } else if (_retryTimeout == 3) {
@ -890,13 +889,13 @@ void Connection::retryByTimer() {
connectToServer(); connectToServer();
} }
void Connection::restartNow() { void SessionPrivate::restartNow() {
_retryTimeout = 1; _retryTimeout = 1;
_retryTimer.cancel(); _retryTimer.cancel();
restart(); restart();
} }
void Connection::connectToServer(bool afterConfig) { void SessionPrivate::connectToServer(bool afterConfig) {
if (afterConfig && (!_testConnections.empty() || _connection)) { if (afterConfig && (!_testConnections.empty() || _connection)) {
return; return;
} }
@ -908,8 +907,7 @@ void Connection::connectToServer(bool afterConfig) {
return; return;
} }
_connectionOptions = std::make_unique<ConnectionOptions>( _options = std::make_unique<SessionOptions>(_sessionData->options());
_sessionData->connectionOptions());
const auto bareDc = BareDcId(_shiftedDcId); const auto bareDc = BareDcId(_shiftedDcId);
@ -920,7 +918,7 @@ void Connection::connectToServer(bool afterConfig) {
return; 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. // host, port, secret for mtproto proxy are taken from proxy.
appendTestConnection(DcOptions::Variants::Tcp, {}, 0, {}); appendTestConnection(DcOptions::Variants::Tcp, {}, 0, {});
} else { } else {
@ -929,11 +927,11 @@ void Connection::connectToServer(bool afterConfig) {
const auto variants = _instance->dcOptions()->lookup( const auto variants = _instance->dcOptions()->lookup(
bareDc, bareDc,
_currentDcType, _currentDcType,
_connectionOptions->proxy.type != ProxyData::Type::None); _options->proxy.type != ProxyData::Type::None);
const auto useIPv4 = special ? true : _connectionOptions->useIPv4; const auto useIPv4 = special ? true : _options->useIPv4;
const auto useIPv6 = special ? false : _connectionOptions->useIPv6; const auto useIPv6 = special ? false : _options->useIPv6;
const auto useTcp = special ? true : _connectionOptions->useTcp; const auto useTcp = special ? true : _options->useTcp;
const auto useHttp = special ? false : _connectionOptions->useHttp; const auto useHttp = special ? false : _options->useHttp;
const auto skipAddress = !useIPv4 const auto skipAddress = !useIPv4
? Variants::IPv4 ? Variants::IPv4
: !useIPv6 : !useIPv6
@ -1001,7 +999,7 @@ void Connection::connectToServer(bool afterConfig) {
_waitForConnectedTimer.callOnce(_waitForConnected); _waitForConnectedTimer.callOnce(_waitForConnected);
} }
void Connection::restart() { void SessionPrivate::restart() {
DEBUG_LOG(("MTP Info: restarting Connection")); DEBUG_LOG(("MTP Info: restarting Connection"));
_waitForReceivedTimer.cancel(); _waitForReceivedTimer.cancel();
@ -1021,7 +1019,7 @@ void Connection::restart() {
setState(-_retryTimeout); setState(-_retryTimeout);
} }
void Connection::onSentSome(uint64 size) { void SessionPrivate::onSentSome(uint64 size) {
if (!_waitForReceivedTimer.isActive()) { if (!_waitForReceivedTimer.isActive()) {
auto remain = static_cast<uint64>(_waitForReceived); auto remain = static_cast<uint64>(_waitForReceived);
if (!_oldConnection) { if (!_oldConnection) {
@ -1042,7 +1040,7 @@ void Connection::onSentSome(uint64 size) {
if (!_firstSentAt) _firstSentAt = crl::now(); if (!_firstSentAt) _firstSentAt = crl::now();
} }
void Connection::onReceivedSome() { void SessionPrivate::onReceivedSome() {
if (_oldConnection) { if (_oldConnection) {
_oldConnection = false; _oldConnection = false;
DEBUG_LOG(("This connection marked as not old!")); DEBUG_LOG(("This connection marked as not old!"));
@ -1060,13 +1058,13 @@ void Connection::onReceivedSome() {
} }
} }
void Connection::markConnectionOld() { void SessionPrivate::markConnectionOld() {
_oldConnection = true; _oldConnection = true;
_waitForReceived = kMinReceiveTimeout; _waitForReceived = kMinReceiveTimeout;
DEBUG_LOG(("This connection marked as old! _waitForReceived now %1ms").arg(_waitForReceived)); DEBUG_LOG(("This connection marked as old! _waitForReceived now %1ms").arg(_waitForReceived));
} }
void Connection::sendPingByTimer() { void SessionPrivate::sendPingByTimer() {
if (_pingId) { if (_pingId) {
// _pingSendAt: when to send next ping (lastPingAt + kPingSendAfter) // _pingSendAt: when to send next ping (lastPingAt + kPingSendAfter)
// could be equal to zero. // 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)); DEBUG_LOG(("MTP Info: send ping force for dcWithShift %1.").arg(_shiftedDcId));
if (!_pingId) { if (!_pingId) {
_pingSendAt = 0; _pingSendAt = 0;
@ -1094,10 +1092,10 @@ void Connection::sendPingForce() {
} }
} }
void Connection::waitReceivedFailed() { void SessionPrivate::waitReceivedFailed() {
Expects(_connectionOptions != nullptr); Expects(_options != nullptr);
if (!_connectionOptions->useTcp) { if (!_options->useTcp) {
return; return;
} }
@ -1114,7 +1112,7 @@ void Connection::waitReceivedFailed() {
InvokeQueued(this, [=] { connectToServer(); }); InvokeQueued(this, [=] { connectToServer(); });
} }
void Connection::waitConnectedFailed() { void SessionPrivate::waitConnectedFailed() {
DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(_waitForConnected)); DEBUG_LOG(("MTP Info: can't connect in %1ms").arg(_waitForConnected));
auto maxTimeout = kMaxConnectedTimeout; auto maxTimeout = kMaxConnectedTimeout;
for (const auto &connection : _testConnections) { for (const auto &connection : _testConnections) {
@ -1130,29 +1128,29 @@ void Connection::waitConnectedFailed() {
InvokeQueued(this, [=] { connectToServer(); }); InvokeQueued(this, [=] { connectToServer(); });
} }
void Connection::waitBetterFailed() { void SessionPrivate::waitBetterFailed() {
confirmBestConnection(); confirmBestConnection();
} }
void Connection::connectingTimedOut() { void SessionPrivate::connectingTimedOut() {
for (const auto &connection : _testConnections) { for (const auto &connection : _testConnections) {
connection.data->timedOut(); connection.data->timedOut();
} }
doDisconnect(); doDisconnect();
} }
void Connection::doDisconnect() { void SessionPrivate::doDisconnect() {
destroyAllConnections(); destroyAllConnections();
setState(DisconnectedState); setState(DisconnectedState);
} }
void Connection::requestCDNConfig() { void SessionPrivate::requestCDNConfig() {
InvokeQueued(_instance, [instance = _instance] { InvokeQueued(_instance, [instance = _instance] {
instance->requestCDNConfig(); instance->requestCDNConfig();
}); });
} }
void Connection::handleReceived() { void SessionPrivate::handleReceived() {
Expects(_encryptionKey != nullptr); Expects(_encryptionKey != nullptr);
onReceivedSome(); onReceivedSome();
@ -1303,7 +1301,7 @@ void Connection::handleReceived() {
auto end = from + (messageLength / kIntSize); auto end = from + (messageLength / kIntSize);
auto sfrom = decryptedInts + 4U; // msg_id + seq_no + length + message auto sfrom = decryptedInts + 4U; // msg_id + seq_no + length + message
MTP_LOG(_shiftedDcId, ("Recv: ") MTP_LOG(_shiftedDcId, ("Recv: ")
+ details::DumpToText(sfrom, end) + DumpToText(sfrom, end)
+ QString(" (protocolDcId:%1,key:%2)" + QString(" (protocolDcId:%1,key:%2)"
).arg(getProtocolDcId() ).arg(getProtocolDcId()
).arg(_encryptionKey->keyId())); ).arg(_encryptionKey->keyId()));
@ -1352,7 +1350,7 @@ void Connection::handleReceived() {
} }
} }
Connection::HandleResult Connection::handleOneReceived( SessionPrivate::HandleResult SessionPrivate::handleOneReceived(
const mtpPrime *from, const mtpPrime *from,
const mtpPrime *end, const mtpPrime *end,
uint64 msgId, uint64 msgId,
@ -1733,7 +1731,7 @@ Connection::HandleResult Connection::handleOneReceived(
// the initConnection, so we're not sure yet that it was inited. // the initConnection, so we're not sure yet that it was inited.
// Wait till a good response is received. // Wait till a good response is received.
} else { } else {
_sessionData->notifyConnectionInited(*_connectionOptions); _sessionData->notifyConnectionInited(*_options);
} }
requestsAcked(ids, true); requestsAcked(ids, true);
@ -1850,7 +1848,7 @@ Connection::HandleResult Connection::handleOneReceived(
return HandleResult::Success; return HandleResult::Success;
} }
Connection::HandleResult Connection::handleBindResponse( SessionPrivate::HandleResult SessionPrivate::handleBindResponse(
mtpMsgId requestMsgId, mtpMsgId requestMsgId,
const mtpBuffer &response) { const mtpBuffer &response) {
if (!_keyCreator || !_bindMsgId || _bindMsgId != requestMsgId) { if (!_keyCreator || !_bindMsgId || _bindMsgId != requestMsgId) {
@ -1878,7 +1876,7 @@ Connection::HandleResult Connection::handleBindResponse(
Unexpected("Result of BoundKeyCreator::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 mtpBuffer result; // * 4 because of mtpPrime type
result.resize(0); result.resize(0);
@ -1930,7 +1928,7 @@ mtpBuffer Connection::ungzip(const mtpPrime *from, const mtpPrime *end) const {
return result; return result;
} }
bool Connection::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt) { bool SessionPrivate::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt) {
uint32 idsCount = ids.size(); uint32 idsCount = ids.size();
for (uint32 i = 0; i < idsCount; ++i) { for (uint32 i = 0; i < idsCount; ++i) {
@ -1945,7 +1943,7 @@ bool Connection::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTi
return false; return false;
} }
void Connection::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) { void SessionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) {
uint32 idsCount = ids.size(); uint32 idsCount = ids.size();
DEBUG_LOG(("Message Info: requests acked, ids %1").arg(LogIdsVector(ids))); DEBUG_LOG(("Message Info: requests acked, ids %1").arg(LogIdsVector(ids)));
@ -2027,7 +2025,7 @@ void Connection::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) {
} }
} }
void Connection::handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states) { void SessionPrivate::handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states) {
const auto idsCount = ids.size(); const auto idsCount = ids.size();
if (!idsCount) { if (!idsCount) {
DEBUG_LOG(("Message Info: void ids vector in handleMsgsStates()")); DEBUG_LOG(("Message Info: void ids vector in handleMsgsStates()"));
@ -2072,7 +2070,7 @@ void Connection::handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray
requestsAcked(acked); requestsAcked(acked);
} }
void Connection::clearSpecialMsgId(mtpMsgId msgId) { void SessionPrivate::clearSpecialMsgId(mtpMsgId msgId) {
if (msgId == _pingMsgId) { if (msgId == _pingMsgId) {
_pingMsgId = 0; _pingMsgId = 0;
_pingId = 0; _pingId = 0;
@ -2081,7 +2079,7 @@ void Connection::clearSpecialMsgId(mtpMsgId msgId) {
} }
} }
void Connection::resend( void SessionPrivate::resend(
mtpMsgId msgId, mtpMsgId msgId,
crl::time msCanWait, crl::time msCanWait,
bool forceContainer) { bool forceContainer) {
@ -2121,7 +2119,7 @@ void Connection::resend(
} }
} }
void Connection::resendAll() { void SessionPrivate::resendAll() {
auto lock = QWriteLocker(_sessionData->haveSentMutex()); auto lock = QWriteLocker(_sessionData->haveSentMutex());
auto haveSent = base::take(_sessionData->haveSentMap()); auto haveSent = base::take(_sessionData->haveSentMap());
lock.unlock(); lock.unlock();
@ -2141,7 +2139,7 @@ void Connection::resendAll() {
_sessionData->queueSendAnything(); _sessionData->queueSendAnything();
} }
void Connection::onConnected( void SessionPrivate::onConnected(
not_null<AbstractConnection*> connection) { not_null<AbstractConnection*> connection) {
disconnect(connection, &AbstractConnection::connected, nullptr, nullptr); disconnect(connection, &AbstractConnection::connected, nullptr, nullptr);
if (!connection->isConnected()) { if (!connection->isConnected()) {
@ -2175,7 +2173,7 @@ void Connection::onConnected(
} }
} }
void Connection::onDisconnected( void SessionPrivate::onDisconnected(
not_null<AbstractConnection*> connection) { not_null<AbstractConnection*> connection) {
removeTestConnection(connection); removeTestConnection(connection);
@ -2187,7 +2185,7 @@ void Connection::onDisconnected(
} }
} }
void Connection::confirmBestConnection() { void SessionPrivate::confirmBestConnection() {
if (_waitForBetterTimer.isActive()) { if (_waitForBetterTimer.isActive()) {
return; return;
} }
@ -2211,7 +2209,7 @@ void Connection::confirmBestConnection() {
checkAuthKey(); checkAuthKey();
} }
void Connection::removeTestConnection( void SessionPrivate::removeTestConnection(
not_null<AbstractConnection*> connection) { not_null<AbstractConnection*> connection) {
_testConnections.erase( _testConnections.erase(
ranges::remove( ranges::remove(
@ -2221,7 +2219,7 @@ void Connection::removeTestConnection(
end(_testConnections)); end(_testConnections));
} }
void Connection::checkAuthKey() { void SessionPrivate::checkAuthKey() {
if (_keyId) { if (_keyId) {
authKeyChecked(); authKeyChecked();
} else if (_instance->isKeysDestroyer()) { } else if (_instance->isKeysDestroyer()) {
@ -2232,7 +2230,7 @@ void Connection::checkAuthKey() {
} }
} }
void Connection::updateAuthKey() { void SessionPrivate::updateAuthKey() {
if (_instance->isKeysDestroyer() || _keyCreator || !_connection) { if (_instance->isKeysDestroyer() || _keyCreator || !_connection) {
return; return;
} }
@ -2250,7 +2248,7 @@ void Connection::updateAuthKey() {
} }
} }
void Connection::setCurrentKeyId(uint64 newKeyId) { void SessionPrivate::setCurrentKeyId(uint64 newKeyId) {
if (_keyId == newKeyId) { if (_keyId == newKeyId) {
return; return;
} }
@ -2260,7 +2258,7 @@ void Connection::setCurrentKeyId(uint64 newKeyId) {
changeSessionId(); changeSessionId();
} }
void Connection::applyAuthKey(AuthKeyPtr &&encryptionKey) { void SessionPrivate::applyAuthKey(AuthKeyPtr &&encryptionKey) {
_encryptionKey = std::move(encryptionKey); _encryptionKey = std::move(encryptionKey);
const auto newKeyId = _encryptionKey ? _encryptionKey->keyId() : 0; const auto newKeyId = _encryptionKey ? _encryptionKey->keyId() : 0;
if (_keyId) { if (_keyId) {
@ -2302,7 +2300,7 @@ void Connection::applyAuthKey(AuthKeyPtr &&encryptionKey) {
} }
} }
bool Connection::destroyOldEnoughPersistentKey() { bool SessionPrivate::destroyOldEnoughPersistentKey() {
Expects(_keyCreator != nullptr); Expects(_keyCreator != nullptr);
const auto key = _keyCreator->bindPersistentKey(); const auto key = _keyCreator->bindPersistentKey();
@ -2321,7 +2319,7 @@ bool Connection::destroyOldEnoughPersistentKey() {
return true; return true;
} }
DcType Connection::tryAcquireKeyCreation() { DcType SessionPrivate::tryAcquireKeyCreation() {
if (_keyCreator) { if (_keyCreator) {
return _currentDcType; return _currentDcType;
} else if (_instance->isKeysDestroyer()) { } else if (_instance->isKeysDestroyer()) {
@ -2395,7 +2393,7 @@ DcType Connection::tryAcquireKeyCreation() {
return forceUseRegular ? DcType::Regular : _realDcType; return forceUseRegular ? DcType::Regular : _realDcType;
} }
void Connection::authKeyChecked() { void SessionPrivate::authKeyChecked() {
connect(_connection, &AbstractConnection::receivedData, [=] { connect(_connection, &AbstractConnection::receivedData, [=] {
handleReceived(); handleReceived();
}); });
@ -2408,7 +2406,7 @@ void Connection::authKeyChecked() {
_sessionData->queueNeedToResumeAndSend(); _sessionData->queueNeedToResumeAndSend();
} }
void Connection::onError( void SessionPrivate::onError(
not_null<AbstractConnection*> connection, not_null<AbstractConnection*> connection,
qint32 errorCode) { qint32 errorCode) {
if (errorCode == -429) { if (errorCode == -429) {
@ -2428,7 +2426,7 @@ void Connection::onError(
} }
} }
void Connection::handleError(int errorCode) { void SessionPrivate::handleError(int errorCode) {
destroyAllConnections(); destroyAllConnections();
_waitForConnectedTimer.cancel(); _waitForConnectedTimer.cancel();
@ -2440,7 +2438,7 @@ void Connection::handleError(int errorCode) {
} }
} }
void Connection::destroyTemporaryKey() { void SessionPrivate::destroyTemporaryKey() {
if (_instance->isKeysDestroyer()) { if (_instance->isKeysDestroyer()) {
LOG(("MTP Info: -404 error received in destroyer %1, assuming key was destroyed.").arg(_shiftedDcId)); LOG(("MTP Info: -404 error received in destroyer %1, assuming key was destroyed.").arg(_shiftedDcId));
_instance->keyWasPossiblyDestroyed(_shiftedDcId); _instance->keyWasPossiblyDestroyed(_shiftedDcId);
@ -2455,7 +2453,7 @@ void Connection::destroyTemporaryKey() {
restart(); restart();
} }
bool Connection::sendSecureRequest( bool SessionPrivate::sendSecureRequest(
SerializedRequest &&request, SerializedRequest &&request,
bool needAnyResponse) { bool needAnyResponse) {
#ifdef TDESKTOP_MTPROTO_OLD #ifdef TDESKTOP_MTPROTO_OLD
@ -2480,7 +2478,7 @@ bool Connection::sendSecureRequest(
auto from = request->constData() + 4; auto from = request->constData() + 4;
MTP_LOG(_shiftedDcId, ("Send: ") MTP_LOG(_shiftedDcId, ("Send: ")
+ details::DumpToText(from, from + messageSize) + DumpToText(from, from + messageSize)
+ QString(" (protocolDcId:%1,key:%2)" + QString(" (protocolDcId:%1,key:%2)"
).arg(getProtocolDcId() ).arg(getProtocolDcId()
).arg(_encryptionKey->keyId())); ).arg(_encryptionKey->keyId()));
@ -2539,7 +2537,7 @@ bool Connection::sendSecureRequest(
return true; return true;
} }
mtpRequestId Connection::wasSent(mtpMsgId msgId) const { mtpRequestId SessionPrivate::wasSent(mtpMsgId msgId) const {
if (msgId == _pingMsgId || msgId == _bindMsgId) { if (msgId == _pingMsgId || msgId == _bindMsgId) {
return mtpRequestId(0xFFFFFFFF); return mtpRequestId(0xFFFFFFFF);
} }
@ -2566,13 +2564,13 @@ mtpRequestId Connection::wasSent(mtpMsgId msgId) const {
return 0; return 0;
} }
void Connection::clearUnboundKeyCreator() { void SessionPrivate::clearUnboundKeyCreator() {
if (_keyCreator) { if (_keyCreator) {
_keyCreator->stop(); _keyCreator->stop();
} }
} }
void Connection::releaseKeyCreationOnFail() { void SessionPrivate::releaseKeyCreationOnFail() {
if (!_keyCreator) { if (!_keyCreator) {
return; return;
} }
@ -2580,5 +2578,5 @@ void Connection::releaseKeyCreationOnFail() {
_sessionData->releaseKeyCreationOnFail(); _sessionData->releaseKeyCreationOnFail();
} }
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -21,26 +21,23 @@ namespace details {
class BoundKeyCreator; class BoundKeyCreator;
} // namespace details } // namespace details
// How much time to wait for some more requests, when sending msg acks.
constexpr auto kAckSendWaiting = 10 * crl::time(1000);
class Instance; class Instance;
namespace internal { namespace details {
class AbstractConnection; class AbstractConnection;
class SessionData; class SessionData;
class RSAPublicKey; class RSAPublicKey;
struct ConnectionOptions; struct SessionOptions;
class Connection : public QObject { class SessionPrivate final : public QObject {
public: public:
Connection( SessionPrivate(
not_null<Instance*> instance, not_null<Instance*> instance,
not_null<QThread*> thread, not_null<QThread*> thread,
std::shared_ptr<SessionData> data, std::shared_ptr<SessionData> data,
ShiftedDcId shiftedDcId); ShiftedDcId shiftedDcId);
~Connection(); ~SessionPrivate();
[[nodiscard]] int32 getShiftedDcId() const; [[nodiscard]] int32 getShiftedDcId() const;
void dcOptionsChanged(); void dcOptionsChanged();
@ -106,20 +103,20 @@ private:
void clearOldContainers(); void clearOldContainers();
mtpMsgId placeToContainer( mtpMsgId placeToContainer(
details::SerializedRequest &toSendRequest, SerializedRequest &toSendRequest,
mtpMsgId &bigMsgId, mtpMsgId &bigMsgId,
bool forceNewMsgId, bool forceNewMsgId,
details::SerializedRequest &req); SerializedRequest &req);
mtpMsgId prepareToSend( mtpMsgId prepareToSend(
details::SerializedRequest &request, SerializedRequest &request,
mtpMsgId currentLastId, mtpMsgId currentLastId,
bool forceNewMsgId); bool forceNewMsgId);
mtpMsgId replaceMsgId( mtpMsgId replaceMsgId(
details::SerializedRequest &request, SerializedRequest &request,
mtpMsgId newId); mtpMsgId newId);
bool sendSecureRequest( bool sendSecureRequest(
details::SerializedRequest &&request, SerializedRequest &&request,
bool needAnyResponse); bool needAnyResponse);
mtpRequestId wasSent(mtpMsgId msgId) const; mtpRequestId wasSent(mtpMsgId msgId) const;
@ -205,7 +202,7 @@ private:
base::Timer _checkSentRequestsTimer; base::Timer _checkSentRequestsTimer;
std::shared_ptr<SessionData> _sessionData; std::shared_ptr<SessionData> _sessionData;
std::unique_ptr<ConnectionOptions> _connectionOptions; std::unique_ptr<SessionOptions> _options;
AuthKeyPtr _encryptionKey; AuthKeyPtr _encryptionKey;
uint64 _keyId = 0; uint64 _keyId = 0;
uint64 _sessionId = 0; uint64 _sessionId = 0;
@ -216,16 +213,16 @@ private:
QVector<MTPlong> _ackRequestData; QVector<MTPlong> _ackRequestData;
QVector<MTPlong> _resendRequestData; QVector<MTPlong> _resendRequestData;
base::flat_set<mtpMsgId> _stateRequestData; base::flat_set<mtpMsgId> _stateRequestData;
details::ReceivedIdsManager _receivedMessageIds; ReceivedIdsManager _receivedMessageIds;
base::flat_map<mtpMsgId, mtpRequestId> _resendingIds; base::flat_map<mtpMsgId, mtpRequestId> _resendingIds;
base::flat_map<mtpMsgId, mtpRequestId> _ackedIds; base::flat_map<mtpMsgId, mtpRequestId> _ackedIds;
base::flat_map<mtpMsgId, details::SerializedRequest> _stateAndResendRequests; base::flat_map<mtpMsgId, SerializedRequest> _stateAndResendRequests;
base::flat_map<mtpMsgId, SentContainer> _sentContainers; base::flat_map<mtpMsgId, SentContainer> _sentContainers;
std::unique_ptr<details::BoundKeyCreator> _keyCreator; std::unique_ptr<BoundKeyCreator> _keyCreator;
mtpMsgId _bindMsgId = 0; mtpMsgId _bindMsgId = 0;
}; };
} // namespace internal } // namespace details
} // namespace MTP } // namespace MTP

View File

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/special_config_request.h" #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/dc_options.h"
#include "mtproto/mtproto_auth_key.h" #include "mtproto/mtproto_auth_key.h"
#include "base/unixtime.h" #include "base/unixtime.h"
@ -19,16 +19,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QJsonArray> #include <QtCore/QJsonArray>
#include <QtCore/QJsonObject> #include <QtCore/QJsonObject>
extern "C" { namespace MTP::details {
#include <openssl/aes.h>
} // extern "C"
namespace MTP {
namespace { namespace {
constexpr auto kSendNextTimeout = crl::time(800); 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("\ constexpr auto kPublicKey = str_const("\
-----BEGIN RSA PUBLIC KEY-----\n\ -----BEGIN RSA PUBLIC KEY-----\n\
@ -41,9 +35,6 @@ Y1hZCxdv6cs5UnW9+PWvS+WIbkh+GaWYxwIDAQAB\n\
-----END RSA PUBLIC KEY-----\ -----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 kRemoteProject = "peak-vista-421";
const auto kFireProject = "reserve-5a846"; const auto kFireProject = "reserve-5a846";
const auto kConfigKey = "ipconfig"; const auto kConfigKey = "ipconfig";
@ -51,21 +42,6 @@ const auto kConfigSubKey = "v3";
const auto kApiKey = "AIzaSyC2-kAkpDsroixRXw-sTw-Wfqo4NxjMwwM"; const auto kApiKey = "AIzaSyC2-kAkpDsroixRXw-sTw-Wfqo4NxjMwwM";
const auto kAppId = "1:560508485281:web:4ee13a6af4e84d49e67ae0"; const auto kAppId = "1:560508485281:web:4ee13a6af4e84d49e67ae0";
struct DnsEntry {
QString data;
crl::time TTL = 0;
};
const std::vector<QString> &DnsDomains() {
static auto result = std::vector<QString>{
qsl("google.com"),
qsl("www.google.com"),
qsl("google.ru"),
qsl("www.google.ru"),
};
return result;
}
QString ApiDomain(const QString &service) { QString ApiDomain(const QString &service) {
return service + ".googleapis.com"; return service + ".googleapis.com";
} }
@ -103,99 +79,6 @@ bool CheckPhoneByPrefixesRules(const QString &phone, const QString &rules) {
return result; 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<uchar>() / 2);
Assert(result <= kMaxPadding);
if (result >= kMinPadding) {
return result;
}
}
}();
result.resize(count);
for (auto &ch : result) {
ch = kValid[rand_value<uchar>() % (sizeof(kValid) - 1)];
}
return result;
}
std::vector<DnsEntry> ParseDnsResponse(
const QByteArray &bytes,
std::optional<int> 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<DnsEntry>();
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<DnsEntry> &response) { QByteArray ConcatenateDnsTxtFields(const std::vector<DnsEntry> &response) {
auto entries = QMap<int, QString>(); auto entries = QMap<int, QString>();
for (const auto &entry : response) { for (const auto &entry : response) {
@ -299,40 +182,6 @@ QByteArray ParseRealtimeResponse(const QByteArray &bytes) {
} // namespace } // namespace
ServiceWebRequest::ServiceWebRequest(not_null<QNetworkReply*> 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( SpecialConfigRequest::SpecialConfigRequest(
Fn<void( Fn<void(
DcId dcId, DcId dcId,
@ -435,7 +284,7 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) {
url.setPath(qsl("/dns-query")); url.setPath(qsl("/dns-query"));
url.setQuery(qsl("name=%1&type=16&random_padding=%2" url.setQuery(qsl("name=%1&type=16&random_padding=%2"
).arg(Global::TxtDomainString() ).arg(Global::TxtDomainString()
).arg(GenerateRandomPadding())); ).arg(GenerateDnsRandomPadding()));
request.setRawHeader("accept", "application/dns-json"); request.setRawHeader("accept", "application/dns-json");
} break; } break;
case Type::Google: { case Type::Google: {
@ -443,7 +292,7 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) {
url.setPath(qsl("/resolve")); url.setPath(qsl("/resolve"));
url.setQuery(qsl("name=%1&type=ANY&random_padding=%2" url.setQuery(qsl("name=%1&type=ANY&random_padding=%2"
).arg(Global::TxtDomainString() ).arg(Global::TxtDomainString()
).arg(GenerateRandomPadding())); ).arg(GenerateDnsRandomPadding()));
if (!attempt.host.isEmpty()) { if (!attempt.host.isEmpty()) {
const auto host = attempt.host + ".google.com"; const auto host = attempt.host + ".google.com";
request.setRawHeader("Host", host.toLatin1()); request.setRawHeader("Host", host.toLatin1());
@ -479,7 +328,7 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) {
default: Unexpected("Type in SpecialConfigRequest::performRequest."); default: Unexpected("Type in SpecialConfigRequest::performRequest.");
} }
request.setUrl(url); request.setUrl(url);
request.setRawHeader("User-Agent", kUserAgent); request.setRawHeader("User-Agent", DnsUserAgent());
const auto reply = _requests.emplace_back(payload.isEmpty() const auto reply = _requests.emplace_back(payload.isEmpty()
? _manager.get(request) ? _manager.get(request)
: _manager.post(request, payload) : _manager.post(request, payload)
@ -587,7 +436,7 @@ bool SpecialConfigRequest::decryptSimpleConfig(const QByteArray &bytes) {
return false; return false;
} }
auto publicKey = internal::RSAPublicKey(bytes::make_span( auto publicKey = details::RSAPublicKey(bytes::make_span(
kPublicKey.c_str(), kPublicKey.c_str(),
kPublicKey.size())); kPublicKey.size()));
auto decrypted = publicKey.decrypt(bytes::make_span(decodedBytes)); auto decrypted = publicKey.decrypt(bytes::make_span(decodedBytes));
@ -693,190 +542,4 @@ void SpecialConfigRequest::handleResponse(const QByteArray &bytes) {
_callback(0, std::string(), 0, {}); _callback(0, std::string(), 0, {});
} }
DomainResolver::DomainResolver(Fn<void( } // namespace MTP::details
const QString &host,
const QStringList &ips,
crl::time expireAt)> 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<Attempt>();
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<ServiceWebRequest>()).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<QNetworkReply*> 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<QNetworkReply*> 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

View File

@ -7,24 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "mtproto/details/mtproto_domain_resolver.h"
#include "base/bytes.h" #include "base/bytes.h"
#include "base/weak_ptr.h"
#include <QtCore/QPointer>
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkAccessManager>
namespace MTP { namespace MTP::details {
struct ServiceWebRequest {
ServiceWebRequest(not_null<QNetworkReply*> reply);
ServiceWebRequest(ServiceWebRequest &&other);
ServiceWebRequest &operator=(ServiceWebRequest &&other);
~ServiceWebRequest();
void destroy();
QPointer<QNetworkReply> reply;
};
class SpecialConfigRequest : public QObject { class SpecialConfigRequest : public QObject {
public: public:
@ -83,71 +74,4 @@ private:
}; };
class DomainResolver : public QObject { } // namespace MTP::details
public:
DomainResolver(Fn<void(
const QString &domain,
const QStringList &ips,
crl::time expireAt)> 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<Attempt> 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<QNetworkReply*> reply);
QByteArray finalizeRequest(
const AttemptKey &key,
not_null<QNetworkReply*> reply);
Fn<void(
const QString &domain,
const QStringList &ips,
crl::time expireAt)> _callback;
QNetworkAccessManager _manager;
std::map<AttemptKey, Attempts> _attempts;
std::map<AttemptKey, std::vector<ServiceWebRequest>> _requests;
std::map<AttemptKey, CacheEntry> _cache;
crl::time _lastTimestamp = 0;
};
} // namespace MTP

View File

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "passport/passport_encryption.h" #include "passport/passport_encryption.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"
#include "mtproto/mtproto_rsa_public_key.h" #include "mtproto/details/mtproto_rsa_public_key.h"
#include <QtCore/QJsonDocument> #include <QtCore/QJsonDocument>
#include <QtCore/QJsonArray> #include <QtCore/QJsonArray>
@ -429,7 +429,7 @@ uint64 CountSecureSecretId(bytes::const_span secret) {
bytes::vector EncryptCredentialsSecret( bytes::vector EncryptCredentialsSecret(
bytes::const_span secret, bytes::const_span secret,
bytes::const_span publicKey) { bytes::const_span publicKey) {
const auto key = MTP::internal::RSAPublicKey(publicKey); const auto key = MTP::details::RSAPublicKey(publicKey);
return key.encryptOAEPpadding(secret); return key.encryptOAEPpadding(secret);
} }

View File

@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "platform/platform_file_utilities.h" #include "platform/platform_file_utilities.h"
#include "mtproto/connection.h" // for MTP::kAckSendWaiting
#include "main/main_session.h" #include "main/main_session.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "core/crash_reports.h" #include "core/crash_reports.h"
@ -28,7 +27,7 @@ namespace Storage {
namespace { namespace {
// How much time without download causes additional session kill. // 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. // Max 16 file parts downloaded at the same time, 128 KB each.
constexpr auto kMaxFileQueries = 16; constexpr auto kMaxFileQueries = 16;
@ -75,11 +74,10 @@ void Downloader::killDownloadSessionsStart(MTP::DcId dcId) {
if (!_killDownloadSessionTimes.contains(dcId)) { if (!_killDownloadSessionTimes.contains(dcId)) {
_killDownloadSessionTimes.emplace( _killDownloadSessionTimes.emplace(
dcId, dcId,
crl::now() + MTP::kAckSendWaiting + kKillSessionTimeout); crl::now() + kKillSessionTimeout);
} }
if (!_killDownloadSessionsTimer.isActive()) { if (!_killDownloadSessionsTimer.isActive()) {
_killDownloadSessionsTimer.callOnce( _killDownloadSessionsTimer.callOnce(kKillSessionTimeout + 5);
MTP::kAckSendWaiting + kKillSessionTimeout + 5);
} }
} }
@ -92,16 +90,17 @@ void Downloader::killDownloadSessionsStop(MTP::DcId dcId) {
} }
void Downloader::killDownloadSessions() { 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(); ) { for (auto i = _killDownloadSessionTimes.begin(); i != _killDownloadSessionTimes.end(); ) {
if (i->second <= ms) { if (i->second <= now) {
for (int j = 0; j < MTP::kDownloadSessionsCount; ++j) { for (int j = 0; j < MTP::kDownloadSessionsCount; ++j) {
MTP::stopSession(MTP::downloadDcId(i->first, j)); MTP::stopSession(MTP::downloadDcId(i->first, j));
} }
i = _killDownloadSessionTimes.erase(i); i = _killDownloadSessionTimes.erase(i);
} else { } else {
if (i->second - ms < left) { if (i->second - now < left) {
left = i->second - ms; left = i->second - now;
} }
++i; ++i;
} }

View File

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localimageloader.h" #include "storage/localimageloader.h"
#include "storage/file_download.h" #include "storage/file_download.h"
#include "mtproto/connection.h" // for MTP::kAckSendWaiting
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_photo.h" #include "data/data_photo.h"
#include "data/data_session.h" #include "data/data_session.h"
@ -42,7 +41,7 @@ constexpr auto kDocumentUploadPartSize4 = 512 * 1024;
constexpr auto kUploadRequestInterval = crl::time(500); constexpr auto kUploadRequestInterval = crl::time(500);
// How much time without upload causes additional session kill. // How much time without upload causes additional session kill.
constexpr auto kKillSessionTimeout = crl::time(5000); constexpr auto kKillSessionTimeout = 15 * crl::time(000);
} // namespace } // namespace
@ -256,8 +255,7 @@ void Uploader::sendNext() {
bool stopping = stopSessionsTimer.isActive(); bool stopping = stopSessionsTimer.isActive();
if (queue.empty()) { if (queue.empty()) {
if (!stopping) { if (!stopping) {
stopSessionsTimer.start( stopSessionsTimer.start(kKillSessionTimeout);
MTP::kAckSendWaiting + kKillSessionTimeout);
} }
return; return;
} }

View File

@ -34,34 +34,40 @@
'<(src_loc)', '<(src_loc)',
], ],
'sources': [ '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.cpp',
'<(src_loc)/mtproto/details/mtproto_bound_key_creator.h', '<(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.cpp',
'<(src_loc)/mtproto/details/mtproto_dc_key_binder.h', '<(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.cpp',
'<(src_loc)/mtproto/details/mtproto_dc_key_creator.h', '<(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.cpp',
'<(src_loc)/mtproto/details/mtproto_dump_to_text.h', '<(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.cpp',
'<(src_loc)/mtproto/details/mtproto_received_ids_manager.h', '<(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.cpp',
'<(src_loc)/mtproto/details/mtproto_serialized_request.h', '<(src_loc)/mtproto/details/mtproto_serialized_request.h',
'<(src_loc)/mtproto/mtproto_abstract_socket.cpp', '<(src_loc)/mtproto/details/mtproto_tcp_socket.cpp',
'<(src_loc)/mtproto/mtproto_abstract_socket.h', '<(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.cpp',
'<(src_loc)/mtproto/mtproto_auth_key.h', '<(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.cpp',
'<(src_loc)/mtproto/mtproto_dh_utils.h', '<(src_loc)/mtproto/mtproto_dh_utils.h',
'<(src_loc)/mtproto/mtproto_proxy_data.cpp', '<(src_loc)/mtproto/mtproto_proxy_data.cpp',
'<(src_loc)/mtproto/mtproto_proxy_data.h', '<(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.cpp',
'<(src_loc)/mtproto/mtproto_rpc_sender.h', '<(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',
], ],
}], }],
} }

View File

@ -537,12 +537,8 @@
<(src_loc)/media/view/media_view_group_thumbs.h <(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.cpp
<(src_loc)/media/view/media_view_overlay_widget.h <(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.cpp
<(src_loc)/mtproto/config_loader.h <(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.cpp
<(src_loc)/mtproto/connection_abstract.h <(src_loc)/mtproto/connection_abstract.h
<(src_loc)/mtproto/connection_http.cpp <(src_loc)/mtproto/connection_http.cpp
@ -552,8 +548,6 @@
<(src_loc)/mtproto/connection_tcp.cpp <(src_loc)/mtproto/connection_tcp.cpp
<(src_loc)/mtproto/connection_tcp.h <(src_loc)/mtproto/connection_tcp.h
<(src_loc)/mtproto/core_types.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.cpp
<(src_loc)/mtproto/dc_options.h <(src_loc)/mtproto/dc_options.h
<(src_loc)/mtproto/dedicated_file_loader.cpp <(src_loc)/mtproto/dedicated_file_loader.cpp
@ -565,6 +559,8 @@
<(src_loc)/mtproto/sender.h <(src_loc)/mtproto/sender.h
<(src_loc)/mtproto/session.cpp <(src_loc)/mtproto/session.cpp
<(src_loc)/mtproto/session.h <(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.cpp
<(src_loc)/mtproto/special_config_request.h <(src_loc)/mtproto/special_config_request.h
<(src_loc)/mtproto/type_utils.h <(src_loc)/mtproto/type_utils.h

@ -1 +1 @@
Subproject commit 13918d5b5c4611ef1563a13ac1daf4d2c77c5f49 Subproject commit 10cddc61a6c5b6cd896ba014fc187d15f5267be3