diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 3b14ad005..39ba1f2af 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -19,6 +19,7 @@ #include "td/telegram/net/NetQueryDispatcher.h" #include "td/telegram/NewPasswordState.h" #include "td/telegram/NotificationManager.h" +#include "td/telegram/OnlineManager.h" #include "td/telegram/OptionManager.h" #include "td/telegram/PasswordManager.h" #include "td/telegram/PromoDataManager.h" @@ -1268,6 +1269,7 @@ void AuthManager::on_get_authorization(tl_object_ptrdialog_filter_manager_->on_authorization_success(); // must be after MessagesManager::on_authorization_success() // to have folders created td_->notification_manager_->init(); + td_->online_manager_->init(); td_->promo_data_manager_->init(); td_->reaction_manager_->init(); td_->stickers_manager_->init(); @@ -1276,10 +1278,7 @@ void AuthManager::on_get_authorization(tl_object_ptrtop_dialog_manager_->init(); td_->updates_manager_->get_difference("on_get_authorization"); if (!is_bot()) { - td_->on_online_updated(false, true); G()->td_db()->get_binlog_pmc()->set("fetched_marks_as_unread", "1"); - } else { - td_->set_is_bot_online(true); } send_closure(G()->config_manager(), &ConfigManager::request_config, false); on_current_query_ok(); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0ebd7220d..c93dd8713 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -69,6 +69,7 @@ #include "td/telegram/NotificationSettingsManager.h" #include "td/telegram/NotificationSound.h" #include "td/telegram/NotificationType.h" +#include "td/telegram/OnlineManager.h" #include "td/telegram/OptionManager.h" #include "td/telegram/Photo.h" #include "td/telegram/PollId.h" @@ -12003,7 +12004,7 @@ void MessagesManager::on_update_viewed_messages_timeout(DialogId dialog_id) { } auto it = dialog_viewed_messages_.find(dialog_id); - if (it == dialog_viewed_messages_.end() || !td_->is_online()) { + if (it == dialog_viewed_messages_.end() || !td_->online_manager_->is_online()) { return; } @@ -19029,7 +19030,7 @@ Status MessagesManager::view_messages(DialogId dialog_id, vector mess td_->create_handler(std::move(promise)) ->send(dialog_id, std::move(viewed_fact_check_message_ids)); } - if (td_->is_online() && dialog_viewed_messages_.count(dialog_id) != 0) { + if (td_->online_manager_->is_online() && dialog_viewed_messages_.count(dialog_id) != 0) { update_viewed_messages_timeout_.add_timeout_in(dialog_id.get(), UPDATE_VIEWED_MESSAGES_PERIOD); } if (!authentication_codes.empty()) { @@ -28514,7 +28515,7 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f int32 min_delay_ms = 0; if (need_delay_message_content_notification(m->content.get(), td_->user_manager_->get_my_id())) { min_delay_ms = 3000; // 3 seconds - } else if (td_->is_online() && d->open_count > 0) { + } else if (td_->online_manager_->is_online() && d->open_count > 0) { min_delay_ms = 1000; // 1 second } auto ringtone_id = get_dialog_notification_ringtone_id(settings_dialog_id, settings_dialog); diff --git a/td/telegram/NotificationManager.cpp b/td/telegram/NotificationManager.cpp index f8e2a434a..59a3a5f6e 100644 --- a/td/telegram/NotificationManager.cpp +++ b/td/telegram/NotificationManager.cpp @@ -21,6 +21,7 @@ #include "td/telegram/misc.h" #include "td/telegram/net/ConnectionCreator.h" #include "td/telegram/net/DcId.h" +#include "td/telegram/OnlineManager.h" #include "td/telegram/OptionManager.h" #include "td/telegram/Photo.h" #include "td/telegram/Photo.hpp" @@ -2789,7 +2790,7 @@ void NotificationManager::process_push_notification(string payload, Promiseis_online()) { + if (!td_->online_manager_->is_online()) { // reset online flag to false to immediately check all connections aliveness send_closure(G()->state_manager(), &StateManager::on_online, false); } diff --git a/td/telegram/OnlineManager.cpp b/td/telegram/OnlineManager.cpp index a91515e22..e8147be30 100644 --- a/td/telegram/OnlineManager.cpp +++ b/td/telegram/OnlineManager.cpp @@ -6,8 +6,51 @@ // #include "td/telegram/OnlineManager.h" +#include "td/telegram/AuthManager.h" +#include "td/telegram/Global.h" +#include "td/telegram/OptionManager.h" +#include "td/telegram/StateManager.h" +#include "td/telegram/Td.h" +#include "td/telegram/telegram_api.h" +#include "td/telegram/UpdatesManager.h" +#include "td/telegram/UserManager.h" + +#include "td/utils/buffer.h" +#include "td/utils/logging.h" +#include "td/utils/Random.h" + namespace td { +class UpdateStatusQuery final : public Td::ResultHandler { + bool is_offline_; + + public: + NetQueryRef send(bool is_offline) { + is_offline_ = is_offline; + auto net_query = G()->net_query_creator().create(telegram_api::account_updateStatus(is_offline)); + auto result = net_query.get_weak(); + send_query(std::move(net_query)); + return result; + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + bool result = result_ptr.ok(); + LOG(INFO) << "Receive result for UpdateStatusQuery: " << result; + td_->online_manager_->on_update_status_success(!is_offline_); + } + + void on_error(Status status) final { + if (status.code() != NetQuery::Canceled && !G()->is_expected_error(status)) { + LOG(ERROR) << "Receive error for UpdateStatusQuery: " << status; + } + } +}; + OnlineManager::OnlineManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { } @@ -15,4 +58,106 @@ void OnlineManager::tear_down() { parent_.reset(); } +void OnlineManager::start_up() { + init(); +} + +void OnlineManager::init() { + if (is_online_) { + on_online_updated(false /*ignored*/, true); + } + if (td_->auth_manager_->is_bot()) { + set_is_bot_online(true); + } +} + +void OnlineManager::on_online_timeout_callback(void *online_manager_ptr) { + if (G()->close_flag()) { + return; + } + + auto online_manager = static_cast(online_manager_ptr); + send_closure_later(online_manager->actor_id(online_manager), &OnlineManager::on_online_updated, false, true); +} + +void OnlineManager::on_ping_server_timeout_callback(void *online_manager_ptr) { + if (G()->close_flag()) { + return; + } + + auto online_manager = static_cast(online_manager_ptr); + send_closure_later(online_manager->actor_id(online_manager), &OnlineManager::on_ping_server_timeout); +} + +void OnlineManager::on_online_updated(bool force, bool send_update) { + if (G()->close_flag() || !td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot()) { + return; + } + if (force || is_online_) { + td_->user_manager_->set_my_online_status(is_online_, send_update, true); + if (!update_status_query_.empty()) { + LOG(INFO) << "Cancel previous update status query"; + cancel_query(update_status_query_); + } + update_status_query_ = td_->create_handler()->send(!is_online_); + } + if (is_online_) { + online_timeout_.set_callback(std::move(on_online_timeout_callback)); + online_timeout_.set_callback_data(static_cast(this)); + online_timeout_.set_timeout_in(static_cast(G()->get_option_integer("online_update_period_ms", 210000)) * + 1e-3); + } else { + online_timeout_.cancel_timeout(); + } +} + +void OnlineManager::on_update_status_success(bool is_online) { + if (is_online == is_online_) { + if (!update_status_query_.empty()) { + update_status_query_ = NetQueryRef(); + } + td_->user_manager_->set_my_online_status(is_online_, true, false); + } +} + +bool OnlineManager::is_online() const { + return is_online_; +} + +void OnlineManager::set_is_online(bool is_online) { + if (is_online == is_online_) { + return; + } + + is_online_ = is_online; + if (td_->auth_manager_ != nullptr) { // postpone if there is no AuthManager yet + on_online_updated(true, true); + } +} + +void OnlineManager::set_is_bot_online(bool is_bot_online) { + ping_server_timeout_.set_callback(std::move(on_ping_server_timeout_callback)); + ping_server_timeout_.set_callback_data(static_cast(this)); + ping_server_timeout_.set_timeout_in(PING_SERVER_TIMEOUT + Random::fast(0, PING_SERVER_TIMEOUT / 5)); + + if (td_->option_manager_->get_option_integer("session_count") > 1) { + is_bot_online = false; + } + + if (is_bot_online == is_bot_online_) { + return; + } + + is_bot_online_ = is_bot_online; + send_closure(G()->state_manager(), &StateManager::on_online, is_bot_online_); +} + +void OnlineManager::on_ping_server_timeout() { + if (G()->close_flag() || td_->updates_manager_ == nullptr || !td_->auth_manager_->is_authorized()) { + return; + } + td_->updates_manager_->ping_server(); + set_is_bot_online(false); +} + } // namespace td diff --git a/td/telegram/OnlineManager.h b/td/telegram/OnlineManager.h index 0bd95b4c9..fda4803e8 100644 --- a/td/telegram/OnlineManager.h +++ b/td/telegram/OnlineManager.h @@ -6,7 +6,10 @@ // #pragma once +#include "td/telegram/net/NetQuery.h" + #include "td/actor/actor.h" +#include "td/actor/Timeout.h" #include "td/utils/common.h" @@ -18,11 +21,40 @@ class OnlineManager final : public Actor { public: OnlineManager(Td *td, ActorShared<> parent); + void init(); + + void on_online_updated(bool force, bool send_update); + + void on_update_status_success(bool is_online); + + bool is_online() const; + + void set_is_online(bool is_online); + + void set_is_bot_online(bool is_bot_online); + private: + static constexpr int32 PING_SERVER_TIMEOUT = 300; + void tear_down() final; + void start_up() final; + + static void on_online_timeout_callback(void *online_manager_ptr); + + static void on_ping_server_timeout_callback(void *online_manager_ptr); + + void on_ping_server_timeout(); + Td *td_; ActorShared<> parent_; + + bool is_online_ = false; + bool is_bot_online_ = false; + NetQueryRef update_status_query_; + + Timeout online_timeout_; + Timeout ping_server_timeout_; }; } // namespace td diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index 821af1ed8..de5baef4e 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -21,6 +21,7 @@ #include "td/telegram/net/MtprotoHeader.h" #include "td/telegram/net/NetQueryDispatcher.h" #include "td/telegram/NotificationManager.h" +#include "td/telegram/OnlineManager.h" #include "td/telegram/PeopleNearbyManager.h" #include "td/telegram/ReactionType.h" #include "td/telegram/StateManager.h" @@ -687,7 +688,7 @@ void OptionManager::get_option(const string &name, Promise(td_->is_online())); + return promise.set_value(td_api::make_object(td_->online_manager_->is_online())); } break; case 'u': @@ -924,7 +925,7 @@ void OptionManager::set_option(const string &name, td_api::object_ptr(value.get())->value_; - td_->set_is_online(is_online); + td_->online_manager_->set_is_online(is_online); if (!is_bot) { send_closure(td_->state_manager_, &StateManager::on_online, is_online); } @@ -1046,7 +1047,7 @@ void OptionManager::get_current_state(vector> get_common_state(updates); updates.push_back(td_api::make_object( - "online", td_api::make_object(td_->is_online()))); + "online", td_api::make_object(td_->online_manager_->is_online()))); updates.push_back(td_api::make_object("unix_time", get_unix_time_option_value_object())); diff --git a/td/telegram/PollManager.cpp b/td/telegram/PollManager.cpp index 24f502bb2..b04597f0f 100644 --- a/td/telegram/PollManager.cpp +++ b/td/telegram/PollManager.cpp @@ -18,6 +18,7 @@ #include "td/telegram/MessageId.h" #include "td/telegram/MessageSender.h" #include "td/telegram/MessagesManager.h" +#include "td/telegram/OnlineManager.h" #include "td/telegram/PollId.hpp" #include "td/telegram/PollManager.hpp" #include "td/telegram/StateManager.h" @@ -1356,7 +1357,7 @@ void PollManager::stop_local_poll(PollId poll_id) { } double PollManager::get_polling_timeout() const { - double result = td_->is_online() ? 60 : 30 * 60; + double result = td_->online_manager_->is_online() ? 60 : 30 * 60; return result * Random::fast(70, 100) * 0.01; } diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 76731fcca..b0f10aa6b 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -393,37 +393,6 @@ class SetBotUpdatesStatusQuery final : public Td::ResultHandler { } }; -class UpdateStatusQuery final : public Td::ResultHandler { - bool is_offline_; - - public: - NetQueryRef send(bool is_offline) { - is_offline_ = is_offline; - auto net_query = G()->net_query_creator().create(telegram_api::account_updateStatus(is_offline)); - auto result = net_query.get_weak(); - send_query(std::move(net_query)); - return result; - } - - void on_result(BufferSlice packet) final { - auto result_ptr = fetch_result(packet); - if (result_ptr.is_error()) { - return on_error(result_ptr.move_as_error()); - } - - bool result = result_ptr.ok(); - LOG(INFO) << "Receive result for UpdateStatusQuery: " << result; - td_->on_update_status_success(!is_offline_); - } - - void on_error(Status status) final { - if (status.code() != NetQuery::Canceled && !G()->is_expected_error(status)) { - LOG(ERROR) << "Receive error for UpdateStatusQuery: " << status; - } - status.ignore(); - } -}; - class TestNetworkQuery final : public Td::ResultHandler { Promise promise_; @@ -2219,17 +2188,6 @@ void Td::on_alarm_timeout_callback(void *td_ptr, int64 alarm_id) { } void Td::on_alarm_timeout(int64 alarm_id) { - if (alarm_id == ONLINE_ALARM_ID) { - on_online_updated(false, true); - return; - } - if (alarm_id == PING_SERVER_ALARM_ID) { - if (!close_flag_ && updates_manager_ != nullptr && auth_manager_->is_authorized()) { - updates_manager_->ping_server(); - set_is_bot_online(false); - } - return; - } if (close_flag_ >= 2) { // pending_alarms_ was already cleared return; @@ -2242,65 +2200,6 @@ void Td::on_alarm_timeout(int64 alarm_id) { send_result(request_id, make_tl_object()); } -void Td::on_online_updated(bool force, bool send_update) { - if (close_flag_ >= 2 || !auth_manager_->is_authorized() || auth_manager_->is_bot()) { - return; - } - if (force || is_online_) { - user_manager_->set_my_online_status(is_online_, send_update, true); - if (!update_status_query_.empty()) { - LOG(INFO) << "Cancel previous update status query"; - cancel_query(update_status_query_); - } - update_status_query_ = create_handler()->send(!is_online_); - } - if (is_online_) { - alarm_timeout_.set_timeout_in( - ONLINE_ALARM_ID, static_cast(G()->get_option_integer("online_update_period_ms", 210000)) * 1e-3); - } else { - alarm_timeout_.cancel_timeout(ONLINE_ALARM_ID); - } -} - -void Td::on_update_status_success(bool is_online) { - if (is_online == is_online_) { - if (!update_status_query_.empty()) { - update_status_query_ = NetQueryRef(); - } - user_manager_->set_my_online_status(is_online_, true, false); - } -} - -bool Td::is_online() const { - return is_online_; -} - -void Td::set_is_online(bool is_online) { - if (is_online == is_online_) { - return; - } - - is_online_ = is_online; - if (auth_manager_ != nullptr) { // postpone if there is no AuthManager yet - on_online_updated(true, true); - } -} - -void Td::set_is_bot_online(bool is_bot_online) { - alarm_timeout_.set_timeout_in(PING_SERVER_ALARM_ID, PING_SERVER_TIMEOUT + Random::fast(0, PING_SERVER_TIMEOUT / 5)); - - if (G()->get_option_integer("session_count") > 1) { - is_bot_online = false; - } - - if (is_bot_online == is_bot_online_) { - return; - } - - is_bot_online_ = is_bot_online; - send_closure(G()->state_manager(), &StateManager::on_online, is_bot_online_); -} - bool Td::ignore_background_updates() const { return can_ignore_background_updates_ && option_manager_->get_option_boolean("ignore_background_updates"); } @@ -2561,7 +2460,7 @@ void Td::on_update(telegram_api::object_ptr updates, uint updates_manager_->on_update_from_auth_key_id(auth_key_id); updates_manager_->on_get_updates(std::move(updates), Promise()); if (auth_manager_->is_bot() && auth_manager_->is_authorized()) { - set_is_bot_online(true); + online_manager_->set_is_bot_online(true); } } } @@ -2812,11 +2711,6 @@ void Td::clear() { state_manager_.reset(); LOG(DEBUG) << "StateManager was cleared" << timer; clear_requests(); - if (is_online_) { - is_online_ = false; - alarm_timeout_.cancel_timeout(ONLINE_ALARM_ID); - } - alarm_timeout_.cancel_timeout(PING_SERVER_ALARM_ID); auto reset_actor = [&timer](ActorOwn actor) { if (!actor.empty()) { @@ -3112,13 +3006,6 @@ void Td::init(Parameters parameters, Result r_opened_datab option_manager_->on_td_inited(); - if (is_online_) { - on_online_updated(true, true); - } - if (auth_manager_->is_bot()) { - set_is_bot_online(true); - } - process_binlog_events(std::move(events)); VLOG(td_init) << "Ping datacenter"; diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b5e71ca82..be6384303 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -142,16 +142,6 @@ class Td final : public Actor { void on_result(NetQueryPtr query); - void on_online_updated(bool force, bool send_update); - - void on_update_status_success(bool is_online); - - bool is_online() const; - - void set_is_online(bool is_online); - - void set_is_bot_online(bool is_bot_online); - bool can_ignore_background_updates() const { return can_ignore_background_updates_; } @@ -339,10 +329,6 @@ class Td final : public Actor { static td_api::object_ptr static_request(td_api::object_ptr function); private: - static constexpr int64 ONLINE_ALARM_ID = 0; - static constexpr int64 PING_SERVER_ALARM_ID = -1; - static constexpr int32 PING_SERVER_TIMEOUT = 300; - void run_request(uint64 id, td_api::object_ptr function); void do_run_request(uint64 id, td_api::object_ptr &&function); @@ -387,10 +373,6 @@ class Td final : public Actor { bool can_ignore_background_updates_ = false; - bool is_online_ = false; - bool is_bot_online_ = false; - NetQueryRef update_status_query_; - int64 alarm_id_ = 1; FlatHashMap pending_alarms_; MultiTimeout alarm_timeout_{"AlarmTimeout"}; diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 4ab388a1c..b62582702 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -48,6 +48,7 @@ #include "td/telegram/NotificationManager.h" #include "td/telegram/NotificationSettingsManager.h" #include "td/telegram/NotificationSettingsScope.h" +#include "td/telegram/OnlineManager.h" #include "td/telegram/OptionManager.h" #include "td/telegram/OrderInfo.h" #include "td/telegram/PeopleNearbyManager.h" @@ -2240,7 +2241,7 @@ void UpdatesManager::try_reload_data_static(void *td) { void UpdatesManager::try_reload_data() { if (!td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot() || running_get_difference_ || - !td_->is_online()) { + !td_->online_manager_->is_online()) { return; } diff --git a/td/telegram/UserManager.cpp b/td/telegram/UserManager.cpp index e15fd506f..5682df16e 100644 --- a/td/telegram/UserManager.cpp +++ b/td/telegram/UserManager.cpp @@ -43,6 +43,7 @@ #include "td/telegram/misc.h" #include "td/telegram/net/NetQuery.h" #include "td/telegram/NotificationManager.h" +#include "td/telegram/OnlineManager.h" #include "td/telegram/OptionManager.h" #include "td/telegram/PeerColor.h" #include "td/telegram/PeopleNearbyManager.h" @@ -2026,7 +2027,7 @@ UserManager::UserManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::m was_online_local_ = to_integer(G()->td_db()->get_binlog_pmc()->get("my_was_online_local")); was_online_remote_ = to_integer(G()->td_db()->get_binlog_pmc()->get("my_was_online_remote")); auto unix_time = G()->unix_time(); - if (was_online_local_ >= unix_time && !td_->is_online()) { + if (was_online_local_ >= unix_time && !td_->online_manager_->is_online()) { was_online_local_ = unix_time - 1; } } @@ -2220,7 +2221,7 @@ UserId UserManager::add_channel_bot_user() { UserManager::MyOnlineStatusInfo UserManager::get_my_online_status() const { MyOnlineStatusInfo status_info; - status_info.is_online_local = td_->is_online(); + status_info.is_online_local = td_->online_manager_->is_online(); status_info.is_online_remote = was_online_remote_ > G()->unix_time(); status_info.was_online_local = was_online_local_; status_info.was_online_remote = was_online_remote_; @@ -3147,7 +3148,7 @@ void UserManager::on_update_user_online(User *u, UserId user_id, u->is_online_status_changed = true; } if (is_offline) { - td_->on_online_updated(false, false); + td_->online_manager_->on_online_updated(false, false); } } else if (old_is_online != new_is_online) { u->is_online_status_changed = true;