// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 // // 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) // #include "td/telegram/net/PublicRsaKeyWatchdog.h" #include "td/telegram/Global.h" #include "td/telegram/telegram_api.h" #include "td/utils/logging.h" #include "td/utils/Time.h" namespace td { PublicRsaKeyWatchdog::PublicRsaKeyWatchdog(ActorShared<> parent) : parent_(std::move(parent)) { } void PublicRsaKeyWatchdog::add_public_rsa_key(std::shared_ptr key) { class Listener : public PublicRsaKeyShared::Listener { public: explicit Listener(ActorId parent) : parent_(std::move(parent)) { } bool notify() override { send_event(parent_, Event::yield()); return parent_.is_alive(); } private: ActorId parent_; }; key->add_listener(std::make_unique(actor_id(this))); sync_key(key); keys_.push_back(std::move(key)); loop(); } void PublicRsaKeyWatchdog::start_up() { flood_control_.add_limit(1, 1); flood_control_.add_limit(2, 60); flood_control_.add_limit(3, 2 * 60); sync(BufferSlice(G()->td_db()->get_binlog_pmc()->get("cdn_config"))); } void PublicRsaKeyWatchdog::loop() { if (has_query_) { return; } if (Time::now_cached() < flood_control_.get_wakeup_at()) { return; } bool ok = true; for (auto &key : keys_) { if (!key->has_keys()) { ok = false; } } if (ok) { return; } flood_control_.add_event(static_cast(Time::now_cached())); has_query_ = true; G()->net_query_dispatcher().dispatch_with_callback( G()->net_query_creator().create(create_storer(telegram_api::help_getCdnConfig()), DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off, NetQuery::GzipFlag::On, 60 * 60 * 24), actor_shared(this)); } void PublicRsaKeyWatchdog::on_result(NetQueryPtr net_query) { has_query_ = false; yield(); if (net_query->is_error()) { LOG(ERROR) << "getCdnConfig error " << net_query->move_as_error(); return; } auto buf = net_query->move_as_ok(); G()->td_db()->get_binlog_pmc()->set("cdn_config", buf.as_slice().str()); sync(std::move(buf)); } void PublicRsaKeyWatchdog::sync(BufferSlice cdn_config_serialized) { if (cdn_config_serialized.empty()) { return; } auto r_keys = fetch_result(cdn_config_serialized); if (r_keys.is_error()) { LOG(WARNING) << "Failed to deserialize help_getCdnConfig (probably not a problem) " << r_keys.error(); return; } cdn_config_ = r_keys.move_as_ok(); for (auto &key : keys_) { sync_key(key); } } void PublicRsaKeyWatchdog::sync_key(std::shared_ptr &key) { if (!cdn_config_) { return; } for (auto &config_key : cdn_config_->public_keys_) { if (key->dc_id().get_raw_id() == config_key->dc_id_) { auto r_rsa = RSA::from_pem(config_key->public_key_); if (r_rsa.is_error()) { LOG(ERROR) << r_rsa.error(); continue; } key->add_rsa(r_rsa.move_as_ok()); } } } } // namespace td