mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-13 22:27:13 +02:00
Merge pull request #1313 from ctrlaltdavid/dev/webrtc-assignment-clients
Assignment client WebRTC connections
This commit is contained in:
commit
211fd474fe
23 changed files with 281 additions and 55 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,45 @@ 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")) {
|
||||
qCDebug(assignment_client) << "Invalid WebRTC signaling echo message received.";
|
||||
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();
|
||||
|
|
|
@ -70,7 +70,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen
|
|||
// create a NodeList so we can receive stats from children
|
||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
auto addressManager = DependencyManager::set<AddressManager>();
|
||||
auto nodeList = DependencyManager::set<LimitedNodeList>(NodeType::Unassigned, listenPort);
|
||||
auto nodeList = DependencyManager::set<LimitedNodeList>(listenPort);
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::AssignmentClientStatus,
|
||||
|
|
|
@ -167,6 +167,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
_gatekeeper(this),
|
||||
_httpManager(QHostAddress::AnyIPv4, DOMAIN_SERVER_HTTP_PORT,
|
||||
QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this)
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
,
|
||||
_webrtcSignalingServer(this)
|
||||
#endif
|
||||
{
|
||||
if (_parentPID != -1) {
|
||||
watchParentProcess(_parentPID);
|
||||
|
@ -248,6 +252,10 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
updateDownstreamNodes();
|
||||
updateUpstreamNodes();
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
setUpWebRTCSignalingServer();
|
||||
#endif
|
||||
|
||||
if (_type != NonMetaverse) {
|
||||
// if we have a metaverse domain, we'll use an access token for API calls
|
||||
resetAccountManagerAccessToken();
|
||||
|
@ -731,7 +739,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
// check for scripts the user wants to persist from their domain-server config
|
||||
populateStaticScriptedAssignmentsFromSettings();
|
||||
|
||||
auto nodeList = DependencyManager::set<LimitedNodeList>(NodeType::DomainServer, domainServerPort, domainServerDTLSPort);
|
||||
auto nodeList = DependencyManager::set<LimitedNodeList>(domainServerPort, domainServerDTLSPort);
|
||||
|
||||
// no matter the local port, save it to shared mem so that local assignment clients can ask what it is
|
||||
nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this,
|
||||
|
@ -846,6 +854,72 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
addStaticAssignmentsToQueue();
|
||||
}
|
||||
|
||||
|
||||
#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);
|
||||
if (!isBound) {
|
||||
qWarning() << "WebRTC signaling server not bound to port. WebRTC connections are not supported.";
|
||||
return;
|
||||
}
|
||||
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
// Route inbound WebRTC signaling messages received from user clients.
|
||||
connect(&_webrtcSignalingServer, &WebRTCSignalingServer::messageReceived,
|
||||
this, &DomainServer::routeWebRTCSignalingMessage);
|
||||
|
||||
// Route domain server signaling messages.
|
||||
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) {
|
||||
qWarning() << NodeType::getNodeTypeName(destinationNodeType) << "not found for WebRTC signaling message.";
|
||||
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
|
||||
|
||||
|
||||
bool DomainServer::resetAccountManagerAccessToken() {
|
||||
if (!_oauthProviderURL.isEmpty()) {
|
||||
// check for an access-token in our settings, can optionally be overidden by env value
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <Assignment.h>
|
||||
#include <HTTPSConnection.h>
|
||||
#include <LimitedNodeList.h>
|
||||
#include <shared/WebRTC.h>
|
||||
#include <webrtc/WebRTCSignalingServer.h>
|
||||
|
||||
#include "AssetsBackupHandler.h"
|
||||
#include "DomainGatekeeper.h"
|
||||
|
@ -148,6 +150,10 @@ private slots:
|
|||
void tokenGrantFinished();
|
||||
void profileRequestFinished();
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void forwardAssignmentClientSignalingMessageToUserClient(QSharedPointer<ReceivedMessage> message);
|
||||
#endif
|
||||
|
||||
void aboutToQuit();
|
||||
|
||||
signals:
|
||||
|
@ -155,6 +161,12 @@ signals:
|
|||
void userConnected();
|
||||
void userDisconnected();
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void webrtcSignalingMessageForDomainServer(const QJsonObject& json);
|
||||
void webrtcSignalingMessageForUserClient(const QJsonObject& json);
|
||||
#endif
|
||||
|
||||
|
||||
private:
|
||||
QUuid getID();
|
||||
|
||||
|
@ -235,6 +247,12 @@ private:
|
|||
std::initializer_list<QString> optionalData = { },
|
||||
bool requireAccessToken = true);
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
void setUpWebRTCSignalingServer();
|
||||
void routeWebRTCSignalingMessage(const QJsonObject& json);
|
||||
void sendWebRTCSignalingMessageToAssignmentClient(const QJsonObject& json);
|
||||
#endif
|
||||
|
||||
QString operationToString(const QNetworkAccessManager::Operation &op);
|
||||
|
||||
SubnetList _acSubnetWhitelist;
|
||||
|
@ -312,6 +330,10 @@ private:
|
|||
std::unordered_map<int, std::unique_ptr<QTemporaryFile>> _pendingContentFiles;
|
||||
|
||||
QThread _assetClientThread;
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
WebRTCSignalingServer _webrtcSignalingServer;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
|
|
@ -3,14 +3,16 @@
|
|||
// libraries/networking/src
|
||||
//
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
#include "BaseAssetScriptingInterface.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QMimeDatabase>
|
||||
#include <QThread>
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ static Setting::Handle<quint16> LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.Loc
|
|||
using namespace std::chrono_literals;
|
||||
static const std::chrono::milliseconds CONNECTION_RATE_INTERVAL_MS = 1s;
|
||||
|
||||
LimitedNodeList::LimitedNodeList(char ownerType, int socketListenPort, int dtlsListenPort) :
|
||||
_nodeSocket(this, true, ownerType),
|
||||
LimitedNodeList::LimitedNodeList(int socketListenPort, int dtlsListenPort) :
|
||||
_nodeSocket(this, true),
|
||||
_packetReceiver(new PacketReceiver(this))
|
||||
{
|
||||
qRegisterMetaType<ConnectionStep>("ConnectionStep");
|
||||
|
@ -74,7 +74,7 @@ LimitedNodeList::LimitedNodeList(char ownerType, int socketListenPort, int dtlsL
|
|||
qCDebug(networking) << "NodeList DTLS socket is listening on" << _dtlsSocket->localPort();
|
||||
}
|
||||
|
||||
_nodeSocket.bind(SocketType::WebRTC, QHostAddress::AnyIPv4, DEFAULT_DOMAIN_SERVER_WS_PORT);
|
||||
_nodeSocket.bind(SocketType::WebRTC, QHostAddress::AnyIPv4);
|
||||
|
||||
// check for local socket updates every so often
|
||||
const int LOCAL_SOCKET_UPDATE_INTERVAL_MSECS = 5 * 1000;
|
||||
|
@ -241,6 +241,12 @@ QUdpSocket& LimitedNodeList::getDTLSSocket() {
|
|||
return *_dtlsSocket;
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
const WebRTCSocket* LimitedNodeList::getWebRTCSocket() {
|
||||
return _nodeSocket.getWebRTCSocket();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool LimitedNodeList::isPacketVerifiedWithSource(const udt::Packet& packet, Node* sourceNode) {
|
||||
// We track bandwidth when doing packet verification to avoid needing to do a node lookup
|
||||
// later when we already do it in packetSourceAndHashMatchAndTrackBandwidth. A node lookup
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "DomainHandler.h"
|
||||
#include "NetworkingConstants.h"
|
||||
#include "Node.h"
|
||||
#include "NLPacket.h"
|
||||
|
@ -139,6 +138,10 @@ public:
|
|||
Q_INVOKABLE void setSocketLocalPort(SocketType socketType, quint16 socketLocalPort);
|
||||
|
||||
QUdpSocket& getDTLSSocket();
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
const WebRTCSocket* getWebRTCSocket();
|
||||
#endif
|
||||
|
||||
|
||||
PacketReceiver& getPacketReceiver() { return *_packetReceiver; }
|
||||
|
||||
|
@ -413,8 +416,7 @@ protected:
|
|||
QUuid connectionSecretUUID;
|
||||
};
|
||||
|
||||
LimitedNodeList(char ownerType = NodeType::DomainServer, int socketListenPort = INVALID_PORT,
|
||||
int dtlsListenPort = INVALID_PORT);
|
||||
LimitedNodeList(int socketListenPort = INVALID_PORT, int dtlsListenPort = INVALID_PORT);
|
||||
LimitedNodeList(LimitedNodeList const&) = delete; // Don't implement, needed to avoid copies of singleton
|
||||
void operator=(LimitedNodeList const&) = delete; // Don't implement, needed to avoid copies of singleton
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ void NetworkPeer::setActiveSocket(SockAddr* discoveredSocket) {
|
|||
// we have an active socket, stop our ping timer
|
||||
stopPingTimer();
|
||||
|
||||
// we're now considered connected to this peer - reset the number of connection attemps
|
||||
// we're now considered connected to this peer - reset the number of connection attempts
|
||||
resetConnectionAttempts();
|
||||
|
||||
if (_activeSocket) {
|
||||
|
|
|
@ -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) :
|
||||
|
|
|
@ -50,7 +50,7 @@ const int KEEPALIVE_PING_INTERVAL_MS = 1000;
|
|||
const int MAX_SYSTEM_INFO_SIZE = 1000;
|
||||
|
||||
NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) :
|
||||
LimitedNodeList(newOwnerType, socketListenPort, dtlsListenPort),
|
||||
LimitedNodeList(socketListenPort, dtlsListenPort),
|
||||
_ownerType(newOwnerType),
|
||||
_nodeTypesOfInterest(),
|
||||
_domainHandler(this),
|
||||
|
|
|
@ -154,7 +154,7 @@ private slots:
|
|||
void maybeSendIgnoreSetToNode(SharedNodePointer node);
|
||||
|
||||
private:
|
||||
NodeList() : LimitedNodeList(NodeType::Unassigned, INVALID_PORT, INVALID_PORT) {
|
||||
NodeList() : LimitedNodeList(INVALID_PORT, INVALID_PORT) {
|
||||
assert(false); // Not implemented, needed for DependencyManager templates compile
|
||||
}
|
||||
NodeList(char ownerType, int socketListenPort = INVALID_PORT, int dtlsListenPort = INVALID_PORT);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
#include "../NetworkLogging.h"
|
||||
|
||||
|
||||
NetworkSocket::NetworkSocket(QObject* parent, NodeType_t nodeType) :
|
||||
NetworkSocket::NetworkSocket(QObject* parent) :
|
||||
QObject(parent),
|
||||
_parent(parent),
|
||||
_udpSocket(this)
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
,
|
||||
_webrtcSocket(this, nodeType)
|
||||
_webrtcSocket(this)
|
||||
#endif
|
||||
{
|
||||
connect(&_udpSocket, &QUdpSocket::readyRead, this, &NetworkSocket::readyRead);
|
||||
|
@ -267,6 +267,13 @@ QString NetworkSocket::errorString(SocketType socketType) const {
|
|||
}
|
||||
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
const WebRTCSocket* NetworkSocket::getWebRTCSocket() {
|
||||
return &_webrtcSocket;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void NetworkSocket::onUDPStateChanged(QAbstractSocket::SocketState socketState) {
|
||||
emit stateChanged(SocketType::UDP, socketState);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,7 @@ public:
|
|||
|
||||
/// @brief Constructs a new NetworkSocket object.
|
||||
/// @param parent Qt parent object.
|
||||
/// @param nodeType The type of node that the NetworkSocket object is being used in.
|
||||
NetworkSocket(QObject* parent, NodeType_t nodeType);
|
||||
NetworkSocket(QObject* parent);
|
||||
|
||||
|
||||
/// @brief Set the value of a UDP or WebRTC socket option.
|
||||
|
@ -91,7 +90,7 @@ public:
|
|||
bool hasPendingDatagrams() const;
|
||||
|
||||
/// @brief Gets the size of the next pending datagram, alternating between socket types if both have datagrams to read.
|
||||
/// @return The size of the next pendign datagram.
|
||||
/// @return The size of the next pending datagram.
|
||||
qint64 pendingDatagramSize();
|
||||
|
||||
/// @brief Reads the next datagram per the most recent pendingDatagramSize call if made, otherwise alternating between
|
||||
|
@ -111,7 +110,7 @@ public:
|
|||
|
||||
/// @brief Gets the type of error that last occurred.
|
||||
/// @param socketType The type of socket for which to get the last error.
|
||||
/// @return The type of error that last occurred
|
||||
/// @return The type of error that last occurred.
|
||||
QAbstractSocket::SocketError error(SocketType socketType) const;
|
||||
|
||||
/// @brief Gets the description of the error that last occurred.
|
||||
|
@ -119,6 +118,13 @@ public:
|
|||
/// @return The description of the error that last occurred.
|
||||
QString errorString(SocketType socketType) const;
|
||||
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
/// @brief Gets a pointer to the WebRTC socket object.
|
||||
/// @return A pointer to the WebRTC socket object.
|
||||
const WebRTCSocket* getWebRTCSocket();
|
||||
#endif
|
||||
|
||||
signals:
|
||||
|
||||
/// @brief Emitted each time new data becomes available for reading.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ using namespace udt;
|
|||
#endif
|
||||
|
||||
|
||||
Socket::Socket(QObject* parent, bool shouldChangeSocketOptions, NodeType_t nodeType) :
|
||||
Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) :
|
||||
QObject(parent),
|
||||
_networkSocket(parent, nodeType),
|
||||
_networkSocket(parent),
|
||||
_readyReadBackupTimer(new QTimer(this)),
|
||||
_shouldChangeSocketOptions(shouldChangeSocketOptions)
|
||||
{
|
||||
|
@ -91,6 +91,12 @@ void Socket::rebind(SocketType socketType, quint16 localPort) {
|
|||
bind(socketType, QHostAddress::AnyIPv4, localPort);
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
const WebRTCSocket* Socket::getWebRTCSocket() {
|
||||
return _networkSocket.getWebRTCSocket();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Socket::setSystemBufferSizes(SocketType socketType) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
QAbstractSocket::SocketOption bufferOpt;
|
||||
|
|
|
@ -55,8 +55,8 @@ class Socket : public QObject {
|
|||
|
||||
public:
|
||||
using StatsVector = std::vector<std::pair<SockAddr, ConnectionStats::Stats>>;
|
||||
|
||||
Socket(QObject* object = 0, bool shouldChangeSocketOptions = true, NodeType_t nodeType = NodeType::Unassigned);
|
||||
|
||||
Socket(QObject* object = 0, bool shouldChangeSocketOptions = true);
|
||||
|
||||
quint16 localPort(SocketType socketType) const { return _networkSocket.localPort(socketType); }
|
||||
|
||||
|
@ -90,6 +90,10 @@ public:
|
|||
|
||||
StatsVector sampleStatsForAllConnections();
|
||||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
const WebRTCSocket* getWebRTCSocket();
|
||||
#endif
|
||||
|
||||
#if (PR_BUILD || DEV_BUILD)
|
||||
void sendFakedHandshakeRequest(const SockAddr& sockAddr);
|
||||
#endif
|
||||
|
|
|
@ -373,13 +373,12 @@ void WDCConnection::closePeerConnection() {
|
|||
}
|
||||
|
||||
|
||||
WebRTCDataChannels::WebRTCDataChannels(QObject* parent, NodeType_t nodeType) :
|
||||
WebRTCDataChannels::WebRTCDataChannels(QObject* parent) :
|
||||
QObject(parent),
|
||||
_parent(parent),
|
||||
_nodeType(nodeType)
|
||||
_parent(parent)
|
||||
{
|
||||
#ifdef WEBRTC_DEBUG
|
||||
qCDebug(networking_webrtc) << "WebRTCDataChannels::WebRTCDataChannels()" << nodeType << NodeType::getNodeTypeName(nodeType);
|
||||
qCDebug(networking_webrtc) << "WebRTCDataChannels::WebRTCDataChannels()";
|
||||
#endif
|
||||
|
||||
// Create a peer connection factory.
|
||||
|
@ -452,12 +451,18 @@ void WebRTCDataChannels::onSignalingMessage(const QJsonObject& message) {
|
|||
const int MAX_DEBUG_DETAIL_LENGTH = 64;
|
||||
auto data = message.value("data").isObject() ? message.value("data").toObject() : QJsonObject();
|
||||
int from = message.value("from").isDouble() ? (quint16)(message.value("from").toInt()) : 0;
|
||||
if (from <= 0 || from > MAXUINT16 || !data.contains("description") && !data.contains("candidate")) {
|
||||
auto to = NodeType::fromChar(message.value("to").toString().at(0));
|
||||
|
||||
if (from <= 0 || from > MAXUINT16 || to == NodeType::Unassigned
|
||||
|| !data.contains("description") && !data.contains("candidate")) {
|
||||
qCWarning(networking_webrtc) << "Unexpected signaling message:"
|
||||
<< QJsonDocument(message).toJson(QJsonDocument::Compact).left(MAX_DEBUG_DETAIL_LENGTH);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember this node's type for the reply.
|
||||
_nodeType = to;
|
||||
|
||||
// Find or create a connection.
|
||||
WDCConnection* connection;
|
||||
if (_connectionsByWebSocket.contains(from)) {
|
||||
|
|
|
@ -227,8 +227,7 @@ public:
|
|||
|
||||
/// @brief Constructs a new WebRTCDataChannels object.
|
||||
/// @param parent The parent Qt object.
|
||||
/// @param nodeType The type of node that the WebRTCDataChannels object is being used in.
|
||||
WebRTCDataChannels(QObject* parent, NodeType_t nodeType);
|
||||
WebRTCDataChannels(QObject* parent);
|
||||
|
||||
/// @brief Destroys a WebRTCDataChannels object.
|
||||
~WebRTCDataChannels();
|
||||
|
@ -319,7 +318,7 @@ private:
|
|||
|
||||
QObject* _parent;
|
||||
|
||||
NodeType_t _nodeType;
|
||||
NodeType_t _nodeType { NodeType::Unassigned };
|
||||
|
||||
std::unique_ptr<rtc::Thread> _rtcNetworkThread { nullptr };
|
||||
std::unique_ptr<rtc::Thread> _rtcWorkerThread { nullptr };
|
||||
|
|
|
@ -10,20 +10,19 @@
|
|||
|
||||
#if defined(WEBRTC_DATA_CHANNELS)
|
||||
|
||||
#include <QHostAddress>
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
#include "../udt/Constants.h"
|
||||
|
||||
|
||||
WebRTCSocket::WebRTCSocket(QObject* parent, NodeType_t nodeType) :
|
||||
WebRTCSocket::WebRTCSocket(QObject* parent) :
|
||||
QObject(parent),
|
||||
_signalingServer(this /*, QHostAddress::AnyIPv4, DEFAULT_DOMAIN_SERVER_WS_PORT*/),
|
||||
_dataChannels(this, nodeType)
|
||||
_dataChannels(this)
|
||||
{
|
||||
// Connect WebRTC signaling server and data channels.
|
||||
connect(&_signalingServer, &WebRTCSignalingServer::messageReceived,
|
||||
&_dataChannels, &WebRTCDataChannels::onSignalingMessage);
|
||||
connect(&_dataChannels, &WebRTCDataChannels::signalingMessage,
|
||||
&_signalingServer, &WebRTCSignalingServer::sendMessage);
|
||||
// Route signaling messages.
|
||||
connect(this, &WebRTCSocket::onSignalingMessage, &_dataChannels, &WebRTCDataChannels::onSignalingMessage);
|
||||
connect(&_dataChannels, &WebRTCDataChannels::signalingMessage, this, &WebRTCSocket::sendSignalingMessage);
|
||||
|
||||
// Route received data channel messages.
|
||||
connect(&_dataChannels, &WebRTCDataChannels::dataMessage, this, &WebRTCSocket::onDataChannelReceivedMessage);
|
||||
|
@ -63,7 +62,7 @@ QVariant WebRTCSocket::socketOption(QAbstractSocket::SocketOption option) {
|
|||
bool WebRTCSocket::bind(const QHostAddress& address, quint16 port, QAbstractSocket::BindMode mode) {
|
||||
// WebRTC data channels aren't bound to ports so just treat this as a successful operation.
|
||||
auto wasBound = _isBound;
|
||||
_isBound = _signalingServer.bind(address, port);
|
||||
_isBound = true;
|
||||
if (_isBound != wasBound) {
|
||||
emit stateChanged(_isBound ? QAbstractSocket::BoundState : QAbstractSocket::UnconnectedState);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <QQueue>
|
||||
|
||||
#include "WebRTCDataChannels.h"
|
||||
#include "WebRTCSignalingServer.h"
|
||||
|
||||
/// @addtogroup Networking
|
||||
/// @{
|
||||
|
@ -32,8 +31,7 @@ public:
|
|||
|
||||
/// @brief Constructs a new WebRTCSocket object.
|
||||
/// @param parent Qt parent object.
|
||||
/// @param nodeType The type of node that the WebRTCsocket object is being used in.
|
||||
WebRTCSocket(QObject* parent, NodeType_t nodeType);
|
||||
WebRTCSocket(QObject* parent);
|
||||
|
||||
|
||||
/// @brief Nominally sets the value of a socket option.
|
||||
|
@ -52,13 +50,14 @@ public:
|
|||
/// @return The value of the socket option.
|
||||
QVariant socketOption(QAbstractSocket::SocketOption option);
|
||||
|
||||
/// @brief Binds the WebRTC socket's signaling server to an address and port.
|
||||
/// @details Note: WebRTC data connections aren't bound to an address or port. Their ports are negotiated as part of the
|
||||
/// @brief Nominally binds the WebRTC socket to an address and port.
|
||||
/// @details WebRTC data connections aren't actually bound to an address or port. Their ports are negotiated as part of the
|
||||
/// WebRTC peer connection process.
|
||||
/// @param address The address to use for the signaling server.
|
||||
/// @param port The port to use for the signaling server.
|
||||
/// @param mode The bind mode. (Not used: included for compatibility with the QUdpSocket interface.)
|
||||
/// @return <code>true</code> if the signaling server was successfully bound, <code>false</code> if it wasn't.
|
||||
/// Included for compatibility with the QUdpSocket interface.
|
||||
/// @param address The address.
|
||||
/// @param port The port.
|
||||
/// @param mode The bind mode.
|
||||
/// @return <code>true</code>.
|
||||
bool bind(const QHostAddress& address, quint16 port = 0, QAbstractSocket::BindMode mode
|
||||
= QAbstractSocket::DefaultForPlatform);
|
||||
|
||||
|
@ -132,17 +131,26 @@ public slots:
|
|||
signals:
|
||||
|
||||
/// @brief Emitted when the state of the socket changes.
|
||||
/// @param socketState The new state of the socket.
|
||||
void stateChanged(QAbstractSocket::SocketState socketState);
|
||||
|
||||
/// @brief Emitted each time new data becomes available for reading.
|
||||
void readyRead();
|
||||
|
||||
/// @brief Emitted when a WebRTC signaling message has been received from the signaling server for this WebRTCSocket.
|
||||
/// @param json The signaling message.
|
||||
void onSignalingMessage(const QJsonObject& json);
|
||||
|
||||
/// @brief Emitted when there's a WebRTC signaling message to send via the signaling server.
|
||||
/// @param json The signaling message.
|
||||
void sendSignalingMessage(const QJsonObject& message);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void setError(QAbstractSocket::SocketError errorType, QString errorString);
|
||||
void clearError();
|
||||
|
||||
WebRTCSignalingServer _signalingServer;
|
||||
WebRTCDataChannels _dataChannels;
|
||||
|
||||
bool _isBound { false };
|
||||
|
|
Loading…
Reference in a new issue