summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/td/telegram/net/DcAuthManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/td/telegram/net/DcAuthManager.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/td/telegram/net/DcAuthManager.cpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/protocols/Telegram/tdlib/td/td/telegram/net/DcAuthManager.cpp b/protocols/Telegram/tdlib/td/td/telegram/net/DcAuthManager.cpp
new file mode 100644
index 0000000000..dd3776a449
--- /dev/null
+++ b/protocols/Telegram/tdlib/td/td/telegram/net/DcAuthManager.cpp
@@ -0,0 +1,217 @@
+//
+// 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/DcAuthManager.h"
+
+#include "td/actor/actor.h"
+
+#include "td/telegram/ConfigShared.h"
+#include "td/telegram/Global.h"
+#include "td/telegram/net/AuthDataShared.h"
+#include "td/telegram/net/NetQuery.h"
+#include "td/telegram/net/NetQueryDispatcher.h"
+#include "td/telegram/UniqueId.h"
+
+#include "td/telegram/telegram_api.h"
+
+#include "td/utils/format.h"
+#include "td/utils/logging.h"
+#include "td/utils/misc.h"
+
+#include <algorithm>
+#include <limits>
+
+namespace td {
+
+DcAuthManager::DcAuthManager(ActorShared<> parent) {
+ parent_ = std::move(parent);
+ auto s_main_dc_id = G()->td_db()->get_binlog_pmc()->get("main_dc_id");
+ if (!s_main_dc_id.empty()) {
+ main_dc_id_ = DcId::internal(to_integer<int32>(s_main_dc_id));
+ }
+}
+
+void DcAuthManager::add_dc(std::shared_ptr<AuthDataShared> auth_data) {
+ VLOG(dc) << "Register " << auth_data->dc_id();
+ class Listener : public AuthDataShared::Listener {
+ public:
+ explicit Listener(ActorShared<DcAuthManager> dc_manager) : dc_manager_(std::move(dc_manager)) {
+ }
+ bool notify() override {
+ if (!dc_manager_.is_alive()) {
+ return false;
+ }
+ send_closure(dc_manager_, &DcAuthManager::update_auth_state);
+ return true;
+ }
+
+ private:
+ ActorShared<DcAuthManager> dc_manager_;
+ };
+
+ DcInfo info;
+ info.dc_id = auth_data->dc_id();
+ CHECK(info.dc_id.is_exact());
+ info.shared_auth_data = std::move(auth_data);
+ auto state_was_auth = info.shared_auth_data->get_auth_state();
+ info.auth_state = state_was_auth.first;
+ was_auth_ |= state_was_auth.second;
+ if (!main_dc_id_.is_exact()) {
+ main_dc_id_ = info.dc_id;
+ }
+ info.shared_auth_data->add_auth_key_listener(std::make_unique<Listener>(actor_shared(this, info.dc_id.get_raw_id())));
+ dcs_.emplace_back(std::move(info));
+ loop();
+}
+
+void DcAuthManager::update_main_dc(DcId new_main_dc_id) {
+ main_dc_id_ = new_main_dc_id;
+ loop();
+}
+
+DcAuthManager::DcInfo &DcAuthManager::get_dc(int32 dc_id) {
+ auto *dc = find_dc(dc_id);
+ CHECK(dc);
+ return *dc;
+}
+DcAuthManager::DcInfo *DcAuthManager::find_dc(int32 dc_id) {
+ auto it = std::find_if(dcs_.begin(), dcs_.end(), [&](auto &x) { return x.dc_id.get_raw_id() == dc_id; });
+ if (it == dcs_.end()) {
+ return nullptr;
+ }
+ return &*it;
+}
+
+void DcAuthManager::update_auth_state() {
+ int32 dc_id = narrow_cast<int32>(get_link_token());
+ auto &dc = get_dc(dc_id);
+ auto state_was_auth = dc.shared_auth_data->get_auth_state();
+ VLOG(dc) << "Update dc auth state " << tag("dc_id", dc_id) << tag("old_auth_state", dc.auth_state)
+ << tag("new_auth_state", state_was_auth.first);
+ dc.auth_state = state_was_auth.first;
+ was_auth_ |= state_was_auth.second;
+
+ loop();
+}
+
+void DcAuthManager::on_result(NetQueryPtr result) {
+ int32 dc_id = narrow_cast<int32>(get_link_token());
+ auto &dc = get_dc(dc_id);
+ CHECK(dc.wait_id == result->id());
+ dc.wait_id = std::numeric_limits<decltype(dc.wait_id)>::max();
+ switch (dc.state) {
+ case DcInfo::State::Import: {
+ if (result->is_error()) {
+ LOG(WARNING) << "DC auth_exportAuthorization error: " << result->error();
+ dc.state = DcInfo::State::Export;
+ break;
+ }
+ auto result_auth_exported = fetch_result<telegram_api::auth_exportAuthorization>(result->ok());
+ if (result_auth_exported.is_error()) {
+ LOG(WARNING) << "Failed to parse result to auth_exportAuthorization: " << result_auth_exported.error();
+ dc.state = DcInfo::State::Export;
+ break;
+ }
+ dc.export_id = result_auth_exported.ok()->id_;
+ dc.export_bytes = std::move(result_auth_exported.ok()->bytes_);
+ break;
+ }
+ case DcInfo::State::BeforeOk: {
+ if (result->is_error()) {
+ LOG(WARNING) << "DC authImport error: " << result->error();
+ dc.state = DcInfo::State::Export;
+ break;
+ }
+ auto result_auth = fetch_result<telegram_api::auth_importAuthorization>(result->ok());
+ if (result_auth.is_error()) {
+ LOG(WARNING) << "Failed to parse result to auth_importAuthorization: " << result_auth.error();
+ dc.state = DcInfo::State::Export;
+ break;
+ }
+ dc.state = DcInfo::State::Ok;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ result->clear();
+ loop();
+}
+
+void DcAuthManager::dc_loop(DcInfo &dc) {
+ VLOG(dc) << "dc_loop " << dc.dc_id << " " << dc.auth_state;
+ if (dc.auth_state == AuthState::OK) {
+ return;
+ }
+ CHECK(dc.shared_auth_data);
+ switch (dc.state) {
+ case DcInfo::State::Waiting: {
+ // wait for timeout
+ // break;
+ }
+ case DcInfo::State::Export: {
+ // send auth.exportAuthorization to auth_dc
+ VLOG(dc) << "Send exportAuthorization to " << dc.dc_id;
+ auto id = UniqueId::next();
+ G()->net_query_dispatcher().dispatch_with_callback(
+ G()->net_query_creator().create(
+ id, create_storer(telegram_api::auth_exportAuthorization(dc.dc_id.get_raw_id())), DcId::main(),
+ NetQuery::Type::Common, NetQuery::AuthFlag::On, NetQuery::GzipFlag::On, 60 * 60 * 24),
+ actor_shared(this, dc.dc_id.get_raw_id()));
+ dc.wait_id = id;
+ dc.export_id = -1;
+ dc.state = DcInfo::State::Import;
+ break;
+ }
+ case DcInfo::State::Import: {
+ // send auth.importAuthorization to dc
+ if (dc.export_id == -1) {
+ break;
+ }
+ uint64 id = UniqueId::next();
+ VLOG(dc) << "Send importAuthorization to " << dc.dc_id;
+ G()->net_query_dispatcher().dispatch_with_callback(
+ G()->net_query_creator().create(
+ id, create_storer(telegram_api::auth_importAuthorization(dc.export_id, std::move(dc.export_bytes))),
+ dc.dc_id, NetQuery::Type::Common, NetQuery::AuthFlag::Off, NetQuery::GzipFlag::On, 60 * 60 * 24),
+ actor_shared(this, dc.dc_id.get_raw_id()));
+ dc.wait_id = id;
+ dc.state = DcInfo::State::BeforeOk;
+ break;
+ }
+ case DcInfo::State::BeforeOk: {
+ break;
+ }
+ case DcInfo::State::Ok: {
+ break;
+ }
+ }
+}
+
+void DcAuthManager::loop() {
+ if (close_flag_) {
+ VLOG(dc) << "Skip loop because close_flag";
+ return;
+ }
+ if (!main_dc_id_.is_exact()) {
+ VLOG(dc) << "Skip loop because main_dc_id is unknown";
+ return;
+ }
+ auto main_dc = find_dc(main_dc_id_.get_raw_id());
+ if (!main_dc || main_dc->auth_state != AuthState::OK) {
+ if (was_auth_) {
+ G()->shared_config().set_option_boolean("auth", false);
+ }
+ VLOG(dc) << "Skip loop because auth state of main dc " << main_dc_id_.get_raw_id() << " is "
+ << (main_dc != nullptr ? (PSTRING() << main_dc->auth_state) : "unknown");
+
+ return;
+ }
+ for (auto &dc : dcs_) {
+ dc_loop(dc);
+ }
+}
+} // namespace td