Store in db AuthManager in state WaitCode

GitOrigin-RevId: 06df8525c60f4de347c694e8c212a138c151ac4c
This commit is contained in:
Arseny Smirnov 2018-03-14 21:04:41 +03:00
parent c10ac96cc9
commit 85d10e91c3
5 changed files with 171 additions and 11 deletions

View File

@ -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

View File

@ -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_ptr<telegram_api::auth_se
phone_code_hash_ = sent_code->phone_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<int32>(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<td_api::authorizationStateWaitCode> SendCodeHelper::get_authorization_state_wait_code() const {
@ -43,9 +45,9 @@ td_api::object_ptr<td_api::authorizationStateWaitCode> SendCodeHelper::get_autho
}
td_api::object_ptr<td_api::authenticationCodeInfo> SendCodeHelper::get_authentication_code_info_object() const {
return make_tl_object<td_api::authenticationCodeInfo>(get_authentication_code_type_object(sent_code_info_),
get_authentication_code_type_object(next_code_info_),
max(next_code_timeout_ - static_cast<int32>(Time::now()), 0));
return make_tl_object<td_api::authenticationCodeInfo>(
get_authentication_code_type_object(sent_code_info_), get_authentication_code_type_object(next_code_info_),
max(static_cast<int32>(next_code_timestamp_.in() + 1 - 1e-9), 0));
}
Result<telegram_api::auth_resendCode> SendCodeHelper::resend_code() {
@ -53,8 +55,8 @@ Result<telegram_api::auth_resendCode> 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<td_api::updateAuthorizationState>(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

View File

@ -38,6 +38,11 @@ class SendCodeHelper {
return phone_registered_;
}
template <class T>
void store(T &storer) const;
template <class T>
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 <class T>
void store(T &storer) const;
template <class T>
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<telegram_api::auth_CodeType> &&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 <class T>
void store(T &storer) const;
template <class T>
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<td_api::AuthorizationState> get_authorization_state_object(State authorization_state) const;
void send_ok(uint64 query_id);

View File

@ -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 <class T>
void SendCodeHelper::AuthenticationCodeInfo::store(T &storer) const {
using td::store;
store(static_cast<int>(type), storer);
store(length, storer);
store(pattern, storer);
}
template <class T>
void SendCodeHelper::AuthenticationCodeInfo::parse(T &parser) {
using td::parse;
int32 type_int;
parse(type_int, parser);
type = narrow_cast<decltype(type)>(type_int);
parse(length, parser);
parse(pattern, parser);
}
template <class T>
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 <class T>
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 <class T>
void AuthManager::DbState::store(T &storer) const {
using td::store;
CHECK(state_ == State::WaitCode);
store(static_cast<int32>(state_), storer);
store(api_id_, storer);
store(api_hash_, storer);
store(send_code_helper_, storer);
store(state_timestamp_, storer);
}
template <class T>
void AuthManager::DbState::parse(T &parser) {
using td::parse;
int32 state;
parse(state, parser);
state_ = narrow_cast<State>(state);
parse(api_id_, parser);
parse(api_hash_, parser);
parse(send_code_helper_, parser);
parse(state_timestamp_, parser);
}
} // namespace td

View File

@ -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<T> &vec, ParserT &parser) {
parse(val, parser);
}
}
template <class T>
void parse(Timestamp &timestamp, T &parser) {
timestamp = Timestamp::in(static_cast<double>(parser.fetch_long()) / 1000000 - Clocks::system());
}
template <class T>
void store(const Timestamp &timestamp, T &storer) {
storer.store_long(static_cast<int64>((timestamp.at() - Time::now() + Clocks::system()) * 1000000));
}
template <class Key, class Hash, class KeyEqual, class Allocator, class StorerT>
void store(const std::unordered_set<Key, Hash, KeyEqual, Allocator> &s, StorerT &storer) {