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/Global.h"
|
|
|
|
|
|
|
|
#include "td/telegram/ConfigShared.h"
|
|
|
|
#include "td/telegram/net/ConnectionCreator.h"
|
|
|
|
#include "td/telegram/net/MtprotoHeader.h"
|
|
|
|
#include "td/telegram/net/NetQueryDispatcher.h"
|
|
|
|
#include "td/telegram/net/TempAuthKeyWatchdog.h"
|
2018-10-28 18:30:47 +01:00
|
|
|
#include "td/telegram/StateManager.h"
|
2020-01-08 21:41:03 +01:00
|
|
|
#include "td/telegram/Td.h"
|
2018-12-31 20:04:05 +01:00
|
|
|
#include "td/telegram/TdDb.h"
|
|
|
|
|
|
|
|
#include "td/actor/PromiseFuture.h"
|
|
|
|
|
|
|
|
#include "td/utils/format.h"
|
2019-02-12 21:48:16 +01:00
|
|
|
#include "td/utils/logging.h"
|
2018-12-31 20:04:05 +01:00
|
|
|
#include "td/utils/port/Clocks.h"
|
|
|
|
#include "td/utils/tl_helpers.h"
|
|
|
|
|
2018-08-14 01:11:49 +02:00
|
|
|
#include <cmath>
|
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
namespace td {
|
|
|
|
|
|
|
|
Global::Global() = default;
|
|
|
|
|
|
|
|
Global::~Global() = default;
|
|
|
|
|
|
|
|
void Global::close_all(Promise<> on_finished) {
|
|
|
|
td_db_->close_all(std::move(on_finished));
|
|
|
|
state_manager_.clear();
|
|
|
|
parameters_ = TdParameters();
|
|
|
|
}
|
|
|
|
void Global::close_and_destroy_all(Promise<> on_finished) {
|
|
|
|
td_db_->close_and_destroy_all(std::move(on_finished));
|
|
|
|
state_manager_.clear();
|
|
|
|
parameters_ = TdParameters();
|
|
|
|
}
|
|
|
|
|
|
|
|
ActorId<ConnectionCreator> Global::connection_creator() const {
|
|
|
|
return connection_creator_.get();
|
|
|
|
}
|
|
|
|
void Global::set_connection_creator(ActorOwn<ConnectionCreator> connection_creator) {
|
|
|
|
connection_creator_ = std::move(connection_creator);
|
|
|
|
}
|
|
|
|
|
|
|
|
ActorId<TempAuthKeyWatchdog> Global::temp_auth_key_watchdog() const {
|
|
|
|
return temp_auth_key_watchdog_.get();
|
|
|
|
}
|
|
|
|
void Global::set_temp_auth_key_watchdog(ActorOwn<TempAuthKeyWatchdog> actor) {
|
|
|
|
temp_auth_key_watchdog_ = std::move(actor);
|
|
|
|
}
|
|
|
|
|
2018-05-08 22:02:15 +02:00
|
|
|
MtprotoHeader &Global::mtproto_header() {
|
2018-12-31 20:04:05 +01:00
|
|
|
return *mtproto_header_;
|
|
|
|
}
|
2018-09-27 03:19:03 +02:00
|
|
|
void Global::set_mtproto_header(unique_ptr<MtprotoHeader> mtproto_header) {
|
2018-12-31 20:04:05 +01:00
|
|
|
mtproto_header_ = std::move(mtproto_header);
|
|
|
|
}
|
|
|
|
|
2019-12-25 15:36:31 +01:00
|
|
|
struct ServerTimeDiff {
|
2019-12-25 11:44:44 +01:00
|
|
|
double diff;
|
|
|
|
double system_time;
|
|
|
|
|
|
|
|
template <class StorerT>
|
|
|
|
void store(StorerT &storer) const {
|
|
|
|
using td::store;
|
|
|
|
store(diff, storer);
|
|
|
|
store(system_time, storer);
|
|
|
|
}
|
|
|
|
template <class ParserT>
|
|
|
|
void parse(ParserT &parser) {
|
|
|
|
using td::parse;
|
|
|
|
parse(diff, parser);
|
|
|
|
if (parser.get_left_len() != 0) {
|
|
|
|
parse(system_time, parser);
|
|
|
|
} else {
|
|
|
|
system_time = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-04-08 00:09:54 +02:00
|
|
|
Status Global::init(const TdParameters ¶meters, ActorId<Td> td, unique_ptr<TdDb> td_db_ptr) {
|
2018-12-31 20:04:05 +01:00
|
|
|
parameters_ = parameters;
|
|
|
|
|
2018-02-12 11:37:54 +01:00
|
|
|
gc_scheduler_id_ = min(Scheduler::instance()->sched_id() + 2, Scheduler::instance()->sched_count() - 1);
|
|
|
|
slow_net_scheduler_id_ = min(Scheduler::instance()->sched_id() + 3, Scheduler::instance()->sched_count() - 1);
|
2018-12-31 20:04:05 +01:00
|
|
|
|
|
|
|
td_ = td;
|
2019-04-08 00:09:54 +02:00
|
|
|
td_db_ = std::move(td_db_ptr);
|
2018-12-31 20:04:05 +01:00
|
|
|
|
2019-12-25 11:44:44 +01:00
|
|
|
string saved_diff_str = td_db()->get_binlog_pmc()->get("server_time_difference");
|
2019-12-29 22:02:12 +01:00
|
|
|
auto system_time = Clocks::system();
|
2019-12-24 16:51:41 +01:00
|
|
|
auto default_time_difference = system_time - Time::now();
|
2019-12-25 11:44:44 +01:00
|
|
|
if (saved_diff_str.empty()) {
|
2019-07-04 18:21:07 +02:00
|
|
|
server_time_difference_ = default_time_difference;
|
2018-12-31 20:04:05 +01:00
|
|
|
} else {
|
2019-12-25 15:36:31 +01:00
|
|
|
ServerTimeDiff saved_diff;
|
2019-12-25 11:44:44 +01:00
|
|
|
unserialize(saved_diff, saved_diff_str).ensure();
|
2019-12-24 16:51:41 +01:00
|
|
|
|
2020-02-22 17:31:08 +01:00
|
|
|
saved_diff_ = saved_diff.diff;
|
|
|
|
saved_system_time_ = saved_diff.system_time;
|
|
|
|
|
2019-12-25 11:44:44 +01:00
|
|
|
double diff = saved_diff.diff + default_time_difference;
|
|
|
|
if (saved_diff.system_time > system_time) {
|
|
|
|
double time_backwards_fix = saved_diff.system_time - system_time;
|
2019-12-25 16:35:36 +01:00
|
|
|
if (time_backwards_fix > 60) {
|
|
|
|
LOG(WARNING) << "Fix system time which went backwards: " << format::as_time(time_backwards_fix) << " "
|
|
|
|
<< tag("saved_system_time", saved_diff.system_time) << tag("system_time", system_time);
|
|
|
|
}
|
2019-12-24 16:51:41 +01:00
|
|
|
diff += time_backwards_fix;
|
2020-01-23 23:07:53 +01:00
|
|
|
} else if (saved_diff.system_time != 0) {
|
2020-01-06 02:23:59 +01:00
|
|
|
const double MAX_TIME_FORWARD = 367 * 86400; // if more than 1 year has passed, the session is logged out anyway
|
|
|
|
if (saved_diff.system_time + MAX_TIME_FORWARD < system_time) {
|
|
|
|
double time_forward_fix = system_time - (saved_diff.system_time + MAX_TIME_FORWARD);
|
|
|
|
LOG(WARNING) << "Fix system time which went forward: " << format::as_time(time_forward_fix) << " "
|
|
|
|
<< tag("saved_system_time", saved_diff.system_time) << tag("system_time", system_time);
|
|
|
|
diff -= time_forward_fix;
|
|
|
|
}
|
2020-03-10 23:24:07 +01:00
|
|
|
} else if (saved_diff.diff >= 1500000000 && system_time >= 1500000000) { // only for saved_diff.system_time == 0
|
|
|
|
diff = default_time_difference;
|
2019-12-24 16:51:41 +01:00
|
|
|
}
|
2018-12-31 20:04:05 +01:00
|
|
|
LOG(DEBUG) << "LOAD: " << tag("server_time_difference", diff);
|
|
|
|
server_time_difference_ = diff;
|
|
|
|
}
|
2019-12-25 15:36:31 +01:00
|
|
|
server_time_difference_was_updated_ = false;
|
2019-07-04 18:21:07 +02:00
|
|
|
dns_time_difference_ = default_time_difference;
|
|
|
|
dns_time_difference_was_updated_ = false;
|
2018-12-31 20:04:05 +01:00
|
|
|
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
2020-02-22 17:31:08 +01:00
|
|
|
int32 Global::to_unix_time(double server_time) const {
|
|
|
|
LOG_CHECK(1.0 <= server_time && server_time <= 2140000000.0)
|
|
|
|
<< server_time << " " << Clocks::system() << " " << saved_diff_ << " " << saved_system_time_;
|
2019-12-25 16:35:36 +01:00
|
|
|
return static_cast<int32>(server_time);
|
|
|
|
}
|
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
void Global::update_server_time_difference(double diff) {
|
|
|
|
if (!server_time_difference_was_updated_ || server_time_difference_ < diff) {
|
|
|
|
server_time_difference_ = diff;
|
|
|
|
server_time_difference_was_updated_ = true;
|
2019-12-25 11:44:44 +01:00
|
|
|
do_save_server_time_difference();
|
2020-01-08 21:41:03 +01:00
|
|
|
|
|
|
|
CHECK(Scheduler::instance());
|
|
|
|
send_closure(td(), &Td::on_update_server_time_difference);
|
2019-12-24 16:51:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-25 14:57:18 +01:00
|
|
|
void Global::save_server_time() {
|
2019-12-24 16:51:41 +01:00
|
|
|
auto t = Time::now();
|
2019-12-25 16:03:08 +01:00
|
|
|
if (server_time_difference_was_updated_ && system_time_saved_at_.load(std::memory_order_relaxed) + 10 < t) {
|
2019-12-24 16:51:41 +01:00
|
|
|
system_time_saved_at_ = t;
|
2019-12-25 11:44:44 +01:00
|
|
|
do_save_server_time_difference();
|
2018-12-31 20:04:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-25 11:44:44 +01:00
|
|
|
void Global::do_save_server_time_difference() {
|
|
|
|
LOG(INFO) << "Save server time difference";
|
|
|
|
// diff = server_time - Time::now
|
|
|
|
// fixed_diff = server_time - Clocks::system
|
|
|
|
double system_time = Clocks::system();
|
|
|
|
double fixed_diff = server_time_difference_ + Time::now() - system_time;
|
|
|
|
|
2019-12-25 15:36:31 +01:00
|
|
|
ServerTimeDiff diff;
|
2019-12-25 11:44:44 +01:00
|
|
|
diff.diff = fixed_diff;
|
|
|
|
diff.system_time = system_time;
|
|
|
|
td_db()->get_binlog_pmc()->set("server_time_difference", serialize(diff));
|
|
|
|
}
|
|
|
|
|
2019-07-04 18:21:07 +02:00
|
|
|
void Global::update_dns_time_difference(double diff) {
|
|
|
|
dns_time_difference_ = diff;
|
|
|
|
dns_time_difference_was_updated_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
double Global::get_dns_time_difference() const {
|
|
|
|
bool dns_flag = dns_time_difference_was_updated_;
|
|
|
|
double dns_diff = dns_time_difference_;
|
|
|
|
bool server_flag = server_time_difference_was_updated_;
|
|
|
|
double server_diff = server_time_difference_;
|
|
|
|
if (dns_flag != server_flag) {
|
|
|
|
return dns_flag ? dns_diff : server_diff;
|
|
|
|
}
|
|
|
|
if (dns_flag) {
|
2019-07-23 00:50:12 +02:00
|
|
|
return max(dns_diff, server_diff);
|
2019-07-04 18:21:07 +02:00
|
|
|
}
|
2019-07-22 04:04:18 +02:00
|
|
|
if (td_db_) {
|
|
|
|
return server_diff;
|
|
|
|
}
|
|
|
|
return Clocks::system() - Time::now();
|
2019-07-04 18:21:07 +02:00
|
|
|
}
|
|
|
|
|
2018-06-25 23:10:53 +02:00
|
|
|
DcId Global::get_webfile_dc_id() const {
|
2019-01-06 23:20:38 +01:00
|
|
|
CHECK(shared_config_ != nullptr);
|
2018-06-25 23:10:53 +02:00
|
|
|
int32 dc_id = shared_config_->get_option_integer("webfile_dc_id");
|
|
|
|
if (!DcId::is_valid(dc_id)) {
|
|
|
|
if (is_test_dc()) {
|
|
|
|
dc_id = 2;
|
|
|
|
} else {
|
|
|
|
dc_id = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(DcId::is_valid(dc_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
return DcId::internal(dc_id);
|
|
|
|
}
|
|
|
|
|
2019-04-21 20:17:11 +02:00
|
|
|
bool Global::ignore_backgrond_updates() const {
|
|
|
|
return !parameters_.use_file_db && !parameters_.use_secret_chats &&
|
|
|
|
shared_config_->get_option_boolean("ignore_background_updates");
|
|
|
|
}
|
|
|
|
|
2018-09-27 03:19:03 +02:00
|
|
|
void Global::set_net_query_dispatcher(unique_ptr<NetQueryDispatcher> net_query_dispatcher) {
|
2018-12-31 20:04:05 +01:00
|
|
|
net_query_dispatcher_ = std::move(net_query_dispatcher);
|
|
|
|
}
|
2018-06-25 23:10:53 +02:00
|
|
|
|
2018-09-27 03:19:03 +02:00
|
|
|
void Global::set_shared_config(unique_ptr<ConfigShared> shared_config) {
|
2018-12-31 20:04:05 +01:00
|
|
|
shared_config_ = std::move(shared_config);
|
|
|
|
}
|
|
|
|
|
2018-08-14 01:11:49 +02:00
|
|
|
int64 Global::get_location_key(double latitude, double longitude) {
|
|
|
|
const double PI = 3.14159265358979323846;
|
|
|
|
latitude *= PI / 180;
|
|
|
|
longitude *= PI / 180;
|
|
|
|
|
|
|
|
int64 key = 0;
|
|
|
|
if (latitude < 0) {
|
|
|
|
latitude = -latitude;
|
|
|
|
key = 65536;
|
|
|
|
}
|
|
|
|
|
|
|
|
double f = std::tan(PI / 4 - latitude / 2);
|
|
|
|
key += static_cast<int64>(f * std::cos(longitude) * 128) * 256;
|
|
|
|
key += static_cast<int64>(f * std::sin(longitude) * 128);
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64 Global::get_location_access_hash(double latitude, double longitude) {
|
|
|
|
auto it = location_access_hashes_.find(get_location_key(latitude, longitude));
|
|
|
|
if (it == location_access_hashes_.end()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Global::add_location_access_hash(double latitude, double longitude, int64 access_hash) {
|
|
|
|
if (access_hash == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
location_access_hashes_[get_location_key(latitude, longitude)] = access_hash;
|
|
|
|
}
|
|
|
|
|
2020-02-01 05:43:54 +01:00
|
|
|
double get_server_time() {
|
|
|
|
return G()->server_time();
|
|
|
|
}
|
|
|
|
|
2018-12-31 20:04:05 +01:00
|
|
|
} // namespace td
|