mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-07 20:22:27 +02:00
WebRTCSignalingServer and WebRTCDataChannels improvements
This commit is contained in:
parent
c9d4fe8558
commit
5b937a1580
4 changed files with 98 additions and 61 deletions
|
@ -24,6 +24,8 @@ const std::string ICE_SERVER_URI = "stun://ice.vircadia.com:7337";
|
|||
|
||||
#define WEBRTC_DEBUG
|
||||
|
||||
using namespace webrtc;
|
||||
|
||||
|
||||
void WDCSetSessionDescriptionObserver::OnSuccess() {
|
||||
#ifdef WEBRTC_DEBUG
|
||||
|
@ -308,6 +310,13 @@ void WDCConnection::onDataChannelMessageReceived(const DataBuffer& buffer) {
|
|||
_parent->emitDataMessage(_dataChannelID, byteArray);
|
||||
}
|
||||
|
||||
qint64 WDCConnection::getBufferedAmount() const {
|
||||
#ifdef WEBRTC_DEBUG
|
||||
qCDebug(networking_webrtc) << "WDCConnection::getBufferedAmount()";
|
||||
#endif
|
||||
return _dataChannel->buffered_amount();
|
||||
}
|
||||
|
||||
bool WDCConnection::sendDataMessage(const DataBuffer& buffer) {
|
||||
#ifdef WEBRTC_DEBUG
|
||||
qCDebug(networking_webrtc) << "WDCConnection::sendDataMessage()";
|
||||
|
@ -321,12 +330,13 @@ bool WDCConnection::sendDataMessage(const DataBuffer& buffer) {
|
|||
}
|
||||
|
||||
|
||||
WebRTCDataChannels::WebRTCDataChannels(NodeType_t nodeType, QObject* parent) :
|
||||
_nodeType(nodeType),
|
||||
_parent(parent)
|
||||
WebRTCDataChannels::WebRTCDataChannels(QObject* parent, NodeType_t nodeType) :
|
||||
QObject(parent),
|
||||
_parent(parent),
|
||||
_nodeType(nodeType)
|
||||
{
|
||||
#ifdef WEBRTC_DEBUG
|
||||
qCDebug(networking_webrtc) << "WebRTCDataChannels::WebRTCDataChannels()";
|
||||
qCDebug(networking_webrtc) << "WebRTCDataChannels::WebRTCDataChannels()" << nodeType << NodeType::getNodeTypeName(nodeType);
|
||||
#endif
|
||||
|
||||
// Create a peer connection factory.
|
||||
|
@ -354,14 +364,7 @@ WebRTCDataChannels::~WebRTCDataChannels() {
|
|||
#ifdef WEBRTC_DEBUG
|
||||
qCDebug(networking_webrtc) << "WebRTCDataChannels::~WebRTCDataChannels()";
|
||||
#endif
|
||||
QHashIterator<quint16, WDCConnection*> i(_connectionsByDataChannel);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
delete i.value();
|
||||
}
|
||||
_connectionsByWebSocket.clear();
|
||||
_connectionsByDataChannel.clear();
|
||||
|
||||
reset();
|
||||
_peerConnectionFactory = nullptr;
|
||||
_rtcSignalingThread->Stop();
|
||||
_rtcSignalingThread = nullptr;
|
||||
|
@ -371,6 +374,16 @@ WebRTCDataChannels::~WebRTCDataChannels() {
|
|||
_rtcNetworkThread = nullptr;
|
||||
}
|
||||
|
||||
void WebRTCDataChannels::reset() {
|
||||
QHashIterator<quint16, WDCConnection*> i(_connectionsByDataChannel);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
delete i.value();
|
||||
}
|
||||
_connectionsByWebSocket.clear();
|
||||
_connectionsByDataChannel.clear();
|
||||
}
|
||||
|
||||
quint16 WebRTCDataChannels::getNewDataChannelID() {
|
||||
static const int QUINT16_LIMIT = std::numeric_limits<uint16_t>::max() + 1;
|
||||
_lastDataChannelID = std::max((_lastDataChannelID + 1) % QUINT16_LIMIT, 1);
|
||||
|
@ -448,7 +461,7 @@ void WebRTCDataChannels::sendSignalingMessage(const QJsonObject& message) {
|
|||
|
||||
void WebRTCDataChannels::emitDataMessage(int dataChannelID, const QByteArray& byteArray) {
|
||||
#ifdef WEBRTC_DEBUG
|
||||
qCDebug(networking_webrtc) << "WebRTCDataChannels::emitDataMessage() :" << dataChannelID;
|
||||
qCDebug(networking_webrtc) << "WebRTCDataChannels::emitDataMessage() :" << dataChannelID << byteArray;
|
||||
#endif
|
||||
emit dataMessage(dataChannelID, byteArray);
|
||||
}
|
||||
|
@ -469,6 +482,14 @@ bool WebRTCDataChannels::sendDataMessage(int dataChannelID, const QByteArray& by
|
|||
return connection->sendDataMessage(buffer);
|
||||
}
|
||||
|
||||
/// @brief Gets the number of bytes waiting to be written on a data channel.
|
||||
/// @param port The data channel ID.
|
||||
/// @return The number of bytes waiting to be written on the data channel.
|
||||
qint64 WebRTCDataChannels::getBufferedAmount(int dataChannelID) const {
|
||||
auto connection = _connectionsByDataChannel.value(dataChannelID);
|
||||
return connection->getBufferedAmount();
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<PeerConnectionInterface> WebRTCDataChannels::createPeerConnection(
|
||||
const std::shared_ptr<WDCPeerConnectionObserver> peerConnectionObserver) {
|
||||
#ifdef WEBRTC_DEBUG
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#include "../NodeType.h"
|
||||
|
||||
using namespace webrtc;
|
||||
|
||||
class WebRTCDataChannels;
|
||||
class WDCConnection;
|
||||
|
||||
|
@ -33,7 +31,7 @@ class WDCConnection;
|
|||
/// @{
|
||||
|
||||
/// @brief A WebRTC session description observer.
|
||||
class WDCSetSessionDescriptionObserver : public SetSessionDescriptionObserver {
|
||||
class WDCSetSessionDescriptionObserver : public webrtc::SetSessionDescriptionObserver {
|
||||
public:
|
||||
|
||||
/// @brief The call to SetLocalDescription or SetRemoteDescription succeeded.
|
||||
|
@ -41,22 +39,22 @@ public:
|
|||
|
||||
/// @brief The call to SetLocalDescription or SetRemoteDescription failed.
|
||||
/// @param error Error information.
|
||||
void OnFailure(RTCError error) override;
|
||||
void OnFailure(webrtc::RTCError error) override;
|
||||
};
|
||||
|
||||
|
||||
/// @brief A WebRTC create session description observer.
|
||||
class WDCCreateSessionDescriptionObserver : public CreateSessionDescriptionObserver {
|
||||
class WDCCreateSessionDescriptionObserver : public webrtc::CreateSessionDescriptionObserver {
|
||||
public:
|
||||
WDCCreateSessionDescriptionObserver(WDCConnection* parent);
|
||||
|
||||
/// @brief The call to CreateAnswer succeeded.
|
||||
/// @param The session description.
|
||||
void OnSuccess(SessionDescriptionInterface* desc) override;
|
||||
void OnSuccess(webrtc::SessionDescriptionInterface* desc) override;
|
||||
|
||||
//@ @brief The call to CreateAnswer failed.
|
||||
/// @param error Error information.
|
||||
void OnFailure(RTCError error) override;
|
||||
void OnFailure(webrtc::RTCError error) override;
|
||||
|
||||
private:
|
||||
WDCConnection* _parent;
|
||||
|
@ -64,32 +62,32 @@ private:
|
|||
|
||||
|
||||
/// @brief A WebRTC peer connection observer.
|
||||
class WDCPeerConnectionObserver : public PeerConnectionObserver {
|
||||
class WDCPeerConnectionObserver : public webrtc::PeerConnectionObserver {
|
||||
public:
|
||||
WDCPeerConnectionObserver(WDCConnection* parent);
|
||||
|
||||
/// @brief Called when the SignalingState changes.
|
||||
/// @param newState The new signaling state.
|
||||
void OnSignalingChange(PeerConnectionInterface::SignalingState newState) override;
|
||||
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState newState) override;
|
||||
|
||||
/// @brief Called when renegotiation is needed. For example, an ICE restart has begun.
|
||||
void OnRenegotiationNeeded() override;
|
||||
|
||||
/// @brief Called when the ICE gather state changes.
|
||||
/// @param newState The new ICE gathering state.
|
||||
void OnIceGatheringChange(PeerConnectionInterface::IceGatheringState newState) override;
|
||||
void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState newState) override;
|
||||
|
||||
/// @brief Called when a new ICE candidate has been gathered.
|
||||
/// @param candidate The new ICE candidate.
|
||||
void OnIceCandidate(const IceCandidateInterface* candidate) override;
|
||||
void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
|
||||
|
||||
/// @brief Called when a remote peer opens a data channel.
|
||||
/// @param dataChannel The data channel.
|
||||
void OnDataChannel(rtc::scoped_refptr<DataChannelInterface> dataChannel) override;
|
||||
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel) override;
|
||||
|
||||
/// @brief Called when the peer connection state changes.
|
||||
/// @param newState The new peer connection state.
|
||||
void OnConnectionChange(PeerConnectionInterface::PeerConnectionState newState) override;
|
||||
void OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState newState) override;
|
||||
|
||||
private:
|
||||
WDCConnection* _parent;
|
||||
|
@ -97,7 +95,7 @@ private:
|
|||
|
||||
|
||||
/// @brief A WebRTC data channel observer.
|
||||
class WDCDataChannelObserver : public DataChannelObserver {
|
||||
class WDCDataChannelObserver : public webrtc::DataChannelObserver {
|
||||
public:
|
||||
WDCDataChannelObserver(WDCConnection* parent);
|
||||
|
||||
|
@ -106,7 +104,7 @@ public:
|
|||
|
||||
/// @brief A data channel message was received.
|
||||
/// @param The message received.
|
||||
void OnMessage(const DataBuffer& buffer) override;
|
||||
void OnMessage(const webrtc::DataBuffer& buffer) override;
|
||||
|
||||
private:
|
||||
WDCConnection* _parent;
|
||||
|
@ -125,11 +123,11 @@ public:
|
|||
|
||||
/// @brief Gets the WebSocket ID.
|
||||
/// @return The ID of the WebSocket.
|
||||
quint16 getWebSocketID() { return _webSocketID; }
|
||||
quint16 getWebSocketID() const { return _webSocketID; }
|
||||
|
||||
/// @brief Gets the WebRTC data channel ID.
|
||||
/// @return The WebRTC data channel ID. `-1` if not open yet.
|
||||
int getDataChannelID() { return _dataChannelID; }
|
||||
int getDataChannelID() const { return _dataChannelID; }
|
||||
|
||||
|
||||
/// @brief Sets the remote session description received from the remote client via the signaling channel.
|
||||
|
@ -141,11 +139,11 @@ public:
|
|||
|
||||
/// @brief Sends an answer to the remote client via the signaling channel.
|
||||
/// @param description The answer.
|
||||
void sendAnswer(SessionDescriptionInterface* description);
|
||||
void sendAnswer(webrtc::SessionDescriptionInterface* description);
|
||||
|
||||
/// @brief Sets the local session description on the WebRTC data channel being connected.
|
||||
/// @param description The local session description.
|
||||
void setLocalDescription(SessionDescriptionInterface* description);
|
||||
void setLocalDescription(webrtc::SessionDescriptionInterface* description);
|
||||
|
||||
/// @brief Adds an ICE candidate received from the remote client via the signaling channel.
|
||||
/// @param data The ICE candidate.
|
||||
|
@ -153,11 +151,11 @@ public:
|
|||
|
||||
/// @brief Sends an ICE candidate to the remote vlient via the signaling channel.
|
||||
/// @param candidate The ICE candidate.
|
||||
void sendIceCandidate(const IceCandidateInterface* candidate);
|
||||
void sendIceCandidate(const webrtc::IceCandidateInterface* candidate);
|
||||
|
||||
/// @brief Handles the WebRTC data channel being opened.
|
||||
/// @param dataChannel The WebRTC data channel.
|
||||
void onDataChannelOpened(rtc::scoped_refptr<DataChannelInterface> dataChannel);
|
||||
void onDataChannelOpened(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel);
|
||||
|
||||
/// @brief Handles a change in the state of the WebRTC data channel.
|
||||
void onDataChannelStateChanged();
|
||||
|
@ -165,12 +163,17 @@ public:
|
|||
|
||||
/// @brief Handles a message being received on the WebRTC data channel.
|
||||
/// @param buffer The message received.
|
||||
void onDataChannelMessageReceived(const DataBuffer& buffer);
|
||||
void onDataChannelMessageReceived(const webrtc::DataBuffer& buffer);
|
||||
|
||||
/// @brief Gets the number of bytes waiting to be sent on the WebRTC data channel.
|
||||
/// @return The number of bytes waiting to be sent on the WebRTC data channel.
|
||||
qint64 getBufferedAmount() const;
|
||||
|
||||
|
||||
/// @brief Sends a message on the WebRTC data channel.
|
||||
/// @param buffer The message to send.
|
||||
/// @return `true` if the message was sent, otherwise `false`.
|
||||
bool sendDataMessage(const DataBuffer& buffer);
|
||||
bool sendDataMessage(const webrtc::DataBuffer& buffer);
|
||||
|
||||
private:
|
||||
WebRTCDataChannels* _parent;
|
||||
|
@ -181,10 +184,10 @@ private:
|
|||
rtc::scoped_refptr<WDCCreateSessionDescriptionObserver> _createSessionDescriptionObserver { nullptr };
|
||||
|
||||
std::shared_ptr<WDCDataChannelObserver> _dataChannelObserver { nullptr };
|
||||
rtc::scoped_refptr<DataChannelInterface> _dataChannel { nullptr };
|
||||
rtc::scoped_refptr<webrtc::DataChannelInterface> _dataChannel { nullptr };
|
||||
|
||||
std::shared_ptr<WDCPeerConnectionObserver> _peerConnectionObserver { nullptr };
|
||||
rtc::scoped_refptr<PeerConnectionInterface> _peerConnection { nullptr };
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection { nullptr };
|
||||
};
|
||||
|
||||
|
||||
|
@ -206,20 +209,25 @@ class WebRTCDataChannels : public QObject {
|
|||
public:
|
||||
|
||||
/// @brief Constructs a new WebRTCDataChannels object.
|
||||
/// @param nodeType The type of node that the WebRTCDataChannels object is being used in.
|
||||
/// @param parent The parent Qt object.
|
||||
WebRTCDataChannels(NodeType_t nodeType, QObject* parent);
|
||||
/// @param nodeType The type of node that the WebRTCDataChannels object is being used in.
|
||||
WebRTCDataChannels(QObject* parent, NodeType_t nodeType);
|
||||
|
||||
/// @brief Destroys a WebRTCDataChannels object.
|
||||
~WebRTCDataChannels();
|
||||
|
||||
/// @brief Returns the type of node that the WebRTCDataChannels object is being used in.
|
||||
/// @brief Gets the type of node that the WebRTCDataChannels object is being used in.
|
||||
/// @return The type of node.
|
||||
NodeType_t getNodeType() {
|
||||
return _nodeType;
|
||||
}
|
||||
|
||||
/// @brief Immediately closes all connections and resets the socket.
|
||||
void reset();
|
||||
|
||||
/// @brief Get a new data channel ID to uniquely identify a WDCConnection.
|
||||
/// @details This ID is assigned by WebRTCDataChannels; it is <em>not</em> the WebRTC data channel ID because that is only
|
||||
/// unique within a peer connection.
|
||||
/// @return A new data channel ID.
|
||||
quint16 getNewDataChannelID();
|
||||
|
||||
|
@ -248,10 +256,15 @@ public:
|
|||
/// @return `true` if the data message was sent, otherwise `false`.
|
||||
bool sendDataMessage(int dataChannelID, const QByteArray& message);
|
||||
|
||||
/// @brief Gets the number of bytes waiting to be sent on a data channel.
|
||||
/// @param dataChannelID The data channel ID.
|
||||
/// @return The number of bytes waiting to be sent on the data channel.
|
||||
qint64 getBufferedAmount(int dataChannelID) const;
|
||||
|
||||
/// @brief Creates a new WebRTC peer connection for connecting to an Interface client.
|
||||
/// @param peerConnectionObserver An observer to monitor the WebRTC peer connection.
|
||||
/// @return The new WebRTC peer connection.
|
||||
rtc::scoped_refptr<PeerConnectionInterface> createPeerConnection(
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> createPeerConnection(
|
||||
const std::shared_ptr<WDCPeerConnectionObserver> peerConnectionObserver);
|
||||
|
||||
public slots:
|
||||
|
@ -283,9 +296,9 @@ private:
|
|||
std::unique_ptr<rtc::Thread> _rtcWorkerThread { nullptr };
|
||||
std::unique_ptr<rtc::Thread> _rtcSignalingThread { nullptr };
|
||||
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> _peerConnectionFactory { nullptr };
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> _peerConnectionFactory { nullptr };
|
||||
|
||||
quint16 _lastDataChannelID { 0 };
|
||||
quint16 _lastDataChannelID { 0 }; // First data channel ID is 1.
|
||||
|
||||
QHash<quint16, WDCConnection*> _connectionsByWebSocket;
|
||||
QHash<quint16, WDCConnection*> _connectionsByDataChannel;
|
||||
|
|
|
@ -19,33 +19,33 @@
|
|||
|
||||
const int WEBRTC_SOCKET_CHECK_INTERVAL_IN_MS = 30000;
|
||||
|
||||
WebRTCSignalingServer::WebRTCSignalingServer(const QHostAddress& address, quint16 port, QObject* parent) :
|
||||
WebRTCSignalingServer::WebRTCSignalingServer(QObject* parent) :
|
||||
QObject(parent),
|
||||
_address(address),
|
||||
_port(port),
|
||||
_webSocketServer(new QWebSocketServer(QStringLiteral("WebRTC Signaling Server"), QWebSocketServer::NonSecureMode, this))
|
||||
{
|
||||
connect(_webSocketServer, &QWebSocketServer::newConnection, this, &WebRTCSignalingServer::newWebSocketConnection);
|
||||
|
||||
bindSocket();
|
||||
|
||||
// Automatically recover from network interruptions.
|
||||
_isWebSocketServerListeningTimer = new QTimer(this);
|
||||
connect(_isWebSocketServerListeningTimer, &QTimer::timeout, this, &WebRTCSignalingServer::checkWebSocketServerIsListening);
|
||||
_isWebSocketServerListeningTimer->start(WEBRTC_SOCKET_CHECK_INTERVAL_IN_MS);
|
||||
}
|
||||
|
||||
bool WebRTCSignalingServer::bind(const QHostAddress& address, quint16 port) {
|
||||
_address = address;
|
||||
_port = port;
|
||||
auto success = _webSocketServer->listen(_address, _port);
|
||||
if (!success) {
|
||||
qCWarning(networking_webrtc) << "Failed to open WebSocket for WebRTC signaling.";
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void WebRTCSignalingServer::checkWebSocketServerIsListening() {
|
||||
if (!_webSocketServer->isListening()) {
|
||||
qCWarning(networking_webrtc) << "WebSocket on port " << QString::number(_port) << " is no longer listening";
|
||||
_webSockets.clear();
|
||||
bindSocket();
|
||||
}
|
||||
}
|
||||
|
||||
void WebRTCSignalingServer::bindSocket() {
|
||||
if (!_webSocketServer->listen(_address, _port)) {
|
||||
qCWarning(networking_webrtc) << "Failed to open WebSocket for WebRTC signaling.";
|
||||
_webSocketServer->listen(_address, _port);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,10 +59,14 @@ class WebRTCSignalingServer : public QObject {
|
|||
public:
|
||||
|
||||
/// @brief Constructs a new WebRTCSignalingServer object.
|
||||
/// @param address The IP address to use for the WebSocket.
|
||||
/// @param port The port to use for the WebSocket.
|
||||
/// @param parent Qt parent object.
|
||||
WebRTCSignalingServer(const QHostAddress& address, quint16 port, QObject* parent = nullptr);
|
||||
WebRTCSignalingServer(QObject* parent);
|
||||
|
||||
/// @brief Binds the WebRTC signaling server's WebSocket to an address and port.
|
||||
/// @param address The address to use for the WebSocket.
|
||||
/// @param port The port to use for the WebSocket.
|
||||
/// @return <code>true</code> if the WebSocket was successfully bound, <code>false</code> if it wasn't.
|
||||
bool bind(const QHostAddress& address, quint16 port);
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -88,11 +92,10 @@ private slots:
|
|||
private:
|
||||
|
||||
void checkWebSocketServerIsListening();
|
||||
void bindSocket();
|
||||
|
||||
QWebSocketServer* _webSocketServer;
|
||||
QHostAddress _address;
|
||||
const quint16 _port;
|
||||
quint16 _port { 0 };
|
||||
|
||||
QHash<quint16, QWebSocket*> _webSockets; // client WebSocket port, client WebSocket object
|
||||
|
||||
|
|
Loading…
Reference in a new issue