mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 20:58:38 +02:00
Merge pull request #1429 from ctrlaltdavid/dev/webrtc-revisions
WebRTC revisions and updates including the addition of secure connections.
This commit is contained in:
commit
66fe21e413
9 changed files with 196 additions and 38 deletions
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": 2.5,
|
"version": 2.6,
|
||||||
"settings": [
|
"settings": [
|
||||||
{
|
{
|
||||||
"name": "metaverse",
|
"name": "metaverse",
|
||||||
|
@ -73,6 +73,28 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "webrtc",
|
||||||
|
"label": "Networking / WebRTC",
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "enable_webrtc",
|
||||||
|
"label": "Enable WebRTC Client Connections",
|
||||||
|
"help": "Allow web clients to connect over WebRTC data channels.",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false,
|
||||||
|
"advanced": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enable_webrtc_websocket_ssl",
|
||||||
|
"label": "Enable WebRTC WebSocket SSL",
|
||||||
|
"help": "Use secure WebSocket (wss:// protocol) for WebRTC signaling channel. If \"on\", the key, cert, and CA files are expected to be in the local Vircadia app directory, in a /domain-server/ subdirectory with filenames vircadia-cert.key, vircadia-cert.crt, and vircadia-crt-ca.crt.",
|
||||||
|
"type": "checkbox",
|
||||||
|
"default": false,
|
||||||
|
"advanced": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "authentication",
|
"name": "authentication",
|
||||||
"label": "Networking / WordPress OAuth2",
|
"label": "Networking / WordPress OAuth2",
|
||||||
|
|
|
@ -196,10 +196,6 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
_gatekeeper(this),
|
_gatekeeper(this),
|
||||||
_httpManager(QHostAddress::AnyIPv4, DOMAIN_SERVER_HTTP_PORT,
|
_httpManager(QHostAddress::AnyIPv4, DOMAIN_SERVER_HTTP_PORT,
|
||||||
QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this)
|
QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this)
|
||||||
#if defined(WEBRTC_DATA_CHANNELS)
|
|
||||||
,
|
|
||||||
_webrtcSignalingServer(this)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (_parentPID != -1) {
|
if (_parentPID != -1) {
|
||||||
watchParentProcess(_parentPID);
|
watchParentProcess(_parentPID);
|
||||||
|
@ -275,6 +271,20 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
|
|
||||||
_settingsManager.apiRefreshGroupInformation();
|
_settingsManager.apiRefreshGroupInformation();
|
||||||
|
|
||||||
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
|
const QString WEBRTC_ENABLE = "webrtc.enable_webrtc";
|
||||||
|
bool isWebRTCEnabled = _settingsManager.valueForKeyPath(WEBRTC_ENABLE).toBool();
|
||||||
|
qCDebug(domain_server) << "WebRTC enabled:" << isWebRTCEnabled;
|
||||||
|
// The domain server's WebRTC signaling server is used by the domain server and the assignment clients, so disabling it
|
||||||
|
// disables WebRTC for the server as a whole.
|
||||||
|
if (isWebRTCEnabled) {
|
||||||
|
const QString WEBRTC_WSS_ENABLE = "webrtc.enable_webrtc_websocket_ssl";
|
||||||
|
bool isWebRTCEnabled = _settingsManager.valueForKeyPath(WEBRTC_WSS_ENABLE).toBool();
|
||||||
|
qCDebug(domain_server) << "WebRTC WSS enabled:" << isWebRTCEnabled;
|
||||||
|
_webrtcSignalingServer.reset(new WebRTCSignalingServer(this, isWebRTCEnabled));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
setupNodeListAndAssignments();
|
setupNodeListAndAssignments();
|
||||||
|
|
||||||
updateReplicatedNodes();
|
updateReplicatedNodes();
|
||||||
|
@ -282,7 +292,9 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
updateUpstreamNodes();
|
updateUpstreamNodes();
|
||||||
|
|
||||||
#if defined(WEBRTC_DATA_CHANNELS)
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
setUpWebRTCSignalingServer();
|
if (isWebRTCEnabled) {
|
||||||
|
setUpWebRTCSignalingServer();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_type != NonMetaverse) {
|
if (_type != NonMetaverse) {
|
||||||
|
@ -889,7 +901,7 @@ void DomainServer::setupNodeListAndAssignments() {
|
||||||
// Sets up the WebRTC signaling server that's hosted by the domain server.
|
// 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);
|
||||||
if (!isBound) {
|
if (!isBound) {
|
||||||
qWarning() << "WebRTC signaling server not bound to port. WebRTC connections are not supported.";
|
qWarning() << "WebRTC signaling server not bound to port. WebRTC connections are not supported.";
|
||||||
return;
|
return;
|
||||||
|
@ -898,13 +910,14 @@ void DomainServer::setUpWebRTCSignalingServer() {
|
||||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||||
|
|
||||||
// Route inbound WebRTC signaling messages received from user clients.
|
// Route inbound WebRTC signaling messages received from user clients.
|
||||||
connect(&_webrtcSignalingServer, &WebRTCSignalingServer::messageReceived,
|
connect(_webrtcSignalingServer.get(), &WebRTCSignalingServer::messageReceived,
|
||||||
this, &DomainServer::routeWebRTCSignalingMessage);
|
this, &DomainServer::routeWebRTCSignalingMessage);
|
||||||
|
|
||||||
// Route domain server signaling messages.
|
// Route domain server signaling messages.
|
||||||
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.get(), &WebRTCSignalingServer::sendMessage);
|
||||||
|
|
||||||
// Forward signaling messages received from assignment clients to user client.
|
// Forward signaling messages received from assignment clients to user client.
|
||||||
PacketReceiver& packetReceiver = limitedNodeList->getPacketReceiver();
|
PacketReceiver& packetReceiver = limitedNodeList->getPacketReceiver();
|
||||||
|
@ -912,7 +925,7 @@ void DomainServer::setUpWebRTCSignalingServer() {
|
||||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this,
|
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this,
|
||||||
&DomainServer::forwardAssignmentClientSignalingMessageToUserClient));
|
&DomainServer::forwardAssignmentClientSignalingMessageToUserClient));
|
||||||
connect(this, &DomainServer::webrtcSignalingMessageForUserClient,
|
connect(this, &DomainServer::webrtcSignalingMessageForUserClient,
|
||||||
&_webrtcSignalingServer, &WebRTCSignalingServer::sendMessage);
|
_webrtcSignalingServer.get(), &WebRTCSignalingServer::sendMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routes an inbound WebRTC signaling message received from a client app to the appropriate recipient.
|
// Routes an inbound WebRTC signaling message received from a client app to the appropriate recipient.
|
||||||
|
|
|
@ -333,7 +333,7 @@ private:
|
||||||
QThread _assetClientThread;
|
QThread _assetClientThread;
|
||||||
|
|
||||||
#if defined(WEBRTC_DATA_CHANNELS)
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
WebRTCSignalingServer _webrtcSignalingServer;
|
std::unique_ptr<WebRTCSignalingServer> _webrtcSignalingServer { nullptr };
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -551,6 +551,8 @@ void DomainServerSettingsManager::setupConfigMap(const QString& userConfigFilena
|
||||||
packPermissions();
|
packPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No migration needed to version 2.6.
|
||||||
|
|
||||||
// write the current description version to our settings
|
// write the current description version to our settings
|
||||||
*versionVariant = _descriptionVersion;
|
*versionVariant = _descriptionVersion;
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,11 @@ void OtherAvatar::removeOrb() {
|
||||||
void OtherAvatar::updateOrbPosition() {
|
void OtherAvatar::updateOrbPosition() {
|
||||||
if (!_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
if (!_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||||
EntityItemProperties properties;
|
EntityItemProperties properties;
|
||||||
properties.setPosition(getHead()->getPosition());
|
glm::vec3 headPosition;
|
||||||
|
if (!_skeletonModel->getHeadPosition(headPosition)) {
|
||||||
|
headPosition = getWorldPosition();
|
||||||
|
}
|
||||||
|
properties.setPosition(headPosition);
|
||||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_otherAvatarOrbMeshPlaceholderID, properties);
|
DependencyManager::get<EntityScriptingInterface>()->editEntity(_otherAvatarOrbMeshPlaceholderID, properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,12 @@
|
||||||
// - https://webrtc.github.io/webrtc-org/native-code/native-apis/
|
// - https://webrtc.github.io/webrtc-org/native-code/native-apis/
|
||||||
// - https://webrtc.googlesource.com/src/+/master/api/peer_connection_interface.h
|
// - https://webrtc.googlesource.com/src/+/master/api/peer_connection_interface.h
|
||||||
|
|
||||||
const std::string ICE_SERVER_URI = "stun://ice.vircadia.com:7337";
|
// FIXME: stun:ice.vircadia.com:7337 doesn't work for WebRTC.
|
||||||
|
// Firefox warns: "WebRTC: Using more than two STUN/TURN servers slows down discovery"
|
||||||
|
const std::list<std::string> ICE_SERVER_URIS = {
|
||||||
|
"stun:stun1.l.google.com:19302",
|
||||||
|
"stun:stun.schlund.de"
|
||||||
|
};
|
||||||
const int MAX_WEBRTC_BUFFER_SIZE = 16777216; // 16MB
|
const int MAX_WEBRTC_BUFFER_SIZE = 16777216; // 16MB
|
||||||
|
|
||||||
// #define WEBRTC_DEBUG
|
// #define WEBRTC_DEBUG
|
||||||
|
@ -66,7 +71,7 @@ WDCPeerConnectionObserver::WDCPeerConnectionObserver(WDCConnection* parent) :
|
||||||
|
|
||||||
void WDCPeerConnectionObserver::OnSignalingChange(PeerConnectionInterface::SignalingState newState) {
|
void WDCPeerConnectionObserver::OnSignalingChange(PeerConnectionInterface::SignalingState newState) {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
QStringList states{
|
QStringList states {
|
||||||
"Stable",
|
"Stable",
|
||||||
"HaveLocalOffer",
|
"HaveLocalOffer",
|
||||||
"HaveLocalPrAnswer",
|
"HaveLocalPrAnswer",
|
||||||
|
@ -74,7 +79,7 @@ void WDCPeerConnectionObserver::OnSignalingChange(PeerConnectionInterface::Signa
|
||||||
"HaveRemotePrAnswer",
|
"HaveRemotePrAnswer",
|
||||||
"Closed"
|
"Closed"
|
||||||
};
|
};
|
||||||
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnSignalingChange()" << newState << states[newState];
|
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnSignalingChange() :" << newState << states[newState];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +91,12 @@ void WDCPeerConnectionObserver::OnRenegotiationNeeded() {
|
||||||
|
|
||||||
void WDCPeerConnectionObserver::OnIceGatheringChange(PeerConnectionInterface::IceGatheringState newState) {
|
void WDCPeerConnectionObserver::OnIceGatheringChange(PeerConnectionInterface::IceGatheringState newState) {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnIceGatheringChange()" << newState;
|
QStringList states {
|
||||||
|
"New",
|
||||||
|
"Gathering",
|
||||||
|
"Complete"
|
||||||
|
};
|
||||||
|
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnIceGatheringChange() :" << newState << states[newState];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +107,39 @@ void WDCPeerConnectionObserver::OnIceCandidate(const IceCandidateInterface* cand
|
||||||
_parent->sendIceCandidate(candidate);
|
_parent->sendIceCandidate(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WDCPeerConnectionObserver::OnIceConnectionChange(PeerConnectionInterface::IceConnectionState newState) {
|
||||||
|
#ifdef WEBRTC_DEBUG
|
||||||
|
QStringList states {
|
||||||
|
"New",
|
||||||
|
"Checking",
|
||||||
|
"Connected",
|
||||||
|
"Completed",
|
||||||
|
"Failed",
|
||||||
|
"Disconnected",
|
||||||
|
"Closed",
|
||||||
|
"Max"
|
||||||
|
};
|
||||||
|
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnIceConnectionChange() :" << newState << states[newState];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void WDCPeerConnectionObserver::OnStandardizedIceConnectionChange(PeerConnectionInterface::IceConnectionState newState) {
|
||||||
|
#ifdef WEBRTC_DEBUG
|
||||||
|
QStringList states {
|
||||||
|
"New",
|
||||||
|
"Checking",
|
||||||
|
"Connected",
|
||||||
|
"Completed",
|
||||||
|
"Failed",
|
||||||
|
"Disconnected",
|
||||||
|
"Closed",
|
||||||
|
"Max"
|
||||||
|
};
|
||||||
|
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnStandardizedIceConnectionChange() :" << newState
|
||||||
|
<< states[newState];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void WDCPeerConnectionObserver::OnDataChannel(rtc::scoped_refptr<DataChannelInterface> dataChannel) {
|
void WDCPeerConnectionObserver::OnDataChannel(rtc::scoped_refptr<DataChannelInterface> dataChannel) {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnDataChannel()";
|
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnDataChannel()";
|
||||||
|
@ -106,7 +149,16 @@ void WDCPeerConnectionObserver::OnDataChannel(rtc::scoped_refptr<DataChannelInte
|
||||||
|
|
||||||
void WDCPeerConnectionObserver::OnConnectionChange(PeerConnectionInterface::PeerConnectionState newState) {
|
void WDCPeerConnectionObserver::OnConnectionChange(PeerConnectionInterface::PeerConnectionState newState) {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnConnectionChange()" << (uint)newState;
|
QStringList states {
|
||||||
|
"New",
|
||||||
|
"Connecting",
|
||||||
|
"Connected",
|
||||||
|
"Disconnected",
|
||||||
|
"Failed",
|
||||||
|
"Closed"
|
||||||
|
};
|
||||||
|
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnConnectionChange() :" << (uint)newState
|
||||||
|
<< states[(uint)newState];
|
||||||
#endif
|
#endif
|
||||||
_parent->onPeerConnectionStateChanged(newState);
|
_parent->onPeerConnectionStateChanged(newState);
|
||||||
}
|
}
|
||||||
|
@ -262,7 +314,7 @@ void WDCConnection::sendIceCandidate(const IceCandidateInterface* candidate) {
|
||||||
|
|
||||||
void WDCConnection::onPeerConnectionStateChanged(PeerConnectionInterface::PeerConnectionState state) {
|
void WDCConnection::onPeerConnectionStateChanged(PeerConnectionInterface::PeerConnectionState state) {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
const char* STATES[] = {
|
QStringList states {
|
||||||
"New",
|
"New",
|
||||||
"Connecting",
|
"Connecting",
|
||||||
"Connected",
|
"Connected",
|
||||||
|
@ -270,7 +322,7 @@ void WDCConnection::onPeerConnectionStateChanged(PeerConnectionInterface::PeerCo
|
||||||
"Failed",
|
"Failed",
|
||||||
"Closed"
|
"Closed"
|
||||||
};
|
};
|
||||||
qCDebug(networking_webrtc) << "WDCConnection::onPeerConnectionStateChanged() :" << (int)state << STATES[(int)state];
|
qCDebug(networking_webrtc) << "WDCConnection::onPeerConnectionStateChanged() :" << (int)state << states[(int)state];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,13 +355,11 @@ void WDCConnection::onDataChannelStateChanged() {
|
||||||
<< DataChannelInterface::DataStateString(state);
|
<< DataChannelInterface::DataStateString(state);
|
||||||
#endif
|
#endif
|
||||||
if (state == DataChannelInterface::kClosed) {
|
if (state == DataChannelInterface::kClosed) {
|
||||||
// Close data channel.
|
// Finish with the data channel.
|
||||||
_dataChannel->UnregisterObserver();
|
_dataChannel->UnregisterObserver();
|
||||||
|
// Don't set _dataChannel = nullptr because it is a scoped_refptr.
|
||||||
_dataChannelObserver = nullptr;
|
_dataChannelObserver = nullptr;
|
||||||
_dataChannel = nullptr;
|
|
||||||
#ifdef WEBRTC_DEBUG
|
|
||||||
qCDebug(networking_webrtc) << "Disposed of data channel";
|
|
||||||
#endif
|
|
||||||
// Close peer connection.
|
// Close peer connection.
|
||||||
_parent->closePeerConnection(this);
|
_parent->closePeerConnection(this);
|
||||||
}
|
}
|
||||||
|
@ -344,17 +394,21 @@ qint64 WDCConnection::getBufferedAmount() const {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "WDCConnection::getBufferedAmount()";
|
qCDebug(networking_webrtc) << "WDCConnection::getBufferedAmount()";
|
||||||
#endif
|
#endif
|
||||||
return _dataChannel ? _dataChannel->buffered_amount() : 0;
|
return _dataChannel && _dataChannel->state() != DataChannelInterface::kClosing
|
||||||
|
&& _dataChannel->state() != DataChannelInterface::kClosed
|
||||||
|
? _dataChannel->buffered_amount() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WDCConnection::sendDataMessage(const DataBuffer& buffer) {
|
bool WDCConnection::sendDataMessage(const DataBuffer& buffer) {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "WDCConnection::sendDataMessage()";
|
qCDebug(networking_webrtc) << "WDCConnection::sendDataMessage()";
|
||||||
if (!_dataChannel) {
|
if (!_dataChannel || _dataChannel->state() == DataChannelInterface::kClosing
|
||||||
|
|| _dataChannel->state() == DataChannelInterface::kClosed) {
|
||||||
qCDebug(networking_webrtc) << "No data channel to send on";
|
qCDebug(networking_webrtc) << "No data channel to send on";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!_dataChannel) {
|
if (!_dataChannel || _dataChannel->state() == DataChannelInterface::kClosing
|
||||||
|
|| _dataChannel->state() == DataChannelInterface::kClosed) {
|
||||||
// Data channel may have been closed while message to send was being prepared.
|
// Data channel may have been closed while message to send was being prepared.
|
||||||
return false;
|
return false;
|
||||||
} else if (_dataChannel->buffered_amount() + buffer.size() > MAX_WEBRTC_BUFFER_SIZE) {
|
} else if (_dataChannel->buffered_amount() + buffer.size() > MAX_WEBRTC_BUFFER_SIZE) {
|
||||||
|
@ -367,10 +421,10 @@ bool WDCConnection::sendDataMessage(const DataBuffer& buffer) {
|
||||||
|
|
||||||
void WDCConnection::closePeerConnection() {
|
void WDCConnection::closePeerConnection() {
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "WDCConnection::closePeerConnection()";
|
qCDebug(networking_webrtc) << "WDCConnection::closePeerConnection() :" << (int)_peerConnection->peer_connection_state();
|
||||||
#endif
|
#endif
|
||||||
_peerConnection->Close();
|
_peerConnection->Close();
|
||||||
_peerConnection = nullptr;
|
// Don't set _peerConnection = nullptr because it is a scoped_refptr.
|
||||||
_peerConnectionObserver = nullptr;
|
_peerConnectionObserver = nullptr;
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "Disposed of peer connection";
|
qCDebug(networking_webrtc) << "Disposed of peer connection";
|
||||||
|
@ -425,6 +479,9 @@ WebRTCDataChannels::~WebRTCDataChannels() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRTCDataChannels::reset() {
|
void WebRTCDataChannels::reset() {
|
||||||
|
#ifdef WEBRTC_DEBUG
|
||||||
|
qCDebug(networking_webrtc) << "WebRTCDataChannels::reset() :" << _connectionsByID.count();
|
||||||
|
#endif
|
||||||
QHashIterator<QString, WDCConnection*> i(_connectionsByID);
|
QHashIterator<QString, WDCConnection*> i(_connectionsByID);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
i.next();
|
i.next();
|
||||||
|
@ -484,7 +541,8 @@ void WebRTCDataChannels::onSignalingMessage(const QJsonObject& message) {
|
||||||
|
|
||||||
// Add a remote ICE candidate.
|
// Add a remote ICE candidate.
|
||||||
if (data.contains("candidate")) {
|
if (data.contains("candidate")) {
|
||||||
connection->addIceCandidate(data);
|
auto candidate = data.value("candidate").toObject();
|
||||||
|
connection->addIceCandidate(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -545,9 +603,11 @@ rtc::scoped_refptr<PeerConnectionInterface> WebRTCDataChannels::createPeerConnec
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PeerConnectionInterface::RTCConfiguration configuration;
|
PeerConnectionInterface::RTCConfiguration configuration;
|
||||||
PeerConnectionInterface::IceServer iceServer;
|
for (const auto& uri : ICE_SERVER_URIS) {
|
||||||
iceServer.uri = ICE_SERVER_URI;
|
PeerConnectionInterface::IceServer iceServer;
|
||||||
configuration.servers.push_back(iceServer);
|
iceServer.uri = uri;
|
||||||
|
configuration.servers.push_back(iceServer);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WEBRTC_DEBUG
|
#ifdef WEBRTC_DEBUG
|
||||||
qCDebug(networking_webrtc) << "2. Create a new peer connection";
|
qCDebug(networking_webrtc) << "2. Create a new peer connection";
|
||||||
|
|
|
@ -88,6 +88,14 @@ public:
|
||||||
/// @param candidate The new ICE candidate.
|
/// @param candidate The new ICE candidate.
|
||||||
void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
|
void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
|
||||||
|
|
||||||
|
/// @brief Called when the legacy ICE connection state changes.
|
||||||
|
/// @param new_state The new ICE connection state.
|
||||||
|
virtual void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState newState) override;
|
||||||
|
|
||||||
|
/// @brief Called when the standards-compliant ICE connection state changes.
|
||||||
|
/// @param new_state The new ICE connection state.
|
||||||
|
virtual void OnStandardizedIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState newState) override;
|
||||||
|
|
||||||
/// @brief Called when a remote peer opens a data channel.
|
/// @brief Called when a remote peer opens a data channel.
|
||||||
/// @param dataChannel The data channel.
|
/// @param dataChannel The data channel.
|
||||||
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel) override;
|
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel) override;
|
||||||
|
|
|
@ -10,19 +10,66 @@
|
||||||
|
|
||||||
#if defined(WEBRTC_DATA_CHANNELS)
|
#if defined(WEBRTC_DATA_CHANNELS)
|
||||||
|
|
||||||
|
#include <QSslKey>
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QWebSocket>
|
#include <QWebSocket>
|
||||||
|
|
||||||
|
#include <BuildInfo.h>
|
||||||
|
#include <PathUtils.h>
|
||||||
|
|
||||||
#include "../NetworkLogging.h"
|
#include "../NetworkLogging.h"
|
||||||
#include "../NodeType.h"
|
#include "../NodeType.h"
|
||||||
|
|
||||||
|
|
||||||
const int WEBRTC_SOCKET_CHECK_INTERVAL_IN_MS = 30000;
|
const int WEBRTC_SOCKET_CHECK_INTERVAL_IN_MS = 30000;
|
||||||
|
|
||||||
WebRTCSignalingServer::WebRTCSignalingServer(QObject* parent) :
|
WebRTCSignalingServer::WebRTCSignalingServer(QObject* parent, bool isWSSEnabled) :
|
||||||
QObject(parent),
|
QObject(parent)
|
||||||
_webSocketServer(new QWebSocketServer(QStringLiteral("WebRTC Signaling Server"), QWebSocketServer::NonSecureMode, this))
|
|
||||||
{
|
{
|
||||||
|
if (isWSSEnabled) {
|
||||||
|
_webSocketServer = (new QWebSocketServer(QStringLiteral("WebRTC Signaling Server"), QWebSocketServer::SecureMode,
|
||||||
|
this));
|
||||||
|
|
||||||
|
auto dsDirPath = PathUtils::getAppLocalDataPath();
|
||||||
|
const QString KEY_FILENAME = "vircadia-cert.key";
|
||||||
|
const QString CRT_FILENAME = "vircadia-cert.crt";
|
||||||
|
const QString CA_CRT_FILENAME = "vircadia-cert-ca.crt";
|
||||||
|
qCDebug(networking_webrtc) << "WebSocket WSS key file:" << dsDirPath + KEY_FILENAME;
|
||||||
|
qCDebug(networking_webrtc) << "WebSocket WSS cert file:" << dsDirPath + CRT_FILENAME;
|
||||||
|
qCDebug(networking_webrtc) << "WebSocket WSS CA cert file:" << dsDirPath + CA_CRT_FILENAME;
|
||||||
|
|
||||||
|
QFile sslCaFile(dsDirPath + CA_CRT_FILENAME);
|
||||||
|
sslCaFile.open(QIODevice::ReadOnly);
|
||||||
|
QSslCertificate sslCaCertificate(&sslCaFile, QSsl::Pem);
|
||||||
|
sslCaFile.close();
|
||||||
|
|
||||||
|
QSslConfiguration sslConfiguration;
|
||||||
|
QFile sslCrtFile(dsDirPath + CRT_FILENAME);
|
||||||
|
sslCrtFile.open(QIODevice::ReadOnly);
|
||||||
|
QSslCertificate sslCertificate(&sslCrtFile, QSsl::Pem);
|
||||||
|
sslCrtFile.close();
|
||||||
|
|
||||||
|
QFile sslKeyFile(dsDirPath + KEY_FILENAME);
|
||||||
|
sslKeyFile.open(QIODevice::ReadOnly);
|
||||||
|
QSslKey sslKey(&sslKeyFile, QSsl::Rsa, QSsl::Pem);
|
||||||
|
sslKeyFile.close();
|
||||||
|
|
||||||
|
if (!sslCaCertificate.isNull() && !sslKey.isNull() && !sslCertificate.isNull()) {
|
||||||
|
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
|
sslConfiguration.addCaCertificate(sslCaCertificate);
|
||||||
|
sslConfiguration.setLocalCertificate(sslCertificate);
|
||||||
|
sslConfiguration.setPrivateKey(sslKey);
|
||||||
|
_webSocketServer->setSslConfiguration(sslConfiguration);
|
||||||
|
qCDebug(networking_webrtc) << "WebSocket SSL mode enabled:"
|
||||||
|
<< (_webSocketServer->secureMode() == QWebSocketServer::SecureMode);
|
||||||
|
} else {
|
||||||
|
qCWarning(networking_webrtc) << "Error creating WebSocket SSL key.";
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_webSocketServer = (new QWebSocketServer(QStringLiteral("WebRTC Signaling Server"), QWebSocketServer::NonSecureMode,
|
||||||
|
this));
|
||||||
|
}
|
||||||
connect(_webSocketServer, &QWebSocketServer::newConnection, this, &WebRTCSignalingServer::newWebSocketConnection);
|
connect(_webSocketServer, &QWebSocketServer::newConnection, this, &WebRTCSignalingServer::newWebSocketConnection);
|
||||||
|
|
||||||
// Automatically recover from network interruptions.
|
// Automatically recover from network interruptions.
|
||||||
|
@ -84,8 +131,9 @@ void WebRTCSignalingServer::webSocketDisconnected() {
|
||||||
auto source = qobject_cast<QWebSocket*>(sender());
|
auto source = qobject_cast<QWebSocket*>(sender());
|
||||||
if (source) {
|
if (source) {
|
||||||
auto address = source->peerAddress().toString() + ":" + QString::number(source->peerPort());
|
auto address = source->peerAddress().toString() + ":" + QString::number(source->peerPort());
|
||||||
delete _webSockets.value(address);
|
|
||||||
_webSockets.remove(address);
|
_webSockets.remove(address);
|
||||||
|
source->abort();
|
||||||
|
source->deleteLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,8 @@ public:
|
||||||
|
|
||||||
/// @brief Constructs a new WebRTCSignalingServer object.
|
/// @brief Constructs a new WebRTCSignalingServer object.
|
||||||
/// @param parent Qt parent object.
|
/// @param parent Qt parent object.
|
||||||
WebRTCSignalingServer(QObject* parent);
|
/// @param isWSSEnabled Whether the WebSocket used for WebRTC signaling should be secure (WSS protocol).
|
||||||
|
WebRTCSignalingServer(QObject* parent, bool isWSSEnabled);
|
||||||
|
|
||||||
/// @brief Binds the WebRTC signaling server's WebSocket to an address and port.
|
/// @brief Binds the WebRTC signaling server's WebSocket to an address and port.
|
||||||
/// @param address The address to use for the WebSocket.
|
/// @param address The address to use for the WebSocket.
|
||||||
|
|
Loading…
Reference in a new issue