diff --git a/Telegram/SourceFiles/countries/countries_manager.cpp b/Telegram/SourceFiles/countries/countries_manager.cpp index 0ed6ac66d..2355208d6 100644 --- a/Telegram/SourceFiles/countries/countries_manager.cpp +++ b/Telegram/SourceFiles/countries/countries_manager.cpp @@ -153,15 +153,11 @@ Manager::Manager(not_null domain) if (!account) { _api.reset(); } - return rpl::combine( - account - ? account->appConfig().refreshed() | rpl::map_to(true) - : rpl::never<>() | rpl::map_to(false), - account - ? account->mtpValue() - : rpl::never>()); + return account + ? account->mtpMainSessionValue() + : rpl::never>(); }) | rpl::flatten_latest( - ) | rpl::start_with_next([=](bool, not_null instance) { + ) | rpl::start_with_next([=](not_null instance) { _api.emplace(instance); request(); }, _lifetime); @@ -193,7 +189,7 @@ void Manager::write() const { } void Manager::request() { - Expects(_api); + Expects(_api.has_value()); const auto convertMTP = [](const auto &vector, bool force = false) { if (!vector) { @@ -202,7 +198,7 @@ void Manager::request() { return ranges::views::all( vector->v ) | ranges::views::transform([](const MTPstring &s) -> QString { - return s.v; + return qs(s); }) | ranges::to_vector; }; diff --git a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp index 2102b60dc..f47ace515 100644 --- a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp +++ b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp @@ -164,7 +164,7 @@ CloudManager::CloudManager(Instance &langpack) _api.reset(); } return account - ? account->mtpValue() + ? account->mtpMainSessionValue() : rpl::never>(); }) | rpl::flatten_latest( ) | rpl::start_with_next([=](not_null instance) { diff --git a/Telegram/SourceFiles/main/main_account.cpp b/Telegram/SourceFiles/main/main_account.cpp index 4eb4dbe17..9643c81f0 100644 --- a/Telegram/SourceFiles/main/main_account.cpp +++ b/Telegram/SourceFiles/main/main_account.cpp @@ -241,6 +241,12 @@ rpl::producer> Account::mtpValue() const { }); } +rpl::producer> Account::mtpMainSessionValue() const { + return mtpValue() | rpl::map([=](not_null instance) { + return instance->mainDcIdValue() | rpl::map_to(instance); + }) | rpl::flatten_latest(); +} + rpl::producer Account::mtpUpdates() const { return _mtpUpdates.events(); } diff --git a/Telegram/SourceFiles/main/main_account.h b/Telegram/SourceFiles/main/main_account.h index 20ede974c..f4978655d 100644 --- a/Telegram/SourceFiles/main/main_account.h +++ b/Telegram/SourceFiles/main/main_account.h @@ -83,6 +83,13 @@ public: } [[nodiscard]] rpl::producer> mtpValue() const; + // Each time the main session changes a new copy of the pointer is fired. + // This allows to resend the requests that were not requiring auth, and + // which could be forgotten without calling .done() or .fail() because + // of the main dc changing. + [[nodiscard]] auto mtpMainSessionValue() const + -> rpl::producer>; + // Set from legacy storage. void setLegacyMtpKey(std::shared_ptr key); diff --git a/Telegram/SourceFiles/main/main_app_config.cpp b/Telegram/SourceFiles/main/main_app_config.cpp index 30727becc..5c43c0bb9 100644 --- a/Telegram/SourceFiles/main/main_app_config.cpp +++ b/Telegram/SourceFiles/main/main_app_config.cpp @@ -19,7 +19,7 @@ constexpr auto kRefreshTimeout = 3600 * crl::time(1000); } // namespace AppConfig::AppConfig(not_null account) : _account(account) { - account->mtpValue( + account->mtpMainSessionValue( ) | rpl::start_with_next([=](not_null instance) { _api.emplace(instance); refresh(); diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index ec7df112e..04df7163c 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -72,6 +72,7 @@ public: void suggestMainDcId(DcId mainDcId); void setMainDcId(DcId mainDcId); [[nodiscard]] DcId mainDcId() const; + [[nodiscard]] rpl::producer mainDcIdValue() const; [[nodiscard]] rpl::producer<> writeKeysRequests() const; @@ -191,7 +192,7 @@ private: Session *findSession(ShiftedDcId shiftedDcId); not_null startSession(ShiftedDcId shiftedDcId); - Session *removeSession(ShiftedDcId shiftedDcId); + void scheduleSessionDestroy(ShiftedDcId shiftedDcId); [[nodiscard]] not_null getThreadForDc(ShiftedDcId shiftedDcId); void applyDomainIps( @@ -225,7 +226,7 @@ private: QString _deviceModel; QString _systemVersion; - DcId _mainDcId = Fields::kDefaultMainDc; + rpl::variable _mainDcId = Fields::kDefaultMainDc; bool _mainDcIdForced = false; base::flat_map> _dcenters; std::vector> _dcentersToDestroy; @@ -356,13 +357,13 @@ void Instance::Private::start() { for (const auto &[shiftedDcId, dc] : _dcenters) { startSession(shiftedDcId); } - } else if (_mainDcId != Fields::kNoneMainDc) { - _mainSession = startSession(_mainDcId); + } else if (mainDcId() != Fields::kNoneMainDc) { + _mainSession = startSession(mainDcId()); } _checkDelayedTimer.setCallback([this] { checkDelayedRequests(); }); - Assert((_mainDcId == Fields::kNoneMainDc) == isKeysDestroyer()); + Assert((mainDcId() == Fields::kNoneMainDc) == isKeysDestroyer()); requestConfig(); } @@ -463,18 +464,26 @@ void Instance::Private::setMainDcId(DcId mainDcId) { } _mainDcIdForced = true; - auto oldMainDcId = _mainSession->getDcWithShift(); - _mainDcId = mainDcId; - if (oldMainDcId != _mainDcId) { - killSession(oldMainDcId); + const auto oldMainDcId = _mainSession->getDcWithShift(); + if (oldMainDcId != mainDcId) { + scheduleSessionDestroy(oldMainDcId); + scheduleSessionDestroy(mainDcId); + _mainSession = startSession(mainDcId); } + _mainDcId = mainDcId; _writeKeysRequests.fire({}); } DcId Instance::Private::mainDcId() const { - Expects(_mainDcId != Fields::kNoneMainDc); + Expects(_mainDcId.current() != Fields::kNoneMainDc); - return _mainDcId; + return _mainDcId.current(); +} + +rpl::producer Instance::Private::mainDcIdValue() const { + Expects(_mainDcId.current() != Fields::kNoneMainDc); + + return _mainDcId.value(); } void Instance::Private::requestConfig() { @@ -548,7 +557,7 @@ void Instance::Private::requestConfigIfExpired() { } void Instance::Private::requestCDNConfig() { - if (_cdnConfigLoadRequestId || _mainDcId == Fields::kNoneMainDc) { + if (_cdnConfigLoadRequestId || mainDcId() == Fields::kNoneMainDc) { return; } _cdnConfigLoadRequestId = request( @@ -652,19 +661,11 @@ int32 Instance::Private::state(mtpRequestId requestId) { } void Instance::Private::killSession(ShiftedDcId shiftedDcId) { - const auto checkIfMainAndKill = [&](ShiftedDcId shiftedDcId) { - if (const auto removed = removeSession(shiftedDcId)) { - return (removed == _mainSession); - } - return false; - }; - if (checkIfMainAndKill(shiftedDcId)) { - checkIfMainAndKill(_mainDcId); - _mainSession = startSession(_mainDcId); + const auto i = _sessions.find(shiftedDcId); + if (i != _sessions.cend()) { + Assert(i->second.get() != _mainSession); } - InvokeQueued(_instance, [=] { - _sessionsToDestroy.clear(); - }); + scheduleSessionDestroy(shiftedDcId); } void Instance::Private::stopSession(ShiftedDcId shiftedDcId) { @@ -1563,15 +1564,17 @@ not_null Instance::Private::startSession(ShiftedDcId shiftedDcId) { return result; } -Session *Instance::Private::removeSession(ShiftedDcId shiftedDcId) { +void Instance::Private::scheduleSessionDestroy(ShiftedDcId shiftedDcId) { const auto i = _sessions.find(shiftedDcId); if (i == _sessions.cend()) { - return nullptr; + return; } i->second->kill(); _sessionsToDestroy.push_back(std::move(i->second)); _sessions.erase(i); - return _sessionsToDestroy.back().get(); + InvokeQueued(_instance, [=] { + _sessionsToDestroy.clear(); + }); } @@ -1790,6 +1793,10 @@ DcId Instance::mainDcId() const { return _private->mainDcId(); } +rpl::producer Instance::mainDcIdValue() const { + return _private->mainDcIdValue(); +} + QString Instance::systemLangCode() const { return Lang::GetInstance().systemLangCode(); } diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.h b/Telegram/SourceFiles/mtproto/mtp_instance.h index 135c64838..2a3bc3d4e 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.h +++ b/Telegram/SourceFiles/mtproto/mtp_instance.h @@ -65,6 +65,7 @@ public: void suggestMainDcId(DcId mainDcId); void setMainDcId(DcId mainDcId); [[nodiscard]] DcId mainDcId() const; + [[nodiscard]] rpl::producer mainDcIdValue() const; [[nodiscard]] QString systemLangCode() const; [[nodiscard]] QString cloudLangCode() const; [[nodiscard]] QString langPackName() const;