mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-06 05:42:49 +02:00
WebRTC signaling with assignment clients via domain server
This commit is contained in:
parent
9b2c773805
commit
a3c1d50478
7 changed files with 129 additions and 6 deletions
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QProcess>
|
||||
#include <QSharedMemory>
|
||||
#include <QThread>
|
||||
|
@ -125,6 +126,18 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
|||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleCreateAssignmentPacket));
|
||||
packetReceiver.registerListener(PacketType::StopNode,
|
||||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleStopNodePacket));
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
auto webrtcSocket = nodeList->getWebRTCSocket();
|
||||
|
||||
// Route inbound WebRTC signaling messages from the Domain Server.
|
||||
packetReceiver.registerListener(PacketType::WebRTCSignaling,
|
||||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleWebRTCSignalingPacket));
|
||||
connect(this, &AssignmentClient::webrtcSignalingMessageFromUserClient, webrtcSocket, &WebRTCSocket::onSignalingMessage);
|
||||
|
||||
// Route outbound WebRTC signaling messages via the Domain Server to the user client.
|
||||
connect(webrtcSocket, &WebRTCSocket::sendSignalingMessage, this, &AssignmentClient::sendSignalingMessageToUserClient);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AssignmentClient::stopAssignmentClient() {
|
||||
|
@ -333,3 +346,44 @@ void AssignmentClient::assignmentCompleted() {
|
|||
|
||||
_isAssigned = false;
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
|
||||
void AssignmentClient::handleWebRTCSignalingPacket(QSharedPointer<ReceivedMessage> message) {
|
||||
auto messageString = message->readString();
|
||||
auto json = QJsonDocument::fromJson(messageString.toUtf8()).object();
|
||||
if (json.keys().contains("echo")) {
|
||||
// Echo message back to sender.
|
||||
|
||||
if (!json.keys().contains("to") || !json.keys().contains("from")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap to/from.
|
||||
auto to = json.value("to");
|
||||
json.insert("to", json.value("from"));
|
||||
json.insert("from", to);
|
||||
|
||||
// Send back to sender via the Domain Server.
|
||||
auto packetList = NLPacketList::create(PacketType::WebRTCSignaling, QByteArray(), true, true);
|
||||
packetList->writeString(QJsonDocument(json).toJson(QJsonDocument::Compact));
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto domainServerAddress = nodeList->getDomainHandler().getSockAddr();
|
||||
nodeList->sendPacketList(std::move(packetList), domainServerAddress);
|
||||
|
||||
} else {
|
||||
// WebRTC signaling message.
|
||||
emit webrtcSignalingMessageFromUserClient(json);
|
||||
}
|
||||
}
|
||||
|
||||
// Sends a signaling message from the assignment client to the user client via the Domain Server.
|
||||
void AssignmentClient::sendSignalingMessageToUserClient(const QJsonObject& json) {
|
||||
auto packetList = NLPacketList::create(PacketType::WebRTCSignaling, QByteArray(), true, true);
|
||||
packetList->writeString(QJsonDocument(json).toJson(QJsonDocument::Compact));
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto domainServerAddress = nodeList->getDomainHandler().getSockAddr();
|
||||
nodeList->sendPacketList(std::move(packetList), domainServerAddress);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include <shared/WebRTC.h>
|
||||
|
||||
#include "ThreadedAssignment.h"
|
||||
|
||||
class QSharedMemory;
|
||||
|
@ -29,19 +31,26 @@ public:
|
|||
quint16 assignmentMonitorPort);
|
||||
~AssignmentClient();
|
||||
|
||||
public slots:
|
||||
void aboutToQuit();
|
||||
|
||||
private slots:
|
||||
void sendAssignmentRequest();
|
||||
void assignmentCompleted();
|
||||
void handleAuthenticationRequest();
|
||||
void sendStatusPacketToACM();
|
||||
void stopAssignmentClient();
|
||||
|
||||
public slots:
|
||||
void aboutToQuit();
|
||||
|
||||
private slots:
|
||||
void handleCreateAssignmentPacket(QSharedPointer<ReceivedMessage> message);
|
||||
void handleStopNodePacket(QSharedPointer<ReceivedMessage> message);
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void handleWebRTCSignalingPacket(QSharedPointer<ReceivedMessage> message);
|
||||
void sendSignalingMessageToUserClient(const QJsonObject& json);
|
||||
#endif
|
||||
|
||||
signals:
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void webrtcSignalingMessageFromUserClient(const QJsonObject& json);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void setUpStatusToMonitor();
|
||||
|
|
|
@ -857,6 +857,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
|
||||
// Sets up the WebRTC signaling server that's hosted by the domain server.
|
||||
void DomainServer::setUpWebRTCSignalingServer() {
|
||||
// Bind the WebRTC signaling server's WebSocket to its port.
|
||||
bool isBound = _webrtcSignalingServer.bind(QHostAddress::AnyIPv4, DEFAULT_DOMAIN_SERVER_WS_PORT);
|
||||
|
@ -875,14 +876,46 @@ void DomainServer::setUpWebRTCSignalingServer() {
|
|||
auto webrtcSocket = limitedNodeList->getWebRTCSocket();
|
||||
connect(this, &DomainServer::webrtcSignalingMessageForDomainServer, webrtcSocket, &WebRTCSocket::onSignalingMessage);
|
||||
connect(webrtcSocket, &WebRTCSocket::sendSignalingMessage, &_webrtcSignalingServer, &WebRTCSignalingServer::sendMessage);
|
||||
|
||||
// Forward signaling messages received from assignment clients to user client.
|
||||
PacketReceiver& packetReceiver = limitedNodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::WebRTCSignaling,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this,
|
||||
&DomainServer::forwardAssignmentClientSignalingMessageToUserClient));
|
||||
connect(this, &DomainServer::webrtcSignalingMessageForUserClient,
|
||||
&_webrtcSignalingServer, &WebRTCSignalingServer::sendMessage);
|
||||
}
|
||||
|
||||
// Routes an inbound WebRTC signaling message received from a client app to the appropriate recipient.
|
||||
void DomainServer::routeWebRTCSignalingMessage(const QJsonObject& json) {
|
||||
if (json.value("to").toString() == NodeType::DomainServer) {
|
||||
emit webrtcSignalingMessageForDomainServer(json);
|
||||
} else {
|
||||
sendWebRTCSignalingMessageToAssignmentClient(json);
|
||||
}
|
||||
}
|
||||
|
||||
// Sends a WebRTC signaling message to the target AC contained in the message.
|
||||
void DomainServer::sendWebRTCSignalingMessageToAssignmentClient(const QJsonObject& json) {
|
||||
NodeType_t destinationNodeType = NodeType::fromChar(json.value("to").toString().at(0));
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
auto destinationNode = limitedNodeList->soloNodeOfType(destinationNodeType);
|
||||
if (!destinationNode) {
|
||||
return;
|
||||
}
|
||||
// Use an NLPacketList because the signaling message is not necessarily small.
|
||||
auto packetList = NLPacketList::create(PacketType::WebRTCSignaling, QByteArray(), true, true);
|
||||
packetList->writeString(QJsonDocument(json).toJson(QJsonDocument::Compact));
|
||||
limitedNodeList->sendPacketList(std::move(packetList), *destinationNode);
|
||||
}
|
||||
|
||||
// Forwards a WebRTC signaling message received from an assignment client to the relevant user client.
|
||||
void DomainServer::forwardAssignmentClientSignalingMessageToUserClient(QSharedPointer<ReceivedMessage> message) {
|
||||
auto messageString = message->readString();
|
||||
auto json = QJsonDocument::fromJson(messageString.toUtf8()).object();
|
||||
emit webrtcSignalingMessageForUserClient(json);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -150,6 +150,10 @@ private slots:
|
|||
void tokenGrantFinished();
|
||||
void profileRequestFinished();
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void forwardAssignmentClientSignalingMessageToUserClient(QSharedPointer<ReceivedMessage> message);
|
||||
#endif
|
||||
|
||||
void aboutToQuit();
|
||||
|
||||
signals:
|
||||
|
@ -159,6 +163,7 @@ signals:
|
|||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void webrtcSignalingMessageForDomainServer(const QJsonObject& json);
|
||||
void webrtcSignalingMessageForUserClient(const QJsonObject& json);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -245,6 +250,7 @@ private:
|
|||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void setUpWebRTCSignalingServer();
|
||||
void routeWebRTCSignalingMessage(const QJsonObject& json);
|
||||
void sendWebRTCSignalingMessageToAssignmentClient(const QJsonObject& json);
|
||||
#endif
|
||||
|
||||
QString operationToString(const QNetworkAccessManager::Operation &op);
|
||||
|
|
|
@ -46,6 +46,22 @@ static const QHash<NodeType_t, QString> TYPE_NAME_HASH {
|
|||
{ NodeType::Unassigned, "Unassigned" }
|
||||
};
|
||||
|
||||
static const QHash<NodeType_t, QString> TYPE_CHAR_HASH {
|
||||
{ NodeType::DomainServer, "D" },
|
||||
{ NodeType::EntityServer, "o" },
|
||||
{ NodeType::Agent, "I" },
|
||||
{ NodeType::AudioMixer, "M" },
|
||||
{ NodeType::AvatarMixer, "W" },
|
||||
{ NodeType::AssetServer, "A" },
|
||||
{ NodeType::MessagesMixer, "m" },
|
||||
{ NodeType::EntityScriptServer, "S" },
|
||||
{ NodeType::UpstreamAudioMixer, "B" },
|
||||
{ NodeType::UpstreamAvatarMixer, "C" },
|
||||
{ NodeType::DownstreamAudioMixer, "a" },
|
||||
{ NodeType::DownstreamAvatarMixer, "w" },
|
||||
{ NodeType::Unassigned, QChar(1) }
|
||||
};
|
||||
|
||||
const QString& NodeType::getNodeTypeName(NodeType_t nodeType) {
|
||||
const auto matchedTypeName = TYPE_NAME_HASH.find(nodeType);
|
||||
return matchedTypeName != TYPE_NAME_HASH.end() ? matchedTypeName.value() : UNKNOWN_NodeType_t_NAME;
|
||||
|
@ -85,6 +101,9 @@ NodeType_t NodeType::fromString(QString type) {
|
|||
return TYPE_NAME_HASH.key(type, NodeType::Unassigned);
|
||||
}
|
||||
|
||||
NodeType_t NodeType::fromChar(QChar type) {
|
||||
return TYPE_CHAR_HASH.key(type, NodeType::Unassigned);
|
||||
}
|
||||
|
||||
Node::Node(const QUuid& uuid, NodeType_t type, const SockAddr& publicSocket,
|
||||
const SockAddr& localSocket, QObject* parent) :
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace NodeType {
|
|||
NodeType_t downstreamType(NodeType_t primaryType);
|
||||
|
||||
NodeType_t fromString(QString type);
|
||||
NodeType_t fromChar(QChar type);
|
||||
}
|
||||
|
||||
typedef QSet<NodeType_t> NodeSet;
|
||||
|
|
|
@ -139,6 +139,7 @@ public:
|
|||
BulkAvatarTraitsAck,
|
||||
StopInjector,
|
||||
AvatarZonePresence,
|
||||
WebRTCSignaling,
|
||||
NUM_PACKET_TYPE
|
||||
};
|
||||
|
||||
|
@ -190,7 +191,7 @@ public:
|
|||
<< PacketTypeEnum::Value::ReplicatedMicrophoneAudioWithEcho << PacketTypeEnum::Value::ReplicatedInjectAudio
|
||||
<< PacketTypeEnum::Value::ReplicatedSilentAudioFrame << PacketTypeEnum::Value::ReplicatedAvatarIdentity
|
||||
<< PacketTypeEnum::Value::ReplicatedKillAvatar << PacketTypeEnum::Value::ReplicatedBulkAvatarData
|
||||
<< PacketTypeEnum::Value::AvatarZonePresence;
|
||||
<< PacketTypeEnum::Value::AvatarZonePresence << PacketTypeEnum::Value::WebRTCSignaling;
|
||||
return NON_SOURCED_PACKETS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue