Keep separate MTP::Config's for separate accounts.

This commit is contained in:
John Preston
2020-06-17 13:36:25 +04:00
parent 63cdda2df7
commit 357caf8007
142 changed files with 1901 additions and 1263 deletions
+86 -79
View File
@@ -11,7 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/special_config_request.h"
#include "mtproto/session.h"
#include "mtproto/dc_options.h"
#include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h"
#include "mtproto/config_loader.h"
#include "mtproto/sender.h"
#include "storage/localstorage.h"
@@ -53,9 +54,18 @@ int GetNextRequestId() {
class Instance::Private : private Sender {
public:
Private(not_null<Instance*> instance, not_null<DcOptions*> options, Instance::Mode mode);
Private(
not_null<Instance*> instance,
Instance::Mode mode,
Fields &&fields);
void start(Config &&config);
void start();
[[nodiscard]] Config &config() const;
[[nodiscard]] const ConfigFields &configValues() const;
[[nodiscard]] DcOptions &dcOptions() const;
[[nodiscard]] Environment environment() const;
[[nodiscard]] bool isTestMode() const;
void resolveProxyDomain(const QString &host);
void setGoodProxyDomain(const QString &host, const QString &ip);
@@ -72,8 +82,6 @@ public:
void addKeysForDestroy(AuthKeysList &&keys);
[[nodiscard]] rpl::producer<> allKeysDestroyed() const;
[[nodiscard]] not_null<DcOptions*> dcOptions();
// Thread safe.
[[nodiscard]] QString deviceModel() const;
[[nodiscard]] QString systemVersion() const;
@@ -195,8 +203,8 @@ private:
void checkDelayedRequests();
const not_null<Instance*> _instance;
const not_null<DcOptions*> _dcOptions;
const Instance::Mode _mode = Instance::Mode::Normal;
const std::unique_ptr<Config> _config;
std::unique_ptr<QThread> _mainSessionThread;
std::unique_ptr<QThread> _otherSessionsThread;
@@ -205,7 +213,7 @@ private:
QString _deviceModel;
QString _systemVersion;
DcId _mainDcId = Config::kDefaultMainDc;
DcId _mainDcId = Fields::kDefaultMainDc;
bool _mainDcIdForced = false;
base::flat_map<DcId, std::unique_ptr<Dcenter>> _dcenters;
std::vector<std::unique_ptr<Dcenter>> _dcentersToDestroy;
@@ -261,27 +269,36 @@ private:
};
Instance::Fields::Fields() = default;
Instance::Fields::Fields(Fields &&other) = default;
auto Instance::Fields::operator=(Fields &&other) -> Fields & = default;
Instance::Fields::~Fields() = default;
Instance::Private::Private(
not_null<Instance*> instance,
not_null<DcOptions*> options,
Instance::Mode mode)
Instance::Mode mode,
Fields &&fields)
: Sender(instance)
, _instance(instance)
, _dcOptions(options)
, _mode(mode) {
, _mode(mode)
, _config(std::move(fields.config)) {
Expects(_config != nullptr);
const auto idealThreadPoolSize = QThread::idealThreadCount();
_fileSessionThreads.resize(2 * std::max(idealThreadPoolSize / 2, 1));
details::unpaused(
) | rpl::start_with_next([=] {
unpaused();
}, _lifetime);
}
void Instance::Private::start(Config &&config) {
_deviceModel = std::move(config.deviceModel);
_systemVersion = std::move(config.systemVersion);
_deviceModel = std::move(fields.deviceModel);
_systemVersion = std::move(fields.systemVersion);
for (auto &key : config.keys) {
for (auto &key : fields.keys) {
auto dcId = key->dcId();
auto shiftedDcId = dcId;
if (isKeysDestroyer()) {
@@ -297,22 +314,24 @@ void Instance::Private::start(Config &&config) {
addDc(shiftedDcId, std::move(key));
}
if (config.mainDcId != Config::kNotSetMainDc) {
_mainDcId = config.mainDcId;
if (fields.mainDcId != Fields::kNotSetMainDc) {
_mainDcId = fields.mainDcId;
_mainDcIdForced = true;
}
}
void Instance::Private::start() {
if (isKeysDestroyer()) {
for (const auto &[shiftedDcId, dc] : _dcenters) {
startSession(shiftedDcId);
}
} else if (_mainDcId != Config::kNoneMainDc) {
} else if (_mainDcId != Fields::kNoneMainDc) {
_mainSession = startSession(_mainDcId);
}
_checkDelayedTimer.setCallback([this] { checkDelayedRequests(); });
Assert((_mainDcId == Config::kNoneMainDc) == isKeysDestroyer());
Assert((_mainDcId == Fields::kNoneMainDc) == isKeysDestroyer());
requestConfig();
}
@@ -418,7 +437,8 @@ void Instance::Private::setMainDcId(DcId mainDcId) {
}
DcId Instance::Private::mainDcId() const {
Expects(_mainDcId != Config::kNoneMainDc);
Expects(_mainDcId != Fields::kNoneMainDc);
return _mainDcId;
}
@@ -457,7 +477,7 @@ void Instance::Private::syncHttpUnixtime() {
InvokeQueued(_instance, [=] {
_httpUnixtimeLoader = nullptr;
});
});
}, configValues().txtDomainString);
}
void Instance::Private::restartedByTimeout(ShiftedDcId shiftedDcId) {
@@ -469,7 +489,7 @@ rpl::producer<ShiftedDcId> Instance::Private::restartsByTimeout() const {
}
void Instance::Private::requestConfigIfOld() {
const auto timeout = Global::BlockedMode()
const auto timeout = _config->values().blockedMode
? kConfigBecomesOldForBlockedIn
: kConfigBecomesOldIn;
if (crl::now() - _lastConfigLoadedTime >= timeout) {
@@ -490,7 +510,7 @@ void Instance::Private::requestConfigIfExpired() {
}
void Instance::Private::requestCDNConfig() {
if (_cdnConfigLoadRequestId || _mainDcId == Config::kNoneMainDc) {
if (_cdnConfigLoadRequestId || _mainDcId == Fields::kNoneMainDc) {
return;
}
_cdnConfigLoadRequestId = request(
@@ -498,7 +518,7 @@ void Instance::Private::requestCDNConfig() {
).done([this](const MTPCdnConfig &result) {
_cdnConfigLoadRequestId = 0;
result.match([&](const MTPDcdnConfig &data) {
dcOptions()->setCDNConfig(data);
dcOptions().setCDNConfig(data);
});
Local::writeSettings();
}).send();
@@ -642,7 +662,7 @@ void Instance::Private::logoutGuestDcs() {
dcIds.push_back(key.first);
}
for (const auto dcId : dcIds) {
if (dcId == mainDcId() || dcOptions()->dcType(dcId) == DcType::Cdn) {
if (dcId == mainDcId() || dcOptions().dcType(dcId) == DcType::Cdn) {
continue;
}
const auto shiftedDcId = MTP::logoutDcId(dcId);
@@ -784,8 +804,24 @@ rpl::producer<> Instance::Private::writeKeysRequests() const {
return _writeKeysRequests.events();
}
not_null<DcOptions*> Instance::Private::dcOptions() {
return _dcOptions;
Config &Instance::Private::config() const {
return *_config;
}
const ConfigFields &Instance::Private::configValues() const {
return _config->values();
}
DcOptions &Instance::Private::dcOptions() const {
return _config->dcOptions();
}
Environment Instance::Private::environment() const {
return _config->environment();
}
bool Instance::Private::isTestMode() const {
return _config->isTestMode();
}
QString Instance::Private::deviceModel() const {
@@ -809,58 +845,13 @@ void Instance::Private::configLoadDone(const MTPConfig &result) {
_lastConfigLoadedTime = crl::now();
const auto &data = result.c_config();
DEBUG_LOG(("MTP Info: got config, chat_size_max: %1, date: %2, test_mode: %3, this_dc: %4, dc_options.length: %5").arg(data.vchat_size_max().v).arg(data.vdate().v).arg(mtpIsTrue(data.vtest_mode())).arg(data.vthis_dc().v).arg(data.vdc_options().v.size()));
if (data.vdc_options().v.empty()) {
LOG(("MTP Error: config with empty dc_options received!"));
} else {
_dcOptions->setFromList(data.vdc_options());
}
Global::SetChatSizeMax(data.vchat_size_max().v);
Global::SetMegagroupSizeMax(data.vmegagroup_size_max().v);
Global::SetForwardedCountMax(data.vforwarded_count_max().v);
Global::SetOnlineUpdatePeriod(data.vonline_update_period_ms().v);
Global::SetOfflineBlurTimeout(data.voffline_blur_timeout_ms().v);
Global::SetOfflineIdleTimeout(data.voffline_idle_timeout_ms().v);
Global::SetOnlineCloudTimeout(data.vonline_cloud_timeout_ms().v);
Global::SetNotifyCloudDelay(data.vnotify_cloud_delay_ms().v);
Global::SetNotifyDefaultDelay(data.vnotify_default_delay_ms().v);
Global::SetPushChatPeriod(data.vpush_chat_period_ms().v);
Global::SetPushChatLimit(data.vpush_chat_limit().v);
Global::SetSavedGifsLimit(data.vsaved_gifs_limit().v);
Global::SetEditTimeLimit(data.vedit_time_limit().v);
Global::SetRevokeTimeLimit(data.vrevoke_time_limit().v);
Global::SetRevokePrivateTimeLimit(data.vrevoke_pm_time_limit().v);
Global::SetRevokePrivateInbox(data.is_revoke_pm_inbox());
Global::SetStickersRecentLimit(data.vstickers_recent_limit().v);
Global::SetStickersFavedLimit(data.vstickers_faved_limit().v);
Global::SetPinnedDialogsCountMax(
std::max(data.vpinned_dialogs_count_max().v, 1));
Global::SetPinnedDialogsInFolderMax(
std::max(data.vpinned_infolder_count_max().v, 1));
Core::App().setInternalLinkDomain(qs(data.vme_url_prefix()));
Global::SetChannelsReadMediaPeriod(data.vchannels_read_media_period().v);
Global::SetWebFileDcId(data.vwebfile_dc_id().v);
Global::SetTxtDomainString(qs(data.vdc_txt_domain_name()));
Global::SetCallReceiveTimeoutMs(data.vcall_receive_timeout_ms().v);
Global::SetCallRingTimeoutMs(data.vcall_ring_timeout_ms().v);
Global::SetCallConnectTimeoutMs(data.vcall_connect_timeout_ms().v);
Global::SetCallPacketTimeoutMs(data.vcall_packet_timeout_ms().v);
if (Global::PhoneCallsEnabled() != data.is_phonecalls_enabled()) {
Global::SetPhoneCallsEnabled(data.is_phonecalls_enabled());
Global::RefPhoneCallsEnabledChanged().notify();
}
Global::SetBlockedMode(data.is_blocked_mode());
Global::SetCaptionLengthMax(data.vcaption_length_max().v);
_config->apply(data);
const auto lang = qs(data.vsuggested_lang_code().value_or_empty());
Lang::CurrentCloudManager().setSuggestedLanguage(lang);
Lang::CurrentCloudManager().setCurrentVersions(
data.vlang_pack_version().value_or_empty(),
data.vbase_lang_pack_version().value_or_empty());
Core::App().activeAccount().configUpdated(); // #TODO multi
if (const auto prefix = data.vautoupdate_url_prefix()) {
Local::writeAutoupdatePrefix(qs(*prefix));
}
@@ -1520,7 +1511,7 @@ not_null<QThread*> Instance::Private::getThreadForDc(
void Instance::Private::scheduleKeyDestroy(ShiftedDcId shiftedDcId) {
Expects(isKeysDestroyer());
if (dcOptions()->dcType(shiftedDcId) == DcType::Cdn) {
if (dcOptions().dcType(shiftedDcId) == DcType::Cdn) {
performKeyDestroy(shiftedDcId);
} else {
_instance->send(MTPauth_LogOut(), rpcDone([=](const MTPBool &) {
@@ -1643,10 +1634,10 @@ void Instance::Private::prepareToDestroy() {
}
}
Instance::Instance(not_null<DcOptions*> options, Mode mode, Config &&config)
Instance::Instance(Mode mode, Fields &&fields)
: QObject()
, _private(std::make_unique<Private>(this, options, mode)) {
_private->start(std::move(config));
, _private(std::make_unique<Private>(this, mode, std::move(fields))) {
_private->start();
}
void Instance::resolveProxyDomain(const QString &host) {
@@ -1787,10 +1778,26 @@ void Instance::addKeysForDestroy(AuthKeysList &&keys) {
_private->addKeysForDestroy(std::move(keys));
}
not_null<DcOptions*> Instance::dcOptions() {
Config &Instance::config() const {
return _private->config();
}
const ConfigFields &Instance::configValues() const {
return _private->configValues();
}
DcOptions &Instance::dcOptions() const {
return _private->dcOptions();
}
Environment Instance::environment() const {
return _private->environment();
}
bool Instance::isTestMode() const {
return _private->isTestMode();
}
QString Instance::deviceModel() const {
return _private->deviceModel();
}