From 85d10e91c3daf7b3518a8f7b2f63759fa8cfd656 Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Wed, 14 Mar 2018 21:04:41 +0300 Subject: [PATCH] Store in db AuthManager in state WaitCode GitOrigin-RevId: 06df8525c60f4de347c694e8c212a138c151ac4c --- CMakeLists.txt | 1 + td/telegram/AuthManager.cpp | 65 ++++++++++++++++++++++++++----- td/telegram/AuthManager.h | 35 ++++++++++++++++- td/telegram/AuthManager.hpp | 72 +++++++++++++++++++++++++++++++++++ tdutils/td/utils/tl_helpers.h | 9 +++++ 5 files changed, 171 insertions(+), 11 deletions(-) create mode 100644 td/telegram/AuthManager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c222ddb7..6bdd33b55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -523,6 +523,7 @@ set(TDLIB_SOURCE td/telegram/AnimationsManager.hpp td/telegram/AudiosManager.hpp + td/telegram/AuthManager.hpp td/telegram/DocumentsManager.hpp td/telegram/files/FileId.hpp td/telegram/files/FileManager.hpp diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index a8ae88965..e157bbe6a 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -5,6 +5,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include "td/telegram/AuthManager.h" +#include "td/telegram/AuthManager.hpp" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -18,6 +19,8 @@ #include "td/telegram/Td.h" #include "td/telegram/UpdatesManager.h" +#include "td/telegram/logevent/LogEvent.h" + #include "td/actor/PromiseFuture.h" #include "td/utils/buffer.h" @@ -34,8 +37,7 @@ void SendCodeHelper::on_sent_code(telegram_api::object_ptrphone_code_hash_; sent_code_info_ = get_authentication_code_info(std::move(sent_code->type_)); next_code_info_ = get_authentication_code_info(std::move(sent_code->next_type_)); - next_code_timeout_ = static_cast(Time::now()) + - ((sent_code->flags_ & SENT_CODE_FLAG_HAS_TIMEOUT) != 0 ? sent_code->timeout_ : 0); + next_code_timestamp_ = Timestamp::in((sent_code->flags_ & SENT_CODE_FLAG_HAS_TIMEOUT) != 0 ? sent_code->timeout_ : 0); } td_api::object_ptr SendCodeHelper::get_authorization_state_wait_code() const { @@ -43,9 +45,9 @@ td_api::object_ptr SendCodeHelper::get_autho } td_api::object_ptr SendCodeHelper::get_authentication_code_info_object() const { - return make_tl_object(get_authentication_code_type_object(sent_code_info_), - get_authentication_code_type_object(next_code_info_), - max(next_code_timeout_ - static_cast(Time::now()), 0)); + return make_tl_object( + get_authentication_code_type_object(sent_code_info_), get_authentication_code_type_object(next_code_info_), + max(static_cast(next_code_timestamp_.in() + 1 - 1e-9), 0)); } Result SendCodeHelper::resend_code() { @@ -53,8 +55,8 @@ Result SendCodeHelper::resend_code() { return Status::Error(8, "Authentication code can't be resend"); } sent_code_info_ = next_code_info_; - next_code_info_ = AuthenticationCodeInfo(); - next_code_timeout_ = 0; + next_code_info_ = {}; + next_code_timestamp_ = {}; return telegram_api::auth_resendCode(phone_number_, phone_code_hash_); } @@ -327,7 +329,9 @@ AuthManager::AuthManager(int32 api_id, const string &api_hash, ActorShared<> par } else if (auth_str == "logout") { update_state(State::LoggingOut); } else { - update_state(State::WaitPhoneNumber); + if (!load_state()) { + update_state(State::WaitPhoneNumber); + } } } @@ -816,11 +820,14 @@ void AuthManager::on_result(NetQueryPtr result) { } } -void AuthManager::update_state(State new_state, bool force) { +void AuthManager::update_state(State new_state, bool force, bool should_save_state) { if (state_ == new_state && !force) { return; } state_ = new_state; + if (should_save_state) { + save_state(); + } send_closure(G()->td(), &Td::send_update, make_tl_object(get_authorization_state_object(state_))); @@ -832,4 +839,44 @@ void AuthManager::update_state(State new_state, bool force) { } } +bool AuthManager::load_state() { + auto data = G()->td_db()->get_binlog_pmc()->get("auth_state"); + DbState db_state; + auto status = log_event_parse(db_state, data); + if (status.is_error()) { + LOG(INFO) << "Ignore auth_state :" << status; + return false; + } + CHECK(db_state.state_ == State::WaitCode); + if (db_state.api_id_ != api_id_ || db_state.api_hash_ != api_hash_) { + LOG(INFO) << "Ignore auth_state : api_id or api_hash changed"; + return false; + } + if (!db_state.state_timestamp_.is_in_past()) { + LOG(INFO) << "Ignore auth_state : timestamp in future"; + return false; + } + if (Timestamp::at(db_state.state_timestamp_.at() + 5 * 60).is_in_past()) { + LOG(INFO) << "Ignore auth_state : expired " << db_state.state_timestamp_.in(); + return false; + } + LOG(INFO) << "Load auth_state from db"; + + send_code_helper_ = db_state.send_code_helper_; + update_state(State::WaitCode, false, false); + return true; +} + +void AuthManager::save_state() { + if (state_ != State::WaitCode) { + if (state_ != State::Closing) { + G()->td_db()->get_binlog_pmc()->erase("auth_state"); + } + return; + } + + DbState db_state{state_, api_id_, api_hash_, send_code_helper_, Timestamp::now()}; + G()->td_db()->get_binlog_pmc()->set("auth_state", log_event_store(db_state).as_slice().str()); +} + } // namespace td diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index 3d9264aa8..f15a3c779 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -38,6 +38,11 @@ class SendCodeHelper { return phone_registered_; } + template + void store(T &storer) const; + template + void parse(T &parser); + private: static constexpr int32 AUTH_SEND_CODE_FLAG_ALLOW_FLASH_CALL = 1 << 0; @@ -55,6 +60,11 @@ class SendCodeHelper { AuthenticationCodeInfo(Type type, int length, string pattern) : type(type), length(length), pattern(std::move(pattern)) { } + + template + void store(T &storer) const; + template + void parse(T &parser); }; string phone_number_; @@ -63,7 +73,7 @@ class SendCodeHelper { SendCodeHelper::AuthenticationCodeInfo sent_code_info_; SendCodeHelper::AuthenticationCodeInfo next_code_info_; - int32 next_code_timeout_; + Timestamp next_code_timestamp_; static AuthenticationCodeInfo get_authentication_code_info( tl_object_ptr &&code_type_ptr); @@ -147,16 +157,37 @@ class AuthManager : public NetActor { DeleteAccount }; + struct DbState { + State state_; + int32 api_id_; + string api_hash_; + SendCodeHelper send_code_helper_; + Timestamp state_timestamp_; + + template + void store(T &storer) const; + template + void parse(T &parser); + }; + + bool load_state(); + void save_state(); + ActorShared<> parent_; + // STATE + // from contructor int32 api_id_; string api_hash_; + // State::WaitCode SendCodeHelper send_code_helper_; + // for bots string bot_token_; uint64 query_id_ = 0; + // State::WaitPassword string current_salt_; string new_salt_; string hint_; @@ -186,7 +217,7 @@ class AuthManager : public NetActor { void on_result(NetQueryPtr result) override; - void update_state(State new_state, bool force = false); + void update_state(State new_state, bool force = false, bool should_save_state = true); tl_object_ptr get_authorization_state_object(State authorization_state) const; void send_ok(uint64 query_id); diff --git a/td/telegram/AuthManager.hpp b/td/telegram/AuthManager.hpp new file mode 100644 index 000000000..41ae996d9 --- /dev/null +++ b/td/telegram/AuthManager.hpp @@ -0,0 +1,72 @@ +// +// 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/AuthManager.h" + +#include "td/utils/tl_helpers.h" + +namespace td { +template +void SendCodeHelper::AuthenticationCodeInfo::store(T &storer) const { + using td::store; + store(static_cast(type), storer); + store(length, storer); + store(pattern, storer); +} +template +void SendCodeHelper::AuthenticationCodeInfo::parse(T &parser) { + using td::parse; + int32 type_int; + parse(type_int, parser); + type = narrow_cast(type_int); + parse(length, parser); + parse(pattern, parser); +} + +template +void SendCodeHelper::store(T &storer) const { + using td::store; + store(phone_number_, storer); + store(phone_registered_, storer); + store(phone_code_hash_, storer); + store(sent_code_info_, storer); + store(next_code_info_, storer); + store(next_code_timestamp_, storer); +} + +template +void SendCodeHelper::parse(T &parser) { + using td::parse; + parse(phone_number_, parser); + parse(phone_registered_, parser); + parse(phone_code_hash_, parser); + parse(sent_code_info_, parser); + parse(next_code_info_, parser); + parse(next_code_timestamp_, parser); +} + +template +void AuthManager::DbState::store(T &storer) const { + using td::store; + CHECK(state_ == State::WaitCode); + store(static_cast(state_), storer); + store(api_id_, storer); + store(api_hash_, storer); + store(send_code_helper_, storer); + store(state_timestamp_, storer); +} +template +void AuthManager::DbState::parse(T &parser) { + using td::parse; + int32 state; + parse(state, parser); + state_ = narrow_cast(state); + parse(api_id_, parser); + parse(api_hash_, parser); + parse(send_code_helper_, parser); + parse(state_timestamp_, parser); +} +} // namespace td diff --git a/tdutils/td/utils/tl_helpers.h b/tdutils/td/utils/tl_helpers.h index b02b685c6..08d3a53cc 100644 --- a/tdutils/td/utils/tl_helpers.h +++ b/tdutils/td/utils/tl_helpers.h @@ -13,6 +13,7 @@ #include "td/utils/Slice.h" #include "td/utils/StackAllocator.h" #include "td/utils/Status.h" +#include "td/utils/Time.h" #include "td/utils/tl_parsers.h" #include "td/utils/tl_storers.h" @@ -139,6 +140,14 @@ void parse(vector &vec, ParserT &parser) { parse(val, parser); } } +template +void parse(Timestamp ×tamp, T &parser) { + timestamp = Timestamp::in(static_cast(parser.fetch_long()) / 1000000 - Clocks::system()); +} +template +void store(const Timestamp ×tamp, T &storer) { + storer.store_long(static_cast((timestamp.at() - Time::now() + Clocks::system()) * 1000000)); +} template void store(const std::unordered_set &s, StorerT &storer) {