diff --git a/Telegram/Resources/scheme.tl b/Telegram/Resources/scheme.tl index 7f357c3a51..f5796d78ef 100644 --- a/Telegram/Resources/scheme.tl +++ b/Telegram/Resources/scheme.tl @@ -107,8 +107,13 @@ new_session_created#9ec20908 first_msg_id:long unique_id:long server_salt:long = http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait; -ipPort ipv4:int port:int = IpPort; -help.configSimple#d997c3c5 date:int expires:int dc_id:int ip_port_list:Vector = help.ConfigSimple; +//ipPort ipv4:int port:int = IpPort; +//help.configSimple#d997c3c5 date:int expires:int dc_id:int ip_port_list:Vector = help.ConfigSimple; + +ipPort#d433ad73 ipv4:int port:int = IpPort; +ipPortSecret#37982646 ipv4:int port:int secret:bytes = IpPort; +accessPointRule#4679b65f phone_prefix_rules:string dc_id:int ips:vector = AccessPointRule; +help.configSimple#5a592a6c date:int expires:int rules:vector = help.ConfigSimple; ---functions--- diff --git a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py index 80de3beea0..f5d1a3a170 100644 --- a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py +++ b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py @@ -57,6 +57,9 @@ parentFlagsCheck = {}; countedTypeIdExceptions = {}; countedTypeIdExceptions[77] = countedTypeIdExceptions[78] = {} countedTypeIdExceptions[77]['channel'] = countedTypeIdExceptions[78]['channel'] = True +countedTypeIdExceptions['ipPortSecret'] = True +countedTypeIdExceptions['accessPointRule'] = True +countedTypeIdExceptions['help_configSimple'] = True lines = []; layer = ''; @@ -143,8 +146,9 @@ for line in lines: typeid = '0x' + typeid; if (typeid != countTypeId): if (not layerIndex in countedTypeIdExceptions or not name in countedTypeIdExceptions[layerIndex]): - print('Warning: counted ' + countTypeId + ' mismatch with provided ' + typeid + ' (' + cleanline + ')'); - continue; + if (not name in countedTypeIdExceptions): + print('Warning: counted ' + countTypeId + ' mismatch with provided ' + typeid + ' (' + cleanline + ')'); + continue; else: typeid = countTypeId; @@ -519,7 +523,9 @@ def addTextSerialize(lst, dct, dataLetter): if (not vtypeget): result += '); vtypes.push_back(0'; else: - result += '0); vtypes.push_back(0'; + if (not vtypeget): + result += '0'; + result += '); vtypes.push_back(0'; result += '); stages.push_back(0); flags.push_back(0); '; if (k in conditions): result += '} else { to.add("[ SKIPPED BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); } '; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 9422397296..469ad4e218 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -435,7 +435,11 @@ void UserData::setName(const QString &newFirstName, const QString &newLastName, } void UserData::setPhone(const QString &newPhone) { - _phone = newPhone; + if (_phone != newPhone) { + _phone = newPhone; + if (bareId() == Auth().userId()) { + } + } } void UserData::setBotInfoVersion(int version) { diff --git a/Telegram/SourceFiles/messenger.cpp b/Telegram/SourceFiles/messenger.cpp index 15c31a7b27..738819d440 100644 --- a/Telegram/SourceFiles/messenger.cpp +++ b/Telegram/SourceFiles/messenger.cpp @@ -390,7 +390,11 @@ void Messenger::setMtpAuthorization(const QByteArray &serialized) { void Messenger::startMtp() { Expects(!_mtproto); - _mtproto = std::make_unique(_dcOptions.get(), MTP::Instance::Mode::Normal, base::take(_private->mtpConfig)); + _mtproto = std::make_unique( + _dcOptions.get(), + MTP::Instance::Mode::Normal, + base::take(_private->mtpConfig)); + _mtproto->setUserPhone(cLoggedPhoneNumber()); _private->mtpConfig.mainDcId = _mtproto->mainDcId(); _mtproto->setStateChangedHandler([](MTP::ShiftedDcId shiftedDcId, int32 state) { @@ -489,6 +493,20 @@ void Messenger::startLocalStorage() { } }); }); + subscribe(Global::RefSelfChanged(), [=] { + InvokeQueued(this, [=] { + const auto phone = App::self() + ? App::self()->phone() + : QString(); + if (cLoggedPhoneNumber() != phone) { + cSetLoggedPhoneNumber(phone); + if (_mtproto) { + _mtproto->setUserPhone(phone); + } + Local::writeSettings(); + } + }); + }); } void Messenger::regPhotoUpdate(const PeerId &peer, const FullMsgId &msgId) { diff --git a/Telegram/SourceFiles/mtproto/config_loader.cpp b/Telegram/SourceFiles/mtproto/config_loader.cpp index 4caa94a0f5..eddde21d46 100644 --- a/Telegram/SourceFiles/mtproto/config_loader.cpp +++ b/Telegram/SourceFiles/mtproto/config_loader.cpp @@ -22,9 +22,11 @@ constexpr auto kSpecialRequestTimeoutMs = 6000; // 4 seconds timeout for it to w ConfigLoader::ConfigLoader( not_null instance, + const QString &phone, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail) : _instance(instance) +, _phone(phone) , _doneHandler(onDone) , _failHandler(onFail) { _enumDCTimer.setCallback([this] { enumerate(); }); @@ -96,24 +98,51 @@ void ConfigLoader::enumerate() { _enumDCTimer.callOnce(kEnumerateDcTimeout); - createSpecialLoader(); + refreshSpecialLoader(); } -void ConfigLoader::createSpecialLoader() { +void ConfigLoader::refreshSpecialLoader() { if (Global::UseProxy()) { _specialLoader.reset(); return; } - if (!_specialLoader || (!_specialEnumRequest && _specialEndpoints.empty())) { - _specialLoader = std::make_unique([this](DcId dcId, const std::string &ip, int port) { - addSpecialEndpoint(dcId, ip, port); - }); - _triedSpecialEndpoints.clear(); + if (!_specialLoader + || (!_specialEnumRequest && _specialEndpoints.empty())) { + createSpecialLoader(); } } -void ConfigLoader::addSpecialEndpoint(DcId dcId, const std::string &ip, int port) { - auto endpoint = SpecialEndpoint { dcId, ip, port }; +void ConfigLoader::setPhone(const QString &phone) { + if (_phone != phone) { + _phone = phone; + if (_specialLoader) { + createSpecialLoader(); + } + } +} + +void ConfigLoader::createSpecialLoader() { + _triedSpecialEndpoints.clear(); + _specialLoader = std::make_unique([=]( + DcId dcId, + const std::string &ip, + int port, + bytes::const_span secret) { + addSpecialEndpoint(dcId, ip, port, secret); + }, _phone); +} + +void ConfigLoader::addSpecialEndpoint( + DcId dcId, + const std::string &ip, + int port, + bytes::const_span secret) { + auto endpoint = SpecialEndpoint { + dcId, + ip, + port, + bytes::make_vector(secret) + }; if (base::contains(_specialEndpoints, endpoint) || base::contains(_triedSpecialEndpoints, endpoint)) { return; @@ -133,7 +162,7 @@ void ConfigLoader::sendSpecialRequest() { return; } if (_specialEndpoints.empty()) { - createSpecialLoader(); + refreshSpecialLoader(); return; } diff --git a/Telegram/SourceFiles/mtproto/config_loader.h b/Telegram/SourceFiles/mtproto/config_loader.h index 1728853e2b..923dc2e256 100644 --- a/Telegram/SourceFiles/mtproto/config_loader.h +++ b/Telegram/SourceFiles/mtproto/config_loader.h @@ -21,16 +21,26 @@ namespace internal { class ConfigLoader : public base::has_weak_ptr { public: - ConfigLoader(not_null instance, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail); + ConfigLoader( + not_null instance, + const QString &phone, + RPCDoneHandlerPtr onDone, + RPCFailHandlerPtr onFail); ~ConfigLoader(); void load(); + void setPhone(const QString &phone); private: mtpRequestId sendRequest(ShiftedDcId shiftedDcId); - void addSpecialEndpoint(DcId dcId, const std::string &ip, int port); + void addSpecialEndpoint( + DcId dcId, + const std::string &ip, + int port, + bytes::const_span secret); void sendSpecialRequest(); void enumerate(); + void refreshSpecialLoader(); void createSpecialLoader(); DcId specialToRealDcId(DcId specialDcId); void specialConfigLoaded(const MTPConfig &result); @@ -55,6 +65,7 @@ private: base::Timer _specialEnumTimer; DcId _specialEnumCurrent = 0; mtpRequestId _specialEnumRequest = 0; + QString _phone; RPCDoneHandlerPtr _doneHandler; RPCFailHandlerPtr _failHandler; diff --git a/Telegram/SourceFiles/mtproto/connection.cpp b/Telegram/SourceFiles/mtproto/connection.cpp index 77f6592b50..abf263f201 100644 --- a/Telegram/SourceFiles/mtproto/connection.cpp +++ b/Telegram/SourceFiles/mtproto/connection.cpp @@ -388,9 +388,13 @@ void ConnectionPrivate::appendTestConnection( onDisconnected(weak); }); + const auto dcId = MTP::bareDcId(_shiftedDcId); + const auto simpleDcId = MTP::isTemporaryDcId(dcId) + ? MTP::getRealIdFromTemporaryDcId(dcId) + : dcId; const auto protocolDcId = (_dcType == DcType::MediaDownload) - ? -MTP::bareDcId(_shiftedDcId) - : MTP::bareDcId(_shiftedDcId); + ? -simpleDcId + : simpleDcId; InvokeQueued(_testConnections.back().data, [=] { weak->connectToServer(ip, port, protocolSecret, protocolDcId); }); diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 042c0b248a..3a1609556d 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -48,6 +48,7 @@ public: void requestConfig(); void requestConfigIfOld(); void requestCDNConfig(); + void setUserPhone(const QString &phone); void restart(); void restart(ShiftedDcId shiftedDcId); @@ -156,6 +157,7 @@ private: base::set_of_unique_ptr _quittingConnections; std::unique_ptr _configLoader; + QString _userPhone; mtpRequestId _cdnConfigLoadRequestId = 0; TimeMs _lastConfigLoadedTime = 0; @@ -283,14 +285,23 @@ void Instance::Private::requestConfig() { if (_configLoader || isKeysDestroyer()) { return; } - _configLoader = std::make_unique(_instance, rpcDone([this](const MTPConfig &result) { - configLoadDone(result); - }), rpcFail([this](const RPCError &error) { - return configLoadFail(error); - })); + _configLoader = std::make_unique( + _instance, + _userPhone, + rpcDone([=](const MTPConfig &result) { configLoadDone(result); }), + rpcFail([=](const RPCError &error) { return configLoadFail(error); })); _configLoader->load(); } +void Instance::Private::setUserPhone(const QString &phone) { + if (_userPhone != phone) { + _userPhone = phone; + if (_configLoader) { + _configLoader->setPhone(_userPhone); + } + } +} + void Instance::Private::requestConfigIfOld() { if (getms(true) - _lastConfigLoadedTime >= kConfigBecomesOldIn) { requestConfig(); @@ -1318,6 +1329,10 @@ void Instance::requestConfig() { _private->requestConfig(); } +void Instance::setUserPhone(const QString &phone) { + _private->setUserPhone(phone); +} + void Instance::requestConfigIfOld() { _private->requestConfigIfOld(); } diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.h b/Telegram/SourceFiles/mtproto/mtp_instance.h index c4929055f5..0e0d3e9155 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.h +++ b/Telegram/SourceFiles/mtproto/mtp_instance.h @@ -137,6 +137,7 @@ public: void requestConfig(); void requestConfigIfOld(); void requestCDNConfig(); + void setUserPhone(const QString &phone); ~Instance(); diff --git a/Telegram/SourceFiles/mtproto/special_config_request.cpp b/Telegram/SourceFiles/mtproto/special_config_request.cpp index b30295b32b..921a1d567e 100644 --- a/Telegram/SourceFiles/mtproto/special_config_request.cpp +++ b/Telegram/SourceFiles/mtproto/special_config_request.cpp @@ -27,57 +27,58 @@ Y1hZCxdv6cs5UnW9+PWvS+WIbkh+GaWYxwIDAQAB\n\ -----END RSA PUBLIC KEY-----\ "); +bool CheckPhoneByPrefixesRules(const QString &phone, const QString &rules) { + auto result = false; + for (const auto &prefix : rules.split(',')) { + if (prefix.isEmpty()) { + result = true; + } else if (prefix[0] == '+' && phone.startsWith(prefix.mid(1))) { + result = true; + } else if (prefix[0] == '-' && phone.startsWith(prefix.mid(1))) { + return false; + } + } + return result; +} + } // namespace SpecialConfigRequest::SpecialConfigRequest( base::lambda callback) -: _callback(std::move(callback)) { - performApp1Request(); - performApp2Request(); + int port, + bytes::const_span secret)> callback, + const QString &phone) +: _callback(std::move(callback)) +, _phone(phone) { + performAppRequest(); performDnsRequest(); } -void SpecialConfigRequest::performApp1Request() { - auto appUrl = QUrl(); - appUrl.setScheme(qsl("https")); - appUrl.setHost(qsl("google.com")); - if (cTestMode()) { - appUrl.setPath(qsl("/test/")); - } - auto appRequest = QNetworkRequest(appUrl); - appRequest.setRawHeader("Host", "dns-telegram.appspot.com"); - _app1Reply.reset(_manager.get(appRequest)); - connect(_app1Reply.get(), &QNetworkReply::finished, this, [=] { - app1Finished(); - }); -} - -void SpecialConfigRequest::performApp2Request() { +void SpecialConfigRequest::performAppRequest() { auto appUrl = QUrl(); appUrl.setScheme(qsl("https")); appUrl.setHost(qsl("software-download.microsoft.com")); appUrl.setPath(cTestMode() ? qsl("/test/config.txt") - : qsl("/prod/config.txt")); + : qsl("/prodv2/config.txt")); auto appRequest = QNetworkRequest(appUrl); appRequest.setRawHeader("Host", "tcdnb.azureedge.net"); - _app2Reply.reset(_manager.get(appRequest)); - connect(_app2Reply.get(), &QNetworkReply::finished, this, [=] { - app2Finished(); + _appReply.reset(_manager.get(appRequest)); + connect(_appReply.get(), &QNetworkReply::finished, this, [=] { + appFinished(); }); } void SpecialConfigRequest::performDnsRequest() { auto dnsUrl = QUrl(); dnsUrl.setScheme(qsl("https")); - dnsUrl.setHost(qsl("google.com")); + dnsUrl.setHost(qsl("www.google.com")); dnsUrl.setPath(qsl("/resolve")); dnsUrl.setQuery( qsl("name=%1.stel.com&type=16").arg( - cTestMode() ? qsl("tap") : qsl("ap"))); + cTestMode() ? qsl("tap") : qsl("apv2"))); auto dnsRequest = QNetworkRequest(QUrl(dnsUrl)); dnsRequest.setRawHeader("Host", "dns.google.com"); _dnsReply.reset(_manager.get(dnsRequest)); @@ -86,21 +87,12 @@ void SpecialConfigRequest::performDnsRequest() { }); } -void SpecialConfigRequest::app1Finished() { - if (!_app1Reply) { +void SpecialConfigRequest::appFinished() { + if (!_appReply) { return; } - auto result = _app1Reply->readAll(); - _app1Reply.release()->deleteLater(); - handleResponse(result); -} - -void SpecialConfigRequest::app2Finished() { - if (!_app2Reply) { - return; - } - auto result = _app2Reply->readAll(); - _app2Reply.release()->deleteLater(); + auto result = _appReply->readAll(); + _appReply.release()->deleteLater(); handleResponse(result); } @@ -237,25 +229,50 @@ void SpecialConfigRequest::handleResponse(const QByteArray &bytes) { LOG(("Config Error: Bad date frame for simple config: %1-%2, our time is %3.").arg(config.vdate.v).arg(config.vexpires.v).arg(now)); return; } - if (config.vip_port_list.v.empty()) { + if (config.vrules.v.empty()) { LOG(("Config Error: Empty simple config received.")); return; } - for (auto &entry : config.vip_port_list.v) { - Assert(entry.type() == mtpc_ipPort); - auto &ipPort = entry.c_ipPort(); - auto ip = *reinterpret_cast(&ipPort.vipv4.v); - auto ipString = qsl("%1.%2.%3.%4").arg((ip >> 24) & 0xFF).arg((ip >> 16) & 0xFF).arg((ip >> 8) & 0xFF).arg(ip & 0xFF); - _callback(config.vdc_id.v, ipString.toStdString(), ipPort.vport.v); + for (auto &rule : config.vrules.v) { + Assert(rule.type() == mtpc_accessPointRule); + auto &data = rule.c_accessPointRule(); + const auto phoneRules = qs(data.vphone_prefix_rules); + if (!CheckPhoneByPrefixesRules(_phone, phoneRules)) { + continue; + } + + const auto dcId = data.vdc_id.v; + for (const auto &address : data.vips.v) { + const auto parseIp = [](const MTPint &ipv4) { + const auto ip = *reinterpret_cast(&ipv4.v); + return qsl("%1.%2.%3.%4" + ).arg((ip >> 24) & 0xFF + ).arg((ip >> 16) & 0xFF + ).arg((ip >> 8) & 0xFF + ).arg(ip & 0xFF).toStdString(); + }; + switch (address.type()) { + case mtpc_ipPort: { + const auto &fields = address.c_ipPort(); + _callback(dcId, parseIp(fields.vipv4), fields.vport.v, {}); + } break; + case mtpc_ipPortSecret: { + const auto &fields = address.c_ipPortSecret(); + _callback( + dcId, + parseIp(fields.vipv4), + fields.vport.v, + bytes::make_span(fields.vsecret.v)); + } break; + default: Unexpected("Type in simpleConfig ips."); + } + } } } SpecialConfigRequest::~SpecialConfigRequest() { - if (_app1Reply) { - _app1Reply->abort(); - } - if (_app2Reply) { - _app2Reply->abort(); + if (_appReply) { + _appReply->abort(); } if (_dnsReply) { _dnsReply->abort(); diff --git a/Telegram/SourceFiles/mtproto/special_config_request.h b/Telegram/SourceFiles/mtproto/special_config_request.h index 3fcf1ca4c9..c1d78bf410 100644 --- a/Telegram/SourceFiles/mtproto/special_config_request.h +++ b/Telegram/SourceFiles/mtproto/special_config_request.h @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/bytes.h" + namespace MTP { class SpecialConfigRequest : public QObject { @@ -15,16 +17,16 @@ public: base::lambda callback); + int port, + bytes::const_span secret)> callback, + const QString &phone); ~SpecialConfigRequest(); private: - void performApp1Request(); - void performApp2Request(); + void performAppRequest(); void performDnsRequest(); - void app1Finished(); - void app2Finished(); + void appFinished(); void dnsFinished(); void handleResponse(const QByteArray &bytes); bool decryptSimpleConfig(const QByteArray &bytes); @@ -32,12 +34,13 @@ private: base::lambda _callback; + int port, + bytes::const_span secret)> _callback; + QString _phone; MTPhelp_ConfigSimple _simpleConfig; QNetworkAccessManager _manager; - std::unique_ptr _app1Reply; - std::unique_ptr _app2Reply; + std::unique_ptr _appReply; std::unique_ptr _dnsReply; std::unique_ptr _localOptions; diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 9a1a3fc96e..3e882e6497 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -2443,6 +2443,7 @@ void writeSettings() { quint32 size = 12 * (sizeof(quint32) + sizeof(qint32)); size += sizeof(quint32) + Serialize::bytearraySize(dcOptionsSerialized); + size += sizeof(quint32) + Serialize::stringSize(cLoggedPhoneNumber()); auto &proxies = Global::RefProxiesList(); const auto &proxy = Global::SelectedProxy(); @@ -2480,6 +2481,7 @@ void writeSettings() { data.stream << quint32(dbiLastUpdateCheck) << qint32(cLastUpdateCheck()); data.stream << quint32(dbiScale) << qint32(cConfigScale()); data.stream << quint32(dbiDcOptions) << dcOptionsSerialized; + data.stream << quint32(dbiLoggedPhoneNumber) << cLoggedPhoneNumber(); data.stream << quint32(dbiConnectionType) << qint32(dbictProxiesList); data.stream << qint32(proxies.size());