From 67623072d6e531307e4f0c86afab71175017763e Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 18 Mar 2021 00:24:36 +0400 Subject: [PATCH] Fix joining a voice chat. --- .../SourceFiles/calls/calls_group_call.cpp | 196 ++++++++++-------- Telegram/SourceFiles/calls/calls_group_call.h | 7 +- Telegram/SourceFiles/calls/calls_instance.cpp | 27 +-- Telegram/SourceFiles/data/data_group_call.h | 2 +- 4 files changed, 130 insertions(+), 102 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index a2a2f4586..1a3a6c8bf 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -713,98 +713,102 @@ void GroupCall::setMutedAndUpdate(MuteState mute) { } } -void GroupCall::handleUpdate(const MTPGroupCall &call) { - return call.match([&](const MTPDgroupCall &data) { - if (_acceptFields) { - if (!_instance && !_id) { - join(MTP_inputGroupCall(data.vid(), data.vaccess_hash())); - } +void GroupCall::handlePossibleCreateOrJoinResponse( + const MTPDupdateGroupCall &data) { + data.vcall().match([&](const MTPDgroupCall &data) { + handlePossibleCreateOrJoinResponse(data); + }, [](const MTPDgroupCallDiscarded &data) { + }); +} + +void GroupCall::handlePossibleCreateOrJoinResponse( + const MTPDgroupCall &data) { + if (_acceptFields) { + if (!_instance && !_id) { + join(MTP_inputGroupCall(data.vid(), data.vaccess_hash())); + } + return; + } else if (_id != data.vid().v + || _accessHash != data.vaccess_hash().v + || !_instance) { + return; + } + const auto streamDcId = MTP::BareDcId( + data.vstream_dc_id().value_or_empty()); + const auto params = data.vparams(); + if (!params) { + return; + } + params->match([&](const MTPDdataJSON &data) { + auto error = QJsonParseError{ 0, QJsonParseError::NoError }; + const auto document = QJsonDocument::fromJson( + data.vdata().v, + &error); + if (error.error != QJsonParseError::NoError) { + LOG(("API Error: " + "Failed to parse group call params, error: %1." + ).arg(error.errorString())); return; - } else if (_id != data.vid().v - || _accessHash != data.vaccess_hash().v - || !_instance) { + } else if (!document.isObject()) { + LOG(("API Error: " + "Not an object received in group call params.")); return; } - const auto streamDcId = MTP::BareDcId( - data.vstream_dc_id().value_or_empty()); - if (const auto params = data.vparams()) { - params->match([&](const MTPDdataJSON &data) { - auto error = QJsonParseError{ 0, QJsonParseError::NoError }; - const auto document = QJsonDocument::fromJson( - data.vdata().v, - &error); - if (error.error != QJsonParseError::NoError) { - LOG(("API Error: " - "Failed to parse group call params, error: %1." - ).arg(error.errorString())); - return; - } else if (!document.isObject()) { - LOG(("API Error: " - "Not an object received in group call params.")); - return; - } - const auto guard = gsl::finally([&] { - addParticipantsToInstance(); - }); + const auto guard = gsl::finally([&] { + addParticipantsToInstance(); + }); - if (document.object().value("stream").toBool()) { - if (!streamDcId) { - LOG(("Api Error: Empty stream_dc_id in groupCall.")); - } - _broadcastDcId = streamDcId - ? streamDcId - : _peer->session().mtp().mainDcId(); - setInstanceMode(InstanceMode::Stream); - return; - } + if (document.object().value("stream").toBool()) { + if (!streamDcId) { + LOG(("Api Error: Empty stream_dc_id in groupCall.")); + } + _broadcastDcId = streamDcId + ? streamDcId + : _peer->session().mtp().mainDcId(); + setInstanceMode(InstanceMode::Stream); + return; + } - const auto readString = []( - const QJsonObject &object, - const char *key) { - return object.value(key).toString().toStdString(); - }; - const auto root = document.object().value("transport").toObject(); - auto payload = tgcalls::GroupJoinResponsePayload(); - payload.ufrag = readString(root, "ufrag"); - payload.pwd = readString(root, "pwd"); - const auto prints = root.value("fingerprints").toArray(); - const auto candidates = root.value("candidates").toArray(); - for (const auto &print : prints) { - const auto object = print.toObject(); - payload.fingerprints.push_back(tgcalls::GroupJoinPayloadFingerprint{ - .hash = readString(object, "hash"), - .setup = readString(object, "setup"), - .fingerprint = readString(object, "fingerprint"), - }); - } - for (const auto &candidate : candidates) { - const auto object = candidate.toObject(); - payload.candidates.push_back(tgcalls::GroupJoinResponseCandidate{ - .port = readString(object, "port"), - .protocol = readString(object, "protocol"), - .network = readString(object, "network"), - .generation = readString(object, "generation"), - .id = readString(object, "id"), - .component = readString(object, "component"), - .foundation = readString(object, "foundation"), - .priority = readString(object, "priority"), - .ip = readString(object, "ip"), - .type = readString(object, "type"), - .tcpType = readString(object, "tcpType"), - .relAddr = readString(object, "relAddr"), - .relPort = readString(object, "relPort"), - }); - } - setInstanceMode(InstanceMode::Rtc); - _instance->setJoinResponsePayload(payload, {}); + const auto readString = []( + const QJsonObject &object, + const char *key) { + return object.value(key).toString().toStdString(); + }; + const auto root = document.object().value("transport").toObject(); + auto payload = tgcalls::GroupJoinResponsePayload(); + payload.ufrag = readString(root, "ufrag"); + payload.pwd = readString(root, "pwd"); + const auto prints = root.value("fingerprints").toArray(); + const auto candidates = root.value("candidates").toArray(); + for (const auto &print : prints) { + const auto object = print.toObject(); + payload.fingerprints.push_back(tgcalls::GroupJoinPayloadFingerprint{ + .hash = readString(object, "hash"), + .setup = readString(object, "setup"), + .fingerprint = readString(object, "fingerprint"), }); } - }, [&](const MTPDgroupCallDiscarded &data) { - if (data.vid().v == _id) { - _mySsrc = 0; - hangup(); + for (const auto &candidate : candidates) { + const auto object = candidate.toObject(); + payload.candidates.push_back(tgcalls::GroupJoinResponseCandidate{ + .port = readString(object, "port"), + .protocol = readString(object, "protocol"), + .network = readString(object, "network"), + .generation = readString(object, "generation"), + .id = readString(object, "id"), + .component = readString(object, "component"), + .foundation = readString(object, "foundation"), + .priority = readString(object, "priority"), + .ip = readString(object, "ip"), + .type = readString(object, "type"), + .tcpType = readString(object, "tcpType"), + .relAddr = readString(object, "relAddr"), + .relPort = readString(object, "relPort"), + }); } + setInstanceMode(InstanceMode::Rtc); + _instance->setJoinResponsePayload(payload, {}); }); } @@ -849,7 +853,33 @@ void GroupCall::addPreparedParticipantsDelayed() { crl::on_main(this, [=] { addPreparedParticipants(); }); } +void GroupCall::handleUpdate(const MTPUpdate &update) { + update.match([&](const MTPDupdateGroupCall &data) { + handleUpdate(data); + }, [&](const MTPDupdateGroupCallParticipants &data) { + handleUpdate(data); + }, [](const auto &) { + Unexpected("Type in Instance::applyGroupCallUpdateChecked."); + }); +} + +void GroupCall::handleUpdate(const MTPDupdateGroupCall &data) { + data.vcall().match([](const MTPDgroupCall &) { + }, [&](const MTPDgroupCallDiscarded &data) { + if (data.vid().v == _id) { + _mySsrc = 0; + hangup(); + } + }); +} + void GroupCall::handleUpdate(const MTPDupdateGroupCallParticipants &data) { + const auto callId = data.vcall().match([](const auto &data) { + return data.vid().v; + }); + if (_id != callId) { + return; + } const auto state = _state.current(); if (state != State::Joined && state != State::Connecting) { return; diff --git a/Telegram/SourceFiles/calls/calls_group_call.h b/Telegram/SourceFiles/calls/calls_group_call.h index e0ad0955d..43dd9b0e2 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.h +++ b/Telegram/SourceFiles/calls/calls_group_call.h @@ -116,8 +116,8 @@ public: void rejoinAs(Group::JoinInfo info); void rejoinWithHash(const QString &hash); void join(const MTPInputGroupCall &inputCall); - void handleUpdate(const MTPGroupCall &call); - void handleUpdate(const MTPDupdateGroupCallParticipants &data); + void handleUpdate(const MTPUpdate &update); + void handlePossibleCreateOrJoinResponse(const MTPDupdateGroupCall &data); void changeTitle(const QString &title); void toggleRecording(bool enabled, const QString &title); [[nodiscard]] bool recordingStoppedByMe() const { @@ -227,6 +227,9 @@ private: RaiseHand, }; + void handlePossibleCreateOrJoinResponse(const MTPDgroupCall &data); + void handleUpdate(const MTPDupdateGroupCall &data); + void handleUpdate(const MTPDupdateGroupCallParticipants &data); void handleRequestError(const MTP::Error &error); void handleControllerError(const QString &error); void ensureControllerCreated(); diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index 40ba895e3..f7462192a 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -427,28 +427,23 @@ void Instance::handleGroupCallUpdate( } else { applyGroupCallUpdateChecked(session, update); } + + if (_currentGroupCall + && (&_currentGroupCall->peer()->session() == session)) { + update.match([&](const MTPDupdateGroupCall &data) { + _currentGroupCall->handlePossibleCreateOrJoinResponse(data); + }, [](const auto &) { + }); + } } void Instance::applyGroupCallUpdateChecked( not_null session, const MTPUpdate &update) { - if (!_currentGroupCall - || (&_currentGroupCall->peer()->session() != session)) { - return; + if (_currentGroupCall + && (&_currentGroupCall->peer()->session() == session)) { + _currentGroupCall->handleUpdate(update); } - - update.match([&](const MTPDupdateGroupCall &data) { - _currentGroupCall->handleUpdate(data.vcall()); - }, [&](const MTPDupdateGroupCallParticipants &data) { - const auto callId = data.vcall().match([](const auto &data) { - return data.vid().v; - }); - if (_currentGroupCall->id() == callId) { - _currentGroupCall->handleUpdate(data); - } - }, [](const auto &) { - Unexpected("Type in Instance::applyGroupCallUpdateChecked."); - }); } void Instance::handleSignalingData( diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index 4731dcd4d..666fad462 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -137,7 +137,7 @@ private: mtpRequestId _reloadRequestId = 0; rpl::variable _title; - base::flat_map, MTPUpdate> _queuedUpdates; + base::flat_multi_map, MTPUpdate> _queuedUpdates; base::Timer _reloadByQueuedUpdatesTimer; std::vector _participants;