diff --git a/td/telegram/ConfigShared.cpp b/td/telegram/ConfigShared.cpp index 4957176e..bed7e039 100644 --- a/td/telegram/ConfigShared.cpp +++ b/td/telegram/ConfigShared.cpp @@ -13,12 +13,20 @@ namespace td { -ConfigShared::ConfigShared(std::shared_ptr config_pmc, unique_ptr callback) - : config_pmc_(std::move(config_pmc)), callback_(std::move(callback)) { +ConfigShared::ConfigShared(std::shared_ptr config_pmc) : config_pmc_(std::move(config_pmc)) { +} + +void ConfigShared::set_callback(unique_ptr callback) { + callback_ = std::move(callback); + if (callback_ == nullptr) { + return; + } + for (auto key_value : config_pmc_->get_all()) { on_option_updated(key_value.first); } } + void ConfigShared::set_option_boolean(Slice name, bool value) { if (set_option(name, value ? Slice("Btrue") : Slice("Bfalse"))) { on_option_updated(name); @@ -134,7 +142,9 @@ tl_object_ptr ConfigShared::get_option_value_object(Slice v } void ConfigShared::on_option_updated(Slice name) const { - callback_->on_option_updated(name.str(), get_option(name)); + if (callback_ != nullptr) { + callback_->on_option_updated(name.str(), get_option(name)); + } } } // namespace td diff --git a/td/telegram/ConfigShared.h b/td/telegram/ConfigShared.h index 2f14e754..ab8045f9 100644 --- a/td/telegram/ConfigShared.h +++ b/td/telegram/ConfigShared.h @@ -25,11 +25,15 @@ class ConfigShared { Callback() = default; Callback(const Callback &) = delete; Callback &operator=(const Callback &) = delete; + Callback(Callback &&) = delete; + Callback &operator=(Callback &&) = delete; virtual ~Callback() = default; virtual void on_option_updated(const string &name, const string &value) const = 0; }; - ConfigShared(std::shared_ptr config_pmc, unique_ptr callback); + explicit ConfigShared(std::shared_ptr config_pmc); + + void set_callback(unique_ptr callback); void set_option_boolean(Slice name, bool value); void set_option_empty(Slice name); diff --git a/td/telegram/Global.h b/td/telegram/Global.h index 3be96ba1..f4d08062 100644 --- a/td/telegram/Global.h +++ b/td/telegram/Global.h @@ -93,6 +93,7 @@ class Global : public ActorContext { void set_net_query_dispatcher(unique_ptr net_query_dispatcher); NetQueryDispatcher &net_query_dispatcher() { + CHECK(have_net_query_dispatcher()); return *net_query_dispatcher_; } diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 6be2655f..4b046aa0 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3943,6 +3943,30 @@ Status Td::init(DbKey key) { G()->set_state_manager(state_manager_.get()); connection_state_ = StateManager::State::Empty; + VLOG(td_init) << "Create ConfigShared"; + G()->set_shared_config(td::make_unique(G()->td_db()->get_config_pmc_shared())); + + if (G()->shared_config().have_option("language_database_path")) { + G()->shared_config().set_option_string("language_pack_database_path", + G()->shared_config().get_option_string("language_database_path")); + G()->shared_config().set_option_empty("language_database_path"); + } + if (G()->shared_config().have_option("language_pack")) { + G()->shared_config().set_option_string("localization_target", + G()->shared_config().get_option_string("language_pack")); + G()->shared_config().set_option_empty("language_pack"); + } + if (G()->shared_config().have_option("language_code")) { + G()->shared_config().set_option_string("language_pack_id", G()->shared_config().get_option_string("language_code")); + G()->shared_config().set_option_empty("language_code"); + } + if (!G()->shared_config().have_option("message_text_length_max")) { + G()->shared_config().set_option_integer("message_text_length_max", 4096); + } + if (!G()->shared_config().have_option("message_caption_length_max")) { + G()->shared_config().set_option_integer("message_caption_length_max", 200); + } + VLOG(td_init) << "Create ConnectionCreator"; { auto connection_creator = create_actor("ConnectionCreator", create_reference()); @@ -3973,7 +3997,6 @@ Status Td::init(DbKey key) { case td_api::removeProxy::ID: case td_api::getProxies::ID: case td_api::getProxyLink::ID: - case td_api::pingProxy::ID: return true; default: return false; @@ -3985,36 +4008,28 @@ Status Td::init(DbKey key) { auto temp_auth_key_watchdog = create_actor("TempAuthKeyWatchdog"); G()->set_temp_auth_key_watchdog(std::move(temp_auth_key_watchdog)); - VLOG(td_init) << "Create ConfigManager and ConfigShared"; + VLOG(td_init) << "Create ConfigManager"; + config_manager_ = create_actor("ConfigManager", create_reference()); + G()->set_config_manager(config_manager_.get()); + + VLOG(td_init) << "Set ConfigShared callback"; class ConfigSharedCallback : public ConfigShared::Callback { public: void on_option_updated(const string &name, const string &value) const override { send_closure(G()->td(), &Td::on_config_option_updated, name); } ~ConfigSharedCallback() override { - LOG(INFO) << "Destroy ConfigShared"; + LOG(INFO) << "Destroy ConfigSharedCallback"; } }; - - G()->set_shared_config( - td::make_unique(G()->td_db()->get_config_pmc_shared(), make_unique())); - config_manager_ = create_actor("ConfigManager", create_reference()); - G()->set_config_manager(config_manager_.get()); - - if (G()->shared_config().have_option("language_database_path")) { - G()->shared_config().set_option_string("language_pack_database_path", - G()->shared_config().get_option_string("language_database_path")); - G()->shared_config().set_option_empty("language_database_path"); - } - if (G()->shared_config().have_option("language_pack")) { - G()->shared_config().set_option_string("localization_target", - G()->shared_config().get_option_string("language_pack")); - G()->shared_config().set_option_empty("language_pack"); - } - if (G()->shared_config().have_option("language_code")) { - G()->shared_config().set_option_string("language_pack_id", G()->shared_config().get_option_string("language_code")); - G()->shared_config().set_option_empty("language_code"); - } + // we need to set ConfigShared callback before td_api::getOption requests are processed for consistency + // TODO currently they will be inconsistent anyway, because td_api::getOption returns current value, + // but in td_api::updateOption there will be a newer value, obtained at the time of update creation + // so, there can be even two succesive updateOption with the same value + // we need to process td_api::getOption along with td_api::setOption for consistency + // we need to process td_api::setOption before managers and MTProto header are created, + // because their initialiation may be affected by the options + G()->shared_config().set_callback(make_unique()); complete_pending_preauthentication_requests([](int32 id) { switch (id) { @@ -4032,17 +4047,15 @@ Status Td::init(DbKey key) { // options_.proxy = Proxy(); G()->set_mtproto_header(make_unique(options_)); - if (!G()->shared_config().have_option("message_text_length_max")) { - G()->shared_config().set_option_integer("message_text_length_max", 4096); - } - if (!G()->shared_config().have_option("message_caption_length_max")) { - G()->shared_config().set_option_integer("message_caption_length_max", 200); - } - VLOG(td_init) << "Create NetQueryDispatcher"; auto net_query_dispatcher = make_unique([&] { return create_reference(); }); G()->set_net_query_dispatcher(std::move(net_query_dispatcher)); + complete_pending_preauthentication_requests([](int32 id) { + // pingProxy uses NetQueryDispatcher to get main_dc_id, so must be called after NetQueryDispatcher is created + return id == td_api::pingProxy::ID; + }); + VLOG(td_init) << "Create AuthManager"; auth_manager_ = td::make_unique(parameters_.api_id, parameters_.api_hash, create_reference()); auth_manager_actor_ = register_actor("AuthManager", auth_manager_.get()); @@ -4203,6 +4216,8 @@ Status Td::init(DbKey key) { complete_pending_preauthentication_requests([](int32 id) { return true; }); + VLOG(td_init) << "Finish initialization"; + state_ = State::Run; return Status::OK(); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 7b1bdbaa..27e3b2ef 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -594,7 +594,7 @@ class CliClient final : public Actor { // LOG(INFO) << "on_result [" << generation << "][id=" << id << "] " << as_json_str; if (generation != generation_) { - LOG(INFO) << "Drop unneded " << to_string(result); + LOG(INFO) << "Drop received from previous Client " << to_string(result); return; } @@ -801,6 +801,8 @@ class CliClient final : public Actor { send_request(td_api::make_object("use_pfs")); send_request(td_api::make_object( "use_pfs", td_api::make_object(std::time(nullptr) / 86400 % 2 == 0))); + send_request(td_api::make_object("notification_group_count_max", + td_api::make_object(1))); send_request(td_api::make_object("use_storage_optimizer", td_api::make_object(false))); send_request( @@ -809,6 +811,11 @@ class CliClient final : public Actor { send_request(td_api::make_object(td_api::make_object())); send_request(td_api::make_object()); send_request(td_api::make_object()); + send_request( + td_api::make_object("1.1.1.1", 1111, true, td_api::make_object())); + send_request(td_api::make_object("1.1.1.1", 1112, false, + td_api::make_object())); + send_request(td_api::make_object(0)); auto bad_parameters = td_api::make_object(); bad_parameters->database_directory_ = "/.."; @@ -3812,6 +3819,7 @@ void main(int argc, char **argv) { dump_memory_usage(); } + } // namespace td int main(int argc, char **argv) {