Remove support for secret chat layers before 73.

This commit is contained in:
levlam 2021-06-08 18:31:29 +03:00
parent c30ccd1e0d
commit d80b613b55
10 changed files with 38 additions and 126 deletions

View File

@ -668,7 +668,7 @@ secretChatStateClosed = SecretChatState;
//@is_outbound True, if the chat was created by the current user; otherwise false //@is_outbound True, if the chat was created by the current user; otherwise false
//@key_hash Hash of the currently used key for comparison with the hash of the chat partner's key. This is a string of 36 little-endian bytes, which must be split into groups of 2 bits, each denoting a pixel of one of 4 colors FFFFFF, D5E6F3, 2D5775, and 2F99C9. //@key_hash Hash of the currently used key for comparison with the hash of the chat partner's key. This is a string of 36 little-endian bytes, which must be split into groups of 2 bits, each denoting a pixel of one of 4 colors FFFFFF, D5E6F3, 2D5775, and 2F99C9.
//-The pixels must be used to make a 12x12 square image filled from left to right, top to bottom. Alternatively, the first 32 bytes of the hash can be converted to the hexadecimal format and printed as 32 2-digit hex numbers //-The pixels must be used to make a 12x12 square image filled from left to right, top to bottom. Alternatively, the first 32 bytes of the hash can be converted to the hexadecimal format and printed as 32 2-digit hex numbers
//@layer Secret chat layer; determines features supported by the chat partner's application. Video notes are supported if the layer >= 66; nested text entities and underline and strikethrough entities are supported if the layer >= 101 //@layer Secret chat layer; determines features supported by the chat partner's application. Nested text entities and underline and strikethrough entities are supported if the layer >= 101
secretChat id:int32 user_id:int32 state:SecretChatState is_outbound:Bool key_hash:bytes layer:int32 = SecretChat; secretChat id:int32 user_id:int32 state:SecretChatState is_outbound:Bool key_hash:bytes layer:int32 = SecretChat;

View File

@ -18,7 +18,6 @@
#include "td/telegram/logevent/LogEvent.h" #include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/misc.h" #include "td/telegram/misc.h"
#include "td/telegram/secret_api.h" #include "td/telegram/secret_api.h"
#include "td/telegram/SecretChatActor.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/TdDb.h" #include "td/telegram/TdDb.h"
@ -402,8 +401,7 @@ tl_object_ptr<telegram_api::InputMedia> AnimationsManager::get_input_media(
SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file_id, SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file_id,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file, tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
const string &caption, BufferSlice thumbnail, const string &caption, BufferSlice thumbnail) const {
int32 layer) const {
auto *animation = get_animation(animation_file_id); auto *animation = get_animation(animation_file_id);
CHECK(animation != nullptr); CHECK(animation != nullptr);
auto file_view = td_->file_manager_->get_file_view(animation_file_id); auto file_view = td_->file_manager_->get_file_view(animation_file_id);
@ -425,13 +423,8 @@ SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file
attributes.push_back(make_tl_object<secret_api::documentAttributeFilename>(animation->file_name)); attributes.push_back(make_tl_object<secret_api::documentAttributeFilename>(animation->file_name));
} }
if (animation->duration != 0 && animation->mime_type == "video/mp4") { if (animation->duration != 0 && animation->mime_type == "video/mp4") {
if (layer >= SecretChatActor::VIDEO_NOTES_LAYER) { attributes.push_back(make_tl_object<secret_api::documentAttributeVideo66>(
attributes.push_back(make_tl_object<secret_api::documentAttributeVideo66>( 0, false, animation->duration, animation->dimensions.width, animation->dimensions.height));
0, false, animation->duration, animation->dimensions.width, animation->dimensions.height));
} else {
attributes.push_back(make_tl_object<secret_api::documentAttributeVideo>(
animation->duration, animation->dimensions.width, animation->dimensions.height));
}
} }
if (animation->dimensions.width != 0 && animation->dimensions.height != 0) { if (animation->dimensions.width != 0 && animation->dimensions.height != 0) {
attributes.push_back(make_tl_object<secret_api::documentAttributeImageSize>(animation->dimensions.width, attributes.push_back(make_tl_object<secret_api::documentAttributeImageSize>(animation->dimensions.width,

View File

@ -45,7 +45,7 @@ class AnimationsManager : public Actor {
SecretInputMedia get_secret_input_media(FileId animation_file_id, SecretInputMedia get_secret_input_media(FileId animation_file_id,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file, tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
const string &caption, BufferSlice thumbnail, int32 layer) const; const string &caption, BufferSlice thumbnail) const;
FileId get_animation_thumbnail_file_id(FileId file_id) const; FileId get_animation_thumbnail_file_id(FileId file_id) const;

View File

@ -50,7 +50,6 @@
#include "td/telegram/PollId.hpp" #include "td/telegram/PollId.hpp"
#include "td/telegram/PollManager.h" #include "td/telegram/PollManager.h"
#include "td/telegram/secret_api.hpp" #include "td/telegram/secret_api.hpp"
#include "td/telegram/SecretChatActor.h"
#include "td/telegram/SecureValue.h" #include "td/telegram/SecureValue.h"
#include "td/telegram/SecureValue.hpp" #include "td/telegram/SecureValue.hpp"
#include "td/telegram/StickersManager.h" #include "td/telegram/StickersManager.h"
@ -2061,12 +2060,12 @@ bool can_have_input_media(const Td *td, const MessageContent *content) {
SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td, SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file, tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
BufferSlice thumbnail, int32 layer) { BufferSlice thumbnail) {
switch (content->get_type()) { switch (content->get_type()) {
case MessageContentType::Animation: { case MessageContentType::Animation: {
auto m = static_cast<const MessageAnimation *>(content); auto m = static_cast<const MessageAnimation *>(content);
return td->animations_manager_->get_secret_input_media(m->file_id, std::move(input_file), m->caption.text, return td->animations_manager_->get_secret_input_media(m->file_id, std::move(input_file), m->caption.text,
std::move(thumbnail), layer); std::move(thumbnail));
} }
case MessageContentType::Audio: { case MessageContentType::Audio: {
auto m = static_cast<const MessageAudio *>(content); auto m = static_cast<const MessageAudio *>(content);
@ -2112,8 +2111,7 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
} }
case MessageContentType::VideoNote: { case MessageContentType::VideoNote: {
auto m = static_cast<const MessageVideoNote *>(content); auto m = static_cast<const MessageVideoNote *>(content);
return td->video_notes_manager_->get_secret_input_media(m->file_id, std::move(input_file), std::move(thumbnail), return td->video_notes_manager_->get_secret_input_media(m->file_id, std::move(input_file), std::move(thumbnail));
layer);
} }
case MessageContentType::VoiceNote: { case MessageContentType::VoiceNote: {
auto m = static_cast<const MessageVoiceNote *>(content); auto m = static_cast<const MessageVoiceNote *>(content);
@ -2567,10 +2565,6 @@ Status can_send_message_content(DialogId dialog_id, const MessageContent *conten
if (!permissions.can_send_media()) { if (!permissions.can_send_media()) {
return Status::Error(400, "Not enough rights to send video notes to the chat"); return Status::Error(400, "Not enough rights to send video notes to the chat");
} }
if (secret_chat_layer < SecretChatActor::VIDEO_NOTES_LAYER) {
return Status::Error(400, PSLICE()
<< "Video notes can't be sent to secret chat with layer " << secret_chat_layer);
}
break; break;
case MessageContentType::VoiceNote: case MessageContentType::VoiceNote:
if (!permissions.can_send_media()) { if (!permissions.can_send_media()) {

View File

@ -107,7 +107,7 @@ bool can_have_input_media(const Td *td, const MessageContent *content);
SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td, SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file, tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
BufferSlice thumbnail, int32 layer); BufferSlice thumbnail);
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputFile> input_file, tl_object_ptr<telegram_api::InputFile> input_file,

View File

@ -8647,11 +8647,10 @@ void MessagesManager::do_send_secret_media(DialogId dialog_id, Message *m, FileI
LOG(INFO) << "Do send secret media file " << file_id << " with thumbnail " << thumbnail_file_id LOG(INFO) << "Do send secret media file " << file_id << " with thumbnail " << thumbnail_file_id
<< ", have_input_file = " << have_input_file; << ", have_input_file = " << have_input_file;
auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id());
on_secret_message_media_uploaded( on_secret_message_media_uploaded(
dialog_id, m, dialog_id, m,
get_secret_input_media(m->content.get(), td_, std::move(input_encrypted_file), std::move(thumbnail), layer), get_secret_input_media(m->content.get(), td_, std::move(input_encrypted_file), std::move(thumbnail)), file_id,
file_id, thumbnail_file_id); thumbnail_file_id);
} }
void MessagesManager::on_upload_media_error(FileId file_id, Status status) { void MessagesManager::on_upload_media_error(FileId file_id, Status status) {
@ -23422,8 +23421,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect
LOG(DEBUG) << "Need to send file " << file_id << " with thumbnail " << thumbnail_file_id; LOG(DEBUG) << "Need to send file " << file_id << " with thumbnail " << thumbnail_file_id;
if (is_secret) { if (is_secret) {
CHECK(!is_edit); CHECK(!is_edit);
auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id()); auto secret_input_media = get_secret_input_media(content, td_, nullptr, BufferSlice());
auto secret_input_media = get_secret_input_media(content, td_, nullptr, BufferSlice(), layer);
if (secret_input_media.empty()) { if (secret_input_media.empty()) {
LOG(INFO) << "Ask to upload encrypted file " << file_id; LOG(INFO) << "Ask to upload encrypted file " << file_id;
CHECK(file_view.is_encrypted_secret()); CHECK(file_view.is_encrypted_secret());
@ -23862,7 +23860,7 @@ void MessagesManager::on_text_message_ready_to_send(DialogId dialog_id, MessageI
auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id()); auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id());
send_closure(td_->create_net_actor<SendSecretMessageActor>(), &SendSecretMessageActor::send, dialog_id, send_closure(td_->create_net_actor<SendSecretMessageActor>(), &SendSecretMessageActor::send, dialog_id,
m->reply_to_random_id, m->ttl, message_text->text, m->reply_to_random_id, m->ttl, message_text->text,
get_secret_input_media(content, td_, nullptr, BufferSlice(), layer), get_secret_input_media(content, td_, nullptr, BufferSlice()),
get_input_secret_message_entities(message_text->entities, layer), m->via_bot_user_id, get_input_secret_message_entities(message_text->entities, layer), m->via_bot_user_id,
m->media_album_id, m->disable_notification, random_id); m->media_album_id, m->disable_notification, random_id);
} else { } else {

View File

@ -180,7 +180,7 @@ void SecretChatActor::replay_inbound_message(unique_ptr<log_event::InboundSecret
CHECK(!binlog_replay_finish_flag_); CHECK(!binlog_replay_finish_flag_);
CHECK(message->decrypted_message_layer); // from binlog CHECK(message->decrypted_message_layer); // from binlog
if (message->is_pending) { // wait for gaps? if (message->is_pending) { // wait for gaps?
// check_status(do_inbound_message_decrypted_unchecked(std::move(message))); // check_status(do_inbound_message_decrypted_unchecked(std::move(message)), -1);
do_inbound_message_decrypted_pending(std::move(message)); do_inbound_message_decrypted_pending(std::move(message));
} else { // just replay } else { // just replay
LOG_CHECK(message->message_id > last_binlog_message_id_) LOG_CHECK(message->message_id > last_binlog_message_id_)
@ -208,31 +208,23 @@ void SecretChatActor::replay_outbound_message(unique_ptr<log_event::OutboundSecr
} }
// NB: my_seq_no is just after message is sent, i.e. my_out_seq_no is already incremented // NB: my_seq_no is just after message is sent, i.e. my_out_seq_no is already incremented
Result<BufferSlice> SecretChatActor::create_encrypted_message(int32 layer, int32 my_in_seq_no, int32 my_out_seq_no, Result<BufferSlice> SecretChatActor::create_encrypted_message(int32 my_in_seq_no, int32 my_out_seq_no,
tl_object_ptr<secret_api::DecryptedMessage> &message) { tl_object_ptr<secret_api::DecryptedMessage> &message) {
if (message->get_id() == secret_api::decryptedMessage::ID && layer < MTPROTO_2_LAYER) {
auto old = secret_api::move_object_as<secret_api::decryptedMessage>(message);
old->flags_ &= ~secret_api::decryptedMessage::GROUPED_ID_MASK;
message = secret_api::make_object<secret_api::decryptedMessage46>(
old->flags_, old->random_id_, old->ttl_, std::move(old->message_), std::move(old->media_),
std::move(old->entities_), std::move(old->via_bot_name_), old->reply_to_random_id_);
}
mtproto::AuthKey *auth_key = &pfs_state_.auth_key; mtproto::AuthKey *auth_key = &pfs_state_.auth_key;
auto in_seq_no = my_in_seq_no * 2 + auth_state_.x; auto in_seq_no = my_in_seq_no * 2 + auth_state_.x;
auto out_seq_no = my_out_seq_no * 2 - 1 - auth_state_.x; auto out_seq_no = my_out_seq_no * 2 - 1 - auth_state_.x;
auto layer = current_layer();
BufferSlice random_bytes(32); BufferSlice random_bytes(32);
Random::secure_bytes(random_bytes.as_slice().ubegin(), random_bytes.size()); Random::secure_bytes(random_bytes.as_slice().ubegin(), random_bytes.size());
auto message_with_layer = secret_api::make_object<secret_api::decryptedMessageLayer>( auto message_with_layer = secret_api::make_object<secret_api::decryptedMessageLayer>(
std::move(random_bytes), layer, in_seq_no, out_seq_no, std::move(message)); std::move(random_bytes), layer, in_seq_no, out_seq_no, std::move(message));
LOG(INFO) << to_string(message_with_layer); LOG(INFO) << "Create message " << to_string(message_with_layer);
auto storer = create_storer(*message_with_layer); auto storer = create_storer(*message_with_layer);
auto new_storer = mtproto::PacketStorer<SecretImpl>(storer); auto new_storer = mtproto::PacketStorer<SecretImpl>(storer);
mtproto::PacketInfo info; mtproto::PacketInfo info;
info.type = mtproto::PacketInfo::EndToEnd; info.type = mtproto::PacketInfo::EndToEnd;
// Send with mtproto 2.0 if current layer is at least MTPROTO_2_LAYER info.version = 2;
info.version = layer >= MTPROTO_2_LAYER ? 2 : 1;
info.is_creator = auth_state_.x == 0; info.is_creator = auth_state_.x == 0;
auto packet_writer = BufferWriter{mtproto::Transport::write(new_storer, *auth_key, &info), 0, 0}; auto packet_writer = BufferWriter{mtproto::Transport::write(new_storer, *auth_key, &info), 0, 0};
mtproto::Transport::write(new_storer, *auth_key, &info, packet_writer.as_slice()); mtproto::Transport::write(new_storer, *auth_key, &info, packet_writer.as_slice());
@ -249,63 +241,6 @@ void SecretChatActor::send_message(tl_object_ptr<secret_api::DecryptedMessage> m
send_message_impl(std::move(message), std::move(file), SendFlag::External | SendFlag::Push, std::move(promise)); send_message_impl(std::move(message), std::move(file), SendFlag::External | SendFlag::Push, std::move(promise));
} }
static int32 get_min_layer(const secret_api::decryptedMessageActionTyping &message) {
switch (message.action_->get_id()) {
case secret_api::sendMessageRecordRoundAction::ID:
case secret_api::sendMessageUploadRoundAction::ID:
return SecretChatActor::VIDEO_NOTES_LAYER;
}
return 0;
}
static int32 get_min_layer(const secret_api::decryptedMessageService &message) {
switch (message.action_->get_id()) {
case secret_api::decryptedMessageActionTyping::ID:
return get_min_layer(static_cast<const secret_api::decryptedMessageActionTyping &>(*message.action_));
default:
return 0;
}
}
static int32 get_min_layer(const secret_api::DocumentAttribute &attribute) {
switch (attribute.get_id()) {
case secret_api::documentAttributeVideo66::ID:
return SecretChatActor::VIDEO_NOTES_LAYER;
default:
return 0;
}
}
static int32 get_min_layer(const secret_api::decryptedMessageMediaDocument &message) {
int32 res = 0;
for (auto &attribute : message.attributes_) {
auto attrirbute_layer = get_min_layer(*attribute);
if (attrirbute_layer > res) {
res = attrirbute_layer;
}
return res;
}
return res;
}
static int32 get_min_layer(const secret_api::decryptedMessage &message) {
if (!message.media_) {
return 0;
}
switch (message.media_->get_id()) {
case secret_api::decryptedMessageMediaDocument::ID:
return get_min_layer(static_cast<const secret_api::decryptedMessageMediaDocument &>(*message.media_));
default:
return 0;
}
}
static int32 get_min_layer(const secret_api::DecryptedMessage &message) {
switch (message.get_id()) {
case secret_api::decryptedMessageService::ID:
return get_min_layer(static_cast<const secret_api::decryptedMessageService &>(message));
case secret_api::decryptedMessage::ID:
return get_min_layer(static_cast<const secret_api::decryptedMessage &>(message));
default:
return 0;
}
}
void SecretChatActor::send_message_impl(tl_object_ptr<secret_api::DecryptedMessage> message, void SecretChatActor::send_message_impl(tl_object_ptr<secret_api::DecryptedMessage> message,
tl_object_ptr<telegram_api::InputEncryptedFile> file, int32 flags, tl_object_ptr<telegram_api::InputEncryptedFile> file, int32 flags,
Promise<> promise) { Promise<> promise) {
@ -317,16 +252,11 @@ void SecretChatActor::send_message_impl(tl_object_ptr<secret_api::DecryptedMessa
LOG(ERROR) << "Ignore send_message: " << tag("message", to_string(message)) << tag("file", to_string(file)); LOG(ERROR) << "Ignore send_message: " << tag("message", to_string(message)) << tag("file", to_string(file));
return promise.set_error(Status::Error(400, "Chat is not accessible")); return promise.set_error(Status::Error(400, "Chat is not accessible"));
} }
if (get_min_layer(*message) > config_state_.his_layer) {
return promise.set_error(Status::Error(400, "Message is not supported by the other side"));
}
LOG_CHECK(binlog_replay_finish_flag_) << "Trying to send message before binlog replay is finished: " LOG_CHECK(binlog_replay_finish_flag_) << "Trying to send message before binlog replay is finished: "
<< to_string(*message) << to_string(file); << to_string(*message) << to_string(file);
int64 random_id = 0; int64 random_id = 0;
downcast_call(*message, [&](auto &x) { random_id = x.random_id_; }); downcast_call(*message, [&](auto &x) { random_id = x.random_id_; });
LOG(INFO) << "Send message: " << to_string(message) << to_string(file);
auto it = random_id_to_outbound_message_state_token_.find(random_id); auto it = random_id_to_outbound_message_state_token_.find(random_id);
if (it != random_id_to_outbound_message_state_token_.end()) { if (it != random_id_to_outbound_message_state_token_.end()) {
return on_outbound_outer_send_message_promise(it->second, std::move(promise)); return on_outbound_outer_send_message_promise(it->second, std::move(promise));
@ -341,8 +271,7 @@ void SecretChatActor::send_message_impl(tl_object_ptr<secret_api::DecryptedMessa
binlog_event->my_out_seq_no = seq_no_state_.my_out_seq_no + 1; binlog_event->my_out_seq_no = seq_no_state_.my_out_seq_no + 1;
binlog_event->his_in_seq_no = seq_no_state_.his_in_seq_no; binlog_event->his_in_seq_no = seq_no_state_.his_in_seq_no;
binlog_event->encrypted_message = binlog_event->encrypted_message =
create_encrypted_message(current_layer(), binlog_event->my_in_seq_no, binlog_event->my_out_seq_no, message) create_encrypted_message(binlog_event->my_in_seq_no, binlog_event->my_out_seq_no, message).move_as_ok();
.move_as_ok();
binlog_event->need_notify_user = (flags & SendFlag::Push) == 0; binlog_event->need_notify_user = (flags & SendFlag::Push) == 0;
binlog_event->is_external = (flags & SendFlag::External) != 0; binlog_event->is_external = (flags & SendFlag::External) != 0;
binlog_event->is_silent = (message->get_id() == secret_api::decryptedMessage::ID && binlog_event->is_silent = (message->get_id() == secret_api::decryptedMessage::ID &&
@ -617,7 +546,7 @@ void SecretChatActor::run_fill_gaps() {
LOG(INFO) << "Replay pending event: " << tag("seq_no", next_seq_no); LOG(INFO) << "Replay pending event: " << tag("seq_no", next_seq_no);
auto message = std::move(begin->second); auto message = std::move(begin->second);
pending_inbound_messages_.erase(begin); pending_inbound_messages_.erase(begin);
check_status(do_inbound_message_decrypted_unchecked(std::move(message))); check_status(do_inbound_message_decrypted_unchecked(std::move(message), -1));
CHECK(pending_inbound_messages_.find(next_seq_no) == pending_inbound_messages_.end()); CHECK(pending_inbound_messages_.find(next_seq_no) == pending_inbound_messages_.end());
} else { } else {
break; break;
@ -861,7 +790,6 @@ Result<std::tuple<uint64, BufferSlice, int32>> SecretChatActor::decrypt(BufferSl
int32 mtproto_version = -1; int32 mtproto_version = -1;
Result<mtproto::Transport::ReadResult> r_read_result; Result<mtproto::Transport::ReadResult> r_read_result;
for (size_t i = 0; i < versions.size(); i++) { for (size_t i = 0; i < versions.size(); i++) {
bool is_last = i + 1 == versions.size();
encrypted_message_copy = encrypted_message.copy(); encrypted_message_copy = encrypted_message.copy();
data = encrypted_message_copy.as_slice(); data = encrypted_message_copy.as_slice();
CHECK(is_aligned_pointer<4>(data.data())); CHECK(is_aligned_pointer<4>(data.data()));
@ -872,7 +800,7 @@ Result<std::tuple<uint64, BufferSlice, int32>> SecretChatActor::decrypt(BufferSl
info.version = mtproto_version; info.version = mtproto_version;
info.is_creator = auth_state_.x == 0; info.is_creator = auth_state_.x == 0;
r_read_result = mtproto::Transport::read(data, *auth_key, &info); r_read_result = mtproto::Transport::read(data, *auth_key, &info);
if (!is_last && r_read_result.is_error()) { if (i + 1 == versions.size() && r_read_result.is_error()) {
LOG(WARNING) << tag("mtproto", mtproto_version) << " decryption failed " << r_read_result.error(); LOG(WARNING) << tag("mtproto", mtproto_version) << " decryption failed " << r_read_result.error();
continue; continue;
} }
@ -883,7 +811,7 @@ Result<std::tuple<uint64, BufferSlice, int32>> SecretChatActor::decrypt(BufferSl
case mtproto::Transport::ReadResult::Quickack: case mtproto::Transport::ReadResult::Quickack:
return Status::Error("Got quickack instead of a message"); return Status::Error("Got quickack instead of a message");
case mtproto::Transport::ReadResult::Error: case mtproto::Transport::ReadResult::Error:
return Status::Error(PSLICE() << "Got mtproto error code instead of a message: " << read_result.error()); return Status::Error(PSLICE() << "Got MTProto error code instead of a message: " << read_result.error());
case mtproto::Transport::ReadResult::Nop: case mtproto::Transport::ReadResult::Nop:
return Status::Error("Got nop instead of a message"); return Status::Error("Got nop instead of a message");
case mtproto::Transport::ReadResult::Packet: case mtproto::Transport::ReadResult::Packet:
@ -938,7 +866,7 @@ Status SecretChatActor::do_inbound_message_encrypted(unique_ptr<log_event::Inbou
return Status::Error(PSLICE() << "Invalid seq_no: " << to_string(message_with_layer)); return Status::Error(PSLICE() << "Invalid seq_no: " << to_string(message_with_layer));
} }
message->decrypted_message_layer = std::move(message_with_layer); message->decrypted_message_layer = std::move(message_with_layer);
return do_inbound_message_decrypted_unchecked(std::move(message)); return do_inbound_message_decrypted_unchecked(std::move(message), mtproto_version);
} else { } else {
status = Status::Error(PSLICE() << parser.get_error() << format::as_hex_dump<4>(data_buffer.as_slice())); status = Status::Error(PSLICE() << parser.get_error() << format::as_hex_dump<4>(data_buffer.as_slice()));
} }
@ -958,7 +886,7 @@ Status SecretChatActor::do_inbound_message_encrypted(unique_ptr<log_event::Inbou
if (!new_parser.get_error()) { if (!new_parser.get_error()) {
message->decrypted_message_layer = secret_api::make_object<secret_api::decryptedMessageLayer>( message->decrypted_message_layer = secret_api::make_object<secret_api::decryptedMessageLayer>(
BufferSlice(), config_state_.his_layer, -1, -1, std::move(message_without_layer)); BufferSlice(), config_state_.his_layer, -1, -1, std::move(message_without_layer));
return do_inbound_message_decrypted_unchecked(std::move(message)); return do_inbound_message_decrypted_unchecked(std::move(message), mtproto_version);
} }
LOG(ERROR) << "Failed to fetch update (DecryptedMessage): " << new_parser.get_error() LOG(ERROR) << "Failed to fetch update (DecryptedMessage): " << new_parser.get_error()
<< format::as_hex_dump<4>(data_buffer.as_slice()); << format::as_hex_dump<4>(data_buffer.as_slice());
@ -995,7 +923,8 @@ Status SecretChatActor::check_seq_no(int in_seq_no, int out_seq_no, int32 his_la
return Status::OK(); return Status::OK();
} }
Status SecretChatActor::do_inbound_message_decrypted_unchecked(unique_ptr<log_event::InboundSecretMessage> message) { Status SecretChatActor::do_inbound_message_decrypted_unchecked(unique_ptr<log_event::InboundSecretMessage> message,
int32 mtproto_version) {
SCOPE_EXIT { SCOPE_EXIT {
CHECK(message == nullptr || !message->promise); CHECK(message == nullptr || !message->promise);
}; };
@ -1056,7 +985,8 @@ Status SecretChatActor::do_inbound_message_decrypted_unchecked(unique_ptr<log_ev
} }
} }
LOG(INFO) << "GOT MESSAGE " << to_string(message->decrypted_message_layer); LOG(INFO) << "Receive message encrypted with MTProto " << mtproto_version << ": "
<< to_string(message->decrypted_message_layer);
if (status.is_error()) { if (status.is_error()) {
CHECK(status.code() == 2); // gap found CHECK(status.code() == 2); // gap found
@ -1592,8 +1522,8 @@ Status SecretChatActor::outbound_rewrite_with_empty(uint64 state_id) {
state->message->random_id, secret_api::make_object<secret_api::decryptedMessageActionDeleteMessages>( state->message->random_id, secret_api::make_object<secret_api::decryptedMessageActionDeleteMessages>(
std::vector<int64>{static_cast<int64>(state->message->random_id)})); std::vector<int64>{static_cast<int64>(state->message->random_id)}));
TRY_RESULT(encrypted_message, create_encrypted_message(current_layer(), state->message->my_in_seq_no, TRY_RESULT(encrypted_message,
state->message->my_out_seq_no, message)); create_encrypted_message(state->message->my_in_seq_no, state->message->my_out_seq_no, message));
state->message->encrypted_message = std::move(encrypted_message); state->message->encrypted_message = std::move(encrypted_message);
LOG(INFO) << tag("crc", crc64(state->message->encrypted_message.as_slice())); LOG(INFO) << tag("crc", crc64(state->message->encrypted_message.as_slice()));
state->message->is_rewritable = false; state->message->is_rewritable = false;
@ -1820,7 +1750,7 @@ void SecretChatActor::on_outbound_outer_send_message_promise(uint64 state_id, Pr
} }
auto *state = outbound_message_states_.get(state_id); auto *state = outbound_message_states_.get(state_id);
CHECK(state); CHECK(state);
LOG(INFO) << "Outbound secret message [TODO] " << tag("log_event_id", state->message->log_event_id()); LOG(INFO) << "Outbound secret message " << tag("log_event_id", state->message->log_event_id());
promise.set_value(Unit()); // Seems like this message is at least stored to binlog already promise.set_value(Unit()); // Seems like this message is at least stored to binlog already
if (state->send_result_) { if (state->send_result_) {
state->send_result_({}); state->send_result_({});
@ -1918,7 +1848,6 @@ Status SecretChatActor::on_update_chat(telegram_api::encryptedChat &update) {
// NB: order is important // NB: order is important
context_->secret_chat_db()->set_value(pfs_state_); context_->secret_chat_db()->set_value(pfs_state_);
context_->secret_chat_db()->set_value(auth_state_); context_->secret_chat_db()->set_value(auth_state_);
LOG(INFO) << "OK! Ready!";
send_update_secret_chat(); send_update_secret_chat();
send_action(secret_api::make_object<secret_api::decryptedMessageActionNotifyLayer>(MY_LAYER), SendFlag::None, send_action(secret_api::make_object<secret_api::decryptedMessageActionNotifyLayer>(MY_LAYER), SendFlag::None,
Promise<>()); Promise<>());

View File

@ -48,10 +48,8 @@ class NetQueryCreator;
class SecretChatActor : public NetQueryCallback { class SecretChatActor : public NetQueryCallback {
public: public:
// do not change DEFAULT_LAYER, unless all it's usages are fixed
enum : int32 { enum : int32 {
DEFAULT_LAYER = 46, DEFAULT_LAYER = 73,
VIDEO_NOTES_LAYER = 66,
MTPROTO_2_LAYER = 73, MTPROTO_2_LAYER = 73,
NEW_ENTITIES_LAYER = 101, NEW_ENTITIES_LAYER = 101,
DELETE_MESSAGES_ON_CLOSE_LAYER = 123, DELETE_MESSAGES_ON_CLOSE_LAYER = 123,
@ -571,7 +569,8 @@ class SecretChatActor : public NetQueryCallback {
Result<std::tuple<uint64, BufferSlice, int32>> decrypt(BufferSlice &encrypted_message); Result<std::tuple<uint64, BufferSlice, int32>> decrypt(BufferSlice &encrypted_message);
Status do_inbound_message_encrypted(unique_ptr<log_event::InboundSecretMessage> message); Status do_inbound_message_encrypted(unique_ptr<log_event::InboundSecretMessage> message);
Status do_inbound_message_decrypted_unchecked(unique_ptr<log_event::InboundSecretMessage> message); Status do_inbound_message_decrypted_unchecked(unique_ptr<log_event::InboundSecretMessage> message,
int32 mtproto_version);
Status do_inbound_message_decrypted(unique_ptr<log_event::InboundSecretMessage> message); Status do_inbound_message_decrypted(unique_ptr<log_event::InboundSecretMessage> message);
void do_inbound_message_decrypted_pending(unique_ptr<log_event::InboundSecretMessage> message); void do_inbound_message_decrypted_pending(unique_ptr<log_event::InboundSecretMessage> message);
@ -620,7 +619,8 @@ class SecretChatActor : public NetQueryCallback {
tl_object_ptr<telegram_api::InputEncryptedFile> file, int32 flags, Promise<> promise); tl_object_ptr<telegram_api::InputEncryptedFile> file, int32 flags, Promise<> promise);
void do_outbound_message_impl(unique_ptr<log_event::OutboundSecretMessage>, Promise<> promise); void do_outbound_message_impl(unique_ptr<log_event::OutboundSecretMessage>, Promise<> promise);
Result<BufferSlice> create_encrypted_message(int32 layer, int32 my_in_seq_no, int32 my_out_seq_no,
Result<BufferSlice> create_encrypted_message(int32 my_in_seq_no, int32 my_out_seq_no,
tl_object_ptr<secret_api::DecryptedMessage> &message); tl_object_ptr<secret_api::DecryptedMessage> &message);
NetQueryPtr create_net_query(const log_event::OutboundSecretMessage &message); NetQueryPtr create_net_query(const log_event::OutboundSecretMessage &message);

View File

@ -9,7 +9,6 @@
#include "td/telegram/AuthManager.h" #include "td/telegram/AuthManager.h"
#include "td/telegram/files/FileManager.h" #include "td/telegram/files/FileManager.h"
#include "td/telegram/secret_api.h" #include "td/telegram/secret_api.h"
#include "td/telegram/SecretChatActor.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
@ -167,7 +166,7 @@ void VideoNotesManager::create_video_note(FileId file_id, string minithumbnail,
SecretInputMedia VideoNotesManager::get_secret_input_media(FileId video_note_file_id, SecretInputMedia VideoNotesManager::get_secret_input_media(FileId video_note_file_id,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file, tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
BufferSlice thumbnail, int32 layer) const { BufferSlice thumbnail) const {
const VideoNote *video_note = get_video_note(video_note_file_id); const VideoNote *video_note = get_video_note(video_note_file_id);
CHECK(video_note != nullptr); CHECK(video_note != nullptr);
auto file_view = td_->file_manager_->get_file_view(video_note_file_id); auto file_view = td_->file_manager_->get_file_view(video_note_file_id);
@ -184,7 +183,6 @@ SecretInputMedia VideoNotesManager::get_secret_input_media(FileId video_note_fil
if (video_note->thumbnail.file_id.is_valid() && thumbnail.empty()) { if (video_note->thumbnail.file_id.is_valid() && thumbnail.empty()) {
return SecretInputMedia{}; return SecretInputMedia{};
} }
CHECK(layer >= SecretChatActor::VIDEO_NOTES_LAYER);
vector<tl_object_ptr<secret_api::DocumentAttribute>> attributes; vector<tl_object_ptr<secret_api::DocumentAttribute>> attributes;
attributes.push_back(make_tl_object<secret_api::documentAttributeVideo66>( attributes.push_back(make_tl_object<secret_api::documentAttributeVideo66>(
secret_api::documentAttributeVideo66::ROUND_MESSAGE_MASK, true, video_note->duration, secret_api::documentAttributeVideo66::ROUND_MESSAGE_MASK, true, video_note->duration,

View File

@ -39,7 +39,7 @@ class VideoNotesManager {
SecretInputMedia get_secret_input_media(FileId video_note_file_id, SecretInputMedia get_secret_input_media(FileId video_note_file_id,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file, tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
BufferSlice thumbnail, int32 layer) const; BufferSlice thumbnail) const;
FileId get_video_note_thumbnail_file_id(FileId file_id) const; FileId get_video_note_thumbnail_file_id(FileId file_id) const;