Improve encryptedChatDiscarded handling.

This commit is contained in:
levlam 2021-01-18 19:02:24 +03:00
parent cc8c0cbe64
commit 091d08b6a9
4 changed files with 57 additions and 34 deletions

View File

@ -115,7 +115,7 @@ void SecretChatActor::on_result_resendable(NetQueryPtr net_query, Promise<NetQue
auto key = UniqueId::extract_key(net_query->id());
if (close_flag_) {
if (key == static_cast<uint8>(QueryType::DiscardEncryption)) {
on_discard_encryption_result(std::move(net_query));
discard_encryption_promise_.set_value(Unit());
}
return;
}
@ -140,7 +140,7 @@ void SecretChatActor::on_result_resendable(NetQueryPtr net_query, Promise<NetQue
}
void SecretChatActor::replay_close_chat(unique_ptr<log_event::CloseSecretChat> event) {
do_close_chat_impl(event->delete_history, event->log_event_id());
do_close_chat_impl(event->delete_history, event->is_already_discarded, event->log_event_id(), Promise<Unit>());
}
void SecretChatActor::replay_create_chat(unique_ptr<log_event::CreateSecretChat> event) {
@ -709,10 +709,10 @@ void SecretChatActor::check_status(Status status) {
void SecretChatActor::on_fatal_error(Status status) {
LOG(ERROR) << "Fatal error: " << status;
cancel_chat(false, Promise<>());
cancel_chat(false, false, Promise<>());
}
void SecretChatActor::cancel_chat(bool delete_history, Promise<> promise) {
void SecretChatActor::cancel_chat(bool delete_history, bool is_already_discarded, Promise<> promise) {
if (close_flag_) {
promise.set_value(Unit());
return;
@ -737,11 +737,11 @@ void SecretChatActor::cancel_chat(bool delete_history, Promise<> promise) {
event->chat_id = auth_state_.id;
auto log_event_id = binlog_add(context_->binlog(), LogEvent::HandlerType::SecretChats, create_storer(*event));
auto on_sync = PromiseCreator::lambda([actor_id = actor_id(this), delete_history, log_event_id,
auto on_sync = PromiseCreator::lambda([actor_id = actor_id(this), delete_history, is_already_discarded, log_event_id,
promise = std::move(promise)](Result<Unit> result) mutable {
if (result.is_ok()) {
send_closure(actor_id, &SecretChatActor::do_close_chat_impl, delete_history, log_event_id);
promise.set_value(Unit());
send_closure(actor_id, &SecretChatActor::do_close_chat_impl, delete_history, is_already_discarded, log_event_id,
std::move(promise));
} else {
promise.set_error(result.error().clone());
send_closure(actor_id, &SecretChatActor::on_promise_error, result.move_as_error(), "cancel_chat");
@ -752,25 +752,56 @@ void SecretChatActor::cancel_chat(bool delete_history, Promise<> promise) {
yield();
}
void SecretChatActor::do_close_chat_impl(bool delete_history, uint64 log_event_id) {
void SecretChatActor::do_close_chat_impl(bool delete_history, bool is_already_discarded, uint64 log_event_id,
Promise<Unit> &&promise) {
close_flag_ = true;
close_log_event_id_ = log_event_id;
LOG(INFO) << "Send messages.discardEncryption";
auth_state_.state = State::Closed;
context_->secret_chat_db()->set_value(auth_state_);
context_->secret_chat_db()->erase_value(config_state_);
context_->secret_chat_db()->erase_value(pfs_state_);
context_->secret_chat_db()->erase_value(seq_no_state_);
int32 flags = 0;
MultiPromiseActorSafe mpas{"DeleteMessagesFromServerMultiPromiseActor"};
mpas.add_promise(
PromiseCreator::lambda([actor_id = actor_id(this), log_event_id, promise = std::move(promise)](Unit) mutable {
send_closure(actor_id, &SecretChatActor::on_closed, log_event_id, std::move(promise));
}));
auto lock = mpas.get_promise();
if (delete_history) {
flags |= telegram_api::messages_discardEncryption::DELETE_HISTORY_MASK;
context_->on_flush_history(MessageId::max(), mpas.get_promise());
}
auto query = create_net_query(QueryType::DiscardEncryption,
telegram_api::messages_discardEncryption(flags, false /*ignored*/, auth_state_.id));
send_update_secret_chat();
context_->send_net_query(std::move(query), actor_shared(this), true);
if (!is_already_discarded) {
int32 flags = 0;
if (delete_history) {
flags |= telegram_api::messages_discardEncryption::DELETE_HISTORY_MASK;
}
auto query = create_net_query(QueryType::DiscardEncryption,
telegram_api::messages_discardEncryption(flags, false /*ignored*/, auth_state_.id));
query->total_timeout_limit_ = 60 * 60 * 24 * 365;
context_->send_net_query(std::move(query), actor_shared(this), true);
discard_encryption_promise_ = mpas.get_promise();
}
lock.set_value(Unit());
}
void SecretChatActor::on_closed(uint64 log_event_id, Promise<Unit> &&promise) {
CHECK(close_flag_);
if (context_->close_flag()) {
return;
}
LOG(INFO) << "Finish closing";
context_->secret_chat_db()->erase_value(auth_state_);
binlog_erase(context_->binlog(), log_event_id);
promise.set_value(Unit());
// skip flush
stop();
}
void SecretChatActor::do_create_chat_impl(unique_ptr<log_event::CreateSecretChat> event) {
@ -793,18 +824,6 @@ void SecretChatActor::do_create_chat_impl(unique_ptr<log_event::CreateSecretChat
create_log_event_id_ = 0;
}
}
void SecretChatActor::on_discard_encryption_result(NetQueryPtr result) {
CHECK(close_flag_);
CHECK(close_log_event_id_ != 0);
if (context_->close_flag()) {
return;
}
LOG(INFO) << "Got result for messages.discardEncryption";
context_->secret_chat_db()->erase_value(auth_state_);
binlog_erase(context_->binlog(), close_log_event_id_);
// skip flush
stop();
}
telegram_api::object_ptr<telegram_api::inputUser> SecretChatActor::get_input_user() {
return telegram_api::make_object<telegram_api::inputUser>(auth_state_.user_id, auth_state_.user_access_hash);
@ -1904,7 +1923,8 @@ Status SecretChatActor::on_update_chat(telegram_api::encryptedChat &update) {
return Status::OK();
}
Status SecretChatActor::on_update_chat(telegram_api::encryptedChatDiscarded &update) {
return Status::Error("Chat discarded");
cancel_chat(update.history_deleted_, true, Promise<Unit>());
return Status::OK();
}
Status SecretChatActor::on_update_chat(NetQueryPtr query) {

View File

@ -116,7 +116,7 @@ class SecretChatActor : public NetQueryCallback {
void update_chat(telegram_api::object_ptr<telegram_api::EncryptedChat> chat);
void create_chat(int32 user_id, int64 user_access_hash, int32 random_id, Promise<SecretChatId> promise);
void cancel_chat(bool delete_history, Promise<> promise);
void cancel_chat(bool delete_history, bool is_already_discarded, Promise<> promise);
// Inbound messages
// Logevent is created by SecretChatsManager, because it must contain qts
@ -462,7 +462,7 @@ class SecretChatActor : public NetQueryCallback {
bool binlog_replay_finish_flag_ = false;
bool close_flag_ = false;
LogEvent::Id close_log_event_id_ = 0;
Promise<Unit> discard_encryption_promise_;
LogEvent::Id create_log_event_id_ = 0;
@ -638,8 +638,8 @@ class SecretChatActor : public NetQueryCallback {
// DiscardEncryption
void on_fatal_error(Status status);
void do_close_chat_impl(bool delete_history, uint64 log_event_id);
void on_discard_encryption_result(NetQueryPtr result);
void do_close_chat_impl(bool delete_history, bool is_already_discarded, uint64 log_event_id, Promise<Unit> &&promise);
void on_closed(uint64 log_event_id, Promise<Unit> &&promise);
// Other
template <class T>

View File

@ -109,7 +109,7 @@ void SecretChatsManager::create_chat(int32 user_id, int64 user_access_hash, Prom
void SecretChatsManager::cancel_chat(SecretChatId secret_chat_id, bool delete_history, Promise<> promise) {
auto actor = get_chat_actor(secret_chat_id.get());
auto safe_promise = SafePromise<>(std::move(promise), Unit());
send_closure(actor, &SecretChatActor::cancel_chat, delete_history, std::move(safe_promise));
send_closure(actor, &SecretChatActor::cancel_chat, delete_history, false, std::move(safe_promise));
}
void SecretChatsManager::send_message(SecretChatId secret_chat_id, tl_object_ptr<secret_api::decryptedMessage> message,

View File

@ -411,12 +411,14 @@ class CloseSecretChat : public SecretChatLogEventBase<CloseSecretChat> {
static constexpr Type type = SecretChatEvent::Type::CloseSecretChat;
int32 chat_id = 0;
bool delete_history = false;
bool is_already_discarded = false;
template <class StorerT>
void store(StorerT &storer) const {
using td::store;
BEGIN_STORE_FLAGS();
STORE_FLAG(delete_history);
STORE_FLAG(is_already_discarded);
END_STORE_FLAGS();
store(chat_id, storer);
}
@ -427,6 +429,7 @@ class CloseSecretChat : public SecretChatLogEventBase<CloseSecretChat> {
if (parser.version() >= 3) {
BEGIN_PARSE_FLAGS();
PARSE_FLAG(delete_history);
PARSE_FLAG(is_already_discarded);
END_PARSE_FLAGS();
}
parse(chat_id, parser);
@ -434,7 +437,7 @@ class CloseSecretChat : public SecretChatLogEventBase<CloseSecretChat> {
StringBuilder &print(StringBuilder &sb) const override {
return sb << "[Logevent CloseSecretChat " << tag("id", log_event_id()) << tag("chat_id", chat_id)
<< tag("delete_history", delete_history) << "]";
<< tag("delete_history", delete_history) << tag("is_already_discarded", is_already_discarded) << "]";
}
};