Separately apply versioned and unversioned group call updates.

This commit is contained in:
levlam 2020-12-18 15:20:05 +03:00
parent 7aadb29e0a
commit 8dd4fe3166
9 changed files with 70 additions and 29 deletions

View File

@ -1182,7 +1182,7 @@ groupCall#55903081 flags:# join_muted:flags.1?true can_change_join_muted:flags.2
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
groupCallParticipant#56b087c9 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true user_id:int date:int active_date:flags.3?int source:int = GroupCallParticipant;
groupCallParticipant#56b087c9 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true user_id:int date:int active_date:flags.3?int source:int = GroupCallParticipant;
phone.groupCall#66ab0bfc call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string users:Vector<User> = phone.GroupCall;

Binary file not shown.

View File

@ -11722,7 +11722,7 @@ void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParti
}
}
if (need_reload_group_call) {
td_->messages_manager_->reload_dialog_group_call(DialogId(chat_id));
td_->messages_manager_->on_update_dialog_group_call_rights(DialogId(chat_id));
}
c->is_changed = true;
@ -12064,7 +12064,7 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
reload_dialog_administrators(DialogId(channel_id), 0, Auto());
}
if (need_reload_group_call) {
td_->messages_manager_->reload_dialog_group_call(DialogId(channel_id));
td_->messages_manager_->on_update_dialog_group_call_rights(DialogId(channel_id));
}
}

View File

@ -427,7 +427,9 @@ struct GroupCallManager::GroupCallParticipants {
int64 min_order = std::numeric_limits<int64>::max();
vector<UserId> administrator_user_ids;
std::map<int32, vector<tl_object_ptr<telegram_api::groupCallParticipant>>> pending_updates_;
std::map<int32, vector<tl_object_ptr<telegram_api::groupCallParticipant>>> pending_version_updates_;
std::map<int32, vector<tl_object_ptr<telegram_api::groupCallParticipant>>> pending_mute_updates_;
};
struct GroupCallManager::GroupCallRecentSpeakers {
@ -870,6 +872,9 @@ void GroupCallManager::on_get_group_call_participants(
group_call->loaded_all_participants = false;
need_update = true;
}
if (process_pending_group_call_participant_updates(input_group_call_id)) {
need_update = false;
}
if (need_update) {
send_update_group_call(group_call, "on_get_group_call_participants");
}
@ -944,13 +949,24 @@ void GroupCallManager::on_update_group_call_participants(
}
auto *group_call_participants = add_group_call_participants(input_group_call_id);
auto &pending_updates = group_call_participants->pending_updates_[version];
if (participants.size() <= pending_updates.size()) {
LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in "
<< input_group_call_id;
return;
auto &pending_mute_updates = group_call_participants->pending_mute_updates_[version];
vector<tl_object_ptr<telegram_api::groupCallParticipant>> version_updates;
for (auto &participant : participants) {
if (GroupCallParticipant::is_versioned_update(participant)) {
version_updates.push_back(std::move(participant));
} else {
pending_mute_updates.push_back(std::move(participant));
}
}
if (!version_updates.empty()) {
auto &pending_version_updates = group_call_participants->pending_version_updates_[version];
if (version_updates.size() <= pending_version_updates.size()) {
LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in "
<< input_group_call_id;
return;
}
pending_version_updates = std::move(version_updates);
}
pending_updates = std::move(participants);
process_pending_group_call_participant_updates(input_group_call_id);
}
@ -964,7 +980,6 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
if (participants_it == group_call_participants_.end()) {
return false;
}
auto &pending_updates = participants_it->second->pending_updates_;
auto group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited);
if (group_call->version == -1 || !group_call->is_active) {
@ -974,31 +989,27 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
int32 diff = 0;
bool is_left = false;
bool need_rejoin = true;
while (!pending_updates.empty()) {
auto it = pending_updates.begin();
auto &pending_version_updates = participants_it->second->pending_version_updates_;
while (!pending_version_updates.empty()) {
auto it = pending_version_updates.begin();
auto version = it->first;
auto &participants = it->second;
if (version <= group_call->version) {
for (auto &group_call_participant : participants) {
GroupCallParticipant participant(group_call_participant);
on_participant_speaking_in_group_call(input_group_call_id, participant);
if (participant.user_id == td_->contacts_manager_->get_my_id()) {
if (participant.user_id == td_->contacts_manager_->get_my_id() && version == group_call->version &&
participant.is_just_joined) {
process_group_call_participant(input_group_call_id, std::move(participant));
}
}
LOG(INFO) << "Ignore already applied updateGroupCallParticipants with version " << version << " in "
<< input_group_call_id << " from " << group_call->dialog_id;
pending_updates.erase(it);
pending_version_updates.erase(it);
continue;
}
if (version < group_call->version + static_cast<int32>(participants.size())) {
LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version
<< ", but current version is " << group_call->version;
sync_group_call_participants(input_group_call_id);
break;
}
if (version == group_call->version + static_cast<int32>(participants.size())) {
if (version == group_call->version + 1) {
group_call->version = version;
for (auto &participant : participants) {
GroupCallParticipant group_call_participant(participant);
@ -1011,7 +1022,7 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
}
diff += process_group_call_participant(input_group_call_id, std::move(group_call_participant));
}
pending_updates.erase(it);
pending_version_updates.erase(it);
} else if (!group_call->syncing_participants) {
// found a gap
LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version
@ -1020,7 +1031,27 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
break;
}
}
if (pending_updates.empty()) {
auto &pending_mute_updates = participants_it->second->pending_mute_updates_;
while (!pending_mute_updates.empty()) {
auto it = pending_mute_updates.begin();
auto version = it->first;
if (version <= group_call->version) {
auto &participants = it->second;
for (auto &group_call_participant : participants) {
GroupCallParticipant participant(group_call_participant);
on_participant_speaking_in_group_call(input_group_call_id, participant);
int mute_diff = process_group_call_participant(input_group_call_id, std::move(participant));
CHECK(mute_diff == 0);
}
pending_mute_updates.erase(it);
continue;
}
on_receive_group_call_version(input_group_call_id, version);
break;
}
if (pending_version_updates.empty() && pending_mute_updates.empty()) {
sync_participants_timeout_.cancel_timeout(group_call->group_call_id.get());
}
@ -1974,8 +2005,9 @@ void GroupCallManager::on_receive_group_call_version(InputGroupCallId input_grou
}
// found a gap
LOG(INFO) << "Receive version " << version << " for group call " << input_group_call_id;
auto *group_call_participants = add_group_call_participants(input_group_call_id);
group_call_participants->pending_updates_[version]; // reserve place for updates
group_call_participants->pending_version_updates_[version]; // reserve place for updates
sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0);
}

View File

@ -30,6 +30,10 @@ GroupCallParticipant::GroupCallParticipant(const tl_object_ptr<telegram_api::gro
is_just_joined = participant->just_joined_;
}
bool GroupCallParticipant::is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant) {
return participant->just_joined_ || participant->left_ || participant->versioned_;
}
bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bool is_admin) {
bool new_can_be_muted = false;
bool new_can_be_unmuted = false;

View File

@ -20,10 +20,10 @@ class ContactsManager;
struct GroupCallParticipant {
UserId user_id;
int32 source = 0;
bool is_muted = false;
bool can_self_unmute = false;
int32 joined_date = 0;
int32 active_date = 0;
bool is_muted = false;
bool can_self_unmute = false;
bool can_be_muted = false;
bool can_be_unmuted = false;
@ -37,6 +37,8 @@ struct GroupCallParticipant {
explicit GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
static bool is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
bool update_can_be_muted(bool can_manage, bool is_self, bool is_admin);
int64 get_real_order() const {

View File

@ -10651,7 +10651,7 @@ void MessagesManager::delete_dialog(DialogId dialog_id) {
close_dialog(d);
}
void MessagesManager::reload_dialog_group_call(DialogId dialog_id) {
void MessagesManager::on_update_dialog_group_call_rights(DialogId dialog_id) {
if (td_->auth_manager_->is_bot()) {
return;
}

View File

@ -397,7 +397,7 @@ class MessagesManager : public Actor {
void delete_dialog(DialogId dialog_id);
void reload_dialog_group_call(DialogId dialog_id);
void on_update_dialog_group_call_rights(DialogId dialog_id);
void read_all_dialog_mentions(DialogId dialog_id, Promise<Unit> &&promise);

View File

@ -3895,6 +3895,9 @@ class CliClient final : public Actor {
} else if (status_str == "addadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, true, false, false);
} else if (status_str == "calladmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, false, true, false);
} else if (status_str == "admin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, true, true, true, true, true,
true, true, true, false, false);