Automatically check whether group call is still joined.

This commit is contained in:
levlam 2020-12-28 00:30:27 +03:00
parent 1d155a8492
commit 1f9d173afb
7 changed files with 72 additions and 38 deletions

View File

@ -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

Binary file not shown.

View File

@ -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<void *>(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<void *>(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<GroupCallManager *>(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<int32>(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<Unit> &&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<CheckGroupCallQuery>(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<Unit> &&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<EditGroupCallMemberQuery>(std::move(promise))->send(input_group_call_id, user_id, is_muted);
}
void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Promise<Unit> &&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<Unit> &&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<CheckGroupCallQuery>(std::move(query_promise))->send(input_group_call_id, source);
}
void GroupCallManager::load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise<Unit> &&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());
}

View File

@ -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<Unit> &&promise);
void check_group_call_is_joined(GroupCallId group_call_id, Promise<Unit> &&promise);
void load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise<Unit> &&promise);
void leave_group_call(GroupCallId group_call_id, Promise<Unit> &&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<tl_object_ptr<telegram_api::phone_groupCall>> &&result);
void finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 source, Result<Unit> &&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<InputGroupCallId, unique_ptr<PendingJoinRequest>, 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"};

View File

@ -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();

View File

@ -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);

View File

@ -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<td_api::toggleGroupCallParticipantIsMuted>(as_group_call_id(group_call_id),
as_user_id(user_id), is_muted));
} else if (op == "cgcij") {
send_request(td_api::make_object<td_api::checkGroupCallIsJoined>(as_group_call_id(args)));
} else if (op == "lgcp") {
string group_call_id;
string limit;