Merge commit '3a626f6df2003e4cd834477de65dc900f074adda'

This commit is contained in:
Andrea Cavalli 2020-08-20 15:31:08 +02:00
commit 8c0ce47f61
25 changed files with 159 additions and 77 deletions

View File

@ -180,7 +180,7 @@ To build `TDLib` in Release mode using MSVC, you will need to additionally speci
<a name="using-cxx"></a> <a name="using-cxx"></a>
## Using in CMake C++ projects ## Using in CMake C++ projects
For C++ projects that use CMake, the best approach is to build `TDLib` as part of your project or to use a prebuilt installation. For C++ projects that use CMake, the best approach is to build `TDLib` as part of your project or to install it system-wide.
There are several libraries that you could use in your CMake project: There are several libraries that you could use in your CMake project:

View File

@ -7,7 +7,7 @@ This is an example of building TDLib with `C++/CLI` support and an example of TD
* Download and install Microsoft Visual Studio 2015 or later. * Download and install Microsoft Visual Studio 2015 or later.
* Download and install [CMake](https://cmake.org/download/); choose "Add CMake to the system PATH" option while installing. * Download and install [CMake](https://cmake.org/download/); choose "Add CMake to the system PATH" option while installing.
* Install [vcpkg](https://github.com/Microsoft/vcpkg#quick-start) or update it to the latest version using `vcpkg update` and following received instructions. * Install [vcpkg](https://github.com/Microsoft/vcpkg#quick-start) or update it to the latest version using `vcpkg update` and following received instructions.
* Install `zlib` and `openssl` for using `vcpkg`: * Install `zlib` and `openssl` using `vcpkg`:
``` ```
cd <path to vcpkg> cd <path to vcpkg>
.\vcpkg.exe install openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows .\vcpkg.exe install openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows

View File

@ -3,7 +3,7 @@
To run this example, you will need installed JDK >= 1.6. To run this example, you will need installed JDK >= 1.6.
For Javadoc documentation generation PHP is needed. For Javadoc documentation generation PHP is needed.
TDLib should be prebuilt for using with Java and installed to local subdirectory `td/` as follows: TDLib should be prebuilt with JNI bindings and installed to local subdirectory `td/` as follows:
``` ```
cd <path to TDLib sources> cd <path to TDLib sources>
mkdir jnibuild mkdir jnibuild

View File

@ -109,7 +109,7 @@ documentAttributeVideo66#ef02ce6 flags:# round_message:flags.0?true duration:int
// layer 73 // layer 73
decryptedMessage#91cc4674 flags:# random_id:long ttl:int message:string media:flags.9?DecryptedMessageMedia entities:flags.7?Vector<MessageEntity> via_bot_name:flags.11?string reply_to_random_id:flags.3?long grouped_id:flags.17?long = DecryptedMessage; decryptedMessage#91cc4674 flags:# silent:flags.5?true random_id:long ttl:int message:string media:flags.9?DecryptedMessageMedia entities:flags.7?Vector<MessageEntity> via_bot_name:flags.11?string reply_to_random_id:flags.3?long grouped_id:flags.17?long = DecryptedMessage;
// layer 101 // layer 101

Binary file not shown.

View File

@ -71,7 +71,7 @@ AuthManager::AuthManager(int32 api_id, const string &api_hash, ActorShared<> par
void AuthManager::start_up() { void AuthManager::start_up() {
if (state_ == State::LoggingOut) { if (state_ == State::LoggingOut) {
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(telegram_api::auth_logOut())); send_log_out_query();
} else if (state_ == State::DestroyingKeys) { } else if (state_ == State::DestroyingKeys) {
destroy_auth_keys(); destroy_auth_keys();
} }
@ -364,10 +364,16 @@ void AuthManager::log_out(uint64 query_id) {
LOG(INFO) << "Logging out"; LOG(INFO) << "Logging out";
G()->td_db()->get_binlog_pmc()->set("auth", "logout"); G()->td_db()->get_binlog_pmc()->set("auth", "logout");
update_state(State::LoggingOut); update_state(State::LoggingOut);
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(telegram_api::auth_logOut())); send_log_out_query();
} }
} }
void AuthManager::send_log_out_query() {
auto query = G()->net_query_creator().create(telegram_api::auth_logOut());
query->set_priority(1);
start_net_query(NetQueryType::LogOut, std::move(query));
}
void AuthManager::delete_account(uint64 query_id, const string &reason) { void AuthManager::delete_account(uint64 query_id, const string &reason) {
if (state_ != State::Ok && state_ != State::WaitPassword) { if (state_ != State::Ok && state_ != State::WaitPassword) {
return on_query_error(query_id, Status::Error(8, "Need to log in first")); return on_query_error(query_id, Status::Error(8, "Need to log in first"));
@ -833,6 +839,8 @@ void AuthManager::update_state(State new_state, bool force, bool should_save_sta
if (state_ == new_state && !force) { if (state_ == new_state && !force) {
return; return;
} }
bool skip_update = (state_ == State::LoggingOut || state_ == State::DestroyingKeys) &&
(new_state == State::LoggingOut || new_state == State::DestroyingKeys);
state_ = new_state; state_ = new_state;
if (should_save_state) { if (should_save_state) {
save_state(); save_state();
@ -840,8 +848,10 @@ void AuthManager::update_state(State new_state, bool force, bool should_save_sta
if (new_state == State::LoggingOut || new_state == State::DestroyingKeys) { if (new_state == State::LoggingOut || new_state == State::DestroyingKeys) {
send_closure(G()->state_manager(), &StateManager::on_logging_out, true); send_closure(G()->state_manager(), &StateManager::on_logging_out, true);
} }
if (!skip_update) {
send_closure(G()->td(), &Td::send_update, send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateAuthorizationState>(get_authorization_state_object(state_))); make_tl_object<td_api::updateAuthorizationState>(get_authorization_state_object(state_)));
}
if (!pending_get_authorization_state_requests_.empty()) { if (!pending_get_authorization_state_requests_.empty()) {
auto query_ids = std::move(pending_get_authorization_state_requests_); auto query_ids = std::move(pending_get_authorization_state_requests_);

View File

@ -217,6 +217,8 @@ class AuthManager : public NetActor {
static void on_update_login_token_static(void *td); static void on_update_login_token_static(void *td);
void send_export_login_token_query(); void send_export_login_token_query();
void set_login_token_expires_at(double login_token_expires_at); void set_login_token_expires_at(double login_token_expires_at);
void send_log_out_query();
void destroy_auth_keys(); void destroy_auth_keys();
void on_send_code_result(NetQueryPtr &result); void on_send_code_result(NetQueryPtr &result);

View File

@ -37,18 +37,9 @@ class MultiTd : public Actor {
CHECK(td.empty()); CHECK(td.empty());
string name = "Td"; string name = "Td";
class TdActorContext : public ActorContext { auto context = std::make_shared<td::ActorContext>();
public:
explicit TdActorContext(string tag) : tag_(std::move(tag)) {
}
int32 get_id() const override {
return 0x172ae58d;
}
string tag_;
};
auto context = std::make_shared<TdActorContext>(to_string(td_id));
auto old_context = set_context(context); auto old_context = set_context(context);
auto old_tag = set_tag(context->tag_); auto old_tag = set_tag(to_string(td_id));
td = create_actor<Td>("Td", std::move(callback), options_); td = create_actor<Td>("Td", std::move(callback), options_);
set_context(old_context); set_context(old_context);
set_tag(old_tag); set_tag(old_tag);

View File

@ -25,7 +25,7 @@
namespace td { namespace td {
int MessageEntity::get_type_priority(Type type) { int MessageEntity::get_type_priority(Type type) {
static const int types[] = {50, 50, 50, 50, 50, 90, 91, 20, 11, 10, 49, 49, 50, 50, 92, 93, 0}; static const int types[] = {50, 50, 50, 50, 50, 90, 91, 20, 11, 10, 49, 49, 50, 50, 92, 93, 0, 50};
return types[static_cast<int32>(type)]; return types[static_cast<int32>(type)];
} }

View File

@ -28,6 +28,7 @@ class ContactsManager;
class MessageEntity { class MessageEntity {
public: public:
// don't forget to update get_type_priority()
enum class Type : int32 { enum class Type : int32 {
Mention, Mention,
Hashtag, Hashtag,

View File

@ -2056,7 +2056,7 @@ class SendSecretMessageActor : public NetActor {
public: public:
void send(DialogId dialog_id, int64 reply_to_random_id, int32 ttl, const string &text, SecretInputMedia media, void send(DialogId dialog_id, int64 reply_to_random_id, int32 ttl, const string &text, SecretInputMedia media,
vector<tl_object_ptr<secret_api::MessageEntity>> &&entities, UserId via_bot_user_id, int64 media_album_id, vector<tl_object_ptr<secret_api::MessageEntity>> &&entities, UserId via_bot_user_id, int64 media_album_id,
int64 random_id) { bool disable_notification, int64 random_id) {
if (false && !media.empty()) { if (false && !media.empty()) {
td->messages_manager_->on_send_secret_message_error(random_id, Status::Error(400, "FILE_PART_1_MISSING"), Auto()); td->messages_manager_->on_send_secret_message_error(random_id, Status::Error(400, "FILE_PART_1_MISSING"), Auto());
stop(); stop();
@ -2083,13 +2083,16 @@ class SendSecretMessageActor : public NetActor {
CHECK(media_album_id < 0); CHECK(media_album_id < 0);
flags |= secret_api::decryptedMessage::GROUPED_ID_MASK; flags |= secret_api::decryptedMessage::GROUPED_ID_MASK;
} }
if (disable_notification) {
flags |= secret_api::decryptedMessage::SILENT_MASK;
}
send_closure(G()->secret_chats_manager(), &SecretChatsManager::send_message, dialog_id.get_secret_chat_id(), send_closure(
G()->secret_chats_manager(), &SecretChatsManager::send_message, dialog_id.get_secret_chat_id(),
make_tl_object<secret_api::decryptedMessage>( make_tl_object<secret_api::decryptedMessage>(
flags, random_id, ttl, text, std::move(media.decrypted_media_), std::move(entities), flags, false /*ignored*/, random_id, ttl, text, std::move(media.decrypted_media_), std::move(entities),
td->contacts_manager_->get_user_username(via_bot_user_id), reply_to_random_id, -media_album_id), td->contacts_manager_->get_user_username(via_bot_user_id), reply_to_random_id, -media_album_id),
std::move(media.input_file_), std::move(media.input_file_), PromiseCreator::event(self_closure(this, &SendSecretMessageActor::done)));
PromiseCreator::event(self_closure(this, &SendSecretMessageActor::done)));
} }
void done() { void done() {
@ -3183,10 +3186,14 @@ class DeleteMessagesQuery : public Td::ResultHandler {
} }
void on_error(uint64 id, Status status) override { void on_error(uint64 id, Status status) override {
if (!G()->is_expected_error(status) && if (!G()->is_expected_error(status)) {
(dialog_id_.get_type() == DialogType::User || status.message() != "MESSAGE_DELETE_FORBIDDEN")) { // MESSAGE_DELETE_FORBIDDEN can be returned in group chats when administrator rights was removed
// MESSAGE_DELETE_FORBIDDEN can be returned in private chats for bots when revoke time limit exceeded
if (status.message() != "MESSAGE_DELETE_FORBIDDEN" ||
(dialog_id_.get_type() == DialogType::User && !td->auth_manager_->is_bot())) {
LOG(ERROR) << "Receive error for delete messages: " << status; LOG(ERROR) << "Receive error for delete messages: " << status;
} }
}
promise_.set_error(std::move(status)); promise_.set_error(std::move(status));
} }
}; };
@ -6411,7 +6418,7 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p
auto channel_id = dialog_id.get_channel_id(); auto channel_id = dialog_id.get_channel_id();
if (!td_->contacts_manager_->have_channel(channel_id)) { if (!td_->contacts_manager_->have_channel(channel_id)) {
// do not create dialog if there is no info about the channel // do not create dialog if there is no info about the channel
LOG(WARNING) << "There is no info about " << channel_id << ", so ignore " << oneline(to_string(update)); LOG(INFO) << "There is no info about " << channel_id << ", so ignore " << oneline(to_string(update));
return; return;
} }
@ -8030,7 +8037,9 @@ void MessagesManager::after_get_difference() {
vector<FullMessageId> update_message_ids_to_delete; vector<FullMessageId> update_message_ids_to_delete;
for (auto &it : update_message_ids_) { for (auto &it : update_message_ids_) {
// this is impossible for ordinary chats because updates coming during getDifference have already been applied // there can be unhandled updateMessageId updates after getDifference even for ordinary chats,
// because despite updates coming during getDifference have already been applied,
// some of them could be postponed because of pts gap
auto full_message_id = it.first; auto full_message_id = it.first;
auto dialog_id = full_message_id.get_dialog_id(); auto dialog_id = full_message_id.get_dialog_id();
auto message_id = full_message_id.get_message_id(); auto message_id = full_message_id.get_message_id();
@ -8059,9 +8068,13 @@ void MessagesManager::after_get_difference() {
const Dialog *d = get_dialog(dialog_id); const Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr); CHECK(d != nullptr);
if (dialog_id.get_type() == DialogType::Channel || pending_updates_.empty() || message_id.is_scheduled() ||
message_id <= d->last_new_message_id) {
LOG(ERROR) << "Receive updateMessageId from " << it.second << " to " << full_message_id LOG(ERROR) << "Receive updateMessageId from " << it.second << " to " << full_message_id
<< " but not receive corresponding message, last_new_message_id = " << d->last_new_message_id; << " but not receive corresponding message, last_new_message_id = " << d->last_new_message_id;
if (dialog_id.get_type() != DialogType::Channel) { }
if (dialog_id.get_type() != DialogType::Channel &&
(pending_updates_.empty() || message_id.is_scheduled() || message_id <= d->last_new_message_id)) {
dump_debug_message_op(get_dialog(dialog_id)); dump_debug_message_op(get_dialog(dialog_id));
} }
if (message_id.is_scheduled() || message_id <= d->last_new_message_id) { if (message_id.is_scheduled() || message_id <= d->last_new_message_id) {
@ -8849,7 +8862,7 @@ void MessagesManager::delete_dialog_messages_from_updates(DialogId dialog_id, co
send_update_delete_messages(dialog_id, std::move(deleted_message_ids), true, false); send_update_delete_messages(dialog_id, std::move(deleted_message_ids), true, false);
} }
string MessagesManager::get_search_text(const Message *m) const { string MessagesManager::get_message_search_text(const Message *m) const {
if (m->is_content_secret) { if (m->is_content_secret) {
return string(); return string();
} }
@ -11615,6 +11628,9 @@ void MessagesManager::on_get_secret_message(SecretChatId secret_chat_id, UserId
if ((message->flags_ & secret_api::decryptedMessage::MEDIA_MASK) != 0) { if ((message->flags_ & secret_api::decryptedMessage::MEDIA_MASK) != 0) {
flags |= MESSAGE_FLAG_HAS_MEDIA; flags |= MESSAGE_FLAG_HAS_MEDIA;
} }
if ((message->flags_ & secret_api::decryptedMessage::SILENT_MASK) != 0) {
flags |= MESSAGE_FLAG_IS_SILENT;
}
if (!clean_input_string(message->via_bot_name_)) { if (!clean_input_string(message->via_bot_name_)) {
LOG(WARNING) << "Receive invalid bot username " << message->via_bot_name_; LOG(WARNING) << "Receive invalid bot username " << message->via_bot_name_;
@ -11893,16 +11909,6 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
} }
int32 flags = message_info.flags; int32 flags = message_info.flags;
if (flags &
~(MESSAGE_FLAG_IS_OUT | MESSAGE_FLAG_IS_FORWARDED | MESSAGE_FLAG_IS_REPLY | MESSAGE_FLAG_HAS_MENTION |
MESSAGE_FLAG_HAS_UNREAD_CONTENT | MESSAGE_FLAG_HAS_REPLY_MARKUP | MESSAGE_FLAG_HAS_ENTITIES |
MESSAGE_FLAG_HAS_FROM_ID | MESSAGE_FLAG_HAS_MEDIA | MESSAGE_FLAG_HAS_VIEWS | MESSAGE_FLAG_IS_SENT_VIA_BOT |
MESSAGE_FLAG_IS_SILENT | MESSAGE_FLAG_IS_POST | MESSAGE_FLAG_HAS_EDIT_DATE | MESSAGE_FLAG_HAS_AUTHOR_SIGNATURE |
MESSAGE_FLAG_HAS_MEDIA_ALBUM_ID | MESSAGE_FLAG_IS_FROM_SCHEDULED | MESSAGE_FLAG_IS_LEGACY |
MESSAGE_FLAG_HIDE_EDIT_DATE | MESSAGE_FLAG_IS_RESTRICTED)) {
LOG(ERROR) << "Unsupported message flags = " << flags << " received";
}
bool is_outgoing = (flags & MESSAGE_FLAG_IS_OUT) != 0; bool is_outgoing = (flags & MESSAGE_FLAG_IS_OUT) != 0;
bool is_silent = (flags & MESSAGE_FLAG_IS_SILENT) != 0; bool is_silent = (flags & MESSAGE_FLAG_IS_SILENT) != 0;
bool is_channel_post = (flags & MESSAGE_FLAG_IS_POST) != 0; bool is_channel_post = (flags & MESSAGE_FLAG_IS_POST) != 0;
@ -19979,7 +19985,14 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
auto live_location_date = m->is_failed_to_send ? 0 : m->date; auto live_location_date = m->is_failed_to_send ? 0 : m->date;
auto date = is_scheduled ? 0 : m->date; auto date = is_scheduled ? 0 : m->date;
auto edit_date = m->hide_edit_date ? 0 : m->edit_date; auto edit_date = m->hide_edit_date ? 0 : m->edit_date;
auto views = m->message_id.is_scheduled() || (m->message_id.is_local() && m->forward_info == nullptr) ? 0 : m->views; auto views = m->views;
if (m->message_id.is_scheduled()) {
if (m->forward_info == nullptr || is_broadcast_channel(dialog_id)) {
views = 0;
}
} else if (m->message_id.is_local() && m->forward_info == nullptr) {
views = 0;
}
return make_tl_object<td_api::message>( return make_tl_object<td_api::message>(
m->message_id.get(), td_->contacts_manager_->get_user_id_object(m->sender_user_id, "sender_user_id"), m->message_id.get(), td_->contacts_manager_->get_user_id_object(m->sender_user_id, "sender_user_id"),
dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, can_be_edited, dialog_id.get(), std::move(sending_state), std::move(scheduling_state), is_outgoing, can_be_edited,
@ -20850,7 +20863,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect
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(), layer),
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, random_id); m->media_album_id, m->disable_notification, random_id);
} else { } else {
send_closure(td_->create_net_actor<SendMessageActor>(), &SendMessageActor::send, get_message_flags(m), dialog_id, send_closure(td_->create_net_actor<SendMessageActor>(), &SendMessageActor::send, get_message_flags(m), dialog_id,
m->reply_to_message_id, get_message_schedule_date(m), get_input_reply_markup(m->reply_markup), m->reply_to_message_id, get_message_schedule_date(m), get_input_reply_markup(m->reply_markup),
@ -21030,7 +21043,7 @@ void MessagesManager::on_secret_message_media_uploaded(DialogId dialog_id, const
} }
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, "", std::move(secret_input_media), std::move(entities), m->reply_to_random_id, m->ttl, "", std::move(secret_input_media), std::move(entities),
m->via_bot_user_id, m->media_album_id, random_id); m->via_bot_user_id, m->media_album_id, m->disable_notification, random_id);
})); }));
} }
@ -23111,8 +23124,9 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
m->real_forward_from_message_id = message_id; m->real_forward_from_message_id = message_id;
m->via_bot_user_id = forwarded_message->via_bot_user_id; m->via_bot_user_id = forwarded_message->via_bot_user_id;
m->in_game_share = in_game_share; m->in_game_share = in_game_share;
if (forwarded_message->views > 0 && m->forward_info != nullptr) { if (forwarded_message->views > 0 && m->forward_info != nullptr && m->views == 0 &&
m->views = 1; !(m->message_id.is_scheduled() && is_broadcast_channel(to_dialog_id))) {
m->views = forwarded_message->views;
} }
if (is_game) { if (is_game) {
@ -27385,6 +27399,11 @@ void MessagesManager::set_dialog_photo(DialogId dialog_id, const tl_object_ptr<t
break; break;
} }
} }
if (input_file == nullptr) {
send_edit_dialog_photo_query(dialog_id, FileId(), make_tl_object<telegram_api::inputChatPhotoEmpty>(),
std::move(promise));
return;
}
const double MAX_ANIMATION_DURATION = 10.0; const double MAX_ANIMATION_DURATION = 10.0;
if (main_frame_timestamp < 0.0 || main_frame_timestamp > MAX_ANIMATION_DURATION) { if (main_frame_timestamp < 0.0 || main_frame_timestamp > MAX_ANIMATION_DURATION) {
@ -29352,7 +29371,7 @@ void MessagesManager::add_message_to_database(const Dialog *d, const Message *m,
unique_message_id = message_id.get_server_message_id(); unique_message_id = message_id.get_server_message_id();
} }
// FOR DEBUG // FOR DEBUG
// text = get_search_text(m); // text = get_message_search_text(m);
// if (!text.empty()) { // if (!text.empty()) {
// search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(Random::secure_int32()); // search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(Random::secure_int32());
// } // }
@ -29361,7 +29380,7 @@ void MessagesManager::add_message_to_database(const Dialog *d, const Message *m,
break; break;
case DialogType::SecretChat: case DialogType::SecretChat:
random_id = m->random_id; random_id = m->random_id;
text = get_search_text(m); text = get_message_search_text(m);
if (!text.empty()) { if (!text.empty()) {
search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(m->random_id); search_id = (static_cast<int64>(m->date) << 32) | static_cast<uint32>(m->random_id);
} }

View File

@ -2692,7 +2692,7 @@ class MessagesManager : public Actor {
void try_hide_distance(DialogId dialog_id, const Message *m); void try_hide_distance(DialogId dialog_id, const Message *m);
string get_search_text(const Message *m) const; string get_message_search_text(const Message *m) const;
unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled); unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled);

View File

@ -1289,7 +1289,7 @@ Status SecretChatActor::do_inbound_message_decrypted(unique_ptr<logevent::Inboun
auto old = move_tl_object_as<secret_api::decryptedMessage46>(message->decrypted_message_layer->message_); auto old = move_tl_object_as<secret_api::decryptedMessage46>(message->decrypted_message_layer->message_);
old->flags_ &= ~secret_api::decryptedMessage::GROUPED_ID_MASK; // just in case old->flags_ &= ~secret_api::decryptedMessage::GROUPED_ID_MASK; // just in case
message->decrypted_message_layer->message_ = secret_api::make_object<secret_api::decryptedMessage>( message->decrypted_message_layer->message_ = secret_api::make_object<secret_api::decryptedMessage>(
old->flags_, old->random_id_, old->ttl_, std::move(old->message_), std::move(old->media_), old->flags_, false /*ignored*/, 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_, 0); std::move(old->entities_), std::move(old->via_bot_name_), old->reply_to_random_id_, 0);
} }
if (message->decrypted_message_layer->message_->get_id() == secret_api::decryptedMessageService8::ID) { if (message->decrypted_message_layer->message_->get_id() == secret_api::decryptedMessageService8::ID) {
@ -1786,7 +1786,7 @@ void SecretChatActor::on_outbound_outer_send_message_promise(uint64 state_id, Pr
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_({});
} else { } else if (state->message->is_sent) {
context_->on_send_message_error(state->message->random_id, Status::Error(400, "Message has already been sent"), context_->on_send_message_error(state->message->random_id, Status::Error(400, "Message has already been sent"),
Auto()); Auto());
} }

View File

@ -3576,6 +3576,10 @@ class CliClient final : public Actor {
std::tie(chat_id, title) = split(args); std::tie(chat_id, title) = split(args);
send_request(td_api::make_object<td_api::setChatTitle>(as_chat_id(chat_id), title)); send_request(td_api::make_object<td_api::setChatTitle>(as_chat_id(chat_id), title));
} else if (op == "scpe") {
string chat_id = args;
send_request(td_api::make_object<td_api::setChatPhoto>(as_chat_id(chat_id), nullptr));
} else if (op == "scpp") { } else if (op == "scpp") {
string chat_id; string chat_id;
string photo_id; string photo_id;

View File

@ -266,6 +266,13 @@ class NetQuery : public TsListNode<NetQueryDebug> {
finish_migrate(cancel_slot_); finish_migrate(cancel_slot_);
} }
int8 priority() const {
return priority_;
}
void set_priority(int8 priority) {
priority_ = priority;
}
private: private:
State state_ = State::Empty; State state_ = State::Empty;
Type type_ = Type::Common; Type type_ = Type::Common;
@ -284,6 +291,7 @@ class NetQuery : public TsListNode<NetQueryDebug> {
uint32 session_rand_ = 0; uint32 session_rand_ = 0;
bool may_be_lost_ = false; bool may_be_lost_ = false;
int8 priority_{0};
template <class T> template <class T>
struct movable_atomic : public std::atomic<T> { struct movable_atomic : public std::atomic<T> {

View File

@ -117,6 +117,25 @@ class GenAuthKeyActor : public Actor {
} // namespace detail } // namespace detail
void Session::PriorityQueue::push(NetQueryPtr query) {
auto priority = query->priority();
queries_[priority].push(std::move(query));
}
NetQueryPtr Session::PriorityQueue::pop() {
CHECK(!empty());
auto it = queries_.begin();
auto res = it->second.pop();
if (it->second.empty()) {
queries_.erase(it);
}
return res;
}
bool Session::PriorityQueue::empty() const {
return queries_.empty();
}
Session::Session(unique_ptr<Callback> callback, std::shared_ptr<AuthDataShared> shared_auth_data, int32 raw_dc_id, Session::Session(unique_ptr<Callback> callback, std::shared_ptr<AuthDataShared> shared_auth_data, int32 raw_dc_id,
int32 dc_id, bool is_main, bool use_pfs, bool is_cdn, bool need_destroy, int32 dc_id, bool is_main, bool use_pfs, bool is_cdn, bool need_destroy,
const mtproto::AuthKey &tmp_auth_key, std::vector<mtproto::ServerSalt> server_salts) const mtproto::AuthKey &tmp_auth_key, std::vector<mtproto::ServerSalt> server_salts)
@ -344,7 +363,7 @@ void Session::return_query(NetQueryPtr &&query) {
void Session::flush_pending_invoke_after_queries() { void Session::flush_pending_invoke_after_queries() {
while (!pending_invoke_after_queries_.empty()) { while (!pending_invoke_after_queries_.empty()) {
auto &query = pending_invoke_after_queries_.front(); auto &query = pending_invoke_after_queries_.front();
pending_queries_.push_back(std::move(query)); pending_queries_.push(std::move(query));
pending_invoke_after_queries_.pop_front(); pending_invoke_after_queries_.pop_front();
} }
} }
@ -359,7 +378,7 @@ void Session::close() {
auto &query = it.second.query; auto &query = it.second.query;
query->set_message_id(0); query->set_message_id(0);
query->cancel_slot_.clear_event(); query->cancel_slot_.clear_event();
pending_queries_.push_back(std::move(query)); pending_queries_.push(std::move(query));
} }
sent_queries_.clear(); sent_queries_.clear();
sent_containers_.clear(); sent_containers_.clear();
@ -367,10 +386,9 @@ void Session::close() {
flush_pending_invoke_after_queries(); flush_pending_invoke_after_queries();
CHECK(sent_queries_.empty()); CHECK(sent_queries_.empty());
while (!pending_queries_.empty()) { while (!pending_queries_.empty()) {
auto &query = pending_queries_.front(); auto query = pending_queries_.pop();
query->set_error_resend(); query->set_error_resend();
return_query(std::move(query)); return_query(std::move(query));
pending_queries_.pop_front();
} }
callback_->on_closed(); callback_->on_closed();
@ -905,7 +923,7 @@ void Session::add_query(NetQueryPtr &&net_query) {
net_query->debug("Session: pending"); net_query->debug("Session: pending");
LOG_IF(FATAL, UniqueId::extract_type(net_query->id()) == UniqueId::BindKey) LOG_IF(FATAL, UniqueId::extract_type(net_query->id()) == UniqueId::BindKey)
<< "Add BindKey query inpo pending_queries_"; << "Add BindKey query inpo pending_queries_";
pending_queries_.emplace_back(std::move(net_query)); pending_queries_.push(std::move(net_query));
} }
void Session::connection_send_query(ConnectionInfo *info, NetQueryPtr &&net_query, uint64 message_id) { void Session::connection_send_query(ConnectionInfo *info, NetQueryPtr &&net_query, uint64 message_id) {
@ -1323,9 +1341,8 @@ void Session::loop() {
if (auth_data_.is_ready(Time::now_cached())) { if (auth_data_.is_ready(Time::now_cached())) {
if (need_send_query()) { if (need_send_query()) {
while (!pending_queries_.empty() && sent_queries_.size() < MAX_INFLIGHT_QUERIES) { while (!pending_queries_.empty() && sent_queries_.size() < MAX_INFLIGHT_QUERIES) {
auto &query = pending_queries_.front(); auto query = pending_queries_.pop();
connection_send_query(&main_connection_, std::move(query)); connection_send_query(&main_connection_, std::move(query));
pending_queries_.pop_front();
need_flush = true; need_flush = true;
} }
} }

View File

@ -25,9 +25,11 @@
#include "td/utils/List.h" #include "td/utils/List.h"
#include "td/utils/Status.h" #include "td/utils/Status.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include "td/utils/VectorQueue.h"
#include <array> #include <array>
#include <deque> #include <deque>
#include <functional>
#include <map> #include <map>
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
@ -124,7 +126,16 @@ class Session final
// Do not invalidate iterators of these two containers! // Do not invalidate iterators of these two containers!
// TODO: better data structures // TODO: better data structures
std::deque<NetQueryPtr> pending_queries_; struct PriorityQueue {
public:
void push(NetQueryPtr query);
NetQueryPtr pop();
bool empty() const;
private:
std::map<int8, VectorQueue<NetQueryPtr>, std::greater<>> queries_;
};
PriorityQueue pending_queries_;
std::map<uint64, Query> sent_queries_; std::map<uint64, Query> sent_queries_;
std::deque<NetQueryPtr> pending_invoke_after_queries_; std::deque<NetQueryPtr> pending_invoke_after_queries_;
ListNode sent_queries_list_; ListNode sent_queries_list_;

View File

@ -75,7 +75,7 @@ class Actor : public ObserverBase {
uint64 get_link_token(); uint64 get_link_token();
std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context); std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context);
CSlice set_tag(CSlice tag); string set_tag(string tag);
void always_wait_for_mailbox(); void always_wait_for_mailbox();

View File

@ -88,13 +88,13 @@ inline uint64 Actor::get_link_token() {
inline std::shared_ptr<ActorContext> Actor::set_context(std::shared_ptr<ActorContext> context) { inline std::shared_ptr<ActorContext> Actor::set_context(std::shared_ptr<ActorContext> context) {
return info_->set_context(std::move(context)); return info_->set_context(std::move(context));
} }
inline CSlice Actor::set_tag(CSlice tag) { inline string Actor::set_tag(string tag) {
auto &tag_ref = info_->get_context()->tag_; auto *ctx = info_->get_context();
CSlice old_tag; string old_tag;
if (tag_ref) { if (ctx->tag_) {
old_tag = CSlice(tag_ref); old_tag = ctx->tag_;
} }
tag_ref = tag.c_str(); ctx->set_tag(std::move(tag));
Scheduler::on_context_updated(); Scheduler::on_context_updated();
return old_tag; return old_tag;
} }

View File

@ -37,7 +37,13 @@ class ActorContext {
return 0; return 0;
} }
void set_tag(string tag) {
tag_storage_ = std::move(tag);
tag_ = tag_storage_.c_str();
}
const char *tag_ = nullptr; const char *tag_ = nullptr;
string tag_storage_; // sometimes tag_ == tag_storage_.c_str()
std::weak_ptr<ActorContext> this_ptr_; std::weak_ptr<ActorContext> this_ptr_;
}; };

View File

@ -146,7 +146,9 @@ inline const Actor *ActorInfo::get_actor_unsafe() const {
inline std::shared_ptr<ActorContext> ActorInfo::set_context(std::shared_ptr<ActorContext> context) { inline std::shared_ptr<ActorContext> ActorInfo::set_context(std::shared_ptr<ActorContext> context) {
CHECK(is_running()); CHECK(is_running());
context->this_ptr_ = context; context->this_ptr_ = context;
context->tag_ = Scheduler::context()->tag_; if (Scheduler::context()->tag_) {
context->set_tag(Scheduler::context()->tag_);
}
std::swap(context_, context); std::swap(context_, context);
Scheduler::context() = context_.get(); Scheduler::context() = context_.get();
Scheduler::on_context_updated(); Scheduler::on_context_updated();

View File

@ -20,15 +20,17 @@ class BinlogActor : public Actor {
} }
void close(Promise<> promise) { void close(Promise<> promise) {
binlog_->close().ensure(); binlog_->close().ensure();
promise.set_value(Unit());
LOG(INFO) << "Finished to close binlog"; LOG(INFO) << "Finished to close binlog";
stop(); stop();
promise.set_value(Unit()); // setting promise can complete closing and destroy the current actor context
} }
void close_and_destroy(Promise<> promise) { void close_and_destroy(Promise<> promise) {
binlog_->close_and_destroy().ensure(); binlog_->close_and_destroy().ensure();
promise.set_value(Unit());
LOG(INFO) << "Finished to destroy binlog"; LOG(INFO) << "Finished to destroy binlog";
stop(); stop();
promise.set_value(Unit()); // setting promise can complete closing and destroy the current actor context
} }
struct Event { struct Event {

View File

@ -136,8 +136,17 @@ TEST(Http, reader) {
{ {
BufferSlice a("test test"); BufferSlice a("test test");
BufferSlice b = std::move(a); BufferSlice b = std::move(a);
#if TD_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wself-move"
#endif
a = std::move(a); a = std::move(a);
b = std::move(b); b = std::move(b);
#if TD_CLANG
#pragma clang diagnostic pop
#endif
a = std::move(b); a = std::move(b);
BufferSlice c = a.from_slice(a); BufferSlice c = a.from_slice(a);
CHECK(c.size() == a.size()); CHECK(c.size() == a.size());

View File

@ -881,8 +881,8 @@ class Master : public Actor {
LOG(INFO) << "Send message: " << tag("id", id) << tag("text", text) << tag("random_id", random_id); LOG(INFO) << "Send message: " << tag("id", id) << tag("text", text) << tag("random_id", random_id);
sent_messages_[random_id] = Message{id, text}; sent_messages_[random_id] = Message{id, text};
send_closure(get_by_id(id), &SecretChatProxy::send_message, send_closure(get_by_id(id), &SecretChatProxy::send_message,
secret_api::make_object<secret_api::decryptedMessage>(0, random_id, 0, text, Auto(), Auto(), Auto(), secret_api::make_object<secret_api::decryptedMessage>(0, false /*ignored*/, random_id, 0, text, Auto(),
Auto(), 0)); Auto(), Auto(), Auto(), 0));
} }
void process_net_query(my_api::messages_sendEncryptedService &&message, NetQueryPtr net_query, void process_net_query(my_api::messages_sendEncryptedService &&message, NetQueryPtr net_query,
ActorShared<NetQueryCallback> callback) { ActorShared<NetQueryCallback> callback) {