2018-12-31 20:04:05 +01:00
|
|
|
//
|
2020-01-01 02:23:48 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
2018-12-31 20:04:05 +01:00
|
|
|
//
|
|
|
|
// 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"
|
2018-06-26 01:43:11 +02:00
|
|
|
#include "td/telegram/net/DcId.h"
|
2019-01-06 20:59:17 +01:00
|
|
|
#include "td/telegram/TdDb.h"
|
2018-12-31 20:04:05 +01:00
|
|
|
|
|
|
|
#include "td/telegram/telegram_api.h"
|
|
|
|
|
2019-01-31 03:05:40 +01:00
|
|
|
#include "td/mtproto/crypto.h"
|
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
#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<PublicRsaKeyShared> key) {
|
|
|
|
class Listener : public PublicRsaKeyShared::Listener {
|
|
|
|
public:
|
|
|
|
explicit Listener(ActorId<PublicRsaKeyWatchdog> parent) : parent_(std::move(parent)) {
|
|
|
|
}
|
|
|
|
bool notify() override {
|
|
|
|
send_event(parent_, Event::yield());
|
|
|
|
return parent_.is_alive();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ActorId<PublicRsaKeyWatchdog> parent_;
|
|
|
|
};
|
|
|
|
|
2018-09-27 03:19:03 +02:00
|
|
|
key->add_listener(make_unique<Listener>(actor_id(this)));
|
2018-12-31 20:04:05 +01:00
|
|
|
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<int32>(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(),
|
2019-12-13 02:00:33 +01:00
|
|
|
NetQuery::Type::Common, NetQuery::AuthFlag::On, NetQuery::GzipFlag::On,
|
2018-12-31 20:04:05 +01:00
|
|
|
60 * 60 * 24),
|
|
|
|
actor_shared(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PublicRsaKeyWatchdog::on_result(NetQueryPtr net_query) {
|
|
|
|
has_query_ = false;
|
|
|
|
yield();
|
|
|
|
if (net_query->is_error()) {
|
2019-02-21 16:58:20 +01:00
|
|
|
LOG(ERROR) << "Receive error for getCdnConfig: " << net_query->move_as_error();
|
2018-12-31 20:04:05 +01:00
|
|
|
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<telegram_api::help_getCdnConfig>(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();
|
2019-12-28 13:04:32 +01:00
|
|
|
LOG(INFO) << "Receive " << to_string(cdn_config_);
|
2018-12-31 20:04:05 +01:00
|
|
|
for (auto &key : keys_) {
|
|
|
|
sync_key(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PublicRsaKeyWatchdog::sync_key(std::shared_ptr<PublicRsaKeyShared> &key) {
|
|
|
|
if (!cdn_config_) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (auto &config_key : cdn_config_->public_keys_) {
|
|
|
|
if (key->dc_id().get_raw_id() == config_key->dc_id_) {
|
2020-03-10 16:27:43 +01:00
|
|
|
auto r_rsa = RSA::from_pem_public_key(config_key->public_key_);
|
2018-12-31 20:04:05 +01:00
|
|
|
if (r_rsa.is_error()) {
|
|
|
|
LOG(ERROR) << r_rsa.error();
|
|
|
|
continue;
|
|
|
|
}
|
2019-12-28 13:04:32 +01:00
|
|
|
LOG(INFO) << "Add CDN " << key->dc_id() << " key with fingerprint " << r_rsa.ok().get_fingerprint();
|
2018-12-31 20:04:05 +01:00
|
|
|
key->add_rsa(r_rsa.move_as_ok());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-09 05:56:06 +02:00
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
} // namespace td
|