// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #include "td/telegram/DhConfig.h" #include "td/telegram/net/DcId.h" #include "td/telegram/net/NetQueryCreator.h" #include "td/telegram/TdParameters.h" #include "td/net/NetStats.h" #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" #include "td/actor/SchedulerLocalStorage.h" #include "td/utils/common.h" #include "td/utils/FlatHashMap.h" #include "td/utils/logging.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" #include "td/utils/Time.h" #include #include #include namespace td { class AnimationsManager; class BackgroundManager; class CallManager; class ConfigManager; class ConfigShared; class ConnectionCreator; class ContactsManager; class DownloadManager; class FileManager; class FileReferenceManager; class GameManager; class GroupCallManager; class LanguagePackManager; class LinkManager; class MessagesManager; class MtprotoHeader; class NetQueryDispatcher; class NotificationManager; class NotificationSettingsManager; class OptionManager; class PasswordManager; class SecretChatsManager; class SponsoredMessageManager; class StateManager; class StickersManager; class StorageManager; class MemoryManager; class Td; class TdDb; class TempAuthKeyWatchdog; class ThemeManager; class TopDialogManager; class UpdatesManager; class WebPagesManager; class Global final : public ActorContext { public: Global(); ~Global() final; Global(const Global &) = delete; Global &operator=(const Global &) = delete; Global(Global &&other) = delete; Global &operator=(Global &&other) = delete; static constexpr int32 ID = -572104940; int32 get_id() const final { return ID; } #define td_db() get_td_db_impl(__FILE__, __LINE__) TdDb *get_td_db_impl(const char *file, int line) { LOG_CHECK(td_db_) << close_flag() << " " << file << " " << line; return td_db_.get(); } void log_out(Slice reason); void close_all(Promise<> on_finished); void close_and_destroy_all(Promise<> on_finished); Status init(const TdParameters ¶meters, ActorId td, unique_ptr td_db_ptr) TD_WARN_UNUSED_RESULT; static bool get_use_custom_database(const std::string &database_directory) { auto s = get_database_directory_opts(database_directory); size_t qmarkpos; std::string token; size_t find_start_index = 0; while ((qmarkpos = s.find_first_of('&'), find_start_index) != std::string::npos) { token = s.substr(find_start_index, qmarkpos - find_start_index); find_start_index = qmarkpos; if ((qmarkpos = token.find_first_of('=')) != std::string::npos) { std::string propkey = token.substr(0, qmarkpos), propval = token.substr(qmarkpos + 1); if (propkey == "use_custom_database_format" && propval == "true") { return true; } } } return false; } static std::string get_database_directory_path(const std::string &database_directory) { if (database_directory.empty()) { return database_directory; } size_t qmarkpos; if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) { std::string path = database_directory.substr(0, qmarkpos), opts = database_directory.substr(qmarkpos + 1); return path; } else { return database_directory; } } static std::string get_database_directory_opts(const std::string &database_directory) { if (database_directory.empty()) { return database_directory; } size_t qmarkpos; if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) { std::string path = database_directory.substr(0, qmarkpos), opts = database_directory.substr(qmarkpos + 1); return opts; } else { return ""; } } bool get_use_custom_database() const { return parameters_.use_custom_db_format; }; Slice get_dir() const { return parameters_.database_directory; } Slice get_secure_files_dir() const { if (store_all_files_in_files_directory_) { return get_files_dir(); } return get_dir(); } Slice get_files_dir() const { return parameters_.files_directory; } bool is_test_dc() const { return parameters_.use_test_dc; } bool ignore_background_updates() const; NetQueryCreator &net_query_creator() { return *net_query_creator_.get(); } void set_net_query_stats(std::shared_ptr net_query_stats); void set_net_query_dispatcher(unique_ptr net_query_dispatcher); NetQueryDispatcher &net_query_dispatcher() { CHECK(have_net_query_dispatcher()); return *net_query_dispatcher_; } bool have_net_query_dispatcher() const { return net_query_dispatcher_.get() != nullptr; } void set_shared_config(unique_ptr shared_config); ConfigShared &shared_config() { CHECK(shared_config_.get() != nullptr); return *shared_config_; } bool is_server_time_reliable() const { return server_time_difference_was_updated_; } double to_server_time(double now) const { return now + get_server_time_difference(); } double server_time() const { return to_server_time(Time::now()); } double server_time_cached() const { return to_server_time(Time::now_cached()); } int32 unix_time() const { return to_unix_time(server_time()); } int32 unix_time_cached() const { return to_unix_time(server_time_cached()); } void update_server_time_difference(double diff); void save_server_time(); double get_server_time_difference() const { return server_time_difference_.load(std::memory_order_relaxed); } void update_dns_time_difference(double diff); double get_dns_time_difference() const; ActorId state_manager() const { return state_manager_; } void set_state_manager(ActorId state_manager) { state_manager_ = state_manager; } ActorId td() const { return td_; } ActorId animations_manager() const { return animations_manager_; } void set_animations_manager(ActorId animations_manager) { animations_manager_ = animations_manager; } ActorId background_manager() const { return background_manager_; } void set_background_manager(ActorId background_manager) { background_manager_ = background_manager; } ActorId call_manager() const { return call_manager_; } void set_call_manager(ActorId call_manager) { call_manager_ = call_manager; } ActorId config_manager() const { return config_manager_; } void set_config_manager(ActorId config_manager) { config_manager_ = config_manager; } ActorId contacts_manager() const { return contacts_manager_; } void set_contacts_manager(ActorId contacts_manager) { contacts_manager_ = contacts_manager; } ActorId download_manager() const { return download_manager_; } void set_download_manager(ActorId download_manager) { download_manager_ = std::move(download_manager); } ActorId file_manager() const { return file_manager_; } void set_file_manager(ActorId file_manager) { file_manager_ = std::move(file_manager); } ActorId file_reference_manager() const { return file_reference_manager_; } void set_file_reference_manager(ActorId file_reference_manager) { file_reference_manager_ = std::move(file_reference_manager); } ActorId game_manager() const { return game_manager_; } void set_game_manager(ActorId game_manager) { game_manager_ = game_manager; } ActorId group_call_manager() const { return group_call_manager_; } void set_group_call_manager(ActorId group_call_manager) { group_call_manager_ = group_call_manager; } ActorId language_pack_manager() const { return language_pack_manager_; } void set_language_pack_manager(ActorId language_pack_manager) { language_pack_manager_ = language_pack_manager; } ActorId link_manager() const { return link_manager_; } void set_link_manager(ActorId link_manager) { link_manager_ = link_manager; } ActorId messages_manager() const { return messages_manager_; } void set_messages_manager(ActorId messages_manager) { messages_manager_ = messages_manager; } ActorId notification_manager() const { return notification_manager_; } void set_notification_manager(ActorId notification_manager) { notification_manager_ = notification_manager; } ActorId notification_settings_manager() const { return notification_settings_manager_; } void set_notification_settings_manager(ActorId notification_settings_manager) { notification_settings_manager_ = notification_settings_manager; } ActorId option_manager() const { return option_manager_; } void set_option_manager(ActorId option_manager) { option_manager_ = option_manager; } ActorId password_manager() const { return password_manager_; } void set_password_manager(ActorId password_manager) { password_manager_ = password_manager; } ActorId secret_chats_manager() const { return secret_chats_manager_; } void set_secret_chats_manager(ActorId secret_chats_manager) { secret_chats_manager_ = secret_chats_manager; } ActorId sponsored_message_manager() const { return sponsored_message_manager_; } void set_sponsored_message_manager(ActorId sponsored_message_manager) { sponsored_message_manager_ = sponsored_message_manager; } ActorId stickers_manager() const { return stickers_manager_; } void set_stickers_manager(ActorId stickers_manager) { stickers_manager_ = stickers_manager; } ActorId storage_manager() const { return storage_manager_; } void set_storage_manager(ActorId storage_manager) { storage_manager_ = storage_manager; } ActorId memory_manager() const { return memory_manager_; } void set_memory_manager(ActorId memory_manager) { memory_manager_ = memory_manager; } ActorId theme_manager() const { return theme_manager_; } void set_theme_manager(ActorId theme_manager) { theme_manager_ = theme_manager; } ActorId top_dialog_manager() const { return top_dialog_manager_; } void set_top_dialog_manager(ActorId top_dialog_manager) { top_dialog_manager_ = top_dialog_manager; } ActorId updates_manager() const { return updates_manager_; } void set_updates_manager(ActorId updates_manager) { updates_manager_ = updates_manager; } ActorId web_pages_manager() const { return web_pages_manager_; } void set_web_pages_manager(ActorId web_pages_manager) { web_pages_manager_ = web_pages_manager; } ActorId connection_creator() const; void set_connection_creator(ActorOwn connection_creator); ActorId temp_auth_key_watchdog() const; void set_temp_auth_key_watchdog(ActorOwn actor); MtprotoHeader &mtproto_header(); void set_mtproto_header(unique_ptr mtproto_header); bool have_mtproto_header() const { return mtproto_header_ != nullptr; } const TdParameters ¶meters() const { return parameters_; } int64 get_my_id() const { return my_id_; } void set_my_id(int64 my_id) { my_id_ = my_id; } int32 get_gc_scheduler_id() const { return gc_scheduler_id_; } int32 get_slow_net_scheduler_id() const { return slow_net_scheduler_id_; } DcId get_webfile_dc_id() const; std::shared_ptr get_dh_config() { #if !TD_HAVE_ATOMIC_SHARED_PTR std::lock_guard guard(dh_config_mutex_); auto res = dh_config_; return res; #else return atomic_load(&dh_config_); #endif } void set_dh_config(std::shared_ptr new_dh_config) { #if !TD_HAVE_ATOMIC_SHARED_PTR std::lock_guard guard(dh_config_mutex_); dh_config_ = std::move(new_dh_config); #else atomic_store(&dh_config_, std::move(new_dh_config)); #endif } static Status request_aborted_error() { return Status::Error(500, "Request aborted"); } void set_close_flag() { close_flag_ = true; } bool close_flag() const { return close_flag_.load(); } Status close_status() const { return close_flag() ? request_aborted_error() : Status::OK(); } bool is_expected_error(const Status &error) const { CHECK(error.is_error()); if (error.code() == 401) { // authorization is lost return true; } if (error.code() == 420 || error.code() == 429) { // flood wait return true; } return close_flag(); } static int32 get_retry_after(int32 error_code, Slice error_message); const std::vector> &get_net_stats_file_callbacks() { return net_stats_file_callbacks_; } void set_net_stats_file_callbacks(std::vector> callbacks) { net_stats_file_callbacks_ = std::move(callbacks); } int64 get_location_access_hash(double latitude, double longitude); void add_location_access_hash(double latitude, double longitude, int64 access_hash); void set_store_all_files_in_files_directory(bool flag) { store_all_files_in_files_directory_ = flag; } private: std::shared_ptr dh_config_; unique_ptr td_db_; ActorId td_; ActorId animations_manager_; ActorId background_manager_; ActorId call_manager_; ActorId config_manager_; ActorId contacts_manager_; ActorId download_manager_; ActorId file_manager_; ActorId file_reference_manager_; ActorId game_manager_; ActorId group_call_manager_; ActorId language_pack_manager_; ActorId link_manager_; ActorId messages_manager_; ActorId notification_manager_; ActorId notification_settings_manager_; ActorId option_manager_; ActorId password_manager_; ActorId secret_chats_manager_; ActorId sponsored_message_manager_; ActorId stickers_manager_; ActorId storage_manager_; ActorId memory_manager_; ActorId theme_manager_; ActorId top_dialog_manager_; ActorId updates_manager_; ActorId web_pages_manager_; ActorOwn connection_creator_; ActorOwn temp_auth_key_watchdog_; unique_ptr mtproto_header_; TdParameters parameters_; int32 gc_scheduler_id_ = 0; int32 slow_net_scheduler_id_ = 0; std::atomic store_all_files_in_files_directory_{false}; std::atomic server_time_difference_{0.0}; std::atomic server_time_difference_was_updated_{false}; std::atomic dns_time_difference_{0.0}; std::atomic dns_time_difference_was_updated_{false}; std::atomic close_flag_{false}; std::atomic system_time_saved_at_{-1e10}; double saved_diff_ = 0.0; double saved_system_time_ = 0.0; #if !TD_HAVE_ATOMIC_SHARED_PTR std::mutex dh_config_mutex_; #endif std::vector> net_stats_file_callbacks_; ActorId state_manager_; LazySchedulerLocalStorage> net_query_creator_; unique_ptr net_query_dispatcher_; unique_ptr shared_config_; int64 my_id_ = 0; // hack static int64 get_location_key(double latitude, double longitude); FlatHashMap location_access_hashes_; int32 to_unix_time(double server_time) const; void do_save_server_time_difference(); void do_close(Promise<> on_finish, bool destroy_flag); }; #define G() G_impl(__FILE__, __LINE__) inline Global *G_impl(const char *file, int line) { ActorContext *context = Scheduler::context(); LOG_CHECK(context != nullptr && context->get_id() == Global::ID) << "Context = " << context << " in " << file << " at " << line; return static_cast(context); } double get_global_server_time(); } // namespace td