diff --git a/td/mtproto/Handshake.cpp b/td/mtproto/Handshake.cpp index db965496c..1ec70aef2 100644 --- a/td/mtproto/Handshake.cpp +++ b/td/mtproto/Handshake.cpp @@ -46,20 +46,19 @@ static Result fetch_result(Slice message, bool check_end return std::move(result); } +AuthKeyHandshake::AuthKeyHandshake(int32 dc_id, int32 expires_in) + : mode_(expires_in == 0 ? Mode::Main : Mode::Temp), dc_id_(dc_id), expires_in_(expires_in) { +} + void AuthKeyHandshake::clear() { last_query_ = BufferSlice(); state_ = Start; } -bool AuthKeyHandshake::is_ready_for_start() const { - return state_ == Start; -} -bool AuthKeyHandshake::is_ready_for_message(const UInt128 &message_nonce) const { - return state_ != Finish && state_ != Start && nonce_ == message_nonce; -} bool AuthKeyHandshake::is_ready_for_finish() const { return state_ == Finish; } + void AuthKeyHandshake::on_finish() { clear(); } @@ -105,7 +104,6 @@ Status AuthKeyHandshake::on_res_pq(Slice message, Callback *connection, PublicRs dc_id_, expires_in_)); expires_at_ = Time::now() + expires_in_; break; - case Mode::Unknown: default: UNREACHABLE(); } @@ -266,17 +264,6 @@ void AuthKeyHandshake::do_send(Callback *connection, const Storer &storer) { return connection->send_no_crypto(storer); } -Status AuthKeyHandshake::start_main(Callback *connection) { - mode_ = Mode::Main; - return on_start(connection); -} - -Status AuthKeyHandshake::start_tmp(Callback *connection, int32 expires_in) { - mode_ = Mode::Temp; - expires_in_ = expires_in; - return on_start(connection); -} - void AuthKeyHandshake::resume(Callback *connection) { if (state_ == Start) { return on_start(connection).ignore(); @@ -289,7 +276,7 @@ void AuthKeyHandshake::resume(Callback *connection) { LOG(ERROR) << "Last query empty! UNREACHABLE " << state_; return clear(); } - LOG(INFO) << "RESUME"; + LOG(INFO) << "Resume handshake"; do_send(connection, create_storer(last_query_.as_slice())); } diff --git a/td/mtproto/Handshake.h b/td/mtproto/Handshake.h index 82debe9f2..14077b546 100644 --- a/td/mtproto/Handshake.h +++ b/td/mtproto/Handshake.h @@ -33,8 +33,6 @@ class AuthKeyHandshakeContext { }; class AuthKeyHandshake { - enum class Mode { Unknown, Main, Temp }; - public: class Callback { public: @@ -45,44 +43,16 @@ class AuthKeyHandshake { virtual void send_no_crypto(const Storer &storer) = 0; }; - AuthKeyHandshake(int32 dc_id, int32 expires_in) { - dc_id_ = dc_id; - if (expires_in == 0) { - mode_ = Mode::Main; - } else { - mode_ = Mode::Temp; - expires_in_ = expires_in; - } - } - - bool is_ready_for_start() const; - Status start_main(Callback *connection) TD_WARN_UNUSED_RESULT; - Status start_tmp(Callback *connection, int32 expires_in) TD_WARN_UNUSED_RESULT; - - bool is_ready_for_message(const UInt128 &message_nonce) const; + AuthKeyHandshake(int32 dc_id, int32 expires_in); bool is_ready_for_finish() const; + void on_finish(); - void init_main() { - clear(); - mode_ = Mode::Main; - } - - void init_temp(int32 expires_in) { - clear(); - mode_ = Mode::Temp; - expires_in_ = expires_in; - } - void resume(Callback *connection); Status on_message(Slice message, Callback *connection, AuthKeyHandshakeContext *context) TD_WARN_UNUSED_RESULT; - bool is_ready() const { - return is_ready_for_finish(); - } - void clear(); const AuthKey &get_auth_key() const { @@ -102,9 +72,10 @@ class AuthKeyHandshake { } private: - using State = enum { Start, ResPQ, ServerDHParams, DHGenResponse, Finish }; + enum State : int32 { Start, ResPQ, ServerDHParams, DHGenResponse, Finish }; State state_ = Start; - Mode mode_ = Mode::Unknown; + enum class Mode : int32 { Main, Temp }; + Mode mode_ = Mode::Main; int32 dc_id_ = 0; int32 expires_in_ = 0; double expires_at_ = 0; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 670cfae7f..68946ee30 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -8416,13 +8416,14 @@ void ContactsManager::load_user_from_database_impl(UserId user_id, Promise G()->td_db()->get_sqlite_pmc()->get(get_user_database_key(user_id), PromiseCreator::lambda([user_id](string value) { send_closure(G()->contacts_manager(), &ContactsManager::on_load_user_from_database, user_id, - std::move(value)); + std::move(value), false); })); } } -void ContactsManager::on_load_user_from_database(UserId user_id, string value) { - if (G()->close_flag()) { +void ContactsManager::on_load_user_from_database(UserId user_id, string value, bool force) { + if (G()->close_flag() && !force) { + // the user is in Binlog and will be saved after restart return; } @@ -8554,7 +8555,7 @@ ContactsManager::User *ContactsManager::get_user_force_impl(UserId user_id) { } LOG(INFO) << "Trying to load " << user_id << " from database"; - on_load_user_from_database(user_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_user_database_key(user_id))); + on_load_user_from_database(user_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_user_database_key(user_id)), true); return get_user(user_id); } @@ -8709,13 +8710,14 @@ void ContactsManager::load_chat_from_database_impl(ChatId chat_id, Promise G()->td_db()->get_sqlite_pmc()->get(get_chat_database_key(chat_id), PromiseCreator::lambda([chat_id](string value) { send_closure(G()->contacts_manager(), &ContactsManager::on_load_chat_from_database, chat_id, - std::move(value)); + std::move(value), false); })); } } -void ContactsManager::on_load_chat_from_database(ChatId chat_id, string value) { - if (G()->close_flag()) { +void ContactsManager::on_load_chat_from_database(ChatId chat_id, string value, bool force) { + if (G()->close_flag() && !force) { + // the chat is in Binlog and will be saved after restart return; } @@ -8791,7 +8793,7 @@ ContactsManager::Chat *ContactsManager::get_chat_force(ChatId chat_id) { } LOG(INFO) << "Trying to load " << chat_id << " from database"; - on_load_chat_from_database(chat_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_chat_database_key(chat_id))); + on_load_chat_from_database(chat_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_chat_database_key(chat_id)), true); return get_chat(chat_id); } @@ -8947,13 +8949,14 @@ void ContactsManager::load_channel_from_database_impl(ChannelId channel_id, Prom G()->td_db()->get_sqlite_pmc()->get( get_channel_database_key(channel_id), PromiseCreator::lambda([channel_id](string value) { send_closure(G()->contacts_manager(), &ContactsManager::on_load_channel_from_database, channel_id, - std::move(value)); + std::move(value), false); })); } } -void ContactsManager::on_load_channel_from_database(ChannelId channel_id, string value) { - if (G()->close_flag()) { +void ContactsManager::on_load_channel_from_database(ChannelId channel_id, string value, bool force) { + if (G()->close_flag() && !force) { + // the channel is in Binlog and will be saved after restart return; } @@ -9044,7 +9047,7 @@ ContactsManager::Channel *ContactsManager::get_channel_force(ChannelId channel_i LOG(INFO) << "Trying to load " << channel_id << " from database"; on_load_channel_from_database(channel_id, - G()->td_db()->get_sqlite_sync_pmc()->get(get_channel_database_key(channel_id))); + G()->td_db()->get_sqlite_sync_pmc()->get(get_channel_database_key(channel_id)), true); return get_channel(channel_id); } @@ -9202,13 +9205,14 @@ void ContactsManager::load_secret_chat_from_database_impl(SecretChatId secret_ch G()->td_db()->get_sqlite_pmc()->get( get_secret_chat_database_key(secret_chat_id), PromiseCreator::lambda([secret_chat_id](string value) { send_closure(G()->contacts_manager(), &ContactsManager::on_load_secret_chat_from_database, secret_chat_id, - std::move(value)); + std::move(value), false); })); } } -void ContactsManager::on_load_secret_chat_from_database(SecretChatId secret_chat_id, string value) { - if (G()->close_flag()) { +void ContactsManager::on_load_secret_chat_from_database(SecretChatId secret_chat_id, string value, bool force) { + if (G()->close_flag() && !force) { + // the secret chat is in Binlog and will be saved after restart return; } @@ -9285,7 +9289,7 @@ ContactsManager::SecretChat *ContactsManager::get_secret_chat_force(SecretChatId LOG(INFO) << "Trying to load " << secret_chat_id << " from database"; on_load_secret_chat_from_database( - secret_chat_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_secret_chat_database_key(secret_chat_id))); + secret_chat_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_secret_chat_database_key(secret_chat_id)), true); return get_secret_chat(secret_chat_id); } @@ -14686,68 +14690,81 @@ void ContactsManager::ban_dialog_participant(DialogId dialog_id, } } -DialogParticipant ContactsManager::get_dialog_participant(DialogId dialog_id, - const tl_object_ptr &participant_id, - int64 &random_id, bool force, Promise &&promise) { - // TODO TRY_RESULT_PROMISE(promise, participant_dialog_id, get_participant_dialog_id(participant_id)); - auto r_participant_dialog_id = get_participant_dialog_id(participant_id); - if (r_participant_dialog_id.is_error()) { - promise.set_error(r_participant_dialog_id.move_as_error()); - return {}; - } - auto participant_dialog_id = r_participant_dialog_id.move_as_ok(); +void ContactsManager::get_dialog_participant(DialogId dialog_id, + const tl_object_ptr &participant_id, + Promise> &&promise) { + TRY_RESULT_PROMISE(promise, participant_dialog_id, get_participant_dialog_id(participant_id)); - LOG(INFO) << "Receive GetChatMember request to get " << participant_dialog_id << " in " << dialog_id - << " with random_id " << random_id; + auto new_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), promise = std::move(promise)](Result &&result) mutable { + TRY_RESULT_PROMISE(promise, dialog_participant, std::move(result)); + send_closure(actor_id, &ContactsManager::finish_get_dialog_participant, std::move(dialog_participant), + std::move(promise)); + }); + get_dialog_participant(dialog_id, participant_dialog_id, std::move(new_promise)); +} + +void ContactsManager::finish_get_dialog_participant(DialogParticipant &&dialog_participant, + Promise> &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + + auto participant_dialog_id = dialog_participant.dialog_id; + bool is_user = participant_dialog_id.get_type() == DialogType::User; + if ((is_user && !have_user(participant_dialog_id.get_user_id())) || + (!is_user && !td_->messages_manager_->have_dialog(participant_dialog_id))) { + return promise.set_error(Status::Error(400, "Member not found")); + } + + promise.set_value(get_chat_member_object(dialog_participant)); +} + +void ContactsManager::get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, + Promise &&promise) { + LOG(INFO) << "Receive GetChatMember request to get " << participant_dialog_id << " in " << dialog_id; if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_participant")) { - promise.set_error(Status::Error(3, "Chat not found")); - return DialogParticipant(); + return promise.set_error(Status::Error(3, "Chat not found")); } switch (dialog_id.get_type()) { case DialogType::User: if (participant_dialog_id == DialogId(get_my_id())) { - promise.set_value(Unit()); - return {participant_dialog_id, dialog_id.get_user_id(), 0, DialogParticipantStatus::Member()}; + return promise.set_value( + DialogParticipant{participant_dialog_id, dialog_id.get_user_id(), 0, DialogParticipantStatus::Member()}); } if (participant_dialog_id == dialog_id) { - promise.set_value(Unit()); - return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; + return promise.set_value( + DialogParticipant{participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}); } - promise.set_error(Status::Error(3, "Member not found")); - break; + return promise.set_error(Status::Error(3, "Member not found")); case DialogType::Chat: if (participant_dialog_id.get_type() != DialogType::User) { - promise.set_value(Unit()); - return DialogParticipant::left(participant_dialog_id); + return promise.set_value(DialogParticipant::left(participant_dialog_id)); } - return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), force, - std::move(promise)); + return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), std::move(promise)); case DialogType::Channel: - return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, random_id, force, - std::move(promise)); + return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, std::move(promise)); case DialogType::SecretChat: { auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id()); if (participant_dialog_id == DialogId(get_my_id())) { - promise.set_value(Unit()); - return {participant_dialog_id, peer_user_id.is_valid() ? peer_user_id : get_my_id(), 0, - DialogParticipantStatus::Member()}; + return promise.set_value(DialogParticipant{participant_dialog_id, + peer_user_id.is_valid() ? peer_user_id : get_my_id(), 0, + DialogParticipantStatus::Member()}); } if (participant_dialog_id == DialogId(peer_user_id)) { - promise.set_value(Unit()); - return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; + return promise.set_value( + DialogParticipant{participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}); } - promise.set_error(Status::Error(3, "Member not found")); - break; + return promise.set_error(Status::Error(3, "Member not found")); } case DialogType::None: default: UNREACHABLE(); - promise.set_error(Status::Error(500, "Wrong chat type")); + return promise.set_error(Status::Error(500, "Wrong chat type")); } - return DialogParticipant(); } DialogParticipants ContactsManager::search_private_chat_participants(UserId my_user_id, UserId peer_user_id, @@ -14874,22 +14891,43 @@ void ContactsManager::search_dialog_participants(DialogId dialog_id, const strin } } -DialogParticipant ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, bool force, - Promise &&promise) { +void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promise &&promise) { LOG(INFO) << "Trying to get " << user_id << " as member of " << chat_id; - if (force) { - promise.set_value(Unit()); - } else if (!load_chat_full(chat_id, force, std::move(promise), "get_chat_participant")) { - return DialogParticipant(); - } - // promise is already set - auto result = get_chat_participant(chat_id, user_id); - if (result == nullptr) { - return DialogParticipant::left(DialogId(user_id)); + auto c = get_chat(chat_id); + if (c == nullptr) { + return promise.set_error(Status::Error(6, "Group not found")); } - return *result; + auto chat_full = get_chat_full_force(chat_id, "get_chat_participant"); + if (chat_full == nullptr || (td_->auth_manager_->is_bot() && is_chat_full_outdated(chat_full, c, chat_id))) { + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), chat_id, user_id, promise = std::move(promise)](Result &&result) mutable { + TRY_STATUS_PROMISE(promise, std::move(result)); + send_closure(actor_id, &ContactsManager::finish_get_chat_participant, chat_id, user_id, std::move(promise)); + }); + send_get_chat_full_query(chat_id, std::move(query_promise), "get_chat_participant"); + } + + if (is_chat_full_outdated(chat_full, c, chat_id)) { + send_get_chat_full_query(chat_id, Auto(), "get_chat_participant lazy"); + } + + finish_get_chat_participant(chat_id, user_id, std::move(promise)); +} + +void ContactsManager::finish_get_chat_participant(ChatId chat_id, UserId user_id, + Promise &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + + const auto *participant = get_chat_participant(chat_id, user_id); + if (participant == nullptr) { + return promise.set_value(DialogParticipant::left(DialogId(user_id))); + } + + promise.set_value(DialogParticipant(*participant)); } void ContactsManager::search_chat_participants(ChatId chat_id, const string &query, int32 limit, @@ -14959,77 +14997,46 @@ void ContactsManager::do_search_chat_participants(ChatId chat_id, const string & })}); } -DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, - int64 &random_id, bool force, Promise &&promise) { - LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id << " with random_id " - << random_id; - if (random_id != 0) { - // request has already been sent before - auto it = received_channel_participant_.find(random_id); - CHECK(it != received_channel_participant_.end()); - auto result = std::move(it->second); - result.status.update_restrictions(); - received_channel_participant_.erase(it); - promise.set_value(Unit()); - return result; - } +void ContactsManager::get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, + Promise &&promise) { + LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id; auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read); if (input_peer == nullptr) { - promise.set_error(Status::Error(6, "User not found")); - return DialogParticipant(); + return promise.set_error(Status::Error(6, "User not found")); } if (have_channel_participant_cache(channel_id)) { auto *participant = get_channel_participant_from_cache(channel_id, participant_dialog_id); if (participant != nullptr) { - promise.set_value(Unit()); - return *participant; + return promise.set_value(DialogParticipant{*participant}); } } - do { - random_id = Random::secure_int64(); - } while (random_id == 0 || received_channel_participant_.find(random_id) != received_channel_participant_.end()); - received_channel_participant_[random_id]; // reserve place for result - - LOG(DEBUG) << "Get info about " << participant_dialog_id << " membership in the " << channel_id << " with random_id " - << random_id; - - auto on_result_promise = - PromiseCreator::lambda([actor_id = actor_id(this), channel_id, random_id, - promise = std::move(promise)](Result r_dialog_participant) mutable { - send_closure(actor_id, &ContactsManager::on_get_channel_participant, channel_id, random_id, - std::move(r_dialog_participant), std::move(promise)); - }); + auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, promise = std::move(promise)]( + Result r_dialog_participant) mutable { + TRY_RESULT_PROMISE(promise, dialog_participant, std::move(r_dialog_participant)); + send_closure(actor_id, &ContactsManager::finish_get_channel_participant, channel_id, std::move(dialog_participant), + std::move(promise)); + }); td_->create_handler(std::move(on_result_promise)) ->send(channel_id, participant_dialog_id, std::move(input_peer)); - return DialogParticipant(); } -void ContactsManager::on_get_channel_participant(ChannelId channel_id, int64 random_id, - Result r_dialog_participant, - Promise &&promise) { +void ContactsManager::finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, + Promise &&promise) { if (G()->close_flag()) { return promise.set_error(Status::Error(500, "Request aborted")); } - LOG(INFO) << "Receive a member of a channel " << channel_id << " with random_id " << random_id; + LOG(INFO) << "Receive a member " << dialog_participant.dialog_id << " of a channel " << channel_id; - auto it = received_channel_participant_.find(random_id); - CHECK(it != received_channel_participant_.end()); - - if (r_dialog_participant.is_error()) { - received_channel_participant_.erase(it); - promise.set_error(r_dialog_participant.move_as_error()); - } else { - it->second = r_dialog_participant.move_as_ok(); - if (have_channel_participant_cache(channel_id)) { - add_channel_participant_to_cache(channel_id, it->second, false); - } - promise.set_value(Unit()); + dialog_participant.status.update_restrictions(); + if (have_channel_participant_cache(channel_id)) { + add_channel_participant_to_cache(channel_id, dialog_participant, false); } + promise.set_value(std::move(dialog_participant)); } void ContactsManager::get_channel_participants(ChannelId channel_id, diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 0233402d0..3fe39c959 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -524,9 +524,8 @@ class ContactsManager final : public Actor { void ban_dialog_participant(DialogId dialog_id, const tl_object_ptr &participant_id, int32 banned_until_date, bool revoke_messages, Promise &&promise); - DialogParticipant get_dialog_participant(DialogId dialog_id, - const tl_object_ptr &participant_id, int64 &random_id, - bool force, Promise &&promise); + void get_dialog_participant(DialogId dialog_id, const tl_object_ptr &participant_id, + Promise> &&promise); void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, Promise &&promise); @@ -1275,7 +1274,7 @@ class ContactsManager final : public Actor { void on_save_user_to_database(UserId user_id, bool success); void load_user_from_database(User *u, UserId user_id, Promise promise); void load_user_from_database_impl(UserId user_id, Promise promise); - void on_load_user_from_database(UserId user_id, string value); + void on_load_user_from_database(UserId user_id, string value, bool force); void save_chat(Chat *c, ChatId chat_id, bool from_binlog); static string get_chat_database_key(ChatId chat_id); @@ -1285,7 +1284,7 @@ class ContactsManager final : public Actor { void on_save_chat_to_database(ChatId chat_id, bool success); void load_chat_from_database(Chat *c, ChatId chat_id, Promise promise); void load_chat_from_database_impl(ChatId chat_id, Promise promise); - void on_load_chat_from_database(ChatId chat_id, string value); + void on_load_chat_from_database(ChatId chat_id, string value, bool force); void save_channel(Channel *c, ChannelId channel_id, bool from_binlog); static string get_channel_database_key(ChannelId channel_id); @@ -1295,7 +1294,7 @@ class ContactsManager final : public Actor { void on_save_channel_to_database(ChannelId channel_id, bool success); void load_channel_from_database(Channel *c, ChannelId channel_id, Promise promise); void load_channel_from_database_impl(ChannelId channel_id, Promise promise); - void on_load_channel_from_database(ChannelId channel_id, string value); + void on_load_channel_from_database(ChannelId channel_id, string value, bool force); void save_secret_chat(SecretChat *c, SecretChatId secret_chat_id, bool from_binlog); static string get_secret_chat_database_key(SecretChatId secret_chat_id); @@ -1305,7 +1304,7 @@ class ContactsManager final : public Actor { void on_save_secret_chat_to_database(SecretChatId secret_chat_id, bool success); void load_secret_chat_from_database(SecretChat *c, SecretChatId secret_chat_id, Promise promise); void load_secret_chat_from_database_impl(SecretChatId secret_chat_id, Promise promise); - void on_load_secret_chat_from_database(SecretChatId secret_chat_id, string value); + void on_load_secret_chat_from_database(SecretChatId secret_chat_id, string value, bool force); void save_user_full(const UserFull *user_full, UserId user_id); static string get_user_full_database_key(UserId user_id); @@ -1414,10 +1413,20 @@ class ContactsManager final : public Actor { DialogParticipants search_private_chat_participants(UserId my_user_id, UserId peer_user_id, const string &query, int32 limit, DialogParticipantsFilter filter) const; - DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise &&promise); + void get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, Promise &&promise); - DialogParticipant get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, int64 &random_id, - bool force, Promise &&promise); + void finish_get_dialog_participant(DialogParticipant &&dialog_participant, + Promise> &&promise); + + void get_chat_participant(ChatId chat_id, UserId user_id, Promise &&promise); + + void finish_get_chat_participant(ChatId chat_id, UserId user_id, Promise &&promise); + + void get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, + Promise &&promise); + + void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, + Promise &&promise); static string get_dialog_administrators_database_key(DialogId dialog_id); @@ -1480,9 +1489,6 @@ class ContactsManager final : public Actor { void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise &&promise); - void on_get_channel_participant(ChannelId channel_id, int64 random_id, Result r_dialog_participant, - Promise &&promise); - void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantsFilter filter, Promise &&promise); @@ -1655,8 +1661,6 @@ class ContactsManager final : public Actor { std::unordered_map, vector>> imported_contacts_; - std::unordered_map received_channel_participant_; - std::unordered_map, ChannelIdHash> cached_channel_participants_; // bot-administrators only diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 7ffc6555c..aef798820 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -14616,6 +14616,7 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector MessagesManager::get_dialog_history(DialogId dia if (from_the_end) { from_message_id = MessageId(); } - send_closure_later(actor_id(this), &MessagesManager::load_messages, d->dialog_id, from_message_id, offset, + send_closure_later(actor_id(this), &MessagesManager::load_messages, dialog_id, from_message_id, offset, limit - static_cast(messages.size()), left_tries, only_local, std::move(promise)); return nullptr; } @@ -22221,7 +22222,7 @@ void MessagesManager::preload_newer_messages(const Dialog *d, MessageId max_mess if (limit > 0 && (d->last_message_id == MessageId() || max_message_id < d->last_message_id)) { // need to preload some new messages LOG(INFO) << "Preloading newer after " << max_message_id; - load_messages(d->dialog_id, max_message_id, -MAX_GET_HISTORY + 1, MAX_GET_HISTORY, 3, false, Promise()); + load_messages_impl(d, max_message_id, -MAX_GET_HISTORY + 1, MAX_GET_HISTORY, 3, false, Promise()); } } @@ -22247,7 +22248,7 @@ void MessagesManager::preload_older_messages(const Dialog *d, MessageId min_mess if (limit > 0) { // need to preload some old messages LOG(INFO) << "Preloading older before " << min_message_id; - load_messages(d->dialog_id, min_message_id, 0, MAX_GET_HISTORY / 2, 3, false, Promise()); + load_messages_impl(d, min_message_id, 0, MAX_GET_HISTORY / 2, 3, false, Promise()); } } @@ -22273,9 +22274,10 @@ unique_ptr MessagesManager::parse_message(DialogId dia return m; } -void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId from_message_id, int32 offset, - int32 limit, bool from_the_end, bool only_local, - vector &&messages, Promise &&promise) { +void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId from_message_id, + MessageId old_last_database_message_id, int32 offset, int32 limit, + bool from_the_end, bool only_local, vector &&messages, + Promise &&promise) { CHECK(-limit < offset && offset <= 0); CHECK(offset < 0 || from_the_end); CHECK(!from_message_id.is_scheduled()); @@ -22302,6 +22304,17 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId << d->first_database_message_id << ", last database message is " << d->last_database_message_id << ", have_full_history = " << d->have_full_history; + if (old_last_database_message_id < d->last_database_message_id && old_last_database_message_id < from_message_id) { + // new messages where added to the database since the request was sent + // they should have been received from the database, so we must repeat the request to get them + if (from_the_end) { + get_history_from_the_end_impl(d, true, only_local, std::move(promise)); + } else { + get_history_impl(d, from_message_id, offset, limit, true, only_local, std::move(promise)); + } + return; + } + if (messages.empty() && from_the_end && d->messages == nullptr) { if (d->have_full_history) { set_dialog_is_empty(d, "on_get_history_from_database empty"); @@ -22419,18 +22432,24 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId if (last_received_message_id < d->last_database_message_id) { set_dialog_last_database_message_id(d, last_received_message_id, "on_get_history_from_database 12"); - get_history_from_the_end(dialog_id, true, only_local, std::move(promise)); + get_history_from_the_end_impl(d, true, only_local, std::move(promise)); return; } if (limit > 1) { // we expected to have messages [first_database_message_id, last_database_message_id] in the database, but - // received newer messages [last_received_message_id, ...], none of which can be added + // received no messages or newer messages [last_received_message_id, ...], none of which can be added // first_database_message_id and last_database_message_id are very wrong, so it is better to drop them, // pretending that the database has no usable messages - LOG(ERROR) << "Receive unusable messages up to " << last_received_message_id << " in " << dialog_id - << " from database from the end, but expected messages from " << d->last_database_message_id - << " up to " << d->first_database_message_id; + if (last_received_message_id == MessageId::max()) { + LOG(ERROR) << "Receive no usable messages in " << dialog_id + << " from database from the end, but expected messages from " << d->last_database_message_id + << " up to " << d->first_database_message_id; + } else { + LOG(ERROR) << "Receive " << messages.size() << " unusable messages up to " << last_received_message_id + << " in " << dialog_id << " from database from the end, but expected messages from " + << d->last_database_message_id << " up to " << d->first_database_message_id; + } set_dialog_first_database_message_id(d, MessageId(), "on_get_history_from_database 13"); set_dialog_last_database_message_id(d, MessageId(), "on_get_history_from_database 14"); } @@ -22441,7 +22460,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId if (from_the_end) { from_message_id = MessageId(); } - load_messages(dialog_id, from_message_id, offset, limit, 1, false, std::move(promise)); + load_messages_impl(d, from_message_id, offset, limit, 1, false, std::move(promise)); return; } @@ -22496,14 +22515,21 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId void MessagesManager::get_history_from_the_end(DialogId dialog_id, bool from_database, bool only_local, Promise &&promise) { - CHECK(dialog_id.is_valid()); - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + get_history_from_the_end_impl(get_dialog(dialog_id), from_database, only_local, std::move(promise)); +} + +void MessagesManager::get_history_from_the_end_impl(const Dialog *d, bool from_database, bool only_local, + Promise &&promise) { + CHECK(d != nullptr); + + auto dialog_id = d->dialog_id; if (!have_input_peer(dialog_id, AccessRights::Read)) { // can't get history in dialogs without read access return promise.set_value(Unit()); } + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } int32 limit = MAX_GET_HISTORY; if (from_database && G()->parameters().use_message_db) { if (!promise) { @@ -22516,10 +22542,12 @@ void MessagesManager::get_history_from_the_end(DialogId dialog_id, bool from_dat db_query.from_message_id = MessageId::max(); db_query.limit = limit; G()->td_db()->get_messages_db_async()->get_messages( - db_query, PromiseCreator::lambda([dialog_id, only_local, limit, actor_id = actor_id(this), + db_query, PromiseCreator::lambda([dialog_id, old_last_database_message_id = d->last_database_message_id, + only_local, limit, actor_id = actor_id(this), promise = std::move(promise)](std::vector messages) mutable { - send_closure(actor_id, &MessagesManager::on_get_history_from_database, dialog_id, MessageId::max(), 0, limit, - true, only_local, std::move(messages), std::move(promise)); + send_closure(actor_id, &MessagesManager::on_get_history_from_database, dialog_id, MessageId::max(), + old_last_database_message_id, 0, limit, true, only_local, std::move(messages), + std::move(promise)); })); } else { if (only_local || dialog_id.get_type() == DialogType::SecretChat) { @@ -22534,8 +22562,16 @@ void MessagesManager::get_history_from_the_end(DialogId dialog_id, bool from_dat void MessagesManager::get_history(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, bool from_database, bool only_local, Promise &&promise) { - CHECK(dialog_id.is_valid()); + get_history_impl(get_dialog(dialog_id), from_message_id, offset, limit, from_database, only_local, + std::move(promise)); +} + +void MessagesManager::get_history_impl(const Dialog *d, MessageId from_message_id, int32 offset, int32 limit, + bool from_database, bool only_local, Promise &&promise) { + CHECK(d != nullptr); CHECK(from_message_id.is_valid()); + + auto dialog_id = d->dialog_id; if (!have_input_peer(dialog_id, AccessRights::Read)) { // can't get history in dialogs without read access return promise.set_value(Unit()); @@ -22553,10 +22589,12 @@ void MessagesManager::get_history(DialogId dialog_id, MessageId from_message_id, db_query.limit = limit; G()->td_db()->get_messages_db_async()->get_messages( db_query, - PromiseCreator::lambda([dialog_id, from_message_id, offset, limit, only_local, actor_id = actor_id(this), + PromiseCreator::lambda([dialog_id, from_message_id, old_last_database_message_id = d->last_database_message_id, + offset, limit, only_local, actor_id = actor_id(this), promise = std::move(promise)](std::vector messages) mutable { - send_closure(actor_id, &MessagesManager::on_get_history_from_database, dialog_id, from_message_id, offset, - limit, false, only_local, std::move(messages), std::move(promise)); + send_closure(actor_id, &MessagesManager::on_get_history_from_database, dialog_id, from_message_id, + old_last_database_message_id, offset, limit, false, only_local, std::move(messages), + std::move(promise)); })); } else { if (only_local || dialog_id.get_type() == DialogType::SecretChat) { @@ -22572,24 +22610,28 @@ void MessagesManager::get_history(DialogId dialog_id, MessageId from_message_id, void MessagesManager::load_messages(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, int left_tries, bool only_local, Promise &&promise) { - LOG(INFO) << "Load " << (only_local ? "local " : "") << "messages in " << dialog_id << " from " << from_message_id - << " with offset = " << offset << " and limit = " << limit << ". " << left_tries << " tries left"; + load_messages_impl(get_dialog(dialog_id), from_message_id, offset, limit, left_tries, only_local, std::move(promise)); +} + +void MessagesManager::load_messages_impl(const Dialog *d, MessageId from_message_id, int32 offset, int32 limit, + int left_tries, bool only_local, Promise &&promise) { + CHECK(d != nullptr); CHECK(offset <= 0); CHECK(left_tries > 0); + auto dialog_id = d->dialog_id; + LOG(INFO) << "Load " << (only_local ? "local " : "") << "messages in " << dialog_id << " from " << from_message_id + << " with offset = " << offset << " and limit = " << limit << ". " << left_tries << " tries left"; only_local |= dialog_id.get_type() == DialogType::SecretChat; - if (!only_local) { - Dialog *d = get_dialog(dialog_id); - if (d != nullptr && d->have_full_history) { - LOG(INFO) << "Have full history in " << dialog_id << ", so don't need to get chat history from server"; - only_local = true; - } + if (!only_local && d->have_full_history) { + LOG(INFO) << "Have full history in " << dialog_id << ", so don't need to get chat history from server"; + only_local = true; } bool from_database = (left_tries > 2 || only_local) && G()->parameters().use_message_db; // TODO do not send requests to database if (from_message_id < d->first_database_message_id || // !d->first_database_message_id.is_valid()) && !d->have_full_history if (from_message_id == MessageId()) { - get_history_from_the_end(dialog_id, from_database, only_local, std::move(promise)); + get_history_from_the_end_impl(d, from_database, only_local, std::move(promise)); return; } if (offset >= -1) { @@ -22603,7 +22645,7 @@ void MessagesManager::load_messages(DialogId dialog_id, MessageId from_message_i offset -= max_add; limit = MAX_GET_HISTORY; } - get_history(dialog_id, from_message_id, offset, limit, from_database, only_local, std::move(promise)); + get_history_impl(d, from_message_id, offset, limit, from_database, only_local, std::move(promise)); } vector MessagesManager::get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, @@ -31952,8 +31994,13 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(DialogId dialog Dialog *d = get_dialog_force(dialog_id, source); if (d == nullptr) { + if (from_update) { + CHECK(!being_added_by_new_message_dialog_id_.is_valid()); + being_added_by_new_message_dialog_id_ = dialog_id; + } d = add_dialog(dialog_id, "add_message_to_dialog"); *need_update_dialog_pos = true; + being_added_by_new_message_dialog_id_ = DialogId(); } else { CHECK(d->dialog_id == dialog_id); } @@ -33861,14 +33908,14 @@ void MessagesManager::force_create_dialog(DialogId dialog_id, const char *source } MessagesManager::Dialog *MessagesManager::add_dialog(DialogId dialog_id, const char *source) { - LOG(DEBUG) << "Creating " << dialog_id; + LOG(DEBUG) << "Creating " << dialog_id << " from " << source; CHECK(!have_dialog(dialog_id)); if (G()->parameters().use_message_db) { // TODO preload dialog asynchronously, remove loading from this function auto r_value = G()->td_db()->get_dialog_db_sync()->get_dialog(dialog_id); if (r_value.is_ok()) { - LOG(INFO) << "Synchronously loaded " << dialog_id << " from database"; + LOG(INFO) << "Synchronously loaded " << dialog_id << " from database from " << source; return add_new_dialog(parse_dialog(dialog_id, r_value.ok(), source), true, source); } } @@ -33913,7 +33960,7 @@ MessagesManager::Dialog *MessagesManager::add_new_dialog(unique_ptr &&d, } case DialogType::SecretChat: if (d->last_new_message_id.get() <= MessageId::min().get()) { - LOG(INFO) << "Set " << d->dialog_id << " last new message in add_new_dialog"; + LOG(INFO) << "Set " << d->dialog_id << " last new message in add_new_dialog from " << source; d->last_new_message_id = MessageId::min().get_next_message_id(MessageType::Local); } @@ -34332,8 +34379,9 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr &&last_datab d->pending_read_channel_inbox_pts = 0; } if (need_get_history && !td_->auth_manager_->is_bot() && dialog_id != being_added_dialog_id_ && - have_input_peer(dialog_id, AccessRights::Read) && (d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) { - get_history_from_the_end(dialog_id, true, false, Auto()); + dialog_id != being_added_by_new_message_dialog_id_ && have_input_peer(dialog_id, AccessRights::Read) && + (d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) { + get_history_from_the_end_impl(d, true, false, Auto()); } if (d->need_repair_server_unread_count && need_unread_counter(d->order)) { CHECK(dialog_type != DialogType::SecretChat); @@ -34350,6 +34398,7 @@ void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptrleft == nullptr); CHECK(last_database_message->right == nullptr); + auto dialog_id = d->dialog_id; auto message_id = last_database_message->message_id; CHECK(message_id.is_valid()); LOG_CHECK(d->last_database_message_id == message_id) @@ -34357,7 +34406,7 @@ void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptrdialog_id, AccessRights::Read)) { + if (have_input_peer(dialog_id, AccessRights::Read)) { bool need_update = false; last_database_message->have_previous = false; last_database_message->have_next = false; @@ -34365,7 +34414,7 @@ void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptrdialog_id; + LOG(ERROR) << "Need to update pos in " << dialog_id; } } if (m != nullptr) { @@ -34377,11 +34426,12 @@ void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptrpending_last_message_id = MessageId(); need_update_dialog_pos = true; } - on_dialog_updated(d->dialog_id, "add_dialog_last_database_message 4"); // resave without last database message + on_dialog_updated(dialog_id, "add_dialog_last_database_message 4"); // resave without last database message - if (!td_->auth_manager_->is_bot() && d->dialog_id != being_added_dialog_id_ && - have_input_peer(d->dialog_id, AccessRights::Read) && (d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) { - get_history_from_the_end(d->dialog_id, true, false, Auto()); + if (!td_->auth_manager_->is_bot() && dialog_id != being_added_dialog_id_ && + dialog_id != being_added_by_new_message_dialog_id_ && have_input_peer(dialog_id, AccessRights::Read) && + (d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) { + get_history_from_the_end_impl(d, true, false, Auto()); } } @@ -37263,10 +37313,10 @@ void MessagesManager::suffix_load_loop(Dialog *d) { d->suffix_load_has_query_ = true; d->suffix_load_query_message_id_ = from_message_id; if (from_message_id.is_valid()) { - get_history(dialog_id, from_message_id, -1, 100, true, true, std::move(promise)); + get_history_impl(d, from_message_id, -1, 100, true, true, std::move(promise)); } else { CHECK(from_message_id == MessageId()); - get_history_from_the_end(dialog_id, true, true, std::move(promise)); + get_history_from_the_end_impl(d, true, true, std::move(promise)); } } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 8cd59548d..9bdad9acb 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2006,18 +2006,27 @@ class MessagesManager final : public Actor { void preload_older_messages(const Dialog *d, MessageId min_message_id); - void on_get_history_from_database(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, + void on_get_history_from_database(DialogId dialog_id, MessageId from_message_id, + MessageId old_last_database_message_id, int32 offset, int32 limit, bool from_the_end, bool only_local, vector &&messages, Promise &&promise); void get_history_from_the_end(DialogId dialog_id, bool from_database, bool only_local, Promise &&promise); + void get_history_from_the_end_impl(const Dialog *d, bool from_database, bool only_local, Promise &&promise); + void get_history(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, bool from_database, bool only_local, Promise &&promise); + void get_history_impl(const Dialog *d, MessageId from_message_id, int32 offset, int32 limit, bool from_database, + bool only_local, Promise &&promise); + void load_messages(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, int left_tries, bool only_local, Promise &&promise); + void load_messages_impl(const Dialog *d, MessageId from_message_id, int32 offset, int32 limit, int left_tries, + bool only_local, Promise &&promise); + void load_dialog_scheduled_messages(DialogId dialog_id, bool from_database, int32 hash, Promise &&promise); void on_get_scheduled_messages_from_database(DialogId dialog_id, vector &&messages); @@ -3339,6 +3348,7 @@ class MessagesManager final : public Actor { FullMessageId being_readded_message_id_; DialogId being_added_dialog_id_; + DialogId being_added_by_new_message_dialog_id_; DialogId debug_channel_difference_dialog_; diff --git a/td/telegram/SecretChatActor.cpp b/td/telegram/SecretChatActor.cpp index 936b69c75..314f77a43 100644 --- a/td/telegram/SecretChatActor.cpp +++ b/td/telegram/SecretChatActor.cpp @@ -215,7 +215,7 @@ Result SecretChatActor::create_encrypted_message(int32 my_in_seq_no auto out_seq_no = my_out_seq_no * 2 - 1 - auth_state_.x; auto layer = current_layer(); - BufferSlice random_bytes(32); + BufferSlice random_bytes(31); Random::secure_bytes(random_bytes.as_slice().ubegin(), random_bytes.size()); auto message_with_layer = secret_api::make_object( std::move(random_bytes), layer, in_seq_no, out_seq_no, std::move(message)); @@ -797,7 +797,9 @@ Result> SecretChatActor::decrypt(BufferSl info.is_creator = auth_state_.x == 0; r_read_result = mtproto::Transport::read(data, *auth_key, &info); if (i + 1 != versions.size() && r_read_result.is_error()) { - LOG(WARNING) << tag("mtproto", mtproto_version) << " decryption failed " << r_read_result.error(); + if (config_state_.his_layer >= static_cast(SecretChatLayer::Mtproto2)) { + LOG(WARNING) << tag("mtproto", mtproto_version) << " decryption failed " << r_read_result.error(); + } continue; } break; @@ -1933,13 +1935,13 @@ void SecretChatActor::get_dh_config() { } auto version = auth_state_.dh_config.version; - int32 random_length = 0; + int32 random_length = 256; // ignored server-side, always returns 256 random bytes auto query = create_net_query(QueryType::DhConfig, telegram_api::messages_getDhConfig(version, random_length)); context_->send_net_query(std::move(query), actor_shared(this), false); } Status SecretChatActor::on_dh_config(NetQueryPtr query) { - LOG(INFO) << "Got dh config"; + LOG(INFO) << "Got DH config"; TRY_RESULT(config, fetch_result(std::move(query))); downcast_call(*config, [&](auto &obj) { this->on_dh_config(obj); }); TRY_STATUS(mtproto::DhHandshake::check_config(auth_state_.dh_config.g, auth_state_.dh_config.prime, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 8e9d65a06..64a87ee63 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1947,39 +1947,6 @@ class UpgradeGroupChatToSupergroupChatRequest final : public RequestActor<> { } }; -class GetChatMemberRequest final : public RequestActor<> { - DialogId dialog_id_; - tl_object_ptr participant_id_; - int64 random_id_; - - DialogParticipant dialog_participant_; - - void do_run(Promise &&promise) final { - dialog_participant_ = td->contacts_manager_->get_dialog_participant(dialog_id_, participant_id_, random_id_, - get_tries() < 3, std::move(promise)); - } - - void do_send_result() final { - auto participant_dialog_id = dialog_participant_.dialog_id; - bool is_user = participant_dialog_id.get_type() == DialogType::User; - if ((is_user && !td->contacts_manager_->have_user(participant_dialog_id.get_user_id())) || - (!is_user && !td->messages_manager_->have_dialog(participant_dialog_id))) { - return send_error(Status::Error(3, "Member not found")); - } - send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_)); - } - - public: - GetChatMemberRequest(ActorShared td, uint64 request_id, int64 dialog_id, - tl_object_ptr participant_id) - : RequestActor(std::move(td), request_id) - , dialog_id_(dialog_id) - , participant_id_(std::move(participant_id)) - , random_id_(0) { - set_tries(3); - } -}; - class GetChatAdministratorsRequest final : public RequestActor<> { DialogId dialog_id_; @@ -6564,7 +6531,9 @@ void Td::on_request(uint64 id, td_api::transferChatOwnership &request) { } void Td::on_request(uint64 id, td_api::getChatMember &request) { - CREATE_REQUEST(GetChatMemberRequest, request.chat_id_, std::move(request.member_id_)); + CREATE_REQUEST_PROMISE(); + contacts_manager_->get_dialog_participant(DialogId(request.chat_id_), std::move(request.member_id_), + std::move(promise)); } void Td::on_request(uint64 id, td_api::searchChatMembers &request) { diff --git a/tdutils/td/utils/Status.h b/tdutils/td/utils/Status.h index 2ffb1e7e2..3f5a55420 100644 --- a/tdutils/td/utils/Status.h +++ b/tdutils/td/utils/Status.h @@ -36,13 +36,13 @@ } \ } -#define TRY_STATUS_PROMISE(promise_name, status) \ - { \ - auto try_status = (status); \ - if (try_status.is_error()) { \ - promise_name.set_error(std::move(try_status)); \ - return; \ - } \ +#define TRY_STATUS_PROMISE(promise_name, status) \ + { \ + auto try_status = (status); \ + if (try_status.is_error()) { \ + promise_name.set_error(try_status.move_as_error()); \ + return; \ + } \ } #define TRY_STATUS_PROMISE_PREFIX(promise_name, status, prefix) \ diff --git a/tdutils/td/utils/port/stacktrace.cpp b/tdutils/td/utils/port/stacktrace.cpp index 9b841a6b6..52817624d 100644 --- a/tdutils/td/utils/port/stacktrace.cpp +++ b/tdutils/td/utils/port/stacktrace.cpp @@ -27,10 +27,11 @@ namespace td { namespace { void print_backtrace(void) { - void *buffer[128]; #if TD_PORT_WINDOWS + void *buffer[128]; USHORT nptrs = CaptureStackBackTrace(0, 128, buffer, nullptr); #elif __GLIBC__ + void *buffer[128]; int nptrs = backtrace(buffer, 128); #else return;