Merge branch 'webapp' into dev/webrtc-packet

# Conflicts:
#	libraries/networking/src/webrtc/WebRTCDataChannels.h
This commit is contained in:
David Rowe 2021-07-08 14:54:21 +12:00
commit ed13cbd01b
3 changed files with 118 additions and 33 deletions

View file

@ -11,7 +11,7 @@ endif ()
if (WIN32)
# we need ws2_32.lib on windows, but it's static so we don't bubble it up
# Libraries needed for WebRTC: security.log winmm.lib
# Libraries needed for WebRTC: security.lib winmm.lib
target_link_libraries(${TARGET_NAME} ws2_32.lib security.lib winmm.lib)
elseif(APPLE)
# IOKit is needed for getting machine fingerprint

View file

@ -21,8 +21,9 @@
// - https://webrtc.googlesource.com/src/+/master/api/peer_connection_interface.h
const std::string ICE_SERVER_URI = "stun://ice.vircadia.com:7337";
const int MAX_WEBRTC_BUFFER_SIZE = 16777216; // 16MB
#define WEBRTC_DEBUG
// #define WEBRTC_DEBUG
using namespace webrtc;
@ -104,6 +105,10 @@ void WDCPeerConnectionObserver::OnDataChannel(rtc::scoped_refptr<DataChannelInte
}
void WDCPeerConnectionObserver::OnConnectionChange(PeerConnectionInterface::PeerConnectionState newState) {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WDCPeerConnectionObserver::OnConnectionChange()" << (uint)newState;
#endif
_parent->onPeerConnectionStateChanged(newState);
}
@ -126,9 +131,9 @@ void WDCDataChannelObserver::OnMessage(const DataBuffer& buffer) {
}
WDCConnection::WDCConnection(quint16 webSocketID, WebRTCDataChannels* parent) :
_webSocketID(webSocketID),
_parent(parent)
WDCConnection::WDCConnection(WebRTCDataChannels* parent, quint16 webSocketID) :
_parent(parent),
_webSocketID(webSocketID)
{
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WDCConnection::WDCConnection() :" << webSocketID;
@ -255,6 +260,20 @@ void WDCConnection::sendIceCandidate(const IceCandidateInterface* candidate) {
_parent->sendSignalingMessage(jsonObject);
}
void WDCConnection::onPeerConnectionStateChanged(PeerConnectionInterface::PeerConnectionState state) {
#ifdef WEBRTC_DEBUG
const char* STATES[] = {
"New",
"Connecting",
"Connected",
"Disconnected",
"Failed",
"Closed"
};
qCDebug(networking_webrtc) << "WDCConnection::onPeerConnectionStateChanged() :" << (int)state << STATES[(int)state];
#endif
}
void WDCConnection::onDataChannelOpened(rtc::scoped_refptr<DataChannelInterface> dataChannel) {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WDCConnection::onDataChannelOpened() :"
@ -278,16 +297,19 @@ void WDCConnection::onDataChannelOpened(rtc::scoped_refptr<DataChannelInterface>
void WDCConnection::onDataChannelStateChanged() {
auto state = _dataChannel->state();
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WDCConnection::dataChannelStateChanged() :" << (int)state
qCDebug(networking_webrtc) << "WDCConnection::onDataChannelStateChanged() :" << (int)state
<< DataChannelInterface::DataStateString(state);
#endif
if (state == DataChannelInterface::kClosed) {
_dataChannel->Close();
// Close data channel.
_dataChannel->UnregisterObserver();
_dataChannelObserver = nullptr;
_dataChannel = nullptr;
// WEBRTC FIXME: The following line causes the _peerConnectionFactory to fail.
//_peerConnection->Close();
//_peerConnection = nullptr;
_parent->onDataChannelClosed(this, _dataChannelID);
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "Disposed of data channel";
#endif
// Close peer connection.
_parent->closePeerConnection(this);
}
}
@ -321,14 +343,27 @@ bool WDCConnection::sendDataMessage(const DataBuffer& buffer) {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WDCConnection::sendDataMessage()";
#endif
const int MAX_WEBRTC_BUFFER_SIZE = 16 * 1024 * 1024; // 16MB
if (_dataChannel->buffered_amount() + buffer.size() > MAX_WEBRTC_BUFFER_SIZE) {
// Don't send, otherwise the data channel will be closed.
return false;
} else {
qCDebug(networking_webrtc) << "WebRTC send buffer overflow";
}
return _dataChannel->Send(buffer);
}
void WDCConnection::closePeerConnection() {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WDCConnection::closePeerConnection()";
#endif
_peerConnection->Close();
_peerConnection = nullptr;
_peerConnectionObserver = nullptr;
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "Disposed of peer connection";
#endif
}
WebRTCDataChannels::WebRTCDataChannels(QObject* parent, NodeType_t nodeType) :
QObject(parent),
@ -358,6 +393,9 @@ WebRTCDataChannels::WebRTCDataChannels(QObject* parent, NodeType_t nodeType) :
if (!_peerConnectionFactory) {
qCWarning(networking_webrtc) << "Failed to create WebRTC peer connection factory";
}
// Set up mechanism for closing peer connections.
connect(this, &WebRTCDataChannels::closePeerConnectionSoon, this, &WebRTCDataChannels::closePeerConnectionNow);
}
WebRTCDataChannels::~WebRTCDataChannels() {
@ -397,18 +435,6 @@ void WebRTCDataChannels::onDataChannelOpened(WDCConnection* connection, quint16
_connectionsByDataChannel.insert(dataChannelID, connection);
}
void WebRTCDataChannels::onDataChannelClosed(WDCConnection* connection, quint16 dataChannelID) {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WebRTCDataChannels::onDataChannelClosed() :" << dataChannelID;
#endif
// Delete WDCConnection.
_connectionsByWebSocket.remove(connection->getWebSocketID());
_connectionsByDataChannel.remove(dataChannelID);
// WEBRTC FIXME: The following line causes the _peerConnectionFactory to fail.
//delete connection;
}
void WebRTCDataChannels::onSignalingMessage(const QJsonObject& message) {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WebRTCDataChannel::onSignalingMessage()" << message;
@ -429,7 +455,7 @@ void WebRTCDataChannels::onSignalingMessage(const QJsonObject& message) {
if (_connectionsByWebSocket.contains(from)) {
connection = _connectionsByWebSocket.value(from);
} else {
connection = new WDCConnection(from, this);
connection = new WDCConnection(this, from);
_connectionsByWebSocket.insert(from, connection);
}
@ -502,12 +528,42 @@ rtc::scoped_refptr<PeerConnectionInterface> WebRTCDataChannels::createPeerConnec
configuration.servers.push_back(iceServer);
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "2. Create a new PeerConnection";
qCDebug(networking_webrtc) << "2. Create a new peer connection";
#endif
PeerConnectionDependencies dependencies(peerConnectionObserver.get());
auto result = _peerConnectionFactory->CreatePeerConnection(configuration, std::move(dependencies));
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "Created peer connection";
#endif
return result;
}
void WebRTCDataChannels::closePeerConnection(WDCConnection* connection) {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WebRTCDataChannels::closePeerConnection()";
#endif
// Use Qt's signals/slots mechanism to close the peer connection on its own call stack, separate from the DataChannel
// callback that initiated the peer connection.
// https://bugs.chromium.org/p/webrtc/issues/detail?id=3721
emit closePeerConnectionSoon(connection);
}
void WebRTCDataChannels::closePeerConnectionNow(WDCConnection* connection) {
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "WebRTCDataChannels::closePeerConnectionNow()";
#endif
// Close the peer connection.
connection->closePeerConnection();
// Delete the WDCConnection.
_connectionsByWebSocket.remove(connection->getWebSocketID());
_connectionsByDataChannel.remove(connection->getDataChannelID());
delete connection;
#ifdef WEBRTC_DEBUG
qCDebug(networking_webrtc) << "Disposed of connection";
#endif
}
#endif // WEBRTC_DATA_CHANNELS

View file

@ -46,6 +46,9 @@ public:
/// @brief A WebRTC create session description observer.
class WDCCreateSessionDescriptionObserver : public webrtc::CreateSessionDescriptionObserver {
public:
/// @brief Constructs a session description observer.
/// @param parent The parent connection object.
WDCCreateSessionDescriptionObserver(WDCConnection* parent);
/// @brief The call to CreateAnswer succeeded.
@ -64,6 +67,9 @@ private:
/// @brief A WebRTC peer connection observer.
class WDCPeerConnectionObserver : public webrtc::PeerConnectionObserver {
public:
/// @brief Constructs a peer connection observer.
/// @param parent The parent connection object.
WDCPeerConnectionObserver(WDCConnection* parent);
/// @brief Called when the SignalingState changes.
@ -97,6 +103,9 @@ private:
/// @brief A WebRTC data channel observer.
class WDCDataChannelObserver : public webrtc::DataChannelObserver {
public:
/// @brief Constructs a data channel observer.
/// @param parent The parent connection object.
WDCDataChannelObserver(WDCConnection* parent);
/// @brief The data channel state changed.
@ -116,10 +125,11 @@ private:
class WDCConnection {
public:
/// @brief Constructs a new WDCConnection and opens a WebRTC data connection.
/// @param webSocketID The signaling channel that initiated the opening of the WebRTC data channel.
/// @param parent The parent WebRTCDataChannels object.
WDCConnection(quint16 webSocketID, WebRTCDataChannels* parent);
/// @param webSocketID The signaling channel that initiated the opening of the WebRTC data channel.
WDCConnection(WebRTCDataChannels* parent, quint16 webSocketID);
/// @brief Gets the WebSocket ID.
/// @return The ID of the WebSocket.
@ -153,6 +163,10 @@ public:
/// @param candidate The ICE candidate.
void sendIceCandidate(const webrtc::IceCandidateInterface* candidate);
/// @brief Monitors the peer connection state.
/// @param state The new peer connection state.
void onPeerConnectionStateChanged(PeerConnectionInterface::PeerConnectionState state);
/// @brief Handles the WebRTC data channel being opened.
/// @param dataChannel The WebRTC data channel.
void onDataChannelOpened(rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel);
@ -174,6 +188,9 @@ public:
/// @param buffer The message to send.
/// @return `true` if the message was sent, otherwise `false`.
bool sendDataMessage(const webrtc::DataBuffer& buffer);
/// @brief Closes the WebRTC peer connection.
void closePeerConnection();
private:
WebRTCDataChannels* _parent;
@ -236,11 +253,6 @@ public:
/// @param dataChannelID The WebRTC data channel ID.
void onDataChannelOpened(WDCConnection* connection, quint16 dataChannelID);
/// @brief Handles a WebRTC data channel closing.
/// @param connection The WebRTC data channel connection.
/// @param dataChannelID The WebRTC data channel ID.
void onDataChannelClosed(WDCConnection* connection, quint16 dataChannelID);
/// @brief Emits a signalingMessage to be sent to the Interface client.
/// @param message The WebRTC signaling message to send.
void sendSignalingMessage(const QJsonObject& message);
@ -267,12 +279,24 @@ public:
rtc::scoped_refptr<webrtc::PeerConnectionInterface> createPeerConnection(
const std::shared_ptr<WDCPeerConnectionObserver> peerConnectionObserver);
/// @brief Initiates closing the peer connection for a WebRTC data channel.
/// @details Emits a {@link WebRTCDataChannels.closePeerConnectionSoon} signal which is connected to
/// {@link WebRTCDataChannels.closePeerConnectionNow} in order to close the peer connection on a new call stack. This is
/// necessary to work around a WebRTC library limitation.
/// @param connection The WebRTC data channel connection.
void closePeerConnection(WDCConnection* connection);
public slots:
/// @brief Handles a WebRTC signaling message received from the Interface client.
/// @param message The WebRTC signaling message.
void onSignalingMessage(const QJsonObject& message);
/// @brief Closes the peer connection for a WebRTC data channel.
/// @details Used by {@link WebRTCDataChannels.closePeerConnection}.
/// @param connection The WebRTC data channel connection.
void closePeerConnectionNow(WDCConnection* connection);
signals:
/// @brief A WebRTC signaling message to be sent to the Interface client.
@ -286,6 +310,11 @@ signals:
/// @param byteArray The Vircadia protocol message.
void dataMessage(int dataChannelID, const QByteArray& byteArray);
/// @brief Signals that the peer connection for a WebRTC data channel should be closed.
/// @details Used by {@link WebRTCDataChannels.closePeerConnection}.
/// @param connection The WebRTC data channel connection.
void closePeerConnectionSoon(WDCConnection* connection);
private:
QObject* _parent;