mirror of https://github.com/procxx/kepka.git
Move some more code to lib_mtproto.
This commit is contained in:
parent
718de09aa6
commit
91f50e8bdc
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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()
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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',
|
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue