Safe and reliable device token re-registration.

GitOrigin-RevId: 25273051c41ced913d1762a42cc0e19d36149a27
This commit is contained in:
levlam 2020-01-01 19:38:54 +03:00
parent 80c35676a2
commit 713608ada1
3 changed files with 34 additions and 24 deletions

View File

@ -10045,6 +10045,7 @@ void ContactsManager::on_get_dialog_invite_link_info(const string &invite_link,
on_get_chat(std::move(chat_invite_already->chat_), "chatInviteAlready"); on_get_chat(std::move(chat_invite_already->chat_), "chatInviteAlready");
CHECK(chat_id == ChatId() || channel_id == ChannelId()); CHECK(chat_id == ChatId() || channel_id == ChannelId());
CHECK(invite_link_info != nullptr);
invite_link_info->chat_id = chat_id; invite_link_info->chat_id = chat_id;
invite_link_info->channel_id = channel_id; invite_link_info->channel_id = channel_id;
@ -10058,6 +10059,7 @@ void ContactsManager::on_get_dialog_invite_link_info(const string &invite_link,
} }
case telegram_api::chatInvite::ID: { case telegram_api::chatInvite::ID: {
auto chat_invite = move_tl_object_as<telegram_api::chatInvite>(chat_invite_ptr); auto chat_invite = move_tl_object_as<telegram_api::chatInvite>(chat_invite_ptr);
CHECK(invite_link_info != nullptr);
invite_link_info->chat_id = ChatId(); invite_link_info->chat_id = ChatId();
invite_link_info->channel_id = ChannelId(); invite_link_info->channel_id = ChannelId();
invite_link_info->title = chat_invite->title_; invite_link_info->title = chat_invite->title_;

View File

@ -37,6 +37,7 @@ void DeviceTokenManager::TokenInfo::store(StorerT &storer) const {
bool is_sync = state == State::Sync; bool is_sync = state == State::Sync;
bool is_unregister = state == State::Unregister; bool is_unregister = state == State::Unregister;
bool is_register = state == State::Register; bool is_register = state == State::Register;
CHECK(state != State::Reregister);
BEGIN_STORE_FLAGS(); BEGIN_STORE_FLAGS();
STORE_FLAG(has_other_user_ids); STORE_FLAG(has_other_user_ids);
STORE_FLAG(is_sync); STORE_FLAG(is_sync);
@ -88,21 +89,24 @@ void DeviceTokenManager::TokenInfo::parse(ParserT &parser) {
} }
} }
StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManager::TokenInfo &token_info) { StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManager::TokenInfo::State &state) {
switch (token_info.state) { switch (state) {
case DeviceTokenManager::TokenInfo::State::Sync: case DeviceTokenManager::TokenInfo::State::Sync:
string_builder << "Synchronized"; return string_builder << "Synchronized";
break;
case DeviceTokenManager::TokenInfo::State::Unregister: case DeviceTokenManager::TokenInfo::State::Unregister:
string_builder << "Unregister"; return string_builder << "Unregister";
break;
case DeviceTokenManager::TokenInfo::State::Register: case DeviceTokenManager::TokenInfo::State::Register:
string_builder << "Register"; return string_builder << "Register";
break; case DeviceTokenManager::TokenInfo::State::Reregister:
return string_builder << "Reregister";
default: default:
UNREACHABLE(); UNREACHABLE();
return string_builder;
} }
string_builder << " token \"" << format::escaped(token_info.token) << "\""; }
StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManager::TokenInfo &token_info) {
string_builder << token_info.state << " token \"" << format::escaped(token_info.token) << "\"";
if (!token_info.other_user_ids.empty()) { if (!token_info.other_user_ids.empty()) {
string_builder << ", with other users " << token_info.other_user_ids; string_builder << ", with other users " << token_info.other_user_ids;
} }
@ -272,7 +276,7 @@ void DeviceTokenManager::reregister_device() {
for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) { for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) {
auto &token = tokens_[token_type]; auto &token = tokens_[token_type];
if (token.state == TokenInfo::State::Sync && !token.token.empty()) { if (token.state == TokenInfo::State::Sync && !token.token.empty()) {
token.state = TokenInfo::State::Register; token.state = TokenInfo::State::Reregister;
} }
} }
loop(); loop();
@ -329,7 +333,7 @@ void DeviceTokenManager::start_up() {
} }
LOG(INFO) << "Have device token " << token_type << "--->" << token; LOG(INFO) << "Have device token " << token_type << "--->" << token;
if (token.state == TokenInfo::State::Sync && !token.token.empty()) { if (token.state == TokenInfo::State::Sync && !token.token.empty()) {
token.state = TokenInfo::State::Register; token.state = TokenInfo::State::Reregister;
} }
} }
loop(); loop();
@ -353,7 +357,7 @@ void DeviceTokenManager::dec_sync_cnt() {
} }
void DeviceTokenManager::loop() { void DeviceTokenManager::loop() {
if (sync_cnt_ != 0) { if (sync_cnt_ != 0 || G()->close_flag()) {
return; return;
} }
for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) { for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) {
@ -390,12 +394,12 @@ void DeviceTokenManager::on_result(NetQueryPtr net_query) {
return; return;
} }
info.net_query_id = 0; info.net_query_id = 0;
CHECK(info.state != TokenInfo::State::Sync);
static_assert(std::is_same<telegram_api::account_registerDevice::ReturnType, static_assert(std::is_same<telegram_api::account_registerDevice::ReturnType,
telegram_api::account_unregisterDevice::ReturnType>::value, telegram_api::account_unregisterDevice::ReturnType>::value,
""); "");
auto r_flag = fetch_result<telegram_api::account_registerDevice>(std::move(net_query)); auto r_flag = fetch_result<telegram_api::account_registerDevice>(std::move(net_query));
info.net_query_id = 0;
if (r_flag.is_ok() && r_flag.ok()) { if (r_flag.is_ok() && r_flag.ok()) {
if (info.promise) { if (info.promise) {
int64 push_token_id = 0; int64 push_token_id = 0;
@ -413,22 +417,24 @@ void DeviceTokenManager::on_result(NetQueryPtr net_query) {
} }
info.state = TokenInfo::State::Sync; info.state = TokenInfo::State::Sync;
} else { } else {
if (info.promise) {
if (r_flag.is_error()) { if (r_flag.is_error()) {
info.promise.set_error(r_flag.error().clone()); if (!G()->close_flag()) {
LOG(ERROR) << "Failed to " << info.state << " device: " << r_flag.error();
}
info.promise.set_error(r_flag.move_as_error());
} else { } else {
info.promise.set_error(Status::Error(5, "Got false as result of server request")); info.promise.set_error(Status::Error(5, "Got false as result of registerDevice server request"));
} }
} if (info.state == TokenInfo::State::Reregister) {
if (info.state == TokenInfo::State::Register) { // keep trying to reregister the token
return loop();
} else if (info.state == TokenInfo::State::Register) {
info.state = TokenInfo::State::Unregister; info.state = TokenInfo::State::Unregister;
} else { } else {
CHECK(info.state == TokenInfo::State::Unregister);
info.state = TokenInfo::State::Sync; info.state = TokenInfo::State::Sync;
info.token.clear(); info.token.clear();
} }
if (r_flag.is_error() && !G()->close_flag()) {
LOG(ERROR) << r_flag.error();
}
} }
save_info(token_type); save_info(token_type);
} }

View File

@ -51,7 +51,7 @@ class DeviceTokenManager : public NetQueryCallback {
SIZE SIZE
}; };
struct TokenInfo { struct TokenInfo {
enum class State : int32 { Sync, Unregister, Register }; enum class State : int32 { Sync, Unregister, Register, Reregister };
State state = State::Sync; State state = State::Sync;
string token; string token;
uint64 net_query_id = 0; uint64 net_query_id = 0;
@ -69,6 +69,8 @@ class DeviceTokenManager : public NetQueryCallback {
void parse(ParserT &parser); void parse(ParserT &parser);
}; };
friend StringBuilder &operator<<(StringBuilder &string_builder, const TokenInfo::State &state);
friend StringBuilder &operator<<(StringBuilder &string_builder, const TokenInfo &token_info); friend StringBuilder &operator<<(StringBuilder &string_builder, const TokenInfo &token_info);
std::array<TokenInfo, TokenType::SIZE> tokens_; std::array<TokenInfo, TokenType::SIZE> tokens_;