Remove support for secret chat layers before 73.
This commit is contained in:
parent
c30ccd1e0d
commit
d80b613b55
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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()) {
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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<>());
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user