Fix joining a voice chat.

This commit is contained in:
John Preston 2021-03-18 00:24:36 +04:00
parent 1291f1c80d
commit 67623072d6
4 changed files with 130 additions and 102 deletions

View file

@ -713,98 +713,102 @@ void GroupCall::setMutedAndUpdate(MuteState mute) {
} }
} }
void GroupCall::handleUpdate(const MTPGroupCall &call) { void GroupCall::handlePossibleCreateOrJoinResponse(
return call.match([&](const MTPDgroupCall &data) { const MTPDupdateGroupCall &data) {
if (_acceptFields) { data.vcall().match([&](const MTPDgroupCall &data) {
if (!_instance && !_id) { handlePossibleCreateOrJoinResponse(data);
join(MTP_inputGroupCall(data.vid(), data.vaccess_hash())); }, [](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; return;
} else if (_id != data.vid().v } else if (!document.isObject()) {
|| _accessHash != data.vaccess_hash().v LOG(("API Error: "
|| !_instance) { "Not an object received in group call params."));
return; 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([&] { const auto guard = gsl::finally([&] {
addParticipantsToInstance(); addParticipantsToInstance();
}); });
if (document.object().value("stream").toBool()) { if (document.object().value("stream").toBool()) {
if (!streamDcId) { if (!streamDcId) {
LOG(("Api Error: Empty stream_dc_id in groupCall.")); LOG(("Api Error: Empty stream_dc_id in groupCall."));
} }
_broadcastDcId = streamDcId _broadcastDcId = streamDcId
? streamDcId ? streamDcId
: _peer->session().mtp().mainDcId(); : _peer->session().mtp().mainDcId();
setInstanceMode(InstanceMode::Stream); setInstanceMode(InstanceMode::Stream);
return; return;
} }
const auto readString = []( const auto readString = [](
const QJsonObject &object, const QJsonObject &object,
const char *key) { const char *key) {
return object.value(key).toString().toStdString(); return object.value(key).toString().toStdString();
}; };
const auto root = document.object().value("transport").toObject(); const auto root = document.object().value("transport").toObject();
auto payload = tgcalls::GroupJoinResponsePayload(); auto payload = tgcalls::GroupJoinResponsePayload();
payload.ufrag = readString(root, "ufrag"); payload.ufrag = readString(root, "ufrag");
payload.pwd = readString(root, "pwd"); payload.pwd = readString(root, "pwd");
const auto prints = root.value("fingerprints").toArray(); const auto prints = root.value("fingerprints").toArray();
const auto candidates = root.value("candidates").toArray(); const auto candidates = root.value("candidates").toArray();
for (const auto &print : prints) { for (const auto &print : prints) {
const auto object = print.toObject(); const auto object = print.toObject();
payload.fingerprints.push_back(tgcalls::GroupJoinPayloadFingerprint{ payload.fingerprints.push_back(tgcalls::GroupJoinPayloadFingerprint{
.hash = readString(object, "hash"), .hash = readString(object, "hash"),
.setup = readString(object, "setup"), .setup = readString(object, "setup"),
.fingerprint = readString(object, "fingerprint"), .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 MTPDgroupCallDiscarded &data) { for (const auto &candidate : candidates) {
if (data.vid().v == _id) { const auto object = candidate.toObject();
_mySsrc = 0; payload.candidates.push_back(tgcalls::GroupJoinResponseCandidate{
hangup(); .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(); }); 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) { 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(); const auto state = _state.current();
if (state != State::Joined && state != State::Connecting) { if (state != State::Joined && state != State::Connecting) {
return; return;

View file

@ -116,8 +116,8 @@ public:
void rejoinAs(Group::JoinInfo info); void rejoinAs(Group::JoinInfo info);
void rejoinWithHash(const QString &hash); void rejoinWithHash(const QString &hash);
void join(const MTPInputGroupCall &inputCall); void join(const MTPInputGroupCall &inputCall);
void handleUpdate(const MTPGroupCall &call); void handleUpdate(const MTPUpdate &update);
void handleUpdate(const MTPDupdateGroupCallParticipants &data); void handlePossibleCreateOrJoinResponse(const MTPDupdateGroupCall &data);
void changeTitle(const QString &title); void changeTitle(const QString &title);
void toggleRecording(bool enabled, const QString &title); void toggleRecording(bool enabled, const QString &title);
[[nodiscard]] bool recordingStoppedByMe() const { [[nodiscard]] bool recordingStoppedByMe() const {
@ -227,6 +227,9 @@ private:
RaiseHand, RaiseHand,
}; };
void handlePossibleCreateOrJoinResponse(const MTPDgroupCall &data);
void handleUpdate(const MTPDupdateGroupCall &data);
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
void handleRequestError(const MTP::Error &error); void handleRequestError(const MTP::Error &error);
void handleControllerError(const QString &error); void handleControllerError(const QString &error);
void ensureControllerCreated(); void ensureControllerCreated();

View file

@ -427,28 +427,23 @@ void Instance::handleGroupCallUpdate(
} else { } else {
applyGroupCallUpdateChecked(session, update); applyGroupCallUpdateChecked(session, update);
} }
if (_currentGroupCall
&& (&_currentGroupCall->peer()->session() == session)) {
update.match([&](const MTPDupdateGroupCall &data) {
_currentGroupCall->handlePossibleCreateOrJoinResponse(data);
}, [](const auto &) {
});
}
} }
void Instance::applyGroupCallUpdateChecked( void Instance::applyGroupCallUpdateChecked(
not_null<Main::Session*> session, not_null<Main::Session*> session,
const MTPUpdate &update) { const MTPUpdate &update) {
if (!_currentGroupCall if (_currentGroupCall
|| (&_currentGroupCall->peer()->session() != session)) { && (&_currentGroupCall->peer()->session() == session)) {
return; _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( void Instance::handleSignalingData(

View file

@ -137,7 +137,7 @@ private:
mtpRequestId _reloadRequestId = 0; mtpRequestId _reloadRequestId = 0;
rpl::variable<QString> _title; rpl::variable<QString> _title;
base::flat_map<std::pair<int,bool>, MTPUpdate> _queuedUpdates; base::flat_multi_map<std::pair<int,bool>, MTPUpdate> _queuedUpdates;
base::Timer _reloadByQueuedUpdatesTimer; base::Timer _reloadByQueuedUpdatesTimer;
std::vector<Participant> _participants; std::vector<Participant> _participants;