mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 07:47:30 +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 <assert.h>
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QSharedMemory>
|
#include <QSharedMemory>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
@ -125,6 +126,18 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleCreateAssignmentPacket));
|
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleCreateAssignmentPacket));
|
||||||
packetReceiver.registerListener(PacketType::StopNode,
|
packetReceiver.registerListener(PacketType::StopNode,
|
||||||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleStopNodePacket));
|
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() {
|
void AssignmentClient::stopAssignmentClient() {
|
||||||
|
@ -333,3 +346,44 @@ void AssignmentClient::assignmentCompleted() {
|
||||||
|
|
||||||
_isAssigned = false;
|
_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/QCoreApplication>
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
|
|
||||||
|
#include <shared/WebRTC.h>
|
||||||
|
|
||||||
#include "ThreadedAssignment.h"
|
#include "ThreadedAssignment.h"
|
||||||
|
|
||||||
class QSharedMemory;
|
class QSharedMemory;
|
||||||
|
@ -29,19 +31,26 @@ public:
|
||||||
quint16 assignmentMonitorPort);
|
quint16 assignmentMonitorPort);
|
||||||
~AssignmentClient();
|
~AssignmentClient();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void aboutToQuit();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void sendAssignmentRequest();
|
void sendAssignmentRequest();
|
||||||
void assignmentCompleted();
|
void assignmentCompleted();
|
||||||
void handleAuthenticationRequest();
|
void handleAuthenticationRequest();
|
||||||
void sendStatusPacketToACM();
|
void sendStatusPacketToACM();
|
||||||
void stopAssignmentClient();
|
void stopAssignmentClient();
|
||||||
|
|
||||||
public slots:
|
|
||||||
void aboutToQuit();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void handleCreateAssignmentPacket(QSharedPointer<ReceivedMessage> message);
|
void handleCreateAssignmentPacket(QSharedPointer<ReceivedMessage> message);
|
||||||
void handleStopNodePacket(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:
|
private:
|
||||||
void setUpStatusToMonitor();
|
void setUpStatusToMonitor();
|
||||||
|
|
|
@ -857,6 +857,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
||||||
|
|
||||||
#if defined(WEBRTC_DATA_CHANNELS)
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
|
|
||||||
|
// Sets up the WebRTC signaling server that's hosted by the domain server.
|
||||||
void DomainServer::setUpWebRTCSignalingServer() {
|
void DomainServer::setUpWebRTCSignalingServer() {
|
||||||
// Bind the WebRTC signaling server's WebSocket to its port.
|
// Bind the WebRTC signaling server's WebSocket to its port.
|
||||||
bool isBound = _webrtcSignalingServer.bind(QHostAddress::AnyIPv4, DEFAULT_DOMAIN_SERVER_WS_PORT);
|
bool isBound = _webrtcSignalingServer.bind(QHostAddress::AnyIPv4, DEFAULT_DOMAIN_SERVER_WS_PORT);
|
||||||
|
@ -875,14 +876,46 @@ void DomainServer::setUpWebRTCSignalingServer() {
|
||||||
auto webrtcSocket = limitedNodeList->getWebRTCSocket();
|
auto webrtcSocket = limitedNodeList->getWebRTCSocket();
|
||||||
connect(this, &DomainServer::webrtcSignalingMessageForDomainServer, webrtcSocket, &WebRTCSocket::onSignalingMessage);
|
connect(this, &DomainServer::webrtcSignalingMessageForDomainServer, webrtcSocket, &WebRTCSocket::onSignalingMessage);
|
||||||
connect(webrtcSocket, &WebRTCSocket::sendSignalingMessage, &_webrtcSignalingServer, &WebRTCSignalingServer::sendMessage);
|
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) {
|
void DomainServer::routeWebRTCSignalingMessage(const QJsonObject& json) {
|
||||||
if (json.value("to").toString() == NodeType::DomainServer) {
|
if (json.value("to").toString() == NodeType::DomainServer) {
|
||||||
emit webrtcSignalingMessageForDomainServer(json);
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,10 @@ private slots:
|
||||||
void tokenGrantFinished();
|
void tokenGrantFinished();
|
||||||
void profileRequestFinished();
|
void profileRequestFinished();
|
||||||
|
|
||||||
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
|
void forwardAssignmentClientSignalingMessageToUserClient(QSharedPointer<ReceivedMessage> message);
|
||||||
|
#endif
|
||||||
|
|
||||||
void aboutToQuit();
|
void aboutToQuit();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -159,6 +163,7 @@ signals:
|
||||||
|
|
||||||
#if defined(WEBRTC_DATA_CHANNELS)
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
void webrtcSignalingMessageForDomainServer(const QJsonObject& json);
|
void webrtcSignalingMessageForDomainServer(const QJsonObject& json);
|
||||||
|
void webrtcSignalingMessageForUserClient(const QJsonObject& json);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -245,6 +250,7 @@ private:
|
||||||
#if defined(WEBRTC_DATA_CHANNELS)
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
void setUpWebRTCSignalingServer();
|
void setUpWebRTCSignalingServer();
|
||||||
void routeWebRTCSignalingMessage(const QJsonObject& json);
|
void routeWebRTCSignalingMessage(const QJsonObject& json);
|
||||||
|
void sendWebRTCSignalingMessageToAssignmentClient(const QJsonObject& json);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QString operationToString(const QNetworkAccessManager::Operation &op);
|
QString operationToString(const QNetworkAccessManager::Operation &op);
|
||||||
|
|
|
@ -46,6 +46,22 @@ static const QHash<NodeType_t, QString> TYPE_NAME_HASH {
|
||||||
{ NodeType::Unassigned, "Unassigned" }
|
{ 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 QString& NodeType::getNodeTypeName(NodeType_t nodeType) {
|
||||||
const auto matchedTypeName = TYPE_NAME_HASH.find(nodeType);
|
const auto matchedTypeName = TYPE_NAME_HASH.find(nodeType);
|
||||||
return matchedTypeName != TYPE_NAME_HASH.end() ? matchedTypeName.value() : UNKNOWN_NodeType_t_NAME;
|
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);
|
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,
|
Node::Node(const QUuid& uuid, NodeType_t type, const SockAddr& publicSocket,
|
||||||
const SockAddr& localSocket, QObject* parent) :
|
const SockAddr& localSocket, QObject* parent) :
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace NodeType {
|
||||||
NodeType_t downstreamType(NodeType_t primaryType);
|
NodeType_t downstreamType(NodeType_t primaryType);
|
||||||
|
|
||||||
NodeType_t fromString(QString type);
|
NodeType_t fromString(QString type);
|
||||||
|
NodeType_t fromChar(QChar type);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef QSet<NodeType_t> NodeSet;
|
typedef QSet<NodeType_t> NodeSet;
|
||||||
|
|
|
@ -139,6 +139,7 @@ public:
|
||||||
BulkAvatarTraitsAck,
|
BulkAvatarTraitsAck,
|
||||||
StopInjector,
|
StopInjector,
|
||||||
AvatarZonePresence,
|
AvatarZonePresence,
|
||||||
|
WebRTCSignaling,
|
||||||
NUM_PACKET_TYPE
|
NUM_PACKET_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ public:
|
||||||
<< PacketTypeEnum::Value::ReplicatedMicrophoneAudioWithEcho << PacketTypeEnum::Value::ReplicatedInjectAudio
|
<< PacketTypeEnum::Value::ReplicatedMicrophoneAudioWithEcho << PacketTypeEnum::Value::ReplicatedInjectAudio
|
||||||
<< PacketTypeEnum::Value::ReplicatedSilentAudioFrame << PacketTypeEnum::Value::ReplicatedAvatarIdentity
|
<< PacketTypeEnum::Value::ReplicatedSilentAudioFrame << PacketTypeEnum::Value::ReplicatedAvatarIdentity
|
||||||
<< PacketTypeEnum::Value::ReplicatedKillAvatar << PacketTypeEnum::Value::ReplicatedBulkAvatarData
|
<< PacketTypeEnum::Value::ReplicatedKillAvatar << PacketTypeEnum::Value::ReplicatedBulkAvatarData
|
||||||
<< PacketTypeEnum::Value::AvatarZonePresence;
|
<< PacketTypeEnum::Value::AvatarZonePresence << PacketTypeEnum::Value::WebRTCSignaling;
|
||||||
return NON_SOURCED_PACKETS;
|
return NON_SOURCED_PACKETS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue