summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/td/telegram/Global.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/td/telegram/Global.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/td/telegram/Global.cpp278
1 files changed, 251 insertions, 27 deletions
diff --git a/protocols/Telegram/tdlib/td/td/telegram/Global.cpp b/protocols/Telegram/tdlib/td/td/telegram/Global.cpp
index 22a3e25323..79bf898a49 100644
--- a/protocols/Telegram/tdlib/td/td/telegram/Global.cpp
+++ b/protocols/Telegram/tdlib/td/td/telegram/Global.cpp
@@ -1,37 +1,43 @@
//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
+// 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)
//
#include "td/telegram/Global.h"
-#include "td/telegram/ConfigShared.h"
+#include "td/telegram/AuthManager.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"
+#include "td/telegram/OptionManager.h"
+#include "td/telegram/StateManager.h"
#include "td/telegram/TdDb.h"
-#include "td/telegram/Version.h"
-
-#include "td/actor/MultiPromise.h"
-#include "td/actor/PromiseFuture.h"
#include "td/utils/format.h"
+#include "td/utils/logging.h"
+#include "td/utils/misc.h"
#include "td/utils/port/Clocks.h"
#include "td/utils/tl_helpers.h"
+#include <cmath>
+
namespace td {
Global::Global() = default;
Global::~Global() = default;
+void Global::log_out(Slice reason) {
+ send_closure(auth_manager_, &AuthManager::on_authorization_lost, reason.str());
+}
+
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();
@@ -52,56 +58,274 @@ void Global::set_temp_auth_key_watchdog(ActorOwn<TempAuthKeyWatchdog> actor) {
temp_auth_key_watchdog_ = std::move(actor);
}
-const MtprotoHeader &Global::mtproto_header() const {
+MtprotoHeader &Global::mtproto_header() {
return *mtproto_header_;
}
-void Global::set_mtproto_header(std::unique_ptr<MtprotoHeader> mtproto_header) {
+void Global::set_mtproto_header(unique_ptr<MtprotoHeader> mtproto_header) {
mtproto_header_ = std::move(mtproto_header);
}
-Status Global::init(const TdParameters &parameters, ActorId<Td> td, std::unique_ptr<TdDb> td_db) {
+struct ServerTimeDiff {
+ 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;
+ }
+ }
+};
+
+Status Global::init(const TdParameters &parameters, ActorId<Td> td, unique_ptr<TdDb> td_db_ptr) {
parameters_ = parameters;
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);
td_ = td;
- td_db_ = std::move(td_db);
+ td_db_ = std::move(td_db_ptr);
- string save_diff_str = this->td_db()->get_binlog_pmc()->get("server_time_difference");
- if (save_diff_str.empty()) {
- server_time_difference_ = Clocks::system() - Time::now();
- server_time_difference_was_updated_ = false;
+ string saved_diff_str = td_db()->get_binlog_pmc()->get("server_time_difference");
+ auto system_time = Clocks::system();
+ auto default_time_difference = system_time - Time::now();
+ if (saved_diff_str.empty()) {
+ server_time_difference_ = default_time_difference;
} else {
- double save_diff;
- unserialize(save_diff, save_diff_str).ensure();
- double diff = save_diff + Clocks::system() - Time::now();
+ ServerTimeDiff saved_diff;
+ unserialize(saved_diff, saved_diff_str).ensure();
+
+ saved_diff_ = saved_diff.diff;
+ saved_system_time_ = saved_diff.system_time;
+
+ 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;
+ 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);
+ }
+ diff += time_backwards_fix;
+ } else if (saved_diff.system_time != 0) {
+ 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;
+ }
+ } else if (saved_diff.diff >= 1500000000 && system_time >= 1500000000) { // only for saved_diff.system_time == 0
+ diff = default_time_difference;
+ }
LOG(DEBUG) << "LOAD: " << tag("server_time_difference", diff);
server_time_difference_ = diff;
- server_time_difference_was_updated_ = false;
}
+ server_time_difference_was_updated_ = false;
+ dns_time_difference_ = default_time_difference;
+ dns_time_difference_was_updated_ = false;
return Status::OK();
}
+int32 Global::get_retry_after(int32 error_code, Slice error_message) {
+ if (error_code != 429) {
+ return 0;
+ }
+
+ Slice retry_after_prefix("Too Many Requests: retry after ");
+ if (!begins_with(error_message, retry_after_prefix)) {
+ return 0;
+ }
+
+ auto r_retry_after = to_integer_safe<int32>(error_message.substr(retry_after_prefix.size()));
+ if (r_retry_after.is_ok() && r_retry_after.ok() > 0) {
+ return r_retry_after.ok();
+ }
+ return 0;
+}
+
+int32 Global::to_unix_time(double server_time) const {
+ LOG_CHECK(1.0 <= server_time && server_time <= 2140000000.0)
+ << server_time << ' ' << Clocks::system() << ' ' << is_server_time_reliable() << ' '
+ << get_server_time_difference() << ' ' << Time::now() << ' ' << saved_diff_ << ' ' << saved_system_time_;
+ return static_cast<int32>(server_time);
+}
+
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;
+ do_save_server_time_difference();
+
+ get_option_manager()->on_update_server_time_difference();
+ }
+}
+
+void Global::save_server_time() {
+ auto t = Time::now();
+ if (server_time_difference_was_updated_ && system_time_saved_at_.load(std::memory_order_relaxed) + 10 < t) {
+ system_time_saved_at_ = t;
+ do_save_server_time_difference();
+ }
+}
+
+void Global::do_save_server_time_difference() {
+ if (get_option_boolean("disable_time_adjustment_protection")) {
+ td_db()->get_binlog_pmc()->erase("server_time_difference");
+ return;
+ }
+
+ // 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;
+
+ ServerTimeDiff diff;
+ diff.diff = fixed_diff;
+ diff.system_time = system_time;
+ td_db()->get_binlog_pmc()->set("server_time_difference", serialize(diff));
+}
+
+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) {
+ return max(dns_diff, server_diff);
+ }
+ if (td_db_) {
+ return server_diff;
+ }
+ return Clocks::system() - Time::now();
+}
+
+DcId Global::get_webfile_dc_id() const {
+ auto dc_id = narrow_cast<int32>(get_option_integer("webfile_dc_id"));
+ if (!DcId::is_valid(dc_id)) {
+ if (is_test_dc()) {
+ dc_id = 2;
+ } else {
+ dc_id = 4;
+ }
- // diff = server_time - Time::now
- // save_diff = server_time - Clocks::system
- double save_diff = diff + Time::now() - Clocks::system();
- auto str = serialize(save_diff);
- td_db()->get_binlog_pmc()->set("server_time_difference", str);
+ CHECK(DcId::is_valid(dc_id));
}
+
+ return DcId::internal(dc_id);
+}
+
+bool Global::ignore_background_updates() const {
+ return !parameters_.use_file_db && !parameters_.use_secret_chats && get_option_boolean("ignore_background_updates");
+}
+
+void Global::set_net_query_stats(std::shared_ptr<NetQueryStats> net_query_stats) {
+ net_query_creator_.set_create_func(
+ [net_query_stats = std::move(net_query_stats)] { return td::make_unique<NetQueryCreator>(net_query_stats); });
}
-void Global::set_net_query_dispatcher(std::unique_ptr<NetQueryDispatcher> net_query_dispatcher) {
+void Global::set_net_query_dispatcher(unique_ptr<NetQueryDispatcher> net_query_dispatcher) {
net_query_dispatcher_ = std::move(net_query_dispatcher);
}
-void Global::set_shared_config(std::unique_ptr<ConfigShared> shared_config) {
- shared_config_ = std::move(shared_config);
+
+const OptionManager *Global::get_option_manager() const {
+ CHECK(option_manager_ != nullptr);
+ return option_manager_;
+}
+
+OptionManager *Global::get_option_manager() {
+ CHECK(option_manager_ != nullptr);
+ return option_manager_;
+}
+
+void Global::set_option_empty(Slice name) {
+ get_option_manager()->set_option_empty(name);
+}
+
+void Global::set_option_boolean(Slice name, bool value) {
+ get_option_manager()->set_option_boolean(name, value);
+}
+
+void Global::set_option_integer(Slice name, int64 value) {
+ get_option_manager()->set_option_integer(name, value);
+}
+
+void Global::set_option_string(Slice name, Slice value) {
+ get_option_manager()->set_option_string(name, value);
+}
+
+bool Global::have_option(Slice name) const {
+ return get_option_manager()->have_option(name);
+}
+
+bool Global::get_option_boolean(Slice name, bool default_value) const {
+ return get_option_manager()->get_option_boolean(name, default_value);
+}
+
+int64 Global::get_option_integer(Slice name, int64 default_value) const {
+ return get_option_manager()->get_option_integer(name, default_value);
+}
+
+string Global::get_option_string(Slice name, string default_value) const {
+ return get_option_manager()->get_option_string(name, std::move(default_value));
+}
+
+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);
+ if (key == 0) {
+ key = 1;
+ }
+ 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;
+}
+
+double get_global_server_time() {
+ return G()->server_time();
}
} // namespace td