From 1f9d173afb81cf4389b52a211a960747c9b96f99 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 28 Dec 2020 00:30:27 +0300 Subject: [PATCH] Automatically check whether group call is still joined. --- td/generate/scheme/td_api.tl | 3 -- td/generate/scheme/td_api.tlo | Bin 191552 -> 191448 bytes td/telegram/GroupCallManager.cpp | 87 +++++++++++++++++++++++-------- td/telegram/GroupCallManager.h | 10 +++- td/telegram/Td.cpp | 6 --- td/telegram/Td.h | 2 - td/telegram/cli.cpp | 2 - 7 files changed, 72 insertions(+), 38 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index be6b7afda..1deba5c51 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4394,9 +4394,6 @@ setGroupCallParticipantIsSpeaking group_call_id:int32 source:int32 is_speaking:B //@group_call_id Group call identifier @user_id User identifier @is_muted Pass true if the user must be muted and false otherwise toggleGroupCallParticipantIsMuted group_call_id:int32 user_id:int32 is_muted:Bool = Ok; -//@description Checks whether a group call is still joined. Should be called every 10 seconds when tgcalls notifies about lost connection with the server @group_call_id Group call identifier -checkGroupCallIsJoined group_call_id:int32 = Ok; - //@description Loads more group call participants. The loaded participants will be received through updates. Use the field groupCall.loaded_all_participants to check whether all participants has already been loaded //@group_call_id Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined //@limit Maximum number of participants to load diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index c92950cd4f574c4b75076ffba2bd597db5e70f80..f397f69f386a30751530f7bfedfcd7e2685bcaf5 100644 GIT binary patch delta 27 jcmX?bgZsvH?uHh|Elf4aj1#ukDl^>|-hRZKsb&iRs6`8S delta 60 zcmca{o%_HI?uHh|Elf4aj1#xlDl^>|maY&wnIx8+k(!+CUX)*2;GCF~<5}#LpP84M QGCg}TlkfHzbEcXt0NSz_cK`qY diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 379c0ea27..8dfa243c8 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -440,6 +440,9 @@ struct GroupCallManager::PendingJoinRequest { }; GroupCallManager::GroupCallManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { + check_group_call_is_joined_timeout_.set_callback(on_check_group_call_is_joined_timeout_callback); + check_group_call_is_joined_timeout_.set_callback_data(static_cast(this)); + pending_send_speaking_action_timeout_.set_callback(on_pending_send_speaking_action_timeout_callback); pending_send_speaking_action_timeout_.set_callback_data(static_cast(this)); @@ -456,6 +459,45 @@ void GroupCallManager::tear_down() { parent_.reset(); } +void GroupCallManager::on_check_group_call_is_joined_timeout_callback(void *group_call_manager_ptr, + int64 group_call_id_int) { + if (G()->close_flag()) { + return; + } + + auto group_call_manager = static_cast(group_call_manager_ptr); + send_closure_later(group_call_manager->actor_id(group_call_manager), + &GroupCallManager::on_check_group_call_is_joined_timeout, + GroupCallId(narrow_cast(group_call_id_int))); +} + +void GroupCallManager::on_check_group_call_is_joined_timeout(GroupCallId group_call_id) { + if (G()->close_flag()) { + return; + } + + LOG(INFO) << "Receive check group call is_joined timeout in " << group_call_id; + auto input_group_call_id = get_input_group_call_id(group_call_id).move_as_ok(); + + auto *group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr && group_call->is_inited); + if (!group_call->is_joined || check_group_call_is_joined_timeout_.has_timeout(group_call_id.get())) { + return; + } + + auto source = group_call->source; + auto promise = + PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source](Result &&result) mutable { + if (result.is_error() && result.error().message() == "GROUP_CALL_JOIN_MISSING") { + send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, true); + result = Unit(); + } + send_closure(actor_id, &GroupCallManager::finish_check_group_call_is_joined, input_group_call_id, source, + std::move(result)); + }); + td_->create_handler(std::move(promise))->send(input_group_call_id, source); +} + void GroupCallManager::on_pending_send_speaking_action_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int) { if (G()->close_flag()) { @@ -779,6 +821,21 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i } } +void GroupCallManager::finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 source, + Result &&result) { + LOG(INFO) << "Finish check group call is_joined for " << input_group_call_id; + + auto *group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr && group_call->is_inited); + if (!group_call->is_joined || check_group_call_is_joined_timeout_.has_timeout(group_call->group_call_id.get()) || + group_call->source != source) { + return; + } + + int32 next_timeout = result.is_ok() ? CHECK_GROUP_CALL_IS_JOINED_TIMEOUT : 1; + check_group_call_is_joined_timeout_.set_timeout_in(group_call->group_call_id.get(), next_timeout); +} + bool GroupCallManager::need_group_call_participants(InputGroupCallId input_group_call_id) const { auto *group_call = get_group_call(input_group_call_id); if (group_call == nullptr || !group_call->is_inited || !group_call->is_active) { @@ -1586,6 +1643,8 @@ bool GroupCallManager::on_join_group_call_response(InputGroupCallId input_group_ group_call->joined_date = G()->unix_time(); group_call->source = it->second->source; it->second->promise.set_value(result.move_as_ok()); + check_group_call_is_joined_timeout_.set_timeout_in(group_call->group_call_id.get(), + CHECK_GROUP_CALL_IS_JOINED_TIMEOUT); need_update = true; } pending_join_requests_.erase(it); @@ -1661,6 +1720,10 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_ } else { recursive = true; } + if (source != group_call->source && !recursive && is_speaking && + check_group_call_is_joined_timeout_.has_timeout(group_call_id.get())) { + check_group_call_is_joined_timeout_.set_timeout_in(group_call_id.get(), CHECK_GROUP_CALL_IS_JOINED_TIMEOUT); + } UserId user_id = set_group_call_participant_is_speaking_by_source(input_group_call_id, source, is_speaking, date); if (!user_id.is_valid()) { if (!recursive) { @@ -1725,29 +1788,6 @@ void GroupCallManager::toggle_group_call_participant_is_muted(GroupCallId group_ td_->create_handler(std::move(promise))->send(input_group_call_id, user_id, is_muted); } -void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Promise &&promise) { - TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); - - auto *group_call = get_group_call(input_group_call_id); - if (group_call == nullptr || !group_call->is_inited) { - return promise.set_error(Status::Error(400, "GROUP_CALL_JOIN_MISSING")); - } - if (!group_call->is_active || !group_call->is_joined || group_call->joined_date > G()->unix_time() - 8) { - return promise.set_value(Unit()); - } - auto source = group_call->source; - - auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source, - promise = std::move(promise)](Result &&result) mutable { - if (result.is_error() && result.error().message() == "GROUP_CALL_JOIN_MISSING") { - send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, true); - result = Unit(); - } - promise.set_result(std::move(result)); - }); - td_->create_handler(std::move(query_promise))->send(input_group_call_id, source); -} - void GroupCallManager::load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise &&promise) { if (limit <= 0) { return promise.set_error(Status::Error(400, "Parameter limit must be positive")); @@ -1816,6 +1856,7 @@ void GroupCallManager::on_group_call_left_impl(GroupCall *group_call, bool need_ group_call->source = 0; group_call->loaded_all_participants = false; group_call->version = -1; + check_group_call_is_joined_timeout_.cancel_timeout(group_call->group_call_id.get()); try_clear_group_call_participants(get_input_group_call_id(group_call->group_call_id).ok()); } diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index fbd0dca24..46d325f0f 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -62,8 +62,6 @@ class GroupCallManager : public Actor { void toggle_group_call_participant_is_muted(GroupCallId group_call_id, UserId user_id, bool is_muted, Promise &&promise); - void check_group_call_is_joined(GroupCallId group_call_id, Promise &&promise); - void load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise &&promise); void leave_group_call(GroupCallId group_call_id, Promise &&promise); @@ -92,9 +90,14 @@ class GroupCallManager : public Actor { struct PendingJoinRequest; static constexpr int32 RECENT_SPEAKER_TIMEOUT = 5 * 60; + static constexpr int32 CHECK_GROUP_CALL_IS_JOINED_TIMEOUT = 10; void tear_down() override; + static void on_check_group_call_is_joined_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int); + + void on_check_group_call_is_joined_timeout(GroupCallId group_call_id); + static void on_pending_send_speaking_action_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int); void on_send_speaking_action_timeout(GroupCallId group_call_id); @@ -125,6 +128,8 @@ class GroupCallManager : public Actor { void finish_get_group_call(InputGroupCallId input_group_call_id, Result> &&result); + void finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 source, Result &&result); + bool need_group_call_participants(InputGroupCallId input_group_call_id) const; bool process_pending_group_call_participant_updates(InputGroupCallId input_group_call_id); @@ -219,6 +224,7 @@ class GroupCallManager : public Actor { std::unordered_map, InputGroupCallIdHash> pending_join_requests_; uint64 join_group_request_generation_ = 0; + MultiTimeout check_group_call_is_joined_timeout_{"CheckGroupCallIsJoinedTimeout"}; MultiTimeout pending_send_speaking_action_timeout_{"PendingSendSpeakingActionTimeout"}; MultiTimeout recent_speaker_update_timeout_{"RecentSpeakerUpdateTimeout"}; MultiTimeout sync_participants_timeout_{"SyncParticipantsTimeout"}; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 5b31c42c1..42c49f5bf 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6074,12 +6074,6 @@ void Td::on_request(uint64 id, const td_api::toggleGroupCallParticipantIsMuted & GroupCallId(request.group_call_id_), UserId(request.user_id_), request.is_muted_, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::checkGroupCallIsJoined &request) { - CHECK_IS_USER(); - CREATE_OK_REQUEST_PROMISE(); - group_call_manager_->check_group_call_is_joined(GroupCallId(request.group_call_id_), std::move(promise)); -} - void Td::on_request(uint64 id, const td_api::loadGroupCallParticipants &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index da095a865..d5e28b22e 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -706,8 +706,6 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::toggleGroupCallParticipantIsMuted &request); - void on_request(uint64 id, const td_api::checkGroupCallIsJoined &request); - void on_request(uint64 id, const td_api::loadGroupCallParticipants &request); void on_request(uint64 id, const td_api::leaveGroupCall &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 8bec04c74..e031ae843 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2664,8 +2664,6 @@ class CliClient final : public Actor { get_args(args, group_call_id, user_id, is_muted); send_request(td_api::make_object(as_group_call_id(group_call_id), as_user_id(user_id), is_muted)); - } else if (op == "cgcij") { - send_request(td_api::make_object(as_group_call_id(args))); } else if (op == "lgcp") { string group_call_id; string limit;