From 95aa9ef588acd1597fbaca4d571485b9eeba5abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 01:43:14 +0200 Subject: [PATCH 01/58] RTC::WebRtcServer first commit --- worker/include/Channel/ChannelRequest.hpp | 2 + worker/include/RTC/WebRtcServer.hpp | 82 +++++ worker/meson.build | 1 + worker/src/Channel/ChannelRequest.cpp | 2 + worker/src/RTC/WebRtcServer.cpp | 390 ++++++++++++++++++++++ 5 files changed, 477 insertions(+) create mode 100644 worker/include/RTC/WebRtcServer.hpp create mode 100644 worker/src/RTC/WebRtcServer.cpp diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index cca5dda3fc..34e924f394 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -44,6 +44,8 @@ namespace Channel TRANSPORT_PRODUCE_DATA, TRANSPORT_CONSUME_DATA, TRANSPORT_ENABLE_TRACE_EVENT, + WEBRTC_SERVER_CLOSE, + WEBRTC_SERVER_DUMP, PRODUCER_CLOSE, PRODUCER_DUMP, PRODUCER_GET_STATS, diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp new file mode 100644 index 0000000000..a5ab2b89b6 --- /dev/null +++ b/worker/include/RTC/WebRtcServer.hpp @@ -0,0 +1,82 @@ +#ifndef MS_RTC_WEBRTC_SERVER_HPP +#define MS_RTC_WEBRTC_SERVER_HPP + +#include "Channel/ChannelRequest.hpp" +#include "RTC/IceCandidate.hpp" +#include "RTC/IceServer.hpp" +#include "RTC/StunPacket.hpp" +#include "RTC/TcpConnection.hpp" +#include "RTC/TcpServer.hpp" +#include "RTC/TransportTuple.hpp" +#include "RTC/UdpSocket.hpp" +#include +#include +#include +#include + +namespace RTC +{ + class WebRtcServer : public RTC::UdpSocket::Listener, + public RTC::TcpServer::Listener, + public RTC::TcpConnection::Listener, + public RTC::IceServer::Listener + { + private: + struct ListenIpPort + { + std::string ip; + std::string announcedIp; + uint16_t port; + }; + + public: + WebRtcServer(const std::string& id, json& data); + ~WebRtcServer(); + + public: + void FillJson(json& jsonObject) const; + void HandleRequest(Channel::ChannelRequest* request); + + private: + void OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + void OnStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + void OnNonStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + + /* Pure virtual methods inherited from RTC::UdpSocket::Listener. */ + public: + void OnUdpSocketPacketReceived( + RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr) override; + + /* Pure virtual methods inherited from RTC::TcpServer::Listener. */ + public: + void OnRtcTcpConnectionClosed(RTC::TcpServer* tcpServer, RTC::TcpConnection* connection) override; + + /* Pure virtual methods inherited from RTC::TcpConnection::Listener. */ + public: + void OnTcpConnectionPacketReceived( + RTC::TcpConnection* connection, const uint8_t* data, size_t len) override; + + /* Pure virtual methods inherited from RTC::IceServer::Listener. */ + public: + void OnIceServerSendStunPacket( + const RTC::IceServer* iceServer, + const RTC::StunPacket* packet, + RTC::TransportTuple* tuple) override; + void OnIceServerSelectedTuple(const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) override; + void OnIceServerConnected(const RTC::IceServer* iceServer) override; + void OnIceServerCompleted(const RTC::IceServer* iceServer) override; + void OnIceServerDisconnected(const RTC::IceServer* iceServer) override; + + public: + // Passed by argument. + const std::string id; + + private: + // Map of UdpSocket/TcpServer and local announced IP (if any). + absl::flat_hash_map udpSockets; + absl::flat_hash_map tcpServers; + std::vector iceCandidates; + }; +} // namespace RTC + +#endif diff --git a/worker/meson.build b/worker/meson.build index 3961e7e297..497667f31e 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -97,6 +97,7 @@ common_sources = [ 'src/RTC/TransportTuple.cpp', 'src/RTC/TrendCalculator.cpp', 'src/RTC/UdpSocket.cpp', + 'src/RTC/WebRtcServer.cpp', 'src/RTC/WebRtcTransport.cpp', 'src/RTC/Codecs/H264.cpp', 'src/RTC/Codecs/H264_SVC.cpp', diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index 1171900f91..66d4ddc1b5 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -38,6 +38,8 @@ namespace Channel { "transport.produceData", ChannelRequest::MethodId::TRANSPORT_PRODUCE_DATA }, { "transport.consumeData", ChannelRequest::MethodId::TRANSPORT_CONSUME_DATA }, { "transport.enableTraceEvent", ChannelRequest::MethodId::TRANSPORT_ENABLE_TRACE_EVENT }, + { "webRtcServer.close", ChannelRequest::MethodId::WEBRTC_SERVER_CLOSE }, + { "webRtcServer.dump", ChannelRequest::MethodId::WEBRTC_SERVER_DUMP }, { "producer.close", ChannelRequest::MethodId::PRODUCER_CLOSE }, { "producer.dump", ChannelRequest::MethodId::PRODUCER_DUMP }, { "producer.getStats", ChannelRequest::MethodId::PRODUCER_GET_STATS }, diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp new file mode 100644 index 0000000000..95e6e00387 --- /dev/null +++ b/worker/src/RTC/WebRtcServer.cpp @@ -0,0 +1,390 @@ +#define MS_CLASS "RTC::WebRtcServer" +// #define MS_LOG_DEV_LEVEL 3 + +#include "RTC/WebRtcServer.hpp" +#include "Logger.hpp" +#include "MediaSoupErrors.hpp" +#include "Utils.hpp" +#include "Channel/ChannelNotifier.hpp" +#include // std::pow() + +namespace RTC +{ + /* Static. */ + + static constexpr uint16_t IceCandidateDefaultLocalPriority{ 10000 }; + // We just provide "host" candidates so type preference is fixed. + static constexpr uint16_t IceTypePreference{ 64 }; + // We do not support non rtcp-mux so component is always 1. + static constexpr uint16_t IceComponent{ 1 }; + + static inline uint32_t generateIceCandidatePriority(uint16_t localPreference) + { + MS_TRACE(); + + return std::pow(2, 24) * IceTypePreference + std::pow(2, 8) * localPreference + + std::pow(2, 0) * (256 - IceComponent); + } + + /* Instance methods. */ + + WebRtcServer::WebRtcServer(const std::string& id, json& data) : id(id) + { + MS_TRACE(); + + bool enableUdp{ true }; + auto jsonEnableUdpIt = data.find("enableUdp"); + + if (jsonEnableUdpIt != data.end()) + { + if (!jsonEnableUdpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)"); + + enableUdp = jsonEnableUdpIt->get(); + } + + bool enableTcp{ false }; + auto jsonEnableTcpIt = data.find("enableTcp"); + + if (jsonEnableTcpIt != data.end()) + { + if (!jsonEnableTcpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)"); + + enableTcp = jsonEnableTcpIt->get(); + } + + bool preferUdp{ false }; + auto jsonPreferUdpIt = data.find("preferUdp"); + + if (jsonPreferUdpIt != data.end()) + { + if (!jsonPreferUdpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)"); + + preferUdp = jsonPreferUdpIt->get(); + } + + bool preferTcp{ false }; + auto jsonPreferTcpIt = data.find("preferTcp"); + + if (jsonPreferTcpIt != data.end()) + { + if (!jsonPreferTcpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)"); + + preferTcp = jsonPreferTcpIt->get(); + } + + auto jsonListenIpPortsIt = data.find("listenIpPorts"); + + if (jsonListenIpPortsIt == data.end()) + MS_THROW_TYPE_ERROR("missing listenIpPorts"); + else if (!jsonListenIpPortsIt->is_array()) + MS_THROW_TYPE_ERROR("wrong listenIpPorts (not an array)"); + else if (jsonListenIpPortsIt->empty()) + MS_THROW_TYPE_ERROR("wrong listenIpPorts (empty array)"); + else if (jsonListenIpPortsIt->size() > 8) + MS_THROW_TYPE_ERROR("wrong listenIpPorts (too many entries)"); + + std::vector listenIpPorts(jsonListenIpPortsIt->size()); + + for (size_t i{ 0 }; i < jsonListenIpPortsIt->size(); ++i) + { + auto& jsonListenIpPort = (*jsonListenIpPortsIt)[i]; + auto& listenIpPort = listenIpPorts[i]; + + if (!jsonListenIpPort.is_object()) + MS_THROW_TYPE_ERROR("wrong listenIpPort (not an object)"); + + auto jsonIpIt = jsonListenIpPort.find("ip"); + + if (jsonIpIt == jsonListenIpPort.end()) + MS_THROW_TYPE_ERROR("missing listenIpPort.ip"); + else if (!jsonIpIt->is_string()) + MS_THROW_TYPE_ERROR("wrong listenIpPort.ip (not an string"); + + listenIpPort.ip.assign(jsonIpIt->get()); + + // This may throw. + Utils::IP::NormalizeIp(listenIpPort.ip); + + auto jsonAnnouncedIpIt = jsonListenIpPort.find("announcedIp"); + + if (jsonAnnouncedIpIt != jsonListenIpPort.end()) + { + if (!jsonAnnouncedIpIt->is_string()) + MS_THROW_TYPE_ERROR("wrong listenIpPort.announcedIp (not an string)"); + + listenIpPort.announcedIp.assign(jsonAnnouncedIpIt->get()); + } + + auto jsonPortIt = jsonListenIpPort.find("port"); + + if (jsonPortIt == jsonListenIpPort.end()) + MS_THROW_TYPE_ERROR("missing listenIpPort.port"); + else if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) + MS_THROW_TYPE_ERROR("wrong listenIpPort.port (not a positive number)"); + + listenIpPort.port = jsonPortIt->get(); + } + + try + { + uint16_t iceLocalPreferenceDecrement{ 0 }; + + if (enableUdp && enableTcp) + this->iceCandidates.reserve(2 * jsonListenIpPortsIt->size()); + else + this->iceCandidates.reserve(jsonListenIpPortsIt->size()); + + for (auto& listenIpPort : listenIpPorts) + { + if (enableUdp) + { + uint16_t iceLocalPreference = + IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; + + if (preferUdp) + iceLocalPreference += 1000; + + uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + + // This may throw. + auto* udpSocket = new RTC::UdpSocket(this, listenIpPort.ip, listenIpPort.port); + + this->udpSockets[udpSocket] = listenIpPort.announcedIp; + + if (listenIpPort.announcedIp.empty()) + this->iceCandidates.emplace_back(udpSocket, icePriority); + else + this->iceCandidates.emplace_back(udpSocket, icePriority, listenIpPort.announcedIp); + } + + if (enableTcp) + { + uint16_t iceLocalPreference = + IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; + + if (preferTcp) + iceLocalPreference += 1000; + + uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + + // This may throw. + auto* tcpServer = new RTC::TcpServer(this, this, listenIpPort.ip, listenIpPort.port); + + this->tcpServers[tcpServer] = listenIpPort.announcedIp; + + if (listenIpPort.announcedIp.empty()) + this->iceCandidates.emplace_back(tcpServer, icePriority); + else + this->iceCandidates.emplace_back(tcpServer, icePriority, listenIpPort.announcedIp); + } + + // Decrement initial ICE local preference for next IP. + iceLocalPreferenceDecrement += 100; + } + } + catch (const MediaSoupError& error) + { + // Must delete everything since the destructor won't be called. + + for (auto& kv : this->udpSockets) + { + auto* udpSocket = kv.first; + + delete udpSocket; + } + this->udpSockets.clear(); + + for (auto& kv : this->tcpServers) + { + auto* tcpServer = kv.first; + + delete tcpServer; + } + this->tcpServers.clear(); + + this->iceCandidates.clear(); + + throw; + } + } + + WebRtcServer::~WebRtcServer() + { + MS_TRACE(); + + for (auto& kv : this->udpSockets) + { + auto* udpSocket = kv.first; + + delete udpSocket; + } + this->udpSockets.clear(); + + for (auto& kv : this->tcpServers) + { + auto* tcpServer = kv.first; + + delete tcpServer; + } + this->tcpServers.clear(); + + this->iceCandidates.clear(); + } + + void WebRtcServer::FillJson(json& jsonObject) const + { + MS_TRACE(); + + // Add id. + jsonObject["id"] = this->id; + + // Add iceCandidates. + jsonObject["iceCandidates"] = json::array(); + auto jsonIceCandidatesIt = jsonObject.find("iceCandidates"); + + for (size_t i{ 0 }; i < this->iceCandidates.size(); ++i) + { + jsonIceCandidatesIt->emplace_back(json::value_t::object); + + auto& jsonEntry = (*jsonIceCandidatesIt)[i]; + auto& iceCandidate = this->iceCandidates[i]; + + iceCandidate.FillJson(jsonEntry); + } + } + + void WebRtcServer::HandleRequest(Channel::ChannelRequest* request) + { + MS_TRACE(); + + switch (request->methodId) + { + case Channel::ChannelRequest::MethodId::WEBRTC_SERVER_DUMP: + { + json data = json::object(); + + FillJson(data); + + request->Accept(data); + + break; + } + + default: + { + MS_THROW_ERROR("unknown method '%s'", request->method.c_str()); + } + } + } + + inline void WebRtcServer::OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len) + { + MS_TRACE(); + + if (RTC::StunPacket::IsStun(data, len)) + { + OnStunDataReceived(tuple, data, len); + } + else + { + OnNonStunDataReceived(tuple, data, len); + } + } + + inline void WebRtcServer::OnStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len) + { + MS_TRACE(); + + RTC::StunPacket* packet = RTC::StunPacket::Parse(data, len); + + if (!packet) + { + MS_WARN_DEV("ignoring wrong STUN packet received"); + + return; + } + + // TODO + + delete packet; + } + + inline void WebRtcServer::OnNonStunDataReceived( + RTC::TransportTuple* tuple, const uint8_t* data, size_t len) + { + MS_TRACE(); + + // TODO + } + + inline void WebRtcServer::OnUdpSocketPacketReceived( + RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr) + { + MS_TRACE(); + + RTC::TransportTuple tuple(socket, remoteAddr); + + OnPacketReceived(&tuple, data, len); + } + + inline void WebRtcServer::OnRtcTcpConnectionClosed( + RTC::TcpServer* /*tcpServer*/, RTC::TcpConnection* connection) + { + MS_TRACE(); + + RTC::TransportTuple tuple(connection); + + // TODO + } + + inline void WebRtcServer::OnTcpConnectionPacketReceived( + RTC::TcpConnection* connection, const uint8_t* data, size_t len) + { + MS_TRACE(); + + RTC::TransportTuple tuple(connection); + + OnPacketReceived(&tuple, data, len); + } + + inline void WebRtcServer::OnIceServerSendStunPacket( + const RTC::IceServer* /*iceServer*/, const RTC::StunPacket* packet, RTC::TransportTuple* tuple) + { + MS_TRACE(); + + // TODO + } + + inline void WebRtcServer::OnIceServerSelectedTuple( + const RTC::IceServer* /*iceServer*/, RTC::TransportTuple* /*tuple*/) + { + MS_TRACE(); + + // TODO + } + + inline void WebRtcServer::OnIceServerConnected(const RTC::IceServer* /*iceServer*/) + { + MS_TRACE(); + + // TODO + } + + inline void WebRtcServer::OnIceServerCompleted(const RTC::IceServer* /*iceServer*/) + { + MS_TRACE(); + + // TODO + } + + inline void WebRtcServer::OnIceServerDisconnected(const RTC::IceServer* /*iceServer*/) + { + MS_TRACE(); + + // TODO + } +} // namespace RTC From 2328e9f755b5ee8372fee7db4d747852361d547d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 14:17:30 +0200 Subject: [PATCH 02/58] Add TODO_WEBRTC_SERVER.md --- TODO_WEBRTC_SERVER.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 TODO_WEBRTC_SERVER.md diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md new file mode 100644 index 0000000000..96d1e6e30f --- /dev/null +++ b/TODO_WEBRTC_SERVER.md @@ -0,0 +1,21 @@ +# TODO WebRtcServer + + +### Remove limit of TcpConnections per TcpServer + +Also increase `backlog(int)` in `uv_listen`(POSIX argument): + + +> The backlog argument defines the maximum length to which the +> queue of pending connections for sockfd may grow. If a connection +> request arrives when the queue is full, the client may receive an +> error with an indication of ECONNREFUSED or, if the underlying +> protocol supports retransmission, the request may be ignored so +> that a later reattempt at connection succeeds. + +No matter the value is super high, in Linux it's limited by `/proc/sys/net/core/somaxconn`. + + +### Handle limit of UDP/TCP tuples in WebRtcTransport + +This is needed no matter `WebRtcServer` is used or not. Each `WebRtcTransport` should manage max number of UDP and TCP tuples and remove old one (non selected one) etc when a new one is created or reject new one, let's see. From 28850794888466670cdd66dc72b978c4db19accb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 15:44:46 +0200 Subject: [PATCH 03/58] more --- worker/include/Channel/ChannelRequest.hpp | 1 + worker/include/RTC/WebRtcServer.hpp | 59 ++-- worker/include/RTC/WebRtcTransport.hpp | 21 ++ worker/src/Channel/ChannelRequest.cpp | 1 + worker/src/RTC/WebRtcServer.cpp | 331 ++++++++++------------ 5 files changed, 208 insertions(+), 205 deletions(-) diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index 34e924f394..d7cca86912 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -27,6 +27,7 @@ namespace Channel ROUTER_CLOSE, ROUTER_DUMP, ROUTER_CREATE_WEBRTC_TRANSPORT, + ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER, ROUTER_CREATE_PLAIN_TRANSPORT, ROUTER_CREATE_PIPE_TRANSPORT, ROUTER_CREATE_DIRECT_TRANSPORT, diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index a5ab2b89b6..389e1aa9e5 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -3,12 +3,12 @@ #include "Channel/ChannelRequest.hpp" #include "RTC/IceCandidate.hpp" -#include "RTC/IceServer.hpp" #include "RTC/StunPacket.hpp" #include "RTC/TcpConnection.hpp" #include "RTC/TcpServer.hpp" #include "RTC/TransportTuple.hpp" #include "RTC/UdpSocket.hpp" +#include "RTC/WebRtcTransport.hpp" #include #include #include @@ -19,16 +19,31 @@ namespace RTC class WebRtcServer : public RTC::UdpSocket::Listener, public RTC::TcpServer::Listener, public RTC::TcpConnection::Listener, - public RTC::IceServer::Listener + public RTC::WebRtcTransport::WebRtcTransportListener { private: - struct ListenIpPort + struct ListenInfo { + RTC::TransportTuple::Protocol protocol; std::string ip; std::string announcedIp; uint16_t port; }; + private: + struct UdpSocketOrTcpServer + { + // Expose a constructor to use vector.emplace_back(). + UdpSocketOrTcpServer(RTC::UdpSocket* udpSocket, RTC::TcpServer* tcpServer, std::string& announcedIp) + : udpSocket(udpSocket), tcpServer(tcpServer), announcedIp(announcedIp) + { + } + + RTC::UdpSocket* udpSocket; + RTC::TcpServer* tcpServer; + std::string announcedIp; + }; + public: WebRtcServer(const std::string& id, json& data); ~WebRtcServer(); @@ -36,12 +51,29 @@ namespace RTC public: void FillJson(json& jsonObject) const; void HandleRequest(Channel::ChannelRequest* request); + std::vector GetIceCandidates( + bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp); private: void OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnNonStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + /* Pure virtual methods inherited from RTC::WebRtcTransport::WebRtcTransportListener. */ + public: + void OnWebRtcTransportIceUsernameFragmentPasswordAdded( + RTC::WebRtcTransport* webRtcTransport, + const std::string& usernameFragment, + const std::string& password) override; + void OnWebRtcTransportIceUsernameFragmentPasswordRemoved( + RTC::WebRtcTransport* webRtcTransport, + const std::string& usernameFragment, + const std::string& password) override; + void OnWebRtcTransportTransportTupleAdded( + RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) override; + void OnWebRtcTransportTransportTupleRemoved( + RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) override; + /* Pure virtual methods inherited from RTC::UdpSocket::Listener. */ public: void OnUdpSocketPacketReceived( @@ -56,26 +88,17 @@ namespace RTC void OnTcpConnectionPacketReceived( RTC::TcpConnection* connection, const uint8_t* data, size_t len) override; - /* Pure virtual methods inherited from RTC::IceServer::Listener. */ - public: - void OnIceServerSendStunPacket( - const RTC::IceServer* iceServer, - const RTC::StunPacket* packet, - RTC::TransportTuple* tuple) override; - void OnIceServerSelectedTuple(const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) override; - void OnIceServerConnected(const RTC::IceServer* iceServer) override; - void OnIceServerCompleted(const RTC::IceServer* iceServer) override; - void OnIceServerDisconnected(const RTC::IceServer* iceServer) override; - public: // Passed by argument. const std::string id; private: - // Map of UdpSocket/TcpServer and local announced IP (if any). - absl::flat_hash_map udpSockets; - absl::flat_hash_map tcpServers; - std::vector iceCandidates; + // Vector of UdpSockets and TcpServers in the user given order. + std::vector udpSocketOrTcpServers; + // Map of WebRtcTransports indexed by ICE usernameFragment:password. + absl::flat_hash_map mapIceUsernameFragmentPasswordWebRtcTransports; + // Map of WebRtcTransports indexed by TransportTuple. + absl::flat_hash_map mapTupleWebRtcTransports; }; } // namespace RTC diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index bcaed162af..0bf9bfc8a0 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -29,6 +29,27 @@ namespace RTC std::string announcedIp; }; + public: + class WebRtcTransportListener + { + public: + virtual ~WebRtcTransportListener() = default; + + public: + virtual void OnWebRtcTransportIceUsernameFragmentPasswordAdded( + RTC::WebRtcTransport* webRtcTransport, + const std::string& usernameFragment, + const std::string& password) = 0; + virtual void OnWebRtcTransportIceUsernameFragmentPasswordRemoved( + RTC::WebRtcTransport* webRtcTransport, + const std::string& usernameFragment, + const std::string& password) = 0; + virtual void OnWebRtcTransportTransportTupleAdded( + RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) = 0; + virtual void OnWebRtcTransportTransportTupleRemoved( + RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) = 0; + }; + public: WebRtcTransport(const std::string& id, RTC::Transport::Listener* listener, json& data); ~WebRtcTransport() override; diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index 66d4ddc1b5..afa67ac28a 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -21,6 +21,7 @@ namespace Channel { "router.close", ChannelRequest::MethodId::ROUTER_CLOSE }, { "router.dump", ChannelRequest::MethodId::ROUTER_DUMP }, { "router.createWebRtcTransport", ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT }, + { "router.createWebRtcTransportWithServer", ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER }, { "router.createPlainTransport", ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT }, { "router.createPipeTransport", ChannelRequest::MethodId::ROUTER_CREATE_PIPE_TRANSPORT }, { "router.createDirectTransport", ChannelRequest::MethodId::ROUTER_CREATE_DIRECT_TRANSPORT }, diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 95e6e00387..83fd0a21ee 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -32,181 +32,110 @@ namespace RTC { MS_TRACE(); - bool enableUdp{ true }; - auto jsonEnableUdpIt = data.find("enableUdp"); + auto jsonListenInfosIt = data.find("listenInfos"); - if (jsonEnableUdpIt != data.end()) - { - if (!jsonEnableUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)"); - - enableUdp = jsonEnableUdpIt->get(); - } - - bool enableTcp{ false }; - auto jsonEnableTcpIt = data.find("enableTcp"); - - if (jsonEnableTcpIt != data.end()) - { - if (!jsonEnableTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)"); - - enableTcp = jsonEnableTcpIt->get(); - } - - bool preferUdp{ false }; - auto jsonPreferUdpIt = data.find("preferUdp"); - - if (jsonPreferUdpIt != data.end()) - { - if (!jsonPreferUdpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)"); - - preferUdp = jsonPreferUdpIt->get(); - } + if (jsonListenInfosIt == data.end()) + MS_THROW_TYPE_ERROR("missing listenInfos"); + else if (!jsonListenInfosIt->is_array()) + MS_THROW_TYPE_ERROR("wrong listenInfos (not an array)"); + else if (jsonListenInfosIt->empty()) + MS_THROW_TYPE_ERROR("wrong listenInfos (empty array)"); + else if (jsonListenInfosIt->size() > 8) + MS_THROW_TYPE_ERROR("wrong listenInfos (too many entries)"); - bool preferTcp{ false }; - auto jsonPreferTcpIt = data.find("preferTcp"); + std::vector listenInfos(jsonListenInfosIt->size()); - if (jsonPreferTcpIt != data.end()) + for (size_t i{ 0 }; i < jsonListenInfosIt->size(); ++i) { - if (!jsonPreferTcpIt->is_boolean()) - MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)"); + auto& jsonListenInfo = (*jsonListenInfosIt)[i]; + auto& listenInfo = listenInfos[i]; - preferTcp = jsonPreferTcpIt->get(); - } + if (!jsonListenInfo.is_object()) + MS_THROW_TYPE_ERROR("wrong listenInfo (not an object)"); - auto jsonListenIpPortsIt = data.find("listenIpPorts"); + auto jsonProtocolIt = jsonListenInfo.find("protocol"); - if (jsonListenIpPortsIt == data.end()) - MS_THROW_TYPE_ERROR("missing listenIpPorts"); - else if (!jsonListenIpPortsIt->is_array()) - MS_THROW_TYPE_ERROR("wrong listenIpPorts (not an array)"); - else if (jsonListenIpPortsIt->empty()) - MS_THROW_TYPE_ERROR("wrong listenIpPorts (empty array)"); - else if (jsonListenIpPortsIt->size() > 8) - MS_THROW_TYPE_ERROR("wrong listenIpPorts (too many entries)"); + if (jsonProtocolIt == jsonListenInfo.end()) + MS_THROW_TYPE_ERROR("missing listenInfo.protocol"); + else if (!jsonProtocolIt->is_string()) + MS_THROW_TYPE_ERROR("wrong listenInfo.protocol (not an string"); - std::vector listenIpPorts(jsonListenIpPortsIt->size()); + std::string protocolStr = jsonProtocolIt->get(); - for (size_t i{ 0 }; i < jsonListenIpPortsIt->size(); ++i) - { - auto& jsonListenIpPort = (*jsonListenIpPortsIt)[i]; - auto& listenIpPort = listenIpPorts[i]; + Utils::String::ToLowerCase(protocolStr); - if (!jsonListenIpPort.is_object()) - MS_THROW_TYPE_ERROR("wrong listenIpPort (not an object)"); + if (protocolStr == "udp") + listenInfo.protocol = RTC::TransportTuple::Protocol::UDP; + else if (protocolStr == "tcp") + listenInfo.protocol = RTC::TransportTuple::Protocol::TCP; + else + MS_THROW_TYPE_ERROR("invalid listenInfo.protocol (must be 'udp' or 'tcp'"); - auto jsonIpIt = jsonListenIpPort.find("ip"); + auto jsonIpIt = jsonListenInfo.find("ip"); - if (jsonIpIt == jsonListenIpPort.end()) - MS_THROW_TYPE_ERROR("missing listenIpPort.ip"); + if (jsonIpIt == jsonListenInfo.end()) + MS_THROW_TYPE_ERROR("missing listenInfo.ip"); else if (!jsonIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIpPort.ip (not an string"); + MS_THROW_TYPE_ERROR("wrong listenInfo.ip (not an string"); - listenIpPort.ip.assign(jsonIpIt->get()); + listenInfo.ip.assign(jsonIpIt->get()); // This may throw. - Utils::IP::NormalizeIp(listenIpPort.ip); + Utils::IP::NormalizeIp(listenInfo.ip); - auto jsonAnnouncedIpIt = jsonListenIpPort.find("announcedIp"); + auto jsonAnnouncedIpIt = jsonListenInfo.find("announcedIp"); - if (jsonAnnouncedIpIt != jsonListenIpPort.end()) + if (jsonAnnouncedIpIt != jsonListenInfo.end()) { if (!jsonAnnouncedIpIt->is_string()) - MS_THROW_TYPE_ERROR("wrong listenIpPort.announcedIp (not an string)"); + MS_THROW_TYPE_ERROR("wrong listenInfo.announcedIp (not an string)"); - listenIpPort.announcedIp.assign(jsonAnnouncedIpIt->get()); + listenInfo.announcedIp.assign(jsonAnnouncedIpIt->get()); } - auto jsonPortIt = jsonListenIpPort.find("port"); + auto jsonPortIt = jsonListenInfo.find("port"); - if (jsonPortIt == jsonListenIpPort.end()) - MS_THROW_TYPE_ERROR("missing listenIpPort.port"); + if (jsonPortIt == jsonListenInfo.end()) + MS_THROW_TYPE_ERROR("missing listenInfo.port"); else if (!(jsonPortIt->is_number() && Utils::Json::IsPositiveInteger(*jsonPortIt))) - MS_THROW_TYPE_ERROR("wrong listenIpPort.port (not a positive number)"); + MS_THROW_TYPE_ERROR("wrong listenInfo.port (not a positive number)"); - listenIpPort.port = jsonPortIt->get(); + listenInfo.port = jsonPortIt->get(); } try { - uint16_t iceLocalPreferenceDecrement{ 0 }; - - if (enableUdp && enableTcp) - this->iceCandidates.reserve(2 * jsonListenIpPortsIt->size()); - else - this->iceCandidates.reserve(jsonListenIpPortsIt->size()); - - for (auto& listenIpPort : listenIpPorts) + for (auto& listenInfo : listenInfos) { - if (enableUdp) + if (listenInfo.protocol == RTC::TransportTuple::Protocol::UDP) { - uint16_t iceLocalPreference = - IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; - - if (preferUdp) - iceLocalPreference += 1000; - - uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); - // This may throw. - auto* udpSocket = new RTC::UdpSocket(this, listenIpPort.ip, listenIpPort.port); - - this->udpSockets[udpSocket] = listenIpPort.announcedIp; + auto* udpSocket = new RTC::UdpSocket(this, listenInfo.ip, listenInfo.port); - if (listenIpPort.announcedIp.empty()) - this->iceCandidates.emplace_back(udpSocket, icePriority); - else - this->iceCandidates.emplace_back(udpSocket, icePriority, listenIpPort.announcedIp); + this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, listenInfo.announcedIp); } - - if (enableTcp) + else if (listenInfo.protocol == RTC::TransportTuple::Protocol::TCP) { - uint16_t iceLocalPreference = - IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; - - if (preferTcp) - iceLocalPreference += 1000; - - uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); - // This may throw. - auto* tcpServer = new RTC::TcpServer(this, this, listenIpPort.ip, listenIpPort.port); + auto* tcpServer = new RTC::TcpServer(this, this, listenInfo.ip, listenInfo.port); - this->tcpServers[tcpServer] = listenIpPort.announcedIp; - - if (listenIpPort.announcedIp.empty()) - this->iceCandidates.emplace_back(tcpServer, icePriority); - else - this->iceCandidates.emplace_back(tcpServer, icePriority, listenIpPort.announcedIp); + this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, listenInfo.announcedIp); } - - // Decrement initial ICE local preference for next IP. - iceLocalPreferenceDecrement += 100; } } catch (const MediaSoupError& error) { // Must delete everything since the destructor won't be called. - for (auto& kv : this->udpSockets) - { - auto* udpSocket = kv.first; - - delete udpSocket; - } - this->udpSockets.clear(); - - for (auto& kv : this->tcpServers) + for (auto& item : this->udpSocketOrTcpServers) { - auto* tcpServer = kv.first; + delete item.udpSocket; + item.udpSocket = nullptr; - delete tcpServer; + delete item.tcpServer; + item.tcpServer = nullptr; } - this->tcpServers.clear(); - - this->iceCandidates.clear(); + this->udpSocketOrTcpServers.clear(); throw; } @@ -216,23 +145,15 @@ namespace RTC { MS_TRACE(); - for (auto& kv : this->udpSockets) - { - auto* udpSocket = kv.first; - - delete udpSocket; - } - this->udpSockets.clear(); - - for (auto& kv : this->tcpServers) + for (auto& item : this->udpSocketOrTcpServers) { - auto* tcpServer = kv.first; + delete item.udpSocket; + item.udpSocket = nullptr; - delete tcpServer; + delete item.tcpServer; + item.tcpServer = nullptr; } - this->tcpServers.clear(); - - this->iceCandidates.clear(); + this->udpSocketOrTcpServers.clear(); } void WebRtcServer::FillJson(json& jsonObject) const @@ -242,19 +163,7 @@ namespace RTC // Add id. jsonObject["id"] = this->id; - // Add iceCandidates. - jsonObject["iceCandidates"] = json::array(); - auto jsonIceCandidatesIt = jsonObject.find("iceCandidates"); - - for (size_t i{ 0 }; i < this->iceCandidates.size(); ++i) - { - jsonIceCandidatesIt->emplace_back(json::value_t::object); - - auto& jsonEntry = (*jsonIceCandidatesIt)[i]; - auto& iceCandidate = this->iceCandidates[i]; - - iceCandidate.FillJson(jsonEntry); - } + // TODO: Dump udpSockets and tcpServers? and webRtcTransports?. } void WebRtcServer::HandleRequest(Channel::ChannelRequest* request) @@ -281,6 +190,52 @@ namespace RTC } } + std::vector WebRtcServer::GetIceCandidates( + bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp) + { + MS_TRACE(); + + std::vector iceCandidates; + uint16_t iceLocalPreferenceDecrement{ 0 }; + + for (auto& item : this->udpSocketOrTcpServers) + { + if (item.udpSocket && enableUdp) + { + uint16_t iceLocalPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; + + if (preferUdp) + iceLocalPreference += 1000; + + uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + + if (item.announcedIp.empty()) + iceCandidates.emplace_back(item.udpSocket, icePriority); + else + iceCandidates.emplace_back(item.udpSocket, icePriority, item.announcedIp); + } + else if (item.tcpServer && enableTcp) + { + uint16_t iceLocalPreference = IceCandidateDefaultLocalPriority - iceLocalPreferenceDecrement; + + if (preferTcp) + iceLocalPreference += 1000; + + uint32_t icePriority = generateIceCandidatePriority(iceLocalPreference); + + if (item.announcedIp.empty()) + iceCandidates.emplace_back(item.tcpServer, icePriority); + else + iceCandidates.emplace_back(item.tcpServer, icePriority, item.announcedIp); + } + + // Decrement initial ICE local preference for next IP. + iceLocalPreferenceDecrement += 100; + } + + return iceCandidates; + } + inline void WebRtcServer::OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len) { MS_TRACE(); @@ -308,7 +263,8 @@ namespace RTC return; } - // TODO + // TODO: Match entry in this->mapIceUsernameFragmentPasswordWebRtcTransports + // and call webRtcTransport.processStunPacketFromWebRtcServer(tuple, packet). delete packet; } @@ -318,73 +274,74 @@ namespace RTC { MS_TRACE(); - // TODO + // TODO: Match entry in this->mapTupleWebRtcTransports and call + // webRtcTransport.processNonStunDataFromWebRtcServer(tuple, data, len). } - inline void WebRtcServer::OnUdpSocketPacketReceived( - RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr) + inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordAdded( + RTC::WebRtcTransport* webRtcTransport, + const std::string& usernameFragment, + const std::string& password) { MS_TRACE(); - RTC::TransportTuple tuple(socket, remoteAddr); - - OnPacketReceived(&tuple, data, len); + // TODO: Add corresponding entry in this->mapIceUsernameFragmentPasswordWebRtcTransports. } - inline void WebRtcServer::OnRtcTcpConnectionClosed( - RTC::TcpServer* /*tcpServer*/, RTC::TcpConnection* connection) + inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordRemoved( + RTC::WebRtcTransport* webRtcTransport, + const std::string& usernameFragment, + const std::string& password) { MS_TRACE(); - RTC::TransportTuple tuple(connection); - - // TODO + // TODO: Remove corresponding entry in this->mapIceUsernameFragmentPasswordWebRtcTransports. } - inline void WebRtcServer::OnTcpConnectionPacketReceived( - RTC::TcpConnection* connection, const uint8_t* data, size_t len) + inline void WebRtcServer::OnWebRtcTransportTransportTupleAdded( + RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) { MS_TRACE(); - RTC::TransportTuple tuple(connection); - - OnPacketReceived(&tuple, data, len); + // TODO: Add corresponding entry in this->mapTupleWebRtcTransports. } - inline void WebRtcServer::OnIceServerSendStunPacket( - const RTC::IceServer* /*iceServer*/, const RTC::StunPacket* packet, RTC::TransportTuple* tuple) + inline void WebRtcServer::OnWebRtcTransportTransportTupleRemoved( + RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) { MS_TRACE(); - // TODO + // TODO: Remove corresponding entry in this->mapTupleWebRtcTransports. } - inline void WebRtcServer::OnIceServerSelectedTuple( - const RTC::IceServer* /*iceServer*/, RTC::TransportTuple* /*tuple*/) + inline void WebRtcServer::OnUdpSocketPacketReceived( + RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr) { MS_TRACE(); - // TODO - } - - inline void WebRtcServer::OnIceServerConnected(const RTC::IceServer* /*iceServer*/) - { - MS_TRACE(); + RTC::TransportTuple tuple(socket, remoteAddr); - // TODO + OnPacketReceived(&tuple, data, len); } - inline void WebRtcServer::OnIceServerCompleted(const RTC::IceServer* /*iceServer*/) + inline void WebRtcServer::OnRtcTcpConnectionClosed( + RTC::TcpServer* /*tcpServer*/, RTC::TcpConnection* connection) { MS_TRACE(); - // TODO + RTC::TransportTuple tuple(connection); + + // TODO: Look for the tuple in this->mapTupleWebRtcTransports and call + // webRtcTransport.removeTuple(tuple). Just it. } - inline void WebRtcServer::OnIceServerDisconnected(const RTC::IceServer* /*iceServer*/) + inline void WebRtcServer::OnTcpConnectionPacketReceived( + RTC::TcpConnection* connection, const uint8_t* data, size_t len) { MS_TRACE(); - // TODO + RTC::TransportTuple tuple(connection); + + OnPacketReceived(&tuple, data, len); } } // namespace RTC From f7fd0f675af16a8d1bfba8e90264dc4e03ae3e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 16:30:58 +0200 Subject: [PATCH 04/58] more --- worker/src/RTC/WebRtcServer.cpp | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 83fd0a21ee..3f341cb134 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -154,6 +154,43 @@ namespace RTC item.tcpServer = nullptr; } this->udpSocketOrTcpServers.clear(); + + // Close all WebRtcTransports. + + for (auto it = this->mapIceUsernameFragmentPasswordWebRtcTransports.begin(); + it != this->mapIceUsernameFragmentPasswordWebRtcTransports.end(); + ++it) + { + auto* webRtcTransport = it->second; + + this->mapIceUsernameFragmentPasswordWebRtcTransports.erase(it); + + // Let the Router be notified about closed Producers/Consumers in the + // WebRtcTransport that will be closed. + webRtcTransport->CloseProducersAndConsumers(); + + // NOTE: The WebRtcTransport destructor will invoke N events in its + // webRtcTransportListener (this is, WebRtcServer) that will affect these + // maps so caution. + delete webRtcTransport; + } + + for (auto it = this->mapTupleWebRtcTransports.begin(); it != this->mapTupleWebRtcTransports.end(); + ++it) + { + auto* webRtcTransport = it->second; + + this->mapTupleWebRtcTransports.erase(it); + + // Let the Router be notified about closed Producers/Consumers in the + // WebRtcTransport that will be closed. + webRtcTransport->CloseProducersAndConsumers(); + + // NOTE: The WebRtcTransport destructor will invoke N events in its + // webRtcTransportListener (this is, WebRtcServer) that will affect these + // maps so caution. + delete webRtcTransport; + } } void WebRtcServer::FillJson(json& jsonObject) const From d1d4f78b44dd9a2e3ab23f6bb3979ac9cf70a562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 17:01:58 +0200 Subject: [PATCH 05/58] more --- TODO_WEBRTC_SERVER.md | 5 +++++ worker/include/RTC/TransportTuple.hpp | 24 ++++++++++++++++++++++++ worker/include/RTC/WebRtcServer.hpp | 4 ++-- worker/src/RTC/TransportTuple.cpp | 1 - worker/src/RTC/WebRtcServer.cpp | 12 ++++++++---- 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index 96d1e6e30f..c89ffa4a23 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -19,3 +19,8 @@ No matter the value is super high, in Linux it's limited by `/proc/sys/net/core/ ### Handle limit of UDP/TCP tuples in WebRtcTransport This is needed no matter `WebRtcServer` is used or not. Each `WebRtcTransport` should manage max number of UDP and TCP tuples and remove old one (non selected one) etc when a new one is created or reject new one, let's see. + + +### Use the new TransportTuple.id + +In `IceServer` we use `tuple.compare()` but now we have `tuple->id` to match things. See `GenerateId()` in `TransportTuple.hpp`. diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index d1c5d28b5d..13319aba29 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -28,11 +28,13 @@ namespace RTC TransportTuple(RTC::UdpSocket* udpSocket, const struct sockaddr* udpRemoteAddr) : udpSocket(udpSocket), udpRemoteAddr((struct sockaddr*)udpRemoteAddr), protocol(Protocol::UDP) { + GenerateId(); } explicit TransportTuple(RTC::TcpConnection* tcpConnection) : tcpConnection(tcpConnection), protocol(Protocol::TCP) { + GenerateId(); } explicit TransportTuple(const TransportTuple* tuple) @@ -40,6 +42,8 @@ namespace RTC tcpConnection(tuple->tcpConnection), localAnnouncedIp(tuple->localAnnouncedIp), protocol(tuple->protocol) { + this->id = tuple->id; + if (protocol == TransportTuple::Protocol::UDP) StoreUdpRemoteAddress(); } @@ -125,6 +129,26 @@ namespace RTC return this->tcpConnection->GetSentBytes(); } + private: + void GenerateId() + { + const std::string protocol = this->protocol == Protocol::UDP ? "udp" : "tcp"; + int family; + std::string localIp; + uint16_t localPort; + std::string remoteIp; + uint16_t remotePort; + + Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); + Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); + + this->id = protocol + "_" + std::to_string(family) + "_" + protocol + "_" + remoteIp + "_" + + std::to_string(remotePort) + "_" + localIp + "_" + std::to_string(localPort); + } + + public: + std::string id; + private: // Passed by argument. RTC::UdpSocket* udpSocket{ nullptr }; diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 389e1aa9e5..3df06a1085 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -97,8 +97,8 @@ namespace RTC std::vector udpSocketOrTcpServers; // Map of WebRtcTransports indexed by ICE usernameFragment:password. absl::flat_hash_map mapIceUsernameFragmentPasswordWebRtcTransports; - // Map of WebRtcTransports indexed by TransportTuple. - absl::flat_hash_map mapTupleWebRtcTransports; + // Map of WebRtcTransports indexed by TransportTuple.id. + absl::flat_hash_map mapTupleWebRtcTransports; }; } // namespace RTC diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index d54c4fd6be..ab8dce24b2 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -3,7 +3,6 @@ #include "RTC/TransportTuple.hpp" #include "Logger.hpp" -#include "Utils.hpp" #include namespace RTC diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 3f341cb134..9c158564f9 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -322,7 +322,9 @@ namespace RTC { MS_TRACE(); - // TODO: Add corresponding entry in this->mapIceUsernameFragmentPasswordWebRtcTransports. + const std::string key = usernameFragment + ":" + password; + + this->mapIceUsernameFragmentPasswordWebRtcTransports[key] = webRtcTransport; } inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordRemoved( @@ -332,7 +334,9 @@ namespace RTC { MS_TRACE(); - // TODO: Remove corresponding entry in this->mapIceUsernameFragmentPasswordWebRtcTransports. + const std::string key = usernameFragment + ":" + password; + + this->mapIceUsernameFragmentPasswordWebRtcTransports.erase(key); } inline void WebRtcServer::OnWebRtcTransportTransportTupleAdded( @@ -340,7 +344,7 @@ namespace RTC { MS_TRACE(); - // TODO: Add corresponding entry in this->mapTupleWebRtcTransports. + this->mapTupleWebRtcTransports[tuple->id] = webRtcTransport; } inline void WebRtcServer::OnWebRtcTransportTransportTupleRemoved( @@ -348,7 +352,7 @@ namespace RTC { MS_TRACE(); - // TODO: Remove corresponding entry in this->mapTupleWebRtcTransports. + this->mapTupleWebRtcTransports.erase(tuple->id); } inline void WebRtcServer::OnUdpSocketPacketReceived( From c0ee2e5ce08565f31825bebb9e20dcc7d0042eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 17:33:44 +0200 Subject: [PATCH 06/58] Handle WebRtcServer closure --- TODO_WEBRTC_SERVER.md | 21 +++++++++++++++++++++ worker/include/RTC/Router.hpp | 1 + worker/include/RTC/Transport.hpp | 2 ++ worker/include/RTC/WebRtcTransport.hpp | 1 + worker/src/RTC/Router.cpp | 21 ++++++++++++++++++++- worker/src/RTC/Transport.cpp | 8 ++++++++ worker/src/RTC/WebRtcServer.cpp | 23 ++++++----------------- worker/src/RTC/WebRtcTransport.cpp | 7 +++++++ 8 files changed, 66 insertions(+), 18 deletions(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index c89ffa4a23..0e168b8b2a 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -1,6 +1,27 @@ # TODO WebRtcServer +### What happens with its WebRtcTransports when closing a WebRtcServer? + +This is hard. And there must be a parallelism between TS/Rust and C++. + +Proposal: + +* `webRtcServer.close()` carefully iterates its maps and calls `webRtcTransport.webRtcServerClosed()`. +* `webRtcTransport.webRtcServerClosed()` calls a new parent `Transport::MustClose()` method. +* `Transport::MustClose()` calls a new `this->listener->OnTransportMustClose(this)`. +* `Router.OnTransportMustClose(transport)` does: + - Call `transport->CloseProducersAndConsumers()` so `Router` is notified about closed `Producers` and `Consumers` and can remove them from its maps. + - Remove the `transport` from it map. + - Call `delete transport`. + +Note that the destructor of `WebRtcTransport` will invoke `delete this->iceServer` which will trigger may callbacks called in `WebRtcServer` that will remove the `transport` from its maps. + +NOTE: All the above is done in the branch. + +And let's see how to do it in TS/Rust for things to be similar. + + ### Remove limit of TcpConnections per TcpServer Also increase `backlog(int)` in `uv_listen`(POSIX argument): diff --git a/worker/include/RTC/Router.hpp b/worker/include/RTC/Router.hpp index 02b331b42d..5844407cf2 100644 --- a/worker/include/RTC/Router.hpp +++ b/worker/include/RTC/Router.hpp @@ -43,6 +43,7 @@ namespace RTC /* Pure virtual methods inherited from RTC::Transport::Listener. */ public: + void OnTransportMustClose(RTC::Transport* transport) override; void OnTransportNewProducer(RTC::Transport* transport, RTC::Producer* producer) override; void OnTransportProducerClosed(RTC::Transport* transport, RTC::Producer* producer) override; void OnTransportProducerPaused(RTC::Transport* transport, RTC::Producer* producer) override; diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index d1195504a1..b5ad926123 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -57,6 +57,7 @@ namespace RTC virtual ~Listener() = default; public: + virtual void OnTransportMustClose(RTC::Transport* transport) = 0; virtual void OnTransportNewProducer(RTC::Transport* transport, RTC::Producer* producer) = 0; virtual void OnTransportProducerClosed(RTC::Transport* transport, RTC::Producer* producer) = 0; virtual void OnTransportProducerPaused(RTC::Transport* transport, RTC::Producer* producer) = 0; @@ -118,6 +119,7 @@ namespace RTC virtual ~Transport(); public: + void MustClose(); void CloseProducersAndConsumers(); // Subclasses must also invoke the parent Close(). virtual void FillJson(json& jsonObject) const; diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 0bf9bfc8a0..2603eaf4ca 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -59,6 +59,7 @@ namespace RTC void FillJsonStats(json& jsonArray) override; void HandleRequest(Channel::ChannelRequest* request) override; void HandleNotification(PayloadChannel::Notification* notification) override; + void WebRtcServerClosed(); private: bool IsConnected() const override; diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 17eac9e9e0..bb5861dbc2 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -318,7 +318,7 @@ namespace RTC // notify us about their closures. transport->CloseProducersAndConsumers(); - // Remove it from the map and delete it. + // Remove it from the map. this->mapTransports.erase(transport->id); MS_DEBUG_DEV("Transport closed [transportId:%s]", transport->id.c_str()); @@ -533,6 +533,25 @@ namespace RTC return producer; } + inline void Router::OnTransportMustClose(RTC::Transport* transport) + { + MS_TRACE(); + + MS_ASSERT( + this->mapTransports.find(transport->id) != this->mapTransports.end(), + "Transport not present in mapTransports"); + + // Tell the Transport to close all its Producers and Consumers so it will + // notify us about their closures. + transport->CloseProducersAndConsumers(); + + // Remove it from the map. + this->mapTransports.erase(transport->id); + + // Delete it. + delete transport; + } + inline void Router::OnTransportNewProducer(RTC::Transport* /*transport*/, RTC::Producer* producer) { MS_TRACE(); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 1c3ac20ccc..14d4a34024 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -246,6 +246,14 @@ namespace RTC #endif } + void Transport::MustClose() + { + MS_TRACE(); + + // Ask our parent Router to close/delete us. + this->listener->OnTransportMustClose(this); + } + void Transport::CloseProducersAndConsumers() { MS_TRACE(); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 9c158564f9..8f313f9e0d 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -155,7 +155,10 @@ namespace RTC } this->udpSocketOrTcpServers.clear(); - // Close all WebRtcTransports. + // Tell all WebRtcTransports that the WebRtcServer must has been closed. + // NOTE: The WebRtcTransport destructor will invoke N events in its + // webRtcTransportListener (this is, WebRtcServer) that will affect these + // maps so caution. for (auto it = this->mapIceUsernameFragmentPasswordWebRtcTransports.begin(); it != this->mapIceUsernameFragmentPasswordWebRtcTransports.end(); @@ -165,14 +168,7 @@ namespace RTC this->mapIceUsernameFragmentPasswordWebRtcTransports.erase(it); - // Let the Router be notified about closed Producers/Consumers in the - // WebRtcTransport that will be closed. - webRtcTransport->CloseProducersAndConsumers(); - - // NOTE: The WebRtcTransport destructor will invoke N events in its - // webRtcTransportListener (this is, WebRtcServer) that will affect these - // maps so caution. - delete webRtcTransport; + webRtcTransport->WebRtcServerClosed(); } for (auto it = this->mapTupleWebRtcTransports.begin(); it != this->mapTupleWebRtcTransports.end(); @@ -182,14 +178,7 @@ namespace RTC this->mapTupleWebRtcTransports.erase(it); - // Let the Router be notified about closed Producers/Consumers in the - // WebRtcTransport that will be closed. - webRtcTransport->CloseProducersAndConsumers(); - - // NOTE: The WebRtcTransport destructor will invoke N events in its - // webRtcTransportListener (this is, WebRtcServer) that will affect these - // maps so caution. - delete webRtcTransport; + webRtcTransport->WebRtcServerClosed(); } } diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 560786a27c..e14eb2808b 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -621,6 +621,13 @@ namespace RTC RTC::Transport::HandleNotification(notification); } + void WebRtcTransport::WebRtcServerClosed() + { + MS_TRACE(); + + RTC::Transport::MustClose(); + } + inline bool WebRtcTransport::IsConnected() const { MS_TRACE(); From e648a53527b3a6b705f2d63fecd89b3b03da5e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 17:38:04 +0200 Subject: [PATCH 07/58] cosmetic --- worker/include/RTC/TransportTuple.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 13319aba29..3294582a16 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -142,8 +142,8 @@ namespace RTC Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); - this->id = protocol + "_" + std::to_string(family) + "_" + protocol + "_" + remoteIp + "_" + - std::to_string(remotePort) + "_" + localIp + "_" + std::to_string(localPort); + this->id = remoteIp + "_" + std::to_string(remotePort) + "_" + localIp + "_" + + std::to_string(localPort) + "_" + std::to_string(family) + "_" + protocol; } public: From 8fb82c67cafea23d8473b7b6cf0e5543a24c49b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 17:59:03 +0200 Subject: [PATCH 08/58] more --- worker/include/RTC/WebRtcServer.hpp | 3 ++ worker/src/RTC/WebRtcServer.cpp | 67 +++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 3df06a1085..9a35ba6468 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -55,6 +55,9 @@ namespace RTC bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp); private: + std::string GetIceUsernameFragmentPasswordKey(RTC::StunPacket* packet) const; + std::string GetIceUsernameFragmentPasswordKey( + const std::string& usernameFragment, const std::string& password) const; void OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnNonStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 8f313f9e0d..280541a27c 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -262,6 +262,24 @@ namespace RTC return iceCandidates; } + inline std::string WebRtcServer::GetIceUsernameFragmentPasswordKey(RTC::StunPacket* packet) const + { + MS_TRACE(); + + // TODO: If this ok? is this gonna return `usernameFragment:password` and those values + // will match those in the IceServer? Must check. + + return packet->GetUsername(); + } + + inline std::string WebRtcServer::GetIceUsernameFragmentPasswordKey( + const std::string& usernameFragment, const std::string& password) const + { + MS_TRACE(); + + return usernameFragment + ":" + password; + } + inline void WebRtcServer::OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len) { MS_TRACE(); @@ -289,8 +307,22 @@ namespace RTC return; } - // TODO: Match entry in this->mapIceUsernameFragmentPasswordWebRtcTransports - // and call webRtcTransport.processStunPacketFromWebRtcServer(tuple, packet). + auto key = GetIceUsernameFragmentPasswordKey(packet); + auto it = this->mapIceUsernameFragmentPasswordWebRtcTransports.find(key); + + if (it == this->mapIceUsernameFragmentPasswordWebRtcTransports.end()) + { + MS_WARN_DEV("ignoring received STUN packet with unknown associated WebRtcTransport"); + + delete packet; + + return; + } + + auto* webRtcTransport = it->second; + + // TODO: Implement. + // webRtcTransport->ProcessStunPacketFromWebRtcServer(packet); delete packet; } @@ -300,8 +332,19 @@ namespace RTC { MS_TRACE(); - // TODO: Match entry in this->mapTupleWebRtcTransports and call - // webRtcTransport.processNonStunDataFromWebRtcServer(tuple, data, len). + auto it = this->mapTupleWebRtcTransports.find(tuple->id); + + if (it == this->mapTupleWebRtcTransports.end()) + { + MS_WARN_DEV("ignoring received non STUN data from unknown source"); + + return; + } + + auto* webRtcTransport = it->second; + + // TODO: Implement. + // webRtcTransport->ProcessNonStunDataFromWebRtcServer(tuple, data, len); } inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordAdded( @@ -311,7 +354,7 @@ namespace RTC { MS_TRACE(); - const std::string key = usernameFragment + ":" + password; + auto key = GetIceUsernameFragmentPasswordKey(usernameFragment, password); this->mapIceUsernameFragmentPasswordWebRtcTransports[key] = webRtcTransport; } @@ -323,7 +366,7 @@ namespace RTC { MS_TRACE(); - const std::string key = usernameFragment + ":" + password; + auto key = GetIceUsernameFragmentPasswordKey(usernameFragment, password); this->mapIceUsernameFragmentPasswordWebRtcTransports.erase(key); } @@ -361,8 +404,16 @@ namespace RTC RTC::TransportTuple tuple(connection); - // TODO: Look for the tuple in this->mapTupleWebRtcTransports and call - // webRtcTransport.removeTuple(tuple). Just it. + auto it = this->mapTupleWebRtcTransports.find(tuple.id); + + MS_ASSERT( + it != this->mapTupleWebRtcTransports.end(), + "closed TCP connection not managed by this WebRtcServer"); + + auto* webRtcTransport = it->second; + + // TODO: Implement. + // webRtcTransport->RemoveTuple(tuple); } inline void WebRtcServer::OnTcpConnectionPacketReceived( From 91b7c6801e39ea0658418e078f49bc965bc2fcd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 17:59:33 +0200 Subject: [PATCH 09/58] foo --- worker/src/RTC/WebRtcServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 280541a27c..ed7e0e42af 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -268,6 +268,7 @@ namespace RTC // TODO: If this ok? is this gonna return `usernameFragment:password` and those values // will match those in the IceServer? Must check. + // See https://datatracker.ietf.org/doc/html/rfc5389 return packet->GetUsername(); } From 9c1f7a76f64fe550a6b3128760cb5a751ddd59b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 18:22:37 +0200 Subject: [PATCH 10/58] Even more --- TODO_WEBRTC_SERVER.md | 4 ++++ worker/include/RTC/WebRtcTransport.hpp | 3 +++ worker/src/RTC/WebRtcServer.cpp | 9 +++------ worker/src/RTC/WebRtcTransport.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index 0e168b8b2a..fbd99c0fae 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -45,3 +45,7 @@ This is needed no matter `WebRtcServer` is used or not. Each `WebRtcTransport` s ### Use the new TransportTuple.id In `IceServer` we use `tuple.compare()` but now we have `tuple->id` to match things. See `GenerateId()` in `TransportTuple.hpp`. + +### New events in `IceServer` + +As far as a tuple is added or removed it must call a new callback. diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 2603eaf4ca..2c35268f48 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -59,6 +59,9 @@ namespace RTC void FillJsonStats(json& jsonArray) override; void HandleRequest(Channel::ChannelRequest* request) override; void HandleNotification(PayloadChannel::Notification* notification) override; + void ProcessStunPacketFromWebRtcServer(const RTC::StunPacket* packet); + void ProcessNonStunDataFromWebRtcServer(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + void RemoveTuple(RTC::TransportTuple* tuple); void WebRtcServerClosed(); private: diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index ed7e0e42af..c10d966260 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -322,8 +322,7 @@ namespace RTC auto* webRtcTransport = it->second; - // TODO: Implement. - // webRtcTransport->ProcessStunPacketFromWebRtcServer(packet); + webRtcTransport->ProcessStunPacketFromWebRtcServer(packet); delete packet; } @@ -344,8 +343,7 @@ namespace RTC auto* webRtcTransport = it->second; - // TODO: Implement. - // webRtcTransport->ProcessNonStunDataFromWebRtcServer(tuple, data, len); + webRtcTransport->ProcessNonStunDataFromWebRtcServer(tuple, data, len); } inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordAdded( @@ -413,8 +411,7 @@ namespace RTC auto* webRtcTransport = it->second; - // TODO: Implement. - // webRtcTransport->RemoveTuple(tuple); + webRtcTransport->RemoveTuple(std::addressof(tuple)); } inline void WebRtcServer::OnTcpConnectionPacketReceived( diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index e14eb2808b..f87719fac9 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -621,6 +621,30 @@ namespace RTC RTC::Transport::HandleNotification(notification); } + void WebRtcTransport::ProcessStunPacketFromWebRtcServer(const RTC::StunPacket* packet) + { + MS_TRACE(); + + // TODO + } + + void WebRtcTransport::ProcessNonStunDataFromWebRtcServer( + RTC::TransportTuple* tuple, const uint8_t* data, size_t len) + { + MS_TRACE(); + + // TODO + } + + void WebRtcTransport::RemoveTuple(RTC::TransportTuple* tuple) + { + { + MS_TRACE(); + + // TODO + } + } + void WebRtcTransport::WebRtcServerClosed() { MS_TRACE(); From 5cca09bb05d31bb6114bdb09511d74c73d981c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 18:28:06 +0200 Subject: [PATCH 11/58] more --- worker/include/RTC/WebRtcTransport.hpp | 5 ++-- worker/src/RTC/WebRtcServer.cpp | 6 ++--- worker/src/RTC/WebRtcTransport.cpp | 37 ++++++++++++++++++++------ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 2c35268f48..8f86bc4252 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -59,8 +59,9 @@ namespace RTC void FillJsonStats(json& jsonArray) override; void HandleRequest(Channel::ChannelRequest* request) override; void HandleNotification(PayloadChannel::Notification* notification) override; - void ProcessStunPacketFromWebRtcServer(const RTC::StunPacket* packet); - void ProcessNonStunDataFromWebRtcServer(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); + void ProcessStunPacketFromWebRtcServer(RTC::TransportTuple* tuple, const RTC::StunPacket* packet); + void ProcessNonStunPacketFromWebRtcServer( + RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void RemoveTuple(RTC::TransportTuple* tuple); void WebRtcServerClosed(); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index c10d966260..8660d75b28 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -322,7 +322,7 @@ namespace RTC auto* webRtcTransport = it->second; - webRtcTransport->ProcessStunPacketFromWebRtcServer(packet); + webRtcTransport->ProcessStunPacketFromWebRtcServer(tuple, packet); delete packet; } @@ -343,7 +343,7 @@ namespace RTC auto* webRtcTransport = it->second; - webRtcTransport->ProcessNonStunDataFromWebRtcServer(tuple, data, len); + webRtcTransport->ProcessNonStunPacketFromWebRtcServer(tuple, data, len); } inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordAdded( @@ -411,7 +411,7 @@ namespace RTC auto* webRtcTransport = it->second; - webRtcTransport->RemoveTuple(std::addressof(tuple)); + webRtcTransport->RemoveTuple(&tuple); } inline void WebRtcServer::OnTcpConnectionPacketReceived( diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index f87719fac9..6424ae0606 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -621,28 +621,49 @@ namespace RTC RTC::Transport::HandleNotification(notification); } - void WebRtcTransport::ProcessStunPacketFromWebRtcServer(const RTC::StunPacket* packet) + void WebRtcTransport::ProcessStunPacketFromWebRtcServer( + RTC::TransportTuple* tuple, const RTC::StunPacket* packet) { MS_TRACE(); - // TODO + // Pass it to the IceServer. + this->iceServer->ProcessStunPacket(packet, tuple); } - void WebRtcTransport::ProcessNonStunDataFromWebRtcServer( + void WebRtcTransport::ProcessNonStunPacketFromWebRtcServer( RTC::TransportTuple* tuple, const uint8_t* data, size_t len) { MS_TRACE(); - // TODO + // Increase receive transmission. + RTC::Transport::DataReceived(len); + + // Check if it's RTCP. + if (RTC::RTCP::Packet::IsRtcp(data, len)) + { + OnRtcpDataReceived(tuple, data, len); + } + // Check if it's RTP. + else if (RTC::RtpPacket::IsRtp(data, len)) + { + OnRtpDataReceived(tuple, data, len); + } + // Check if it's DTLS. + else if (RTC::DtlsTransport::IsDtls(data, len)) + { + OnDtlsDataReceived(tuple, data, len); + } + else + { + MS_WARN_DEV("ignoring received packet of unknown type"); + } } void WebRtcTransport::RemoveTuple(RTC::TransportTuple* tuple) { - { - MS_TRACE(); + MS_TRACE(); - // TODO - } + this->iceServer->RemoveTuple(tuple); } void WebRtcTransport::WebRtcServerClosed() From 08063547613f0643aa60e4fad640904492a39c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 18:30:03 +0200 Subject: [PATCH 12/58] fix things --- worker/include/RTC/WebRtcTransport.hpp | 2 +- worker/src/RTC/WebRtcTransport.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 8f86bc4252..9dc29ee986 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -59,7 +59,7 @@ namespace RTC void FillJsonStats(json& jsonArray) override; void HandleRequest(Channel::ChannelRequest* request) override; void HandleNotification(PayloadChannel::Notification* notification) override; - void ProcessStunPacketFromWebRtcServer(RTC::TransportTuple* tuple, const RTC::StunPacket* packet); + void ProcessStunPacketFromWebRtcServer(RTC::TransportTuple* tuple, RTC::StunPacket* packet); void ProcessNonStunPacketFromWebRtcServer( RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void RemoveTuple(RTC::TransportTuple* tuple); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 6424ae0606..1d209075f2 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -622,7 +622,7 @@ namespace RTC } void WebRtcTransport::ProcessStunPacketFromWebRtcServer( - RTC::TransportTuple* tuple, const RTC::StunPacket* packet) + RTC::TransportTuple* tuple, RTC::StunPacket* packet) { MS_TRACE(); From b0881592074bcbcdd3d748e2b971ee854076b31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 19:04:19 +0200 Subject: [PATCH 13/58] Document an issue --- TODO_WEBRTC_SERVER.md | 33 ++++++++++++++++++++++++++++++++- worker/src/RTC/WebRtcServer.cpp | 1 + 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index fbd99c0fae..a655cd1c1d 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -1,6 +1,37 @@ # TODO WebRtcServer +### Issue obtainining `usernameFragment:password` from received STUN packets + +When we create a ICE server we decide the mediasoup side `usernameFragment` and `password` and pass them to the `IceServer` constructor. + +However, when a STUN packet is received from a client, if we check `packet->GetUsername()` (which returns `usernameFragment:password` values don't match. AFAIR this is because the STUN USERNAME field contains the remote `usernameFragment` concatenated with ":" and the **local** password. + +I've added some logs to show the problem: + +``` +mediasoup:ERROR:Channel [pid:35897 RTC::IceServer::IceServer() | ----------- IceServer constructor | usernameFragment:5k23pn9092feeudr, password:qlvg20mhaf43r7ysju41fxjafw9c0ovd +0ms + +mediasoup:ERROR:Channel [pid:35897 RTC::IceServer::IceServer() | ----------- IceServer constructor | usernameFragment:bxuwysb0l2hltk2h, password:0275z9opi3uiql3apboece5qrgvffm03 +6ms + +mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): bxuwysb0l2hltk2h:1dRN +36ms + +mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): bxuwysb0l2hltk2h:1dRN +50ms + +mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): 5k23pn9092feeudr:pJjB +22ms + +mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): bxuwysb0l2hltk2h:1dRN +40ms + +mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): 5k23pn9092feeudr:pJjB +16ms + +mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): 5k23pn9092feeudr:pJjB +64ms +```` + +So how to match received STUN packets against the credentials of our `IceServer`? We may just compare the "usernameFragment" component but unclear if this is good. Obviously the `usernameFragmet` is chosen by mediasoup `WebRtcTransport` constructor by doing `Utils::Crypto::GetRandomString(16)` so it could be good enough but still... + +STUN RFC: See https://datatracker.ietf.org/doc/html/rfc5389 + + ### What happens with its WebRtcTransports when closing a WebRtcServer? This is hard. And there must be a parallelism between TS/Rust and C++. @@ -48,4 +79,4 @@ In `IceServer` we use `tuple.compare()` but now we have `tuple->id` to match thi ### New events in `IceServer` -As far as a tuple is added or removed it must call a new callback. +As far as a tuple is added or removed it must call a new callback. Also new events when ICE username&passwd are initially set or changed later. diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 8660d75b28..cbc5eca778 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -269,6 +269,7 @@ namespace RTC // TODO: If this ok? is this gonna return `usernameFragment:password` and those values // will match those in the IceServer? Must check. // See https://datatracker.ietf.org/doc/html/rfc5389 + // No, it's not ok. See TODO_WEBRTC_SERVER.md file. return packet->GetUsername(); } From 762ee75ba7177af1b3c3caf52458c09c99f00825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 19:10:59 +0200 Subject: [PATCH 14/58] Better doc --- TODO_WEBRTC_SERVER.md | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index a655cd1c1d..adc5ea454e 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -5,29 +5,23 @@ When we create a ICE server we decide the mediasoup side `usernameFragment` and `password` and pass them to the `IceServer` constructor. -However, when a STUN packet is received from a client, if we check `packet->GetUsername()` (which returns `usernameFragment:password` values don't match. AFAIR this is because the STUN USERNAME field contains the remote `usernameFragment` concatenated with ":" and the **local** password. +However, when a STUN packet is received from a client, if we check `packet->GetUsername()` it doesn't return the mediasoup side `usernameFragment:password` values but instead `mediasoupUsernameFragment:clientUsernameFragment`. I've added some logs to show the problem: ``` -mediasoup:ERROR:Channel [pid:35897 RTC::IceServer::IceServer() | ----------- IceServer constructor | usernameFragment:5k23pn9092feeudr, password:qlvg20mhaf43r7ysju41fxjafw9c0ovd +0ms - mediasoup:ERROR:Channel [pid:35897 RTC::IceServer::IceServer() | ----------- IceServer constructor | usernameFragment:bxuwysb0l2hltk2h, password:0275z9opi3uiql3apboece5qrgvffm03 +6ms mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): bxuwysb0l2hltk2h:1dRN +36ms +```` -mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): bxuwysb0l2hltk2h:1dRN +50ms - -mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): 5k23pn9092feeudr:pJjB +22ms - -mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): bxuwysb0l2hltk2h:1dRN +40ms - -mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): 5k23pn9092feeudr:pJjB +16ms +In fact, if we show the local SDP of the client it clearly shows: -mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): 5k23pn9092feeudr:pJjB +64ms -```` +``` +a=ice-ufrag:1dRN +``` -So how to match received STUN packets against the credentials of our `IceServer`? We may just compare the "usernameFragment" component but unclear if this is good. Obviously the `usernameFragmet` is chosen by mediasoup `WebRtcTransport` constructor by doing `Utils::Crypto::GetRandomString(16)` so it could be good enough but still... +So how to match received STUN packets against the credentials of our `IceServer`? We may just compare the "usernameFragment" component but unclear if this is good. Obviously the `usernameFragmet` is chosen by mediasoup `WebRtcTransport` constructor by doing `Utils::Crypto::GetRandomString(16)` so it could be good enough but still... The thing is that mediasoup-client does NOT signal the client `a=ice-ufrag` to mediasoup because being mediasoup ICE-Lite it doesn't need it. STUN RFC: See https://datatracker.ietf.org/doc/html/rfc5389 From f33dae626e8718465a5d7da8b0a8284456223c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 20:00:50 +0200 Subject: [PATCH 15/58] fix STUN USERNAME attribute matching --- TODO_WEBRTC_SERVER.md | 8 +++- worker/include/RTC/WebRtcServer.hpp | 20 +++------ worker/include/RTC/WebRtcTransport.hpp | 12 ++---- worker/src/RTC/WebRtcServer.cpp | 59 +++++++++++--------------- worker/src/RTC/WebRtcTransport.cpp | 2 +- 5 files changed, 44 insertions(+), 57 deletions(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index adc5ea454e..23ea8a2982 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -25,6 +25,12 @@ So how to match received STUN packets against the credentials of our `IceServer` STUN RFC: See https://datatracker.ietf.org/doc/html/rfc5389 +Suggested solution: use a 32 bytes mediasoup side `usernameFragment`. + +However, there is no rule in RFC 5389 telling that `USERNAME` attribute should contain `remoteUsernameFragment:localUsernameFragment`. Anyway, in `StunPacket::CheckAuthentication()` we already rely on `USERNAME` starting by our local username fragment followed by ":". + +Done. + ### What happens with its WebRtcTransports when closing a WebRtcServer? @@ -73,4 +79,4 @@ In `IceServer` we use `tuple.compare()` but now we have `tuple->id` to match thi ### New events in `IceServer` -As far as a tuple is added or removed it must call a new callback. Also new events when ICE username&passwd are initially set or changed later. +As far as a tuple is added or removed it must call a new callback. Also new events when local ICE usernameFrag is initially set or changed later. diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 9a35ba6468..f1959067a7 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -55,23 +55,17 @@ namespace RTC bool enableUdp, bool enableTcp, bool preferUdp, bool preferTcp); private: - std::string GetIceUsernameFragmentPasswordKey(RTC::StunPacket* packet) const; - std::string GetIceUsernameFragmentPasswordKey( - const std::string& usernameFragment, const std::string& password) const; + std::string GetLocalIceUsernameFragmentFromReceivedStunPacket(RTC::StunPacket* packet) const; void OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void OnNonStunDataReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len); /* Pure virtual methods inherited from RTC::WebRtcTransport::WebRtcTransportListener. */ public: - void OnWebRtcTransportIceUsernameFragmentPasswordAdded( - RTC::WebRtcTransport* webRtcTransport, - const std::string& usernameFragment, - const std::string& password) override; - void OnWebRtcTransportIceUsernameFragmentPasswordRemoved( - RTC::WebRtcTransport* webRtcTransport, - const std::string& usernameFragment, - const std::string& password) override; + void OnWebRtcTransportLocalIceUsernameFragmentAdded( + RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) override; + void OnWebRtcTransportLocalIceUsernameFragmentRemoved( + RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) override; void OnWebRtcTransportTransportTupleAdded( RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) override; void OnWebRtcTransportTransportTupleRemoved( @@ -98,8 +92,8 @@ namespace RTC private: // Vector of UdpSockets and TcpServers in the user given order. std::vector udpSocketOrTcpServers; - // Map of WebRtcTransports indexed by ICE usernameFragment:password. - absl::flat_hash_map mapIceUsernameFragmentPasswordWebRtcTransports; + // Map of WebRtcTransports indexed by local ICE usernameFragment. + absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransports; // Map of WebRtcTransports indexed by TransportTuple.id. absl::flat_hash_map mapTupleWebRtcTransports; }; diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 9dc29ee986..b215b027e7 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -36,14 +36,10 @@ namespace RTC virtual ~WebRtcTransportListener() = default; public: - virtual void OnWebRtcTransportIceUsernameFragmentPasswordAdded( - RTC::WebRtcTransport* webRtcTransport, - const std::string& usernameFragment, - const std::string& password) = 0; - virtual void OnWebRtcTransportIceUsernameFragmentPasswordRemoved( - RTC::WebRtcTransport* webRtcTransport, - const std::string& usernameFragment, - const std::string& password) = 0; + virtual void OnWebRtcTransportLocalIceUsernameFragmentAdded( + RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) = 0; + virtual void OnWebRtcTransportLocalIceUsernameFragmentRemoved( + RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) = 0; virtual void OnWebRtcTransportTransportTupleAdded( RTC::WebRtcTransport* webRtcTransport, RTC::TransportTuple* tuple) = 0; virtual void OnWebRtcTransportTransportTupleRemoved( diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index cbc5eca778..612588d9ba 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -160,13 +160,13 @@ namespace RTC // webRtcTransportListener (this is, WebRtcServer) that will affect these // maps so caution. - for (auto it = this->mapIceUsernameFragmentPasswordWebRtcTransports.begin(); - it != this->mapIceUsernameFragmentPasswordWebRtcTransports.end(); + for (auto it = this->mapLocalIceUsernameFragmentWebRtcTransports.begin(); + it != this->mapLocalIceUsernameFragmentWebRtcTransports.end(); ++it) { auto* webRtcTransport = it->second; - this->mapIceUsernameFragmentPasswordWebRtcTransports.erase(it); + this->mapLocalIceUsernameFragmentWebRtcTransports.erase(it); webRtcTransport->WebRtcServerClosed(); } @@ -262,24 +262,23 @@ namespace RTC return iceCandidates; } - inline std::string WebRtcServer::GetIceUsernameFragmentPasswordKey(RTC::StunPacket* packet) const + inline std::string WebRtcServer::GetLocalIceUsernameFragmentFromReceivedStunPacket( + RTC::StunPacket* packet) const { MS_TRACE(); - // TODO: If this ok? is this gonna return `usernameFragment:password` and those values - // will match those in the IceServer? Must check. - // See https://datatracker.ietf.org/doc/html/rfc5389 - // No, it's not ok. See TODO_WEBRTC_SERVER.md file. + // Here we inspect the USERNAME attribute of a received STUN request and + // extract its remote usernameFragment (the one given to our IceServwer) + // which is the first value in the attribute value before the ":" symbol. - return packet->GetUsername(); - } + auto& username = packet->GetUsername(); + size_t colonPos = username.find(":"); - inline std::string WebRtcServer::GetIceUsernameFragmentPasswordKey( - const std::string& usernameFragment, const std::string& password) const - { - MS_TRACE(); + // If no colon is found just return the whole USERNAME attribute anyway. + if (colonPos == std::string::npos) + return username; - return usernameFragment + ":" + password; + return username.substr(0, colonPos); } inline void WebRtcServer::OnPacketReceived(RTC::TransportTuple* tuple, const uint8_t* data, size_t len) @@ -309,12 +308,12 @@ namespace RTC return; } - auto key = GetIceUsernameFragmentPasswordKey(packet); - auto it = this->mapIceUsernameFragmentPasswordWebRtcTransports.find(key); + auto key = GetLocalIceUsernameFragmentFromReceivedStunPacket(packet); + auto it = this->mapLocalIceUsernameFragmentWebRtcTransports.find(key); - if (it == this->mapIceUsernameFragmentPasswordWebRtcTransports.end()) + if (it == this->mapLocalIceUsernameFragmentWebRtcTransports.end()) { - MS_WARN_DEV("ignoring received STUN packet with unknown associated WebRtcTransport"); + MS_WARN_DEV("ignoring received STUN packet with unknown remote ICE usernameFragment"); delete packet; @@ -337,7 +336,7 @@ namespace RTC if (it == this->mapTupleWebRtcTransports.end()) { - MS_WARN_DEV("ignoring received non STUN data from unknown source"); + MS_WARN_DEV("ignoring received non STUN data from unknown tuple"); return; } @@ -347,28 +346,20 @@ namespace RTC webRtcTransport->ProcessNonStunPacketFromWebRtcServer(tuple, data, len); } - inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordAdded( - RTC::WebRtcTransport* webRtcTransport, - const std::string& usernameFragment, - const std::string& password) + inline void WebRtcServer::OnWebRtcTransportLocalIceUsernameFragmentAdded( + RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) { MS_TRACE(); - auto key = GetIceUsernameFragmentPasswordKey(usernameFragment, password); - - this->mapIceUsernameFragmentPasswordWebRtcTransports[key] = webRtcTransport; + this->mapLocalIceUsernameFragmentWebRtcTransports[usernameFragment] = webRtcTransport; } - inline void WebRtcServer::OnWebRtcTransportIceUsernameFragmentPasswordRemoved( - RTC::WebRtcTransport* webRtcTransport, - const std::string& usernameFragment, - const std::string& password) + inline void WebRtcServer::OnWebRtcTransportLocalIceUsernameFragmentRemoved( + RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) { MS_TRACE(); - auto key = GetIceUsernameFragmentPasswordKey(usernameFragment, password); - - this->mapIceUsernameFragmentPasswordWebRtcTransports.erase(key); + this->mapLocalIceUsernameFragmentWebRtcTransports.erase(usernameFragment); } inline void WebRtcServer::OnWebRtcTransportTransportTupleAdded( diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 1d209075f2..cd3c508ba0 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -199,7 +199,7 @@ namespace RTC // Create a ICE server. this->iceServer = new RTC::IceServer( - this, Utils::Crypto::GetRandomString(16), Utils::Crypto::GetRandomString(32)); + this, Utils::Crypto::GetRandomString(32), Utils::Crypto::GetRandomString(32)); // Create a DTLS transport. this->dtlsTransport = new RTC::DtlsTransport(this); From 0d26814126cd98b90080ac9084a960b9b74609b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 20:06:29 +0200 Subject: [PATCH 16/58] HArdcode TCP listen backlog to 256 because it's mostly irrelevant --- worker/include/handles/TcpServerHandler.hpp | 2 +- worker/src/RTC/TcpServer.cpp | 6 +++--- worker/src/handles/TcpServerHandler.cpp | 8 ++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/worker/include/handles/TcpServerHandler.hpp b/worker/include/handles/TcpServerHandler.hpp index 7c5ddc400c..ad7b52e8aa 100644 --- a/worker/include/handles/TcpServerHandler.hpp +++ b/worker/include/handles/TcpServerHandler.hpp @@ -13,7 +13,7 @@ class TcpServerHandler : public TcpConnectionHandler::Listener /** * uvHandle must be an already initialized and binded uv_tcp_t pointer. */ - TcpServerHandler(uv_tcp_t* uvHandle, int backlog); + TcpServerHandler(uv_tcp_t* uvHandle); virtual ~TcpServerHandler() override; public: diff --git a/worker/src/RTC/TcpServer.cpp b/worker/src/RTC/TcpServer.cpp index 098a559c1d..9c0579ae00 100644 --- a/worker/src/RTC/TcpServer.cpp +++ b/worker/src/RTC/TcpServer.cpp @@ -16,7 +16,7 @@ namespace RTC TcpServer::TcpServer(Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip) : // This may throw. - ::TcpServerHandler::TcpServerHandler(RTC::PortManager::BindTcp(ip), 256), listener(listener), + ::TcpServerHandler::TcpServerHandler(RTC::PortManager::BindTcp(ip)), listener(listener), connListener(connListener), fixedPort(false) { MS_TRACE(); @@ -25,8 +25,8 @@ namespace RTC TcpServer::TcpServer( Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, uint16_t port) : // This may throw. - ::TcpServerHandler::TcpServerHandler(RTC::PortManager::BindTcp(ip, port), 256), - listener(listener), connListener(connListener), fixedPort(true) + ::TcpServerHandler::TcpServerHandler(RTC::PortManager::BindTcp(ip, port)), listener(listener), + connListener(connListener), fixedPort(true) { MS_TRACE(); } diff --git a/worker/src/handles/TcpServerHandler.cpp b/worker/src/handles/TcpServerHandler.cpp index 82fc9adc26..50f8418845 100644 --- a/worker/src/handles/TcpServerHandler.cpp +++ b/worker/src/handles/TcpServerHandler.cpp @@ -6,6 +6,10 @@ #include "MediaSoupErrors.hpp" #include "Utils.hpp" +/* Static. */ + +static constexpr int ListenBacklog{ 256 }; + /* Static methods for UV callbacks. */ inline static void onConnection(uv_stream_t* handle, int status) @@ -24,7 +28,7 @@ inline static void onClose(uv_handle_t* handle) /* Instance methods. */ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -TcpServerHandler::TcpServerHandler(uv_tcp_t* uvHandle, int backlog) : uvHandle(uvHandle) +TcpServerHandler::TcpServerHandler(uv_tcp_t* uvHandle) : uvHandle(uvHandle) { MS_TRACE(); @@ -34,7 +38,7 @@ TcpServerHandler::TcpServerHandler(uv_tcp_t* uvHandle, int backlog) : uvHandle(u err = uv_listen( reinterpret_cast(this->uvHandle), - backlog, + ListenBacklog, static_cast(onConnection)); if (err != 0) From 3637fa36995a79435a9de0b945dcf26c1877da85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 16 Jun 2022 20:07:15 +0200 Subject: [PATCH 17/58] foo --- TODO_WEBRTC_SERVER.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index 23ea8a2982..f9dbb3cd1d 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -67,6 +67,8 @@ Also increase `backlog(int)` in `uv_listen`(POSIX argument): No matter the value is super high, in Linux it's limited by `/proc/sys/net/core/somaxconn`. +Done by just hardcoding it to 256 since it's irrelevant after investigating it. + ### Handle limit of UDP/TCP tuples in WebRtcTransport From 899b7f1794ea830ca5d07cdcad7c56c51b65dd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 03:01:15 +0200 Subject: [PATCH 18/58] Complete more events --- TODO_WEBRTC_SERVER.md | 6 +- worker/include/RTC/IceServer.hpp | 14 +++++ worker/include/RTC/WebRtcServer.hpp | 4 +- worker/include/RTC/WebRtcTransport.hpp | 14 +++++ worker/src/RTC/IceServer.cpp | 47 ++++++++------ worker/src/RTC/WebRtcServer.cpp | 30 ++++----- worker/src/RTC/WebRtcTransport.cpp | 84 +++++++++++++++++++++++++- 7 files changed, 158 insertions(+), 41 deletions(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index f9dbb3cd1d..b2a58b5a92 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -77,8 +77,4 @@ This is needed no matter `WebRtcServer` is used or not. Each `WebRtcTransport` s ### Use the new TransportTuple.id -In `IceServer` we use `tuple.compare()` but now we have `tuple->id` to match things. See `GenerateId()` in `TransportTuple.hpp`. - -### New events in `IceServer` - -As far as a tuple is added or removed it must call a new callback. Also new events when local ICE usernameFrag is initially set or changed later. +In `IceServer` we use `tuple.compare()` but now we have `tuple->id` to match things. We should use it and usage in `WebRtcServer.cpp`. See `GenerateId()` in `TransportTuple.hpp`. diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index 1df80065ec..d1e26330af 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -33,6 +33,13 @@ namespace RTC */ virtual void OnIceServerSendStunPacket( const RTC::IceServer* iceServer, const RTC::StunPacket* packet, RTC::TransportTuple* tuple) = 0; + virtual void OnIceServerLocalUsernameFragmentAdded( + const RTC::IceServer* iceServer, const std::string& usernameFragment) = 0; + virtual void OnIceServerLocalUsernameFragmentRemoved( + const RTC::IceServer* iceServer, const std::string& usernameFragment) = 0; + virtual void OnIceServerTupleAdded(const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) = 0; + virtual void OnIceServerTupleRemoved( + const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) = 0; virtual void OnIceServerSelectedTuple( const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) = 0; virtual void OnIceServerConnected(const RTC::IceServer* iceServer) = 0; @@ -70,6 +77,13 @@ namespace RTC this->password = password; this->remoteNomination = 0u; + + // Notify the listener. + this->listener->OnIceServerLocalUsernameFragmentAdded(this, usernameFragment); + + // NOTE: Do not yet call listener->OnIceServerLocalUsernameFragmentRemoved() + // with old usernameFragment. Wait until we receive a STUN packet with the + // new one. } bool IsValidTuple(const RTC::TransportTuple* tuple) const; void RemoveTuple(RTC::TransportTuple* tuple); diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index f1959067a7..f453743a18 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -93,9 +93,9 @@ namespace RTC // Vector of UdpSockets and TcpServers in the user given order. std::vector udpSocketOrTcpServers; // Map of WebRtcTransports indexed by local ICE usernameFragment. - absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransports; + absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransport; // Map of WebRtcTransports indexed by TransportTuple.id. - absl::flat_hash_map mapTupleWebRtcTransports; + absl::flat_hash_map mapTupleWebRtcTransport; }; } // namespace RTC diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index b215b027e7..1be20d3003 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -48,6 +48,12 @@ namespace RTC public: WebRtcTransport(const std::string& id, RTC::Transport::Listener* listener, json& data); + WebRtcTransport( + const std::string& id, + RTC::Transport::Listener* listener, + WebRtcTransportListener* webRtcTransportListener, + std::vector& iceCandidates, + json& data); ~WebRtcTransport() override; public: @@ -105,6 +111,12 @@ namespace RTC const RTC::IceServer* iceServer, const RTC::StunPacket* packet, RTC::TransportTuple* tuple) override; + void OnIceServerLocalUsernameFragmentAdded( + const RTC::IceServer* iceServer, const std::string& usernameFragment) override; + void OnIceServerLocalUsernameFragmentRemoved( + const RTC::IceServer* iceServer, const std::string& usernameFragment) override; + void OnIceServerTupleAdded(const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) override; + void OnIceServerTupleRemoved(const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) override; void OnIceServerSelectedTuple(const RTC::IceServer* iceServer, RTC::TransportTuple* tuple) override; void OnIceServerConnected(const RTC::IceServer* iceServer) override; void OnIceServerCompleted(const RTC::IceServer* iceServer) override; @@ -129,6 +141,8 @@ namespace RTC const RTC::DtlsTransport* dtlsTransport, const uint8_t* data, size_t len) override; private: + // Passed by argument. + WebRtcTransportListener* webRtcTransportListener{ nullptr }; // Allocated by this. RTC::IceServer* iceServer{ nullptr }; // Map of UdpSocket/TcpServer and local announced IP (if any). diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index b6df5f2bba..09f4a2eb15 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -19,6 +19,9 @@ namespace RTC : listener(listener), usernameFragment(usernameFragment), password(password) { MS_TRACE(); + + // Notify the listener. + this->listener->OnIceServerLocalUsernameFragmentAdded(this, usernameFragment); } void IceServer::ProcessStunPacket(RTC::StunPacket* packet, RTC::TransportTuple* tuple) @@ -106,6 +109,9 @@ namespace RTC { MS_DEBUG_TAG(ice, "new ICE credentials applied"); + // Notify the listener. + this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); + this->oldUsernameFragment.clear(); this->oldPassword.clear(); } @@ -267,26 +273,28 @@ namespace RTC // Remove from the list of tuples. this->tuples.erase(it); - // If this is not the selected tuple, stop here. - if (removedTuple != this->selectedTuple) - return; - - // Otherwise this was the selected tuple. - this->selectedTuple = nullptr; - - // Mark the first tuple as selected tuple (if any). - if (this->tuples.begin() != this->tuples.end()) - { - SetSelectedTuple(std::addressof(*this->tuples.begin())); - } - // Or just emit 'disconnected'. - else + // If this is the selected tuple, do things. + if (removedTuple == this->selectedTuple) { - // Update state. - this->state = IceState::DISCONNECTED; - // Notify the listener. - this->listener->OnIceServerDisconnected(this); + this->selectedTuple = nullptr; + + // Mark the first tuple as selected tuple (if any). + if (this->tuples.begin() != this->tuples.end()) + { + SetSelectedTuple(std::addressof(*this->tuples.begin())); + } + // Or just emit 'disconnected'. + else + { + // Update state. + this->state = IceState::DISCONNECTED; + // Notify the listener. + this->listener->OnIceServerDisconnected(this); + } } + + // Notify the listener. + this->listener->OnIceServerTupleRemoved(this, removedTuple); } void IceServer::ForceSelectedTuple(const RTC::TransportTuple* tuple) @@ -531,6 +539,9 @@ namespace RTC if (storedTuple->GetProtocol() == TransportTuple::Protocol::UDP) storedTuple->StoreUdpRemoteAddress(); + // Notify the listener. + this->listener->OnIceServerTupleAdded(this, storedTuple); + // Return the address of the inserted tuple. return storedTuple; } diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 612588d9ba..2b8b873efb 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -160,23 +160,23 @@ namespace RTC // webRtcTransportListener (this is, WebRtcServer) that will affect these // maps so caution. - for (auto it = this->mapLocalIceUsernameFragmentWebRtcTransports.begin(); - it != this->mapLocalIceUsernameFragmentWebRtcTransports.end(); + for (auto it = this->mapLocalIceUsernameFragmentWebRtcTransport.begin(); + it != this->mapLocalIceUsernameFragmentWebRtcTransport.end(); ++it) { auto* webRtcTransport = it->second; - this->mapLocalIceUsernameFragmentWebRtcTransports.erase(it); + this->mapLocalIceUsernameFragmentWebRtcTransport.erase(it); webRtcTransport->WebRtcServerClosed(); } - for (auto it = this->mapTupleWebRtcTransports.begin(); it != this->mapTupleWebRtcTransports.end(); + for (auto it = this->mapTupleWebRtcTransport.begin(); it != this->mapTupleWebRtcTransport.end(); ++it) { auto* webRtcTransport = it->second; - this->mapTupleWebRtcTransports.erase(it); + this->mapTupleWebRtcTransport.erase(it); webRtcTransport->WebRtcServerClosed(); } @@ -309,9 +309,9 @@ namespace RTC } auto key = GetLocalIceUsernameFragmentFromReceivedStunPacket(packet); - auto it = this->mapLocalIceUsernameFragmentWebRtcTransports.find(key); + auto it = this->mapLocalIceUsernameFragmentWebRtcTransport.find(key); - if (it == this->mapLocalIceUsernameFragmentWebRtcTransports.end()) + if (it == this->mapLocalIceUsernameFragmentWebRtcTransport.end()) { MS_WARN_DEV("ignoring received STUN packet with unknown remote ICE usernameFragment"); @@ -332,9 +332,9 @@ namespace RTC { MS_TRACE(); - auto it = this->mapTupleWebRtcTransports.find(tuple->id); + auto it = this->mapTupleWebRtcTransport.find(tuple->id); - if (it == this->mapTupleWebRtcTransports.end()) + if (it == this->mapTupleWebRtcTransport.end()) { MS_WARN_DEV("ignoring received non STUN data from unknown tuple"); @@ -351,7 +351,7 @@ namespace RTC { MS_TRACE(); - this->mapLocalIceUsernameFragmentWebRtcTransports[usernameFragment] = webRtcTransport; + this->mapLocalIceUsernameFragmentWebRtcTransport[usernameFragment] = webRtcTransport; } inline void WebRtcServer::OnWebRtcTransportLocalIceUsernameFragmentRemoved( @@ -359,7 +359,7 @@ namespace RTC { MS_TRACE(); - this->mapLocalIceUsernameFragmentWebRtcTransports.erase(usernameFragment); + this->mapLocalIceUsernameFragmentWebRtcTransport.erase(usernameFragment); } inline void WebRtcServer::OnWebRtcTransportTransportTupleAdded( @@ -367,7 +367,7 @@ namespace RTC { MS_TRACE(); - this->mapTupleWebRtcTransports[tuple->id] = webRtcTransport; + this->mapTupleWebRtcTransport[tuple->id] = webRtcTransport; } inline void WebRtcServer::OnWebRtcTransportTransportTupleRemoved( @@ -375,7 +375,7 @@ namespace RTC { MS_TRACE(); - this->mapTupleWebRtcTransports.erase(tuple->id); + this->mapTupleWebRtcTransport.erase(tuple->id); } inline void WebRtcServer::OnUdpSocketPacketReceived( @@ -395,10 +395,10 @@ namespace RTC RTC::TransportTuple tuple(connection); - auto it = this->mapTupleWebRtcTransports.find(tuple.id); + auto it = this->mapTupleWebRtcTransport.find(tuple.id); MS_ASSERT( - it != this->mapTupleWebRtcTransports.end(), + it != this->mapTupleWebRtcTransport.end(), "closed TCP connection not managed by this WebRtcServer"); auto* webRtcTransport = it->second; diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index cd3c508ba0..31cbec5225 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -236,6 +236,42 @@ namespace RTC } } + WebRtcTransport::WebRtcTransport( + const std::string& id, + RTC::Transport::Listener* listener, + WebRtcTransportListener* webRtcTransportListener, + std::vector& iceCandidates, + json& data) + : RTC::Transport::Transport(id, listener, data), + webRtcTransportListener(webRtcTransportListener), iceCandidates(iceCandidates) + { + MS_TRACE(); + + try + { + // Create a ICE server. + this->iceServer = new RTC::IceServer( + this, Utils::Crypto::GetRandomString(32), Utils::Crypto::GetRandomString(32)); + + // Create a DTLS transport. + this->dtlsTransport = new RTC::DtlsTransport(this); + } + catch (const MediaSoupError& error) + { + // Must delete everything since the destructor won't be called. + + delete this->dtlsTransport; + this->dtlsTransport = nullptr; + + delete this->iceServer; + this->iceServer = nullptr; + + this->iceCandidates.clear(); + + throw; + } + } + WebRtcTransport::~WebRtcTransport() { MS_TRACE(); @@ -582,7 +618,7 @@ namespace RTC case Channel::ChannelRequest::MethodId::TRANSPORT_RESTART_ICE: { - std::string usernameFragment = Utils::Crypto::GetRandomString(16); + std::string usernameFragment = Utils::Crypto::GetRandomString(32); std::string password = Utils::Crypto::GetRandomString(32); this->iceServer->RestartIce(usernameFragment, password); @@ -1172,6 +1208,52 @@ namespace RTC RTC::Transport::DataSent(packet->GetSize()); } + inline void WebRtcTransport::OnIceServerLocalUsernameFragmentAdded( + const RTC::IceServer* /*iceServer*/, const std::string& usernameFragment) + { + MS_TRACE(); + + if (this->webRtcTransportListener) + { + this->webRtcTransportListener->OnWebRtcTransportLocalIceUsernameFragmentAdded( + this, usernameFragment); + } + } + + inline void WebRtcTransport::OnIceServerLocalUsernameFragmentRemoved( + const RTC::IceServer* /*iceServer*/, const std::string& usernameFragment) + { + MS_TRACE(); + + if (this->webRtcTransportListener) + { + this->webRtcTransportListener->OnWebRtcTransportLocalIceUsernameFragmentRemoved( + this, usernameFragment); + } + } + + inline void WebRtcTransport::OnIceServerTupleAdded( + const RTC::IceServer* /*iceServer*/, RTC::TransportTuple* tuple) + { + MS_TRACE(); + + if (this->webRtcTransportListener) + { + this->webRtcTransportListener->OnWebRtcTransportTransportTupleAdded(this, tuple); + } + } + + inline void WebRtcTransport::OnIceServerTupleRemoved( + const RTC::IceServer* /*iceServer*/, RTC::TransportTuple* tuple) + { + MS_TRACE(); + + if (this->webRtcTransportListener) + { + this->webRtcTransportListener->OnWebRtcTransportTransportTupleRemoved(this, tuple); + } + } + inline void WebRtcTransport::OnIceServerSelectedTuple( const RTC::IceServer* /*iceServer*/, RTC::TransportTuple* /*tuple*/) { From 809149e3db3b0f69c5d9c34f62395267d3396582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 03:08:14 +0200 Subject: [PATCH 19/58] cosmetic --- worker/src/RTC/WebRtcServer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 2b8b873efb..5db242a252 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -268,8 +268,9 @@ namespace RTC MS_TRACE(); // Here we inspect the USERNAME attribute of a received STUN request and - // extract its remote usernameFragment (the one given to our IceServwer) - // which is the first value in the attribute value before the ":" symbol. + // extract its remote usernameFragment (the one given to our IceServer as + // local usernameFragment) which is the first value in the attribute value + // before the ":" symbol. auto& username = packet->GetUsername(); size_t colonPos = username.find(":"); From b50998df4d34fcb2af64c8cd0a71c3d201c66b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 03:31:14 +0200 Subject: [PATCH 20/58] Add missing IceServer destructor --- worker/include/RTC/IceServer.hpp | 1 + worker/src/RTC/IceServer.cpp | 24 +++++++++++++++++++++++- worker/src/RTC/WebRtcTransport.cpp | 4 ++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index d1e26330af..d1f3945a6d 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -49,6 +49,7 @@ namespace RTC public: IceServer(Listener* listener, const std::string& usernameFragment, const std::string& password); + ~IceServer(); public: void ProcessStunPacket(RTC::StunPacket* packet, RTC::TransportTuple* tuple); diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index 09f4a2eb15..bffd6b2876 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -24,6 +24,28 @@ namespace RTC this->listener->OnIceServerLocalUsernameFragmentAdded(this, usernameFragment); } + IceServer::~IceServer() + { + MS_TRACE(); + + // Here we must notify to the listener about the removal of all handled + // tuples and usernameFragment (including the old one if any). + + this->listener->OnIceServerLocalUsernameFragmentRemoved(this, usernameFragment); + + if (!this->oldUsernameFragment.empty()) + { + this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); + } + + for (const auto& it : this->tuples) + { + auto* storedTuple = const_cast(std::addressof(it)); + + this->listener->OnIceServerTupleRemoved(this, storedTuple); + } + } + void IceServer::ProcessStunPacket(RTC::StunPacket* packet, RTC::TransportTuple* tuple) { MS_TRACE(); @@ -105,7 +127,7 @@ namespace RTC { case RTC::StunPacket::Authentication::OK: { - if (!this->oldPassword.empty()) + if (!this->oldUsernameFragment.empty() && !this->oldPassword.empty()) { MS_DEBUG_TAG(ice, "new ICE credentials applied"); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 31cbec5225..d648cb4201 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -706,6 +706,10 @@ namespace RTC { MS_TRACE(); + // It's important to unset the WebRtcTransportListener here so it won't be + // used again. + this->webRtcTransportListener = nullptr; + RTC::Transport::MustClose(); } From 1ad4c526792b35ea60cec1554a771b560855a2de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 03:40:47 +0200 Subject: [PATCH 21/58] upps --- worker/include/RTC/IceServer.hpp | 6 +++--- worker/src/RTC/WebRtcTransport.cpp | 4 ---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index d1f3945a6d..8c428b3b67 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -82,9 +82,9 @@ namespace RTC // Notify the listener. this->listener->OnIceServerLocalUsernameFragmentAdded(this, usernameFragment); - // NOTE: Do not yet call listener->OnIceServerLocalUsernameFragmentRemoved() - // with old usernameFragment. Wait until we receive a STUN packet with the - // new one. + // NOTE: Do not call listener->OnIceServerLocalUsernameFragmentRemoved() + // yet with old usernameFragment. Wait until we receive a STUN packet + // with the new one. } bool IsValidTuple(const RTC::TransportTuple* tuple) const; void RemoveTuple(RTC::TransportTuple* tuple); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index d648cb4201..31cbec5225 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -706,10 +706,6 @@ namespace RTC { MS_TRACE(); - // It's important to unset the WebRtcTransportListener here so it won't be - // used again. - this->webRtcTransportListener = nullptr; - RTC::Transport::MustClose(); } From 550a46280690a322c3ffc6433d8fa94dc1c9f068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 13:26:21 +0200 Subject: [PATCH 22/58] More events and a new Set --- TODO_WEBRTC_SERVER.md | 3 +- worker/include/RTC/WebRtcServer.hpp | 5 + worker/include/RTC/WebRtcTransport.hpp | 3 +- worker/src/RTC/WebRtcServer.cpp | 132 ++++++++++++++++++++----- worker/src/RTC/WebRtcTransport.cpp | 17 ++-- 5 files changed, 127 insertions(+), 33 deletions(-) diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md index b2a58b5a92..75101f0b69 100644 --- a/TODO_WEBRTC_SERVER.md +++ b/TODO_WEBRTC_SERVER.md @@ -38,8 +38,7 @@ This is hard. And there must be a parallelism between TS/Rust and C++. Proposal: -* `webRtcServer.close()` carefully iterates its maps and calls `webRtcTransport.webRtcServerClosed()`. -* `webRtcTransport.webRtcServerClosed()` calls a new parent `Transport::MustClose()` method. +* `webRtcServer.close()` iterates its `Set` of `WebRtcTransports` and calls `webRtcTransport.mustClose()`. * `Transport::MustClose()` calls a new `this->listener->OnTransportMustClose(this)`. * `Router.OnTransportMustClose(transport)` does: - Call `transport->CloseProducersAndConsumers()` so `Router` is notified about closed `Producers` and `Consumers` and can remove them from its maps. diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index f453743a18..6add633057 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -10,6 +10,7 @@ #include "RTC/UdpSocket.hpp" #include "RTC/WebRtcTransport.hpp" #include +#include #include #include #include @@ -62,6 +63,8 @@ namespace RTC /* Pure virtual methods inherited from RTC::WebRtcTransport::WebRtcTransportListener. */ public: + void OnWebRtcTransportCreated(RTC::WebRtcTransport* webRtcTransport) override; + void OnWebRtcTransportClosed(RTC::WebRtcTransport* webRtcTransport) override; void OnWebRtcTransportLocalIceUsernameFragmentAdded( RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) override; void OnWebRtcTransportLocalIceUsernameFragmentRemoved( @@ -92,6 +95,8 @@ namespace RTC private: // Vector of UdpSockets and TcpServers in the user given order. std::vector udpSocketOrTcpServers; + // Set of WebRtcTransports. + absl::flat_hash_set webRtcTransports; // Map of WebRtcTransports indexed by local ICE usernameFragment. absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransport; // Map of WebRtcTransports indexed by TransportTuple.id. diff --git a/worker/include/RTC/WebRtcTransport.hpp b/worker/include/RTC/WebRtcTransport.hpp index 1be20d3003..4ed48a4d95 100644 --- a/worker/include/RTC/WebRtcTransport.hpp +++ b/worker/include/RTC/WebRtcTransport.hpp @@ -36,6 +36,8 @@ namespace RTC virtual ~WebRtcTransportListener() = default; public: + virtual void OnWebRtcTransportCreated(RTC::WebRtcTransport* webRtcTransport) = 0; + virtual void OnWebRtcTransportClosed(RTC::WebRtcTransport* webRtcTransport) = 0; virtual void OnWebRtcTransportLocalIceUsernameFragmentAdded( RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) = 0; virtual void OnWebRtcTransportLocalIceUsernameFragmentRemoved( @@ -65,7 +67,6 @@ namespace RTC void ProcessNonStunPacketFromWebRtcServer( RTC::TransportTuple* tuple, const uint8_t* data, size_t len); void RemoveTuple(RTC::TransportTuple* tuple); - void WebRtcServerClosed(); private: bool IsConnected() const override; diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 5db242a252..2df8b9090e 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -155,41 +155,105 @@ namespace RTC } this->udpSocketOrTcpServers.clear(); - // Tell all WebRtcTransports that the WebRtcServer must has been closed. - // NOTE: The WebRtcTransport destructor will invoke N events in its - // webRtcTransportListener (this is, WebRtcServer) that will affect these - // maps so caution. - - for (auto it = this->mapLocalIceUsernameFragmentWebRtcTransport.begin(); - it != this->mapLocalIceUsernameFragmentWebRtcTransport.end(); - ++it) + for (auto* webRtcTransport : this->webRtcTransports) { - auto* webRtcTransport = it->second; + webRtcTransport->MustClose(); + } + this->webRtcTransports.clear(); + } + + void WebRtcServer::FillJson(json& jsonObject) const + { + MS_TRACE(); + + // Add id. + jsonObject["id"] = this->id; + + // Add udpSockets and tcpServers. + jsonObject["udpSockets"] = json::array(); + auto jsonUdpSocketsIt = jsonObject.find("udpSockets"); + jsonObject["tcpServers"] = json::array(); + auto jsonTcpServersIt = jsonObject.find("tcpServers"); + + size_t udpSocketIdx{ 0 }; + size_t tcpServerIdx{ 0 }; + + for (auto& item : this->udpSocketOrTcpServers) + { + if (item.udpSocket) + { + jsonUdpSocketsIt->emplace_back(json::value_t::object); + + auto& jsonEntry = (*jsonUdpSocketsIt)[udpSocketIdx]; + + jsonEntry["ip"] = item.udpSocket->GetLocalIp(); + jsonEntry["port"] = item.udpSocket->GetLocalPort(); + + ++udpSocketIdx; + } + else if (item.tcpServer) + { + jsonTcpServersIt->emplace_back(json::value_t::object); + + auto& jsonEntry = (*jsonTcpServersIt)[tcpServerIdx]; - this->mapLocalIceUsernameFragmentWebRtcTransport.erase(it); + jsonEntry["ip"] = item.tcpServer->GetLocalIp(); + jsonEntry["port"] = item.tcpServer->GetLocalPort(); - webRtcTransport->WebRtcServerClosed(); + ++tcpServerIdx; + } } - for (auto it = this->mapTupleWebRtcTransport.begin(); it != this->mapTupleWebRtcTransport.end(); - ++it) + // Add webRtcTransportIds. + jsonObject["webRtcTransportIds"] = json::array(); + auto jsonWebRtcTransportIdsIt = jsonObject.find("webRtcTransportIds"); + + for (auto* webRtcTransport : this->webRtcTransports) + { + jsonWebRtcTransportIdsIt->emplace_back(webRtcTransport->id); + } + + size_t idx; + + // Add localIceUsernameFragments. + jsonObject["localIceUsernameFragments"] = json::array(); + auto jsonLocalIceUsernamesIt = jsonObject.find("localIceUsernameFragments"); + + idx = 0; + for (auto& kv : this->mapLocalIceUsernameFragmentWebRtcTransport) { - auto* webRtcTransport = it->second; + const auto& localIceUsernameFragment = kv.first; + const auto* webRtcTransport = kv.second; - this->mapTupleWebRtcTransport.erase(it); + jsonLocalIceUsernamesIt->emplace_back(json::value_t::object); - webRtcTransport->WebRtcServerClosed(); + auto& jsonEntry = (*jsonLocalIceUsernamesIt)[idx]; + + jsonEntry["localIceUsernameFragment"] = localIceUsernameFragment; + jsonEntry["webRtcTransportId"] = webRtcTransport->id; + + ++idx; } - } - void WebRtcServer::FillJson(json& jsonObject) const - { - MS_TRACE(); + // Add tuples. + jsonObject["tuples"] = json::array(); + auto jsonTuplesIt = jsonObject.find("tuples"); - // Add id. - jsonObject["id"] = this->id; + idx = 0; + for (auto& kv : this->mapTupleWebRtcTransport) + { + const auto& tuple = kv.first; + const auto* webRtcTransport = kv.second; + + jsonTuplesIt->emplace_back(json::value_t::object); + + auto& jsonEntry = (*jsonTuplesIt)[idx]; - // TODO: Dump udpSockets and tcpServers? and webRtcTransports?. + jsonEntry["tuple"] = tuple; + jsonEntry["webRtcTransportId"] = webRtcTransport->id; + + ++idx; + } } void WebRtcServer::HandleRequest(Channel::ChannelRequest* request) @@ -347,6 +411,28 @@ namespace RTC webRtcTransport->ProcessNonStunPacketFromWebRtcServer(tuple, data, len); } + inline void WebRtcServer::OnWebRtcTransportCreated(RTC::WebRtcTransport* webRtcTransport) + { + MS_TRACE(); + + MS_ASSERT( + this->webRtcTransports.find(webRtcTransport) == this->webRtcTransports.end(), + "WebRtcTransport already handled"); + + this->webRtcTransports.insert(webRtcTransport); + } + + inline void WebRtcServer::OnWebRtcTransportClosed(RTC::WebRtcTransport* webRtcTransport) + { + MS_TRACE(); + + MS_ASSERT( + this->webRtcTransports.find(webRtcTransport) != this->webRtcTransports.end(), + "WebRtcTransport not handled"); + + this->webRtcTransports.erase(webRtcTransport); + } + inline void WebRtcServer::OnWebRtcTransportLocalIceUsernameFragmentAdded( RTC::WebRtcTransport* webRtcTransport, const std::string& usernameFragment) { diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 31cbec5225..f4dc86e1e2 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -236,6 +236,9 @@ namespace RTC } } + /** + * This constructor is used when the WebRtcTransport uses a WebRtcServer. + */ WebRtcTransport::WebRtcTransport( const std::string& id, RTC::Transport::Listener* listener, @@ -255,6 +258,9 @@ namespace RTC // Create a DTLS transport. this->dtlsTransport = new RTC::DtlsTransport(this); + + // Notify the webRtcTransportListener. + this->webRtcTransportListener->OnWebRtcTransportCreated(this); } catch (const MediaSoupError& error) { @@ -307,6 +313,10 @@ namespace RTC delete this->srtpRecvSession; this->srtpRecvSession = nullptr; + + // Notify the webRtcTransportListener. + if (this->webRtcTransportListener) + this->webRtcTransportListener->OnWebRtcTransportClosed(this); } void WebRtcTransport::FillJson(json& jsonObject) const @@ -702,13 +712,6 @@ namespace RTC this->iceServer->RemoveTuple(tuple); } - void WebRtcTransport::WebRtcServerClosed() - { - MS_TRACE(); - - RTC::Transport::MustClose(); - } - inline bool WebRtcTransport::IsConnected() const { MS_TRACE(); From 4c869512a40ac45e2c302d43ef5dd30d2aa921d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 13:52:07 +0200 Subject: [PATCH 23/58] more --- node/tests/test-Router.js | 2 +- node/tests/test-Worker.js | 2 +- worker/include/Channel/ChannelRequest.hpp | 5 +- worker/include/Worker.hpp | 4 + worker/src/Channel/ChannelRequest.cpp | 5 +- worker/src/Worker.cpp | 120 ++++++++++++++++++++++ 6 files changed, 132 insertions(+), 6 deletions(-) diff --git a/node/tests/test-Router.js b/node/tests/test-Router.js index 0e6899416a..264580f773 100644 --- a/node/tests/test-Router.js +++ b/node/tests/test-Router.js @@ -63,7 +63,7 @@ test('worker.createRouter() succeeds', async () => await expect(worker.dump()) .resolves - .toEqual({ pid: worker.pid, routerIds: [ router.id ] }); + .toEqual({ pid: worker.pid, webRtcServerIds: [], routerIds: [ router.id ] }); await expect(router.dump()) .resolves diff --git a/node/tests/test-Worker.js b/node/tests/test-Worker.js index fa5163ce87..525054741c 100644 --- a/node/tests/test-Worker.js +++ b/node/tests/test-Worker.js @@ -124,7 +124,7 @@ test('worker.dump() succeeds', async () => await expect(worker.dump()) .resolves - .toEqual({ pid: worker.pid, routerIds: [] }); + .toEqual({ pid: worker.pid, webRtcServerIds: [], routerIds: [] }); worker.close(); }, 2000); diff --git a/worker/include/Channel/ChannelRequest.hpp b/worker/include/Channel/ChannelRequest.hpp index d7cca86912..dfb8231e2f 100644 --- a/worker/include/Channel/ChannelRequest.hpp +++ b/worker/include/Channel/ChannelRequest.hpp @@ -23,7 +23,10 @@ namespace Channel WORKER_DUMP, WORKER_GET_RESOURCE_USAGE, WORKER_UPDATE_SETTINGS, + WORKER_CREATE_WEBRTC_SERVER, WORKER_CREATE_ROUTER, + WEBRTC_SERVER_CLOSE, + WEBRTC_SERVER_DUMP, ROUTER_CLOSE, ROUTER_DUMP, ROUTER_CREATE_WEBRTC_TRANSPORT, @@ -45,8 +48,6 @@ namespace Channel TRANSPORT_PRODUCE_DATA, TRANSPORT_CONSUME_DATA, TRANSPORT_ENABLE_TRACE_EVENT, - WEBRTC_SERVER_CLOSE, - WEBRTC_SERVER_DUMP, PRODUCER_CLOSE, PRODUCER_DUMP, PRODUCER_GET_STATS, diff --git a/worker/include/Worker.hpp b/worker/include/Worker.hpp index bbed438e4e..6649b316c9 100644 --- a/worker/include/Worker.hpp +++ b/worker/include/Worker.hpp @@ -8,6 +8,7 @@ #include "PayloadChannel/PayloadChannelRequest.hpp" #include "PayloadChannel/PayloadChannelSocket.hpp" #include "RTC/Router.hpp" +#include "RTC/WebRtcServer.hpp" #include "handles/SignalsHandler.hpp" #include #include @@ -27,6 +28,8 @@ class Worker : public Channel::ChannelSocket::Listener, void Close(); void FillJson(json& jsonObject) const; void FillJsonResourceUsage(json& jsonObject) const; + void SetNewWebRtcServerIdFromInternal(json& internal, std::string& webRtcServerId) const; + RTC::WebRtcServer* GetWebRtcServerFromInternal(json& internal) const; void SetNewRouterIdFromInternal(json& internal, std::string& routerId) const; RTC::Router* GetRouterFromInternal(json& internal) const; @@ -55,6 +58,7 @@ class Worker : public Channel::ChannelSocket::Listener, PayloadChannel::PayloadChannelSocket* payloadChannel{ nullptr }; // Allocated by this. SignalsHandler* signalsHandler{ nullptr }; + absl::flat_hash_map mapWebRtcServers; absl::flat_hash_map mapRouters; // Others. bool closed{ false }; diff --git a/worker/src/Channel/ChannelRequest.cpp b/worker/src/Channel/ChannelRequest.cpp index afa67ac28a..520537e69d 100644 --- a/worker/src/Channel/ChannelRequest.cpp +++ b/worker/src/Channel/ChannelRequest.cpp @@ -17,7 +17,10 @@ namespace Channel { "worker.dump", ChannelRequest::MethodId::WORKER_DUMP }, { "worker.getResourceUsage", ChannelRequest::MethodId::WORKER_GET_RESOURCE_USAGE }, { "worker.updateSettings", ChannelRequest::MethodId::WORKER_UPDATE_SETTINGS }, + { "worker.createWebRtcServer", ChannelRequest::MethodId::WORKER_CREATE_WEBRTC_SERVER }, { "worker.createRouter", ChannelRequest::MethodId::WORKER_CREATE_ROUTER }, + { "webRtcServer.close", ChannelRequest::MethodId::WEBRTC_SERVER_CLOSE }, + { "webRtcServer.dump", ChannelRequest::MethodId::WEBRTC_SERVER_DUMP }, { "router.close", ChannelRequest::MethodId::ROUTER_CLOSE }, { "router.dump", ChannelRequest::MethodId::ROUTER_DUMP }, { "router.createWebRtcTransport", ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT }, @@ -39,8 +42,6 @@ namespace Channel { "transport.produceData", ChannelRequest::MethodId::TRANSPORT_PRODUCE_DATA }, { "transport.consumeData", ChannelRequest::MethodId::TRANSPORT_CONSUME_DATA }, { "transport.enableTraceEvent", ChannelRequest::MethodId::TRANSPORT_ENABLE_TRACE_EVENT }, - { "webRtcServer.close", ChannelRequest::MethodId::WEBRTC_SERVER_CLOSE }, - { "webRtcServer.dump", ChannelRequest::MethodId::WEBRTC_SERVER_DUMP }, { "producer.close", ChannelRequest::MethodId::PRODUCER_CLOSE }, { "producer.dump", ChannelRequest::MethodId::PRODUCER_DUMP }, { "producer.getStats", ChannelRequest::MethodId::PRODUCER_GET_STATS }, diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 1754e81ab6..63fd4a00c6 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -64,6 +64,15 @@ void Worker::Close() // Delete the SignalsHandler. delete this->signalsHandler; + // Delete all WebRtcServers. + for (auto& kv : this->mapWebRtcServers) + { + auto* webRtcServer = kv.second; + + delete webRtcServer; + } + this->mapWebRtcServers.clear(); + // Delete all Routers. for (auto& kv : this->mapRouters) { @@ -90,6 +99,17 @@ void Worker::FillJson(json& jsonObject) const // Add pid. jsonObject["pid"] = Logger::pid; + // Add webRtcServerIds. + jsonObject["webRtcServerIds"] = json::array(); + auto jsonWebRtcServerIdsIt = jsonObject.find("webRtcServerIds"); + + for (auto& kv : this->mapWebRtcServers) + { + auto& WebRtcServerId = kv.first; + + jsonWebRtcServerIdsIt->emplace_back(WebRtcServerId); + } + // Add routerIds. jsonObject["routerIds"] = json::array(); auto jsonRouterIdsIt = jsonObject.find("routerIds"); @@ -165,6 +185,40 @@ void Worker::FillJsonResourceUsage(json& jsonObject) const jsonObject["ru_nivcsw"] = uvRusage.ru_nivcsw; } +void Worker::SetNewWebRtcServerIdFromInternal(json& internal, std::string& webRtcServerId) const +{ + MS_TRACE(); + + auto jsonWebRtcServerIdIt = internal.find("webRtcServerId"); + + if (jsonWebRtcServerIdIt == internal.end() || !jsonWebRtcServerIdIt->is_string()) + MS_THROW_ERROR("missing internal.webRtcServerId"); + + webRtcServerId.assign(jsonWebRtcServerIdIt->get()); + + if (this->mapWebRtcServers.find(webRtcServerId) != this->mapWebRtcServers.end()) + MS_THROW_ERROR("a WebRtcServer with same webRtcServerId already exists"); +} + +RTC::WebRtcServer* Worker::GetWebRtcServerFromInternal(json& internal) const +{ + MS_TRACE(); + + auto jsonWebRtcServerIdIt = internal.find("webRtcServerId"); + + if (jsonWebRtcServerIdIt == internal.end() || !jsonWebRtcServerIdIt->is_string()) + MS_THROW_ERROR("missing internal.webRtcServerId"); + + auto it = this->mapWebRtcServers.find(jsonWebRtcServerIdIt->get()); + + if (it == this->mapWebRtcServers.end()) + MS_THROW_ERROR("WebRtcServer not found"); + + RTC::WebRtcServer* webRtcServer = it->second; + + return webRtcServer; +} + void Worker::SetNewRouterIdFromInternal(json& internal, std::string& routerId) const { MS_TRACE(); @@ -249,6 +303,72 @@ inline void Worker::OnChannelRequest(Channel::ChannelSocket* /*channel*/, Channe break; } + case Channel::ChannelRequest::MethodId::WORKER_CREATE_WEBRTC_SERVER: + { + try + { + std::string webRtcServerId; + + SetNewWebRtcServerIdFromInternal(request->internal, webRtcServerId); + + auto* webRtcServer = new RTC::WebRtcServer(webRtcServerId, request->data); + + this->mapWebRtcServers[webRtcServerId] = webRtcServer; + + MS_DEBUG_DEV("WebRtcServer created [webRtcServerId:%s]", webRtcServerId.c_str()); + + request->Accept(); + } + catch (const MediaSoupError& error) + { + MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + } + + break; + } + + case Channel::ChannelRequest::MethodId::WEBRTC_SERVER_CLOSE: + { + RTC::WebRtcServer* webRtcServer{ nullptr }; + + try + { + webRtcServer = GetWebRtcServerFromInternal(request->internal); + } + catch (const MediaSoupError& error) + { + MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + } + + // Remove it from the map and delete it. + this->mapWebRtcServers.erase(webRtcServer->id); + delete webRtcServer; + + MS_DEBUG_DEV("WebRtcServer closed [id:%s]", webRtcServer->id.c_str()); + + request->Accept(); + + break; + } + + case Channel::ChannelRequest::MethodId::WEBRTC_SERVER_DUMP: + { + RTC::WebRtcServer* webRtcServer{ nullptr }; + + try + { + webRtcServer = GetWebRtcServerFromInternal(request->internal); + + webRtcServer->HandleRequest(request); + } + catch (const MediaSoupError& error) + { + MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + } + + break; + } + case Channel::ChannelRequest::MethodId::WORKER_CREATE_ROUTER: { std::string routerId; From 652aad0e3392f9444536af01f345f29270ea8c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Fri, 17 Jun 2022 15:35:14 +0200 Subject: [PATCH 24/58] TransportTuple: replace id (string) for hash (size_t) --- worker/include/RTC/TransportTuple.hpp | 17 ++++++++++------- worker/include/RTC/WebRtcServer.hpp | 4 ++-- worker/src/RTC/WebRtcServer.cpp | 8 ++++---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 3294582a16..dbed548567 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -28,13 +28,13 @@ namespace RTC TransportTuple(RTC::UdpSocket* udpSocket, const struct sockaddr* udpRemoteAddr) : udpSocket(udpSocket), udpRemoteAddr((struct sockaddr*)udpRemoteAddr), protocol(Protocol::UDP) { - GenerateId(); + GenerateHash(); } explicit TransportTuple(RTC::TcpConnection* tcpConnection) : tcpConnection(tcpConnection), protocol(Protocol::TCP) { - GenerateId(); + GenerateHash(); } explicit TransportTuple(const TransportTuple* tuple) @@ -42,7 +42,7 @@ namespace RTC tcpConnection(tuple->tcpConnection), localAnnouncedIp(tuple->localAnnouncedIp), protocol(tuple->protocol) { - this->id = tuple->id; + this->hash = tuple->hash; if (protocol == TransportTuple::Protocol::UDP) StoreUdpRemoteAddress(); @@ -130,9 +130,10 @@ namespace RTC } private: - void GenerateId() + void GenerateHash() { const std::string protocol = this->protocol == Protocol::UDP ? "udp" : "tcp"; + std::string id; int family; std::string localIp; uint16_t localPort; @@ -142,12 +143,14 @@ namespace RTC Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); - this->id = remoteIp + "_" + std::to_string(remotePort) + "_" + localIp + "_" + - std::to_string(localPort) + "_" + std::to_string(family) + "_" + protocol; + id = remoteIp + std::to_string(remotePort) + localIp + std::to_string(localPort) + + std::to_string(family) + protocol; + + this->hash = std::hash{}(id); } public: - std::string id; + size_t hash; private: // Passed by argument. diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 6add633057..504ff18f81 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -99,8 +99,8 @@ namespace RTC absl::flat_hash_set webRtcTransports; // Map of WebRtcTransports indexed by local ICE usernameFragment. absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransport; - // Map of WebRtcTransports indexed by TransportTuple.id. - absl::flat_hash_map mapTupleWebRtcTransport; + // Map of WebRtcTransports indexed by TransportTuple.hash. + absl::flat_hash_map mapTupleWebRtcTransport; }; } // namespace RTC diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 2df8b9090e..ad43f7b88b 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -397,7 +397,7 @@ namespace RTC { MS_TRACE(); - auto it = this->mapTupleWebRtcTransport.find(tuple->id); + auto it = this->mapTupleWebRtcTransport.find(tuple->hash); if (it == this->mapTupleWebRtcTransport.end()) { @@ -454,7 +454,7 @@ namespace RTC { MS_TRACE(); - this->mapTupleWebRtcTransport[tuple->id] = webRtcTransport; + this->mapTupleWebRtcTransport[tuple->hash] = webRtcTransport; } inline void WebRtcServer::OnWebRtcTransportTransportTupleRemoved( @@ -462,7 +462,7 @@ namespace RTC { MS_TRACE(); - this->mapTupleWebRtcTransport.erase(tuple->id); + this->mapTupleWebRtcTransport.erase(tuple->hash); } inline void WebRtcServer::OnUdpSocketPacketReceived( @@ -482,7 +482,7 @@ namespace RTC RTC::TransportTuple tuple(connection); - auto it = this->mapTupleWebRtcTransport.find(tuple.id); + auto it = this->mapTupleWebRtcTransport.find(tuple.hash); MS_ASSERT( it != this->mapTupleWebRtcTransport.end(), From 0d1142db71390505fa1b6b7231a3f97d7e2be9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 15:47:15 +0200 Subject: [PATCH 25/58] more --- worker/include/RTC/Router.hpp | 15 ++++++++++++++- worker/include/Worker.hpp | 7 ++++++- worker/src/RTC/Router.cpp | 24 +++++++++++++++++++++++- worker/src/Worker.cpp | 19 ++++++++++++++++++- 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/worker/include/RTC/Router.hpp b/worker/include/RTC/Router.hpp index 5844407cf2..d7c7cc16a1 100644 --- a/worker/include/RTC/Router.hpp +++ b/worker/include/RTC/Router.hpp @@ -13,6 +13,7 @@ #include "RTC/RtpPacket.hpp" #include "RTC/RtpStream.hpp" #include "RTC/Transport.hpp" +#include "RTC/WebRtcServer.hpp" #include #include #include @@ -25,7 +26,18 @@ namespace RTC class Router : public RTC::Transport::Listener { public: - explicit Router(const std::string& id); + class Listener + { + public: + virtual ~Listener() = default; + + public: + virtual RTC::WebRtcServer* OnRouterNeedWebRtcServer( + RTC::Router* router, std::string& webRtcServerId) = 0; + }; + + public: + explicit Router(const std::string& id, Listener* listener); virtual ~Router(); public: @@ -91,6 +103,7 @@ namespace RTC public: // Passed by argument. const std::string id; + Listener* listener{ nullptr }; private: // Allocated by this. diff --git a/worker/include/Worker.hpp b/worker/include/Worker.hpp index 6649b316c9..033f42091e 100644 --- a/worker/include/Worker.hpp +++ b/worker/include/Worker.hpp @@ -18,7 +18,8 @@ using json = nlohmann::json; class Worker : public Channel::ChannelSocket::Listener, public PayloadChannel::PayloadChannelSocket::Listener, - public SignalsHandler::Listener + public SignalsHandler::Listener, + public RTC::Router::Listener { public: explicit Worker(Channel::ChannelSocket* channel, PayloadChannel::PayloadChannelSocket* payloadChannel); @@ -52,6 +53,10 @@ class Worker : public Channel::ChannelSocket::Listener, public: void OnSignal(SignalsHandler* signalsHandler, int signum) override; + /* Pure virtual methods inherited from RTC::Router::Listener. */ +public: + RTC::WebRtcServer* OnRouterNeedWebRtcServer(RTC::Router* router, std::string& webRtcServerId) override; + private: // Passed by argument. Channel::ChannelSocket* channel{ nullptr }; diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index bb5861dbc2..e7906ef397 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -16,7 +16,7 @@ namespace RTC { /* Instance methods. */ - Router::Router(const std::string& id) : id(id) + Router::Router(const std::string& id, Listener* listener) : id(id), listener(listener) { MS_TRACE(); } @@ -202,6 +202,28 @@ namespace RTC break; } + // case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER: + // { + // RTC::Router* router{ nullptr }; + // RTC::WebRtcServer* webRtcServer{ nullptr }; + + // try + // { + // router = GetRouterFromInternal(request->internal); + // webRtcServer = GetWebRtcServerFromInternal(request->internal); + // } + // catch (const MediaSoupError& error) + // { + // MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + // } + + // router->createWebRtcTransportWithServer(webRtcServer) + + // request->Accept(); + + // break; + // } + case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT: { std::string transportId; diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 63fd4a00c6..db7a5aa48f 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -382,7 +382,7 @@ inline void Worker::OnChannelRequest(Channel::ChannelSocket* /*channel*/, Channe MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); } - auto* router = new RTC::Router(routerId); + auto* router = new RTC::Router(routerId, this); this->mapRouters[routerId] = router; @@ -557,3 +557,20 @@ inline void Worker::OnSignal(SignalsHandler* /*signalsHandler*/, int signum) } } } + +inline RTC::WebRtcServer* Worker::OnRouterNeedWebRtcServer( + RTC::Router* /*router*/, std::string& webRtcServerId) +{ + MS_TRACE(); + + RTC::WebRtcServer* webRtcServer{ nullptr }; + + auto it = this->mapWebRtcServers.find(webRtcServerId); + + if (it != this->mapWebRtcServers.end()) + { + webRtcServer = it->second; + } + + return webRtcServer; +} From 8cc29c744333b90398d7402975f7f8d3dcd28934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 16:04:33 +0200 Subject: [PATCH 26/58] Complete C++ side --- worker/include/RTC/TransportTuple.hpp | 5 +- worker/src/RTC/Router.cpp | 104 ++++++++++++++++++++------ worker/src/RTC/WebRtcTransport.cpp | 3 + 3 files changed, 88 insertions(+), 24 deletions(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index dbed548567..8e3d170713 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -133,7 +133,6 @@ namespace RTC void GenerateHash() { const std::string protocol = this->protocol == Protocol::UDP ? "udp" : "tcp"; - std::string id; int family; std::string localIp; uint16_t localPort; @@ -143,8 +142,8 @@ namespace RTC Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); - id = remoteIp + std::to_string(remotePort) + localIp + std::to_string(localPort) + - std::to_string(family) + protocol; + std::string id = remoteIp + std::to_string(remotePort) + localIp + std::to_string(localPort) + + std::to_string(family) + protocol; this->hash = std::hash{}(id); } diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index e7906ef397..84bc72681a 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -202,27 +202,89 @@ namespace RTC break; } - // case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER: - // { - // RTC::Router* router{ nullptr }; - // RTC::WebRtcServer* webRtcServer{ nullptr }; - - // try - // { - // router = GetRouterFromInternal(request->internal); - // webRtcServer = GetWebRtcServerFromInternal(request->internal); - // } - // catch (const MediaSoupError& error) - // { - // MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); - // } - - // router->createWebRtcTransportWithServer(webRtcServer) - - // request->Accept(); - - // break; - // } + case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT_WITH_SERVER: + { + std::string transportId; + + // This may throw. + SetNewTransportIdFromInternal(request->internal, transportId); + + auto jsonWebRtcServerIdIt = request->data.find("webRtcServerId"); + + if (jsonWebRtcServerIdIt == request->data.end() || !jsonWebRtcServerIdIt->is_string()) + { + MS_THROW_TYPE_ERROR("wrong webRtcServerId (not a string)"); + } + + std::string webRtcServerId = jsonWebRtcServerIdIt->get(); + + auto* webRtcServer = this->listener->OnRouterNeedWebRtcServer(this, webRtcServerId); + + bool enableUdp{ true }; + auto jsonEnableUdpIt = request->data.find("enableUdp"); + + if (jsonEnableUdpIt != request->data.end()) + { + if (!jsonEnableUdpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong enableUdp (not a boolean)"); + + enableUdp = jsonEnableUdpIt->get(); + } + + bool enableTcp{ false }; + auto jsonEnableTcpIt = request->data.find("enableTcp"); + + if (jsonEnableTcpIt != request->data.end()) + { + if (!jsonEnableTcpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong enableTcp (not a boolean)"); + + enableTcp = jsonEnableTcpIt->get(); + } + + bool preferUdp{ false }; + auto jsonPreferUdpIt = request->data.find("preferUdp"); + + if (jsonPreferUdpIt != request->data.end()) + { + if (!jsonPreferUdpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong preferUdp (not a boolean)"); + + preferUdp = jsonPreferUdpIt->get(); + } + + bool preferTcp{ false }; + auto jsonPreferTcpIt = request->data.find("preferTcp"); + + if (jsonPreferTcpIt != request->data.end()) + { + if (!jsonPreferTcpIt->is_boolean()) + MS_THROW_TYPE_ERROR("wrong preferTcp (not a boolean)"); + + preferTcp = jsonPreferTcpIt->get(); + } + + auto iceCandidates = + webRtcServer->GetIceCandidates(enableUdp, enableTcp, preferUdp, preferTcp); + + // This may throw. + auto* webRtcTransport = + new RTC::WebRtcTransport(transportId, this, webRtcServer, iceCandidates, request->data); + + // Insert into the map. + this->mapTransports[transportId] = webRtcTransport; + + MS_DEBUG_DEV( + "WebRtcTransport with WebRtcServer created [transportId:%s]", transportId.c_str()); + + json data = json::object(); + + webRtcTransport->FillJson(data); + + request->Accept(data); + + break; + } case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT: { diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index f4dc86e1e2..1e889e7e36 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -252,6 +252,9 @@ namespace RTC try { + if (iceCandidates.empty()) + MS_THROW_TYPE_ERROR("empty iceCandidates"); + // Create a ICE server. this->iceServer = new RTC::IceServer( this, Utils::Crypto::GetRandomString(32), Utils::Crypto::GetRandomString(32)); From 7762b0ff5a7981a66517509d803f41d5ba42f6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 17:02:14 +0200 Subject: [PATCH 27/58] Add TypeScript layer --- node/lib/Router.d.ts | 2 +- node/lib/Router.d.ts.map | 2 +- node/lib/Router.js | 45 +++--- node/lib/Transport.d.ts | 7 + node/lib/Transport.d.ts.map | 2 +- node/lib/Transport.js | 41 ++++++ node/lib/WebRtcServer.d.ts | 95 +++++++++++++ node/lib/WebRtcServer.d.ts.map | 1 + node/lib/WebRtcServer.js | 120 ++++++++++++++++ node/lib/WebRtcTransport.d.ts | 17 ++- node/lib/WebRtcTransport.d.ts.map | 2 +- node/lib/WebRtcTransport.js | 17 +++ node/lib/Worker.d.ts | 12 ++ node/lib/Worker.d.ts.map | 2 +- node/lib/Worker.js | 42 ++++++ node/lib/types.d.ts | 1 + node/lib/types.d.ts.map | 2 +- node/lib/types.js | 1 + node/src/Router.ts | 54 ++++--- node/src/Transport.ts | 57 ++++++++ node/src/WebRtcServer.ts | 226 ++++++++++++++++++++++++++++++ node/src/WebRtcTransport.ts | 33 ++++- node/src/Worker.ts | 64 +++++++++ node/src/types.ts | 1 + 24 files changed, 797 insertions(+), 49 deletions(-) create mode 100644 node/lib/WebRtcServer.d.ts create mode 100644 node/lib/WebRtcServer.d.ts.map create mode 100644 node/lib/WebRtcServer.js create mode 100644 node/src/WebRtcServer.ts diff --git a/node/lib/Router.d.ts b/node/lib/Router.d.ts index b3db928aa6..02f5f17155 100644 --- a/node/lib/Router.d.ts +++ b/node/lib/Router.d.ts @@ -147,7 +147,7 @@ export declare class Router extends EnhancedEventEmitter { /** * Create a WebRtcTransport. */ - createWebRtcTransport({ listenIps, port, enableUdp, enableTcp, preferUdp, preferTcp, initialAvailableOutgoingBitrate, enableSctp, numSctpStreams, maxSctpMessageSize, sctpSendBufferSize, appData }: WebRtcTransportOptions): Promise; + createWebRtcTransport({ webRtcServer, listenIps, port, enableUdp, enableTcp, preferUdp, preferTcp, initialAvailableOutgoingBitrate, enableSctp, numSctpStreams, maxSctpMessageSize, sctpSendBufferSize, appData }: WebRtcTransportOptions): Promise; /** * Create a PlainTransport. */ diff --git a/node/lib/Router.d.ts.map b/node/lib/Router.d.ts.map index 5af7e10d54..5268910021 100644 --- a/node/lib/Router.d.ts.map +++ b/node/lib/Router.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node/lib/Router.js b/node/lib/Router.js index 437900b988..23e110fc90 100644 --- a/node/lib/Router.js +++ b/node/lib/Router.js @@ -159,28 +159,33 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { /** * Create a WebRtcTransport. */ - async createWebRtcTransport({ listenIps, port, enableUdp = true, enableTcp = false, preferUdp = false, preferTcp = false, initialAvailableOutgoingBitrate = 600000, enableSctp = false, numSctpStreams = { OS: 1024, MIS: 1024 }, maxSctpMessageSize = 262144, sctpSendBufferSize = 262144, appData }) { + async createWebRtcTransport({ webRtcServer, listenIps, port, enableUdp = true, enableTcp = false, preferUdp = false, preferTcp = false, initialAvailableOutgoingBitrate = 600000, enableSctp = false, numSctpStreams = { OS: 1024, MIS: 1024 }, maxSctpMessageSize = 262144, sctpSendBufferSize = 262144, appData }) { logger.debug('createWebRtcTransport()'); - if (!Array.isArray(listenIps)) - throw new TypeError('missing listenIps'); + if (!webRtcServer && !Array.isArray(listenIps)) + throw new TypeError('missing webRtcServer and listenIps (one of them is mandatory)'); else if (appData && typeof appData !== 'object') throw new TypeError('if given, appData must be an object'); - listenIps = listenIps.map((listenIp) => { - if (typeof listenIp === 'string' && listenIp) { - return { ip: listenIp }; - } - else if (typeof listenIp === 'object') { - return { - ip: listenIp.ip, - announcedIp: listenIp.announcedIp || undefined - }; - } - else { - throw new TypeError('wrong listenIp'); - } - }); + if (webRtcServer) + listenIps = undefined; + if (listenIps) { + listenIps = listenIps.map((listenIp) => { + if (typeof listenIp === 'string' && listenIp) { + return { ip: listenIp }; + } + else if (typeof listenIp === 'object') { + return { + ip: listenIp.ip, + announcedIp: listenIp.announcedIp || undefined + }; + } + else { + throw new TypeError('wrong listenIp'); + } + }); + } const internal = { ...this.#internal, transportId: (0, uuid_1.v4)() }; const reqData = { + webRtcServerId: webRtcServer?.id, listenIps, port, enableUdp, @@ -194,7 +199,9 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { sctpSendBufferSize, isDataChannel: true }; - const data = await this.#channel.request('router.createWebRtcTransport', internal, reqData); + const data = webRtcServer + ? await this.#channel.request('router.createWebRtcTransportWithServer', internal, reqData) + : await this.#channel.request('router.createWebRtcTransport', internal, reqData); const transport = new WebRtcTransport_1.WebRtcTransport({ internal, data, @@ -211,6 +218,8 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { transport.on('@producerclose', (producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer) => (this.#dataProducers.set(dataProducer.id, dataProducer))); transport.on('@dataproducerclose', (dataProducer) => (this.#dataProducers.delete(dataProducer.id))); + if (webRtcServer) + webRtcServer.handleWebRtcTransport(transport); // Emit observer event. this.#observer.safeEmit('newtransport', transport); return transport; diff --git a/node/lib/Transport.d.ts b/node/lib/Transport.d.ts index fe60668767..f8aa764584 100644 --- a/node/lib/Transport.d.ts +++ b/node/lib/Transport.d.ts @@ -141,6 +141,13 @@ export declare class Transport; +}; +export declare type WebRtcServerEvents = { + workerclose: []; +}; +export declare type WebRtcServerObserverEvents = { + close: []; + newwebrtctransport: [WebRtcTransport]; +}; +export declare class WebRtcServer extends EnhancedEventEmitter { + #private; + /** + * @private + * @emits workerclose + * @emits @close + */ + constructor({ internal, channel, appData }: { + internal: any; + channel: Channel; + appData?: Record; + }); + /** + * Router id. + */ + get id(): string; + /** + * Whether the Router is closed. + */ + get closed(): boolean; + /** + * App custom data. + */ + get appData(): Record; + /** + * Invalid setter. + */ + set appData(appData: Record); + /** + * Observer. + * + * @emits close + * @emits newwebrtctransport - (webRtcTransport: WebRtcTransport) + */ + get observer(): EnhancedEventEmitter; + /** + * Close the WebRtcServer. + */ + close(): void; + /** + * Worker was closed. + * + * @private + */ + workerClosed(): void; + /** + * Dump WebRtcServer. + */ + dump(): Promise; + /** + * @private + */ + handleWebRtcTransport(webRtcTransport: WebRtcTransport): void; +} +//# sourceMappingURL=WebRtcServer.d.ts.map \ No newline at end of file diff --git a/node/lib/WebRtcServer.d.ts.map b/node/lib/WebRtcServer.d.ts.map new file mode 100644 index 0000000000..bb17bb3df0 --- /dev/null +++ b/node/lib/WebRtcServer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;CACtC,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;;;OAIG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAsBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAQ7D"} \ No newline at end of file diff --git a/node/lib/WebRtcServer.js b/node/lib/WebRtcServer.js new file mode 100644 index 0000000000..68b5a9f3ae --- /dev/null +++ b/node/lib/WebRtcServer.js @@ -0,0 +1,120 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WebRtcServer = void 0; +const Logger_1 = require("./Logger"); +const EnhancedEventEmitter_1 = require("./EnhancedEventEmitter"); +const logger = new Logger_1.Logger('WebRtcServer'); +class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { + // Internal data. + #internal; + // Channel instance. + #channel; + // Closed flag. + #closed = false; + // Custom app data. + #appData; + // Transports map. + #webRtcTransports = new Map(); + // Observer instance. + #observer = new EnhancedEventEmitter_1.EnhancedEventEmitter(); + /** + * @private + * @emits workerclose + * @emits @close + */ + constructor({ internal, channel, appData }) { + super(); + logger.debug('constructor()'); + this.#internal = internal; + this.#channel = channel; + this.#appData = appData || {}; + } + /** + * Router id. + */ + get id() { + return this.#internal.webRtcServerId; + } + /** + * Whether the Router is closed. + */ + get closed() { + return this.#closed; + } + /** + * App custom data. + */ + get appData() { + return this.#appData; + } + /** + * Invalid setter. + */ + set appData(appData) { + throw new Error('cannot override appData object'); + } + /** + * Observer. + * + * @emits close + * @emits newwebrtctransport - (webRtcTransport: WebRtcTransport) + */ + get observer() { + return this.#observer; + } + /** + * Close the WebRtcServer. + */ + close() { + if (this.#closed) + return; + logger.debug('close()'); + this.#closed = true; + this.#channel.request('webRtcServer.close', this.#internal) + .catch(() => { }); + // Close every WebRtcTransport. + for (const webRtcTransport of this.#webRtcTransports.values()) { + webRtcTransport.mustClose(); + } + this.#webRtcTransports.clear(); + this.emit('@close'); + // Emit observer event. + this.#observer.safeEmit('close'); + } + /** + * Worker was closed. + * + * @private + */ + workerClosed() { + if (this.#closed) + return; + logger.debug('workerClosed()'); + this.#closed = true; + // Close every WebRtcTransport. + for (const webRtcTransport of this.#webRtcTransports.values()) { + webRtcTransport.mustClose(); + } + this.#webRtcTransports.clear(); + this.safeEmit('workerclose'); + // Emit observer event. + this.#observer.safeEmit('close'); + } + /** + * Dump WebRtcServer. + */ + async dump() { + logger.debug('dump()'); + return this.#channel.request('webRtcServer.dump', this.#internal); + } + /** + * @private + */ + handleWebRtcTransport(webRtcTransport) { + this.#webRtcTransports.set(webRtcTransport.id, webRtcTransport); + webRtcTransport.on('@close', () => this.#webRtcTransports.delete(webRtcTransport.id)); + // Emit observer event. + this.#observer.safeEmit('newwebrtctransport', webRtcTransport); + } +} +exports.WebRtcServer = WebRtcServer; diff --git a/node/lib/WebRtcTransport.d.ts b/node/lib/WebRtcTransport.d.ts index 6e33bc4f82..79561de334 100644 --- a/node/lib/WebRtcTransport.d.ts +++ b/node/lib/WebRtcTransport.d.ts @@ -1,11 +1,16 @@ import { Transport, TransportListenIp, TransportProtocol, TransportTuple, TransportEvents, TransportObserverEvents, SctpState } from './Transport'; +import { WebRtcServer } from './WebRtcServer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; export declare type WebRtcTransportOptions = { + /** + * Instance of WebRtcServer. Mandatory unless lisntenIps is given. + */ + webRtcServer?: WebRtcServer; /** * Listening IP address or addresses in order of preference (first one is the - * preferred one). + * preferred one). Mandatory unless webRtcServer is given. */ - listenIps: (TransportListenIp | string)[]; + listenIps?: (TransportListenIp | string)[]; /** * Fixed port to listen on instead of selecting automatically from Worker's port * range. @@ -117,6 +122,7 @@ export declare type WebRtcTransportEvents = TransportEvents & { iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; sctpstatechange: [SctpState]; + webrtcserverclosed: []; }; export declare type WebRtcTransportObserverEvents = TransportObserverEvents & { icestatechange: [IceState]; @@ -203,6 +209,13 @@ export declare class WebRtcTransport extends Transport { @@ -150,9 +152,15 @@ export declare class Worker extends EnhancedEventEmitter { * Observer. * * @emits close + * @emits newwebrtcserver: - (webRtcServer: WebRtcServer) * @emits newrouter - (router: Router) */ get observer(): EnhancedEventEmitter; + /** + * @private + * Just for testing purposes. + */ + get webRtcServersForTesting(): Set; /** * @private * Just for testing purposes. @@ -174,6 +182,10 @@ export declare class Worker extends EnhancedEventEmitter { * Update settings. */ updateSettings({ logLevel, logTags }?: WorkerUpdateableSettings): Promise; + /** + * Create a WebRtcServer. + */ + createWebRtcServer({ listenInfos, appData }: WebRtcServerOptions): Promise; /** * Create a Router. */ diff --git a/node/lib/Worker.d.ts.map b/node/lib/Worker.d.ts.map index 1558310f34..aecebb2a34 100644 --- a/node/lib/Worker.d.ts.map +++ b/node/lib/Worker.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Worker.d.ts","sourceRoot":"","sources":["../src/Worker.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Worker.d.ts","sourceRoot":"","sources":["../src/Worker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node/lib/Worker.js b/node/lib/Worker.js index 5c84268ee8..a2e577e337 100644 --- a/node/lib/Worker.js +++ b/node/lib/Worker.js @@ -11,6 +11,7 @@ const ortc = require("./ortc"); const Channel_1 = require("./Channel"); const PayloadChannel_1 = require("./PayloadChannel"); const Router_1 = require("./Router"); +const WebRtcServer_1 = require("./WebRtcServer"); // If env MEDIASOUP_WORKER_BIN is given, use it as worker binary. // Otherwise if env MEDIASOUP_BUILDTYPE is 'Debug' use the Debug binary. // Otherwise use the Release binary. @@ -36,6 +37,8 @@ class Worker extends EnhancedEventEmitter_1.EnhancedEventEmitter { #died = false; // Custom app data. #appData; + // WebRtcServers set. + #webRtcServers = new Set(); // Routers set. #routers = new Set(); // Observer instance. @@ -203,11 +206,19 @@ class Worker extends EnhancedEventEmitter_1.EnhancedEventEmitter { * Observer. * * @emits close + * @emits newwebrtcserver: - (webRtcServer: WebRtcServer) * @emits newrouter - (router: Router) */ get observer() { return this.#observer; } + /** + * @private + * Just for testing purposes. + */ + get webRtcServersForTesting() { + return this.#webRtcServers; + } /** * @private * Just for testing purposes. @@ -242,6 +253,11 @@ class Worker extends EnhancedEventEmitter_1.EnhancedEventEmitter { router.workerClosed(); } this.#routers.clear(); + // Close every WebRtcServer. + for (const webRtcServer of this.#webRtcServers) { + webRtcServer.workerClosed(); + } + this.#webRtcServers.clear(); // Emit observer event. this.#observer.safeEmit('close'); } @@ -267,6 +283,27 @@ class Worker extends EnhancedEventEmitter_1.EnhancedEventEmitter { const reqData = { logLevel, logTags }; await this.#channel.request('worker.updateSettings', undefined, reqData); } + /** + * Create a WebRtcServer. + */ + async createWebRtcServer({ listenInfos, appData }) { + logger.debug('createWebRtcServer()'); + if (appData && typeof appData !== 'object') + throw new TypeError('if given, appData must be an object'); + const internal = { webRtcServerId: (0, uuid_1.v4)() }; + const reqData = { listenInfos }; + await this.#channel.request('worker.createWebRtcServer', internal, reqData); + const webRtcServer = new WebRtcServer_1.WebRtcServer({ + internal, + channel: this.#channel, + appData + }); + this.#webRtcServers.add(webRtcServer); + webRtcServer.on('@close', () => this.#webRtcServers.delete(webRtcServer)); + // Emit observer event. + this.#observer.safeEmit('newwebrtcserver', webRtcServer); + return webRtcServer; + } /** * Create a Router. */ @@ -307,6 +344,11 @@ class Worker extends EnhancedEventEmitter_1.EnhancedEventEmitter { router.workerClosed(); } this.#routers.clear(); + // Close every WebRtcServer. + for (const webRtcServer of this.#webRtcServers) { + webRtcServer.workerClosed(); + } + this.#webRtcServers.clear(); this.safeEmit('died', error); // Emit observer event. this.#observer.safeEmit('close'); diff --git a/node/lib/types.d.ts b/node/lib/types.d.ts index e6357b6c3d..01ad1c323e 100644 --- a/node/lib/types.d.ts +++ b/node/lib/types.d.ts @@ -1,4 +1,5 @@ export * from './Worker'; +export * from './WebRtcServer'; export * from './Router'; export * from './Transport'; export * from './WebRtcTransport'; diff --git a/node/lib/types.d.ts.map b/node/lib/types.d.ts.map index 88f029fe0f..b34a5c6f17 100644 --- a/node/lib/types.d.ts.map +++ b/node/lib/types.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"} \ No newline at end of file +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"} \ No newline at end of file diff --git a/node/lib/types.js b/node/lib/types.js index 00c6b24b1d..65d74efd03 100644 --- a/node/lib/types.js +++ b/node/lib/types.js @@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) { }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(require("./Worker"), exports); +__exportStar(require("./WebRtcServer"), exports); __exportStar(require("./Router"), exports); __exportStar(require("./Transport"), exports); __exportStar(require("./WebRtcTransport"), exports); diff --git a/node/src/Router.ts b/node/src/Router.ts index 126be35f3c..19b4939dbe 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -345,6 +345,7 @@ export class Router extends EnhancedEventEmitter */ async createWebRtcTransport( { + webRtcServer, listenIps, port, enableUdp = true, @@ -362,32 +363,39 @@ export class Router extends EnhancedEventEmitter { logger.debug('createWebRtcTransport()'); - if (!Array.isArray(listenIps)) - throw new TypeError('missing listenIps'); + if (!webRtcServer && !Array.isArray(listenIps)) + throw new TypeError('missing webRtcServer and listenIps (one of them is mandatory)'); else if (appData && typeof appData !== 'object') throw new TypeError('if given, appData must be an object'); - listenIps = listenIps.map((listenIp) => + if (webRtcServer) + listenIps = undefined; + + if (listenIps) { - if (typeof listenIp === 'string' && listenIp) - { - return { ip: listenIp }; - } - else if (typeof listenIp === 'object') - { - return { - ip : listenIp.ip, - announcedIp : listenIp.announcedIp || undefined - }; - } - else + listenIps = listenIps.map((listenIp) => { - throw new TypeError('wrong listenIp'); - } - }); + if (typeof listenIp === 'string' && listenIp) + { + return { ip: listenIp }; + } + else if (typeof listenIp === 'object') + { + return { + ip : listenIp.ip, + announcedIp : listenIp.announcedIp || undefined + }; + } + else + { + throw new TypeError('wrong listenIp'); + } + }); + } const internal = { ...this.#internal, transportId: uuidv4() }; const reqData = { + webRtcServerId : webRtcServer?.id, listenIps, port, enableUdp, @@ -399,11 +407,12 @@ export class Router extends EnhancedEventEmitter numSctpStreams, maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : true + isDataChannel : true }; - const data = - await this.#channel.request('router.createWebRtcTransport', internal, reqData); + const data = webRtcServer + ? await this.#channel.request('router.createWebRtcTransportWithServer', internal, reqData) + : await this.#channel.request('router.createWebRtcTransport', internal, reqData); const transport = new WebRtcTransport( { @@ -432,6 +441,9 @@ export class Router extends EnhancedEventEmitter this.#dataProducers.delete(dataProducer.id) )); + if (webRtcServer) + webRtcServer.handleWebRtcTransport(transport); + // Emit observer event. this.#observer.safeEmit('newtransport', transport); diff --git a/node/src/Transport.ts b/node/src/Transport.ts index f081c97a6f..46b39f151e 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -385,6 +385,63 @@ export class Transport; +} + +export type WebRtcServerEvents = +{ + workerclose: []; +} + +export type WebRtcServerObserverEvents = +{ + close: []; + newwebrtctransport: [WebRtcTransport]; +} + +const logger = new Logger('WebRtcServer'); + +export class WebRtcServer extends EnhancedEventEmitter +{ + // Internal data. + readonly #internal: + { + webRtcServerId: string; + }; + + // Channel instance. + readonly #channel: Channel; + + // Closed flag. + #closed = false; + + // Custom app data. + readonly #appData: Record; + + // Transports map. + readonly #webRtcTransports: Map = new Map(); + + // Observer instance. + readonly #observer = new EnhancedEventEmitter(); + + /** + * @private + * @emits workerclose + * @emits @close + */ + constructor( + { + internal, + channel, + appData + }: + { + internal: any; + channel: Channel; + appData?: Record; + } + ) + { + super(); + + logger.debug('constructor()'); + + this.#internal = internal; + this.#channel = channel; + this.#appData = appData || {}; + } + + /** + * Router id. + */ + get id(): string + { + return this.#internal.webRtcServerId; + } + + /** + * Whether the Router is closed. + */ + get closed(): boolean + { + return this.#closed; + } + + /** + * App custom data. + */ + get appData(): Record + { + return this.#appData; + } + + /** + * Invalid setter. + */ + set appData(appData: Record) // eslint-disable-line no-unused-vars + { + throw new Error('cannot override appData object'); + } + + /** + * Observer. + * + * @emits close + * @emits newwebrtctransport - (webRtcTransport: WebRtcTransport) + */ + get observer(): EnhancedEventEmitter + { + return this.#observer; + } + + /** + * Close the WebRtcServer. + */ + close(): void + { + if (this.#closed) + return; + + logger.debug('close()'); + + this.#closed = true; + + this.#channel.request('webRtcServer.close', this.#internal) + .catch(() => {}); + + // Close every WebRtcTransport. + for (const webRtcTransport of this.#webRtcTransports.values()) + { + webRtcTransport.mustClose(); + } + this.#webRtcTransports.clear(); + + this.emit('@close'); + + // Emit observer event. + this.#observer.safeEmit('close'); + } + + /** + * Worker was closed. + * + * @private + */ + workerClosed(): void + { + if (this.#closed) + return; + + logger.debug('workerClosed()'); + + this.#closed = true; + + // Close every WebRtcTransport. + for (const webRtcTransport of this.#webRtcTransports.values()) + { + webRtcTransport.mustClose(); + } + this.#webRtcTransports.clear(); + + this.safeEmit('workerclose'); + + // Emit observer event. + this.#observer.safeEmit('close'); + } + + /** + * Dump WebRtcServer. + */ + async dump(): Promise + { + logger.debug('dump()'); + + return this.#channel.request('webRtcServer.dump', this.#internal); + } + + /** + * @private + */ + handleWebRtcTransport(webRtcTransport: WebRtcTransport): void + { + this.#webRtcTransports.set(webRtcTransport.id, webRtcTransport); + webRtcTransport.on('@close', () => this.#webRtcTransports.delete(webRtcTransport.id)); + + // Emit observer event. + this.#observer.safeEmit('newwebrtctransport', webRtcTransport); + } +} diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 8449fd74bc..094058d3b1 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -9,15 +9,20 @@ import { TransportObserverEvents, SctpState } from './Transport'; +import { WebRtcServer } from './WebRtcServer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; export type WebRtcTransportOptions = { + /** + * Instance of WebRtcServer. Mandatory unless lisntenIps is given. + */ + webRtcServer?: WebRtcServer; /** * Listening IP address or addresses in order of preference (first one is the - * preferred one). + * preferred one). Mandatory unless webRtcServer is given. */ - listenIps: (TransportListenIp | string)[]; + listenIps?: (TransportListenIp | string)[]; /** * Fixed port to listen on instead of selecting automatically from Worker's port @@ -157,6 +162,7 @@ export type WebRtcTransportEvents = TransportEvents & iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; sctpstatechange: [SctpState]; + webrtcserverclosed: []; } export type WebRtcTransportObserverEvents = TransportObserverEvents & @@ -358,6 +364,29 @@ export class WebRtcTransport extends super.routerClosed(); } + /** + * Called when closing the associated WebRtcServer. + * + * @private + * @override + */ + mustClose(): void + { + if (this.closed) + return; + + this.#data.iceState = 'closed'; + this.#data.iceSelectedTuple = undefined; + this.#data.dtlsState = 'closed'; + + if (this.#data.sctpState) + this.#data.sctpState = 'closed'; + + super.mustClose(); + + this.safeEmit('webrtcserverclosed'); + } + /** * Get WebRtcTransport stats. * diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 8678b75591..40e5e0e778 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -8,6 +8,7 @@ import * as ortc from './ortc'; import { Channel } from './Channel'; import { PayloadChannel } from './PayloadChannel'; import { Router, RouterOptions } from './Router'; +import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; export type WorkerLogLevel = 'debug' | 'warn' | 'error' | 'none'; @@ -172,6 +173,7 @@ export type WorkerEvents = export type WorkerObserverEvents = { close: []; + newwebrtcserver: [WebRtcServer]; newrouter: [Router]; } @@ -210,6 +212,9 @@ export class Worker extends EnhancedEventEmitter // Custom app data. readonly #appData: Record; + // WebRtcServers set. + readonly #webRtcServers: Set = new Set(); + // Routers set. readonly #routers: Set = new Set(); @@ -467,6 +472,7 @@ export class Worker extends EnhancedEventEmitter * Observer. * * @emits close + * @emits newwebrtcserver: - (webRtcServer: WebRtcServer) * @emits newrouter - (router: Router) */ get observer(): EnhancedEventEmitter @@ -474,6 +480,15 @@ export class Worker extends EnhancedEventEmitter return this.#observer; } + /** + * @private + * Just for testing purposes. + */ + get webRtcServersForTesting(): Set + { + return this.#webRtcServers; + } + /** * @private * Just for testing purposes. @@ -520,6 +535,13 @@ export class Worker extends EnhancedEventEmitter } this.#routers.clear(); + // Close every WebRtcServer. + for (const webRtcServer of this.#webRtcServers) + { + webRtcServer.workerClosed(); + } + this.#webRtcServers.clear(); + // Emit observer event. this.#observer.safeEmit('close'); } @@ -561,6 +583,41 @@ export class Worker extends EnhancedEventEmitter await this.#channel.request('worker.updateSettings', undefined, reqData); } + /** + * Create a WebRtcServer. + */ + async createWebRtcServer( + { + listenInfos, + appData + }: WebRtcServerOptions): Promise + { + logger.debug('createWebRtcServer()'); + + if (appData && typeof appData !== 'object') + throw new TypeError('if given, appData must be an object'); + + const internal = { webRtcServerId: uuidv4() }; + const reqData = { listenInfos }; + + await this.#channel.request('worker.createWebRtcServer', internal, reqData); + + const webRtcServer = new WebRtcServer( + { + internal, + channel : this.#channel, + appData + }); + + this.#webRtcServers.add(webRtcServer); + webRtcServer.on('@close', () => this.#webRtcServers.delete(webRtcServer)); + + // Emit observer event. + this.#observer.safeEmit('newwebrtcserver', webRtcServer); + + return webRtcServer; + } + /** * Create a Router. */ @@ -624,6 +681,13 @@ export class Worker extends EnhancedEventEmitter } this.#routers.clear(); + // Close every WebRtcServer. + for (const webRtcServer of this.#webRtcServers) + { + webRtcServer.workerClosed(); + } + this.#webRtcServers.clear(); + this.safeEmit('died', error); // Emit observer event. diff --git a/node/src/types.ts b/node/src/types.ts index f6187b7675..b3fe195f77 100644 --- a/node/src/types.ts +++ b/node/src/types.ts @@ -1,4 +1,5 @@ export * from './Worker'; +export * from './WebRtcServer'; export * from './Router'; export * from './Transport'; export * from './WebRtcTransport'; From 67ba1d0a8d0f4a6ad740785e9df54b032ff4764c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 17:10:27 +0200 Subject: [PATCH 28/58] Fix comment --- node/lib/Transport.d.ts | 2 +- node/lib/Transport.js | 2 +- node/src/Transport.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/node/lib/Transport.d.ts b/node/lib/Transport.d.ts index f8aa764584..b2862a7621 100644 --- a/node/lib/Transport.d.ts +++ b/node/lib/Transport.d.ts @@ -142,7 +142,7 @@ export declare class Transport Date: Fri, 17 Jun 2022 17:14:39 +0200 Subject: [PATCH 29/58] TransportTuple: compare tuple by checking the hash --- worker/include/RTC/TransportTuple.hpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 8e3d170713..9555aea318 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -63,20 +63,7 @@ namespace RTC bool Compare(const TransportTuple* tuple) const { - if (this->protocol == Protocol::UDP && tuple->GetProtocol() == Protocol::UDP) - { - return ( - this->udpSocket == tuple->udpSocket && - Utils::IP::CompareAddresses(this->udpRemoteAddr, tuple->GetRemoteAddress())); - } - else if (this->protocol == Protocol::TCP && tuple->GetProtocol() == Protocol::TCP) - { - return (this->tcpConnection == tuple->tcpConnection); - } - else - { - return false; - } + return this->hash == tuple->hash; } void SetLocalAnnouncedIp(std::string& localAnnouncedIp) From fb133bd2daed645958ebc6a6c999d68810cc8d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 17:47:24 +0200 Subject: [PATCH 30/58] Add node/tests/test-WebRtcServer.js (hoever last test produces a crash) --- node/tests/test-WebRtcServer.js | 256 ++++++++++++++++++++++++++++++++ worker/src/Worker.cpp | 4 + 2 files changed, 260 insertions(+) create mode 100644 node/tests/test-WebRtcServer.js diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js new file mode 100644 index 0000000000..b8af616d26 --- /dev/null +++ b/node/tests/test-WebRtcServer.js @@ -0,0 +1,256 @@ +const { toBeType } = require('jest-tobetype'); +const pickPort = require('pick-port'); +const mediasoup = require('../lib/'); +const { createWorker } = mediasoup; +const { InvalidStateError } = require('../lib/errors'); + +expect.extend({ toBeType }); + +let worker; + +beforeEach(() => worker && !worker.closed && worker.close()); +afterEach(() => worker && !worker.closed && worker.close()); + +test('worker.createWebRtcServer() succeeds', async () => +{ + worker = await createWorker(); + + const onObserverNewWebRtcServer = jest.fn(); + + worker.observer.once('newwebrtcserver', onObserverNewWebRtcServer); + + const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); + + const webRtcServer = await worker.createWebRtcServer( + { + listenInfos : + [ + { + protocol : 'udp', + ip : '127.0.0.1', + port : port1 + }, + { + protocol : 'tcp', + ip : '127.0.0.1', + announcedIp : '1.2.3.4', + port : port2 + } + ], + appData : { foo: 123 } + }); + + expect(onObserverNewWebRtcServer).toHaveBeenCalledTimes(1); + expect(onObserverNewWebRtcServer).toHaveBeenCalledWith(webRtcServer); + expect(webRtcServer.id).toBeType('string'); + expect(webRtcServer.closed).toBe(false); + expect(webRtcServer.appData).toEqual({ foo: 123 }); + + await expect(worker.dump()) + .resolves + .toEqual({ pid: worker.pid, webRtcServerIds: [ webRtcServer.id ], routerIds: [] }); + + await expect(webRtcServer.dump()) + .resolves + .toMatchObject( + { + id : webRtcServer.id, + udpSockets : + [ + { ip: '127.0.0.1', port: port1 } + ], + tcpServers : + [ + { ip: '127.0.0.1', port: port2 } + ], + webRtcTransportIds : [], + localIceUsernameFragments : [], + tuples : [] + }); + + // Private API. + expect(worker.webRtcServersForTesting.size).toBe(1); + + worker.close(); + + expect(webRtcServer.closed).toBe(true); + + // Private API. + expect(worker.webRtcServersForTesting.size).toBe(0); +}, 2000); + +test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', async () => +{ + worker = await createWorker(); + + await expect(worker.createWebRtcServer({ })) + .rejects + .toThrow(TypeError); + + await expect(worker.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' })) + .rejects + .toThrow(TypeError); + + await expect(worker.createWebRtcServer({ listenInfos: [ 'NOT-AN-OBJECT' ] })) + .rejects + .toThrow(TypeError); + + // Empty listenInfos so should fail. + await expect(worker.createWebRtcServer({ listenInfos: [] })) + .rejects + .toThrow(TypeError); + + worker.close(); +}, 2000); + +test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => +{ + worker = await createWorker(); + + worker.close(); + + const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + + await expect(worker.createWebRtcServer( + { + listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] + })) + .rejects + .toThrow(InvalidStateError); +}, 2000); + +test('webRtcServer.close() succeeds', async () => +{ + worker = await createWorker(); + + const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const webRtcServer = await worker.createWebRtcServer( + { + listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] + }); + const onObserverClose = jest.fn(); + + webRtcServer.observer.once('close', onObserverClose); + webRtcServer.close(); + + expect(onObserverClose).toHaveBeenCalledTimes(1); + expect(webRtcServer.closed).toBe(true); +}, 2000); + +test('WebRtcServer emits "workerclose" if Worker is closed', async () => +{ + worker = await createWorker(); + + const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const webRtcServer = await worker.createWebRtcServer( + { + listenInfos : [ { protocol: 'tcp', ip: '127.0.0.1', port } ] + }); + const onObserverClose = jest.fn(); + + webRtcServer.observer.once('close', onObserverClose); + + await new Promise((resolve) => + { + webRtcServer.on('workerclose', resolve); + worker.close(); + }); + + expect(onObserverClose).toHaveBeenCalledTimes(1); + expect(webRtcServer.closed).toBe(true); +}, 2000); + +test('router.createWebRtcTransport() with webRtcServer succeeds', async () => +{ + worker = await createWorker(); + + const router = await worker.createRouter(); + const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); + const webRtcServer = await worker.createWebRtcServer( + { + listenInfos : + [ + { protocol: 'udp', ip: '127.0.0.1', port: port1 }, + { protocol: 'tcp', ip: '127.0.0.1', port: port2 }, + ] + }); + + await expect(router.dump()) + .resolves + .toMatchObject({ transportIds: [ transport.id ] }); + + const onObserverNewTransport = jest.fn(); + + router.observer.once('newtransport', onObserverNewTransport); + + // Create a separate transport here. + const transport = await router.createWebRtcTransport( + { + webRtcServer, + enableTcp : false, + preferUdp : true, + appData : { foo: 'bar' } + }); + + expect(onObserverNewTransport).toHaveBeenCalledTimes(1); + expect(onObserverNewTransport).toHaveBeenCalledWith(transport); + expect(transport.id).toBeType('string'); + expect(transport.closed).toBe(false); + expect(transport.appData).toEqual({ foo: 'bar' }); + + const iceCandidates = transport.iceCandidates; + + expect(iceCandidates.length).toBe(1); + expect(iceCandidates[0].ip).toBe('127.0.0.1'); + expect(iceCandidates[0].port).toBe(port1); + expect(iceCandidates[0].protocol).toBe('udp'); + expect(iceCandidates[0].type).toBe('host'); + expect(iceCandidates[0].tcpType).toBeUndefined(); + + expect(transport.iceState).toBe('new'); + expect(transport.iceSelectedTuple).toBeUndefined(); + + await expect(webRtcServer.dump()) + .resolves + .toMatchObject( + { + id : webRtcServer.id, + udpSockets : + [ + { ip: '127.0.0.1', port: port1 } + ], + tcpServers : + [ + { ip: '127.0.0.1', port: port2 } + ], + webRtcTransportIds : [ transport.id ], + localIceUsernameFragments : + [ + { /*localIceUsernameFragment*/ webRtcTransportId: transport.id } + ], + tuples : [] + }); + + transport.close(); + expect(transport.closed).toBe(true); + + await expect(webRtcServer.dump()) + .resolves + .toMatchObject( + { + id : webRtcServer.id, + udpSockets : + [ + { ip: '127.0.0.1', port: port1 } + ], + tcpServers : + [ + { ip: '127.0.0.1', port: port2 } + ], + webRtcTransportIds : [], + localIceUsernameFragments : [], + tuples : [] + }); +}, 2000); diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index db7a5aa48f..c344bdb80c 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -319,6 +319,10 @@ inline void Worker::OnChannelRequest(Channel::ChannelSocket* /*channel*/, Channe request->Accept(); } + catch (const MediaSoupTypeError& error) + { + MS_THROW_TYPE_ERROR("%s [method:%s]", error.what(), request->method.c_str()); + } catch (const MediaSoupError& error) { MS_THROW_ERROR("%s [method:%s]", error.what(), request->method.c_str()); From da815c565432b9bb55c78daf5a9f118537490a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 17:48:35 +0200 Subject: [PATCH 31/58] fix lint --- node/tests/test-WebRtcServer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index b8af616d26..ec8a6919b6 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -173,7 +173,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port: port1 }, - { protocol: 'tcp', ip: '127.0.0.1', port: port2 }, + { protocol: 'tcp', ip: '127.0.0.1', port: port2 } ] }); @@ -228,7 +228,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => webRtcTransportIds : [ transport.id ], localIceUsernameFragments : [ - { /*localIceUsernameFragment*/ webRtcTransportId: transport.id } + { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } ], tuples : [] }); From 370ba49153a12119cc7871d4195de28031bbe4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 18:02:28 +0200 Subject: [PATCH 32/58] fix node/tests/test-WebRtcServer.js --- node/lib/WebRtcServer.d.ts | 5 +++++ node/lib/WebRtcServer.d.ts.map | 2 +- node/lib/WebRtcServer.js | 7 +++++++ node/src/WebRtcServer.ts | 9 +++++++++ node/tests/test-WebRtcServer.js | 15 +++++++++------ 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/node/lib/WebRtcServer.d.ts b/node/lib/WebRtcServer.d.ts index 9e160ded5a..79056a9f85 100644 --- a/node/lib/WebRtcServer.d.ts +++ b/node/lib/WebRtcServer.d.ts @@ -73,6 +73,11 @@ export declare class WebRtcServer extends EnhancedEventEmitter; + /** + * @private + * Just for testing purposes. + */ + get webRtcTransportsForTesting(): Map; /** * Close the WebRtcServer. */ diff --git a/node/lib/WebRtcServer.d.ts.map b/node/lib/WebRtcServer.d.ts.map index bb17bb3df0..65b26bb744 100644 --- a/node/lib/WebRtcServer.d.ts.map +++ b/node/lib/WebRtcServer.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;CACtC,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;;;OAIG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAsBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAQ7D"} \ No newline at end of file +{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;CACtC,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;;;OAIG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAG7D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAsBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAQ7D"} \ No newline at end of file diff --git a/node/lib/WebRtcServer.js b/node/lib/WebRtcServer.js index 68b5a9f3ae..22548506aa 100644 --- a/node/lib/WebRtcServer.js +++ b/node/lib/WebRtcServer.js @@ -62,6 +62,13 @@ class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { get observer() { return this.#observer; } + /** + * @private + * Just for testing purposes. + */ + get webRtcTransportsForTesting() { + return this.#webRtcTransports; + } /** * Close the WebRtcServer. */ diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 4f802fcabb..33fe697a26 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -147,6 +147,15 @@ export class WebRtcServer extends EnhancedEventEmitter return this.#observer; } + /** + * @private + * Just for testing purposes. + */ + get webRtcTransportsForTesting(): Map + { + return this.#webRtcTransports; + } + /** * Close the WebRtcServer. */ diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index ec8a6919b6..bbea0d73fa 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -165,7 +165,6 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => { worker = await createWorker(); - const router = await worker.createRouter(); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); const webRtcServer = await worker.createWebRtcServer( @@ -176,10 +175,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => { protocol: 'tcp', ip: '127.0.0.1', port: port2 } ] }); - - await expect(router.dump()) - .resolves - .toMatchObject({ transportIds: [ transport.id ] }); + const router = await worker.createRouter(); const onObserverNewTransport = jest.fn(); @@ -190,10 +186,13 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => { webRtcServer, enableTcp : false, - preferUdp : true, appData : { foo: 'bar' } }); + await expect(router.dump()) + .resolves + .toMatchObject({ transportIds: [ transport.id ] }); + expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(transport); expect(transport.id).toBeType('string'); @@ -212,6 +211,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => expect(transport.iceState).toBe('new'); expect(transport.iceSelectedTuple).toBeUndefined(); + expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); + await expect(webRtcServer.dump()) .resolves .toMatchObject( @@ -236,6 +237,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => transport.close(); expect(transport.closed).toBe(true); + expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); + await expect(webRtcServer.dump()) .resolves .toMatchObject( From ad1dcd5073b6250944aca5dd909e72f8ddf9a8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 18:22:54 +0200 Subject: [PATCH 33/58] made old Node happy --- node/lib/Router.js | 2 +- node/src/Router.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/node/lib/Router.js b/node/lib/Router.js index 23e110fc90..33077cccad 100644 --- a/node/lib/Router.js +++ b/node/lib/Router.js @@ -185,7 +185,7 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { } const internal = { ...this.#internal, transportId: (0, uuid_1.v4)() }; const reqData = { - webRtcServerId: webRtcServer?.id, + webRtcServerId: webRtcServer ? webRtcServer.id : undefined, listenIps, port, enableUdp, diff --git a/node/src/Router.ts b/node/src/Router.ts index 19b4939dbe..e52e2c172d 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -395,7 +395,7 @@ export class Router extends EnhancedEventEmitter const internal = { ...this.#internal, transportId: uuidv4() }; const reqData = { - webRtcServerId : webRtcServer?.id, + webRtcServerId : webRtcServer ? webRtcServer.id : undefined, listenIps, port, enableUdp, From e18e23149b79b0d37e88cd3e6ea1d415f3679022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 20:04:45 +0200 Subject: [PATCH 34/58] Fix event name and add test --- node/lib/WebRtcTransport.d.ts | 2 +- node/lib/WebRtcTransport.d.ts.map | 2 +- node/lib/WebRtcTransport.js | 2 +- node/src/WebRtcTransport.ts | 4 +- node/tests/test-WebRtcServer.js | 124 +++++++++++++++++++++++++++++- 5 files changed, 127 insertions(+), 7 deletions(-) diff --git a/node/lib/WebRtcTransport.d.ts b/node/lib/WebRtcTransport.d.ts index 79561de334..813c00417f 100644 --- a/node/lib/WebRtcTransport.d.ts +++ b/node/lib/WebRtcTransport.d.ts @@ -122,7 +122,7 @@ export declare type WebRtcTransportEvents = TransportEvents & { iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; sctpstatechange: [SctpState]; - webrtcserverclosed: []; + webrtcserverclose: []; }; export declare type WebRtcTransportObserverEvents = TransportObserverEvents & { icestatechange: [IceState]; diff --git a/node/lib/WebRtcTransport.d.ts.map b/node/lib/WebRtcTransport.d.ts.map index 3a4ce853ee..d86124754f 100644 --- a/node/lib/WebRtcTransport.d.ts.map +++ b/node/lib/WebRtcTransport.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"WebRtcTransport.d.ts","sourceRoot":"","sources":["../src/WebRtcTransport.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"WebRtcTransport.d.ts","sourceRoot":"","sources":["../src/WebRtcTransport.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node/lib/WebRtcTransport.js b/node/lib/WebRtcTransport.js index 1fd8998f66..3f310f3aab 100644 --- a/node/lib/WebRtcTransport.js +++ b/node/lib/WebRtcTransport.js @@ -156,7 +156,7 @@ class WebRtcTransport extends Transport_1.Transport { if (this.#data.sctpState) this.#data.sctpState = 'closed'; super.mustClose(); - this.safeEmit('webrtcserverclosed'); + this.safeEmit('webrtcserverclose'); } /** * Get WebRtcTransport stats. diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 094058d3b1..8f413ce713 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -162,7 +162,7 @@ export type WebRtcTransportEvents = TransportEvents & iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; sctpstatechange: [SctpState]; - webrtcserverclosed: []; + webrtcserverclose: []; } export type WebRtcTransportObserverEvents = TransportObserverEvents & @@ -384,7 +384,7 @@ export class WebRtcTransport extends super.mustClose(); - this.safeEmit('webrtcserverclosed'); + this.safeEmit('webrtcserverclose'); } /** diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index bbea0d73fa..1db1e3dd51 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -161,7 +161,7 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => expect(webRtcServer.closed).toBe(true); }, 2000); -test('router.createWebRtcTransport() with webRtcServer succeeds', async () => +test('router.createWebRtcTransport() with webRtcServer succeeds and transport is closed', async () => { worker = await createWorker(); @@ -181,7 +181,6 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => router.observer.once('newtransport', onObserverNewTransport); - // Create a separate transport here. const transport = await router.createWebRtcTransport( { webRtcServer, @@ -257,3 +256,124 @@ test('router.createWebRtcTransport() with webRtcServer succeeds', async () => tuples : [] }); }, 2000); + +test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer is closed', async () => +{ + worker = await createWorker(); + + const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port2 = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); + const webRtcServer = await worker.createWebRtcServer( + { + listenInfos : + [ + { protocol: 'udp', ip: '127.0.0.1', port: port1 }, + { protocol: 'tcp', ip: '127.0.0.1', port: port2 } + ] + }); + const router = await worker.createRouter(); + const transport = await router.createWebRtcTransport( + { + webRtcServer, + enableUdp : false, + enableTcp : true, + appData : { foo: 'bar' } + }); + + await expect(router.dump()) + .resolves + .toMatchObject({ transportIds: [ transport.id ] }); + + expect(transport.id).toBeType('string'); + expect(transport.closed).toBe(false); + expect(transport.appData).toEqual({ foo: 'bar' }); + + const iceCandidates = transport.iceCandidates; + + expect(iceCandidates.length).toBe(1); + expect(iceCandidates[0].ip).toBe('127.0.0.1'); + expect(iceCandidates[0].port).toBe(port2); + expect(iceCandidates[0].protocol).toBe('tcp'); + expect(iceCandidates[0].type).toBe('host'); + expect(iceCandidates[0].tcpType).toBe('passive'); + + expect(transport.iceState).toBe('new'); + expect(transport.iceSelectedTuple).toBeUndefined(); + + expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); + + await expect(webRtcServer.dump()) + .resolves + .toMatchObject( + { + id : webRtcServer.id, + udpSockets : + [ + { ip: '127.0.0.1', port: port1 } + ], + tcpServers : + [ + { ip: '127.0.0.1', port: port2 } + ], + webRtcTransportIds : [ transport.id ], + localIceUsernameFragments : + [ + { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } + ], + tuples : [] + }); + + // Let's restart ICE in the transport so it should add a new entry in + // localIceUsernameFragments in the WebRtcServer. + await transport.restartIce(); + + await expect(webRtcServer.dump()) + .resolves + .toMatchObject( + { + id : webRtcServer.id, + udpSockets : + [ + { ip: '127.0.0.1', port: port1 } + ], + tcpServers : + [ + { ip: '127.0.0.1', port: port2 } + ], + webRtcTransportIds : [ transport.id ], + localIceUsernameFragments : + [ + { /* localIceUsernameFragment, */ webRtcTransportId: transport.id }, + { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } + ], + tuples : [] + }); + + const onObserverClose = jest.fn(); + + webRtcServer.observer.once('close', onObserverClose); + + const onWebRtcServerClose = jest.fn(); + + transport.once('webrtcserverclose', onWebRtcServerClose); + + webRtcServer.close(); + + expect(webRtcServer.closed).toBe(true); + expect(onObserverClose).toHaveBeenCalledTimes(1); + expect(onWebRtcServerClose).toHaveBeenCalledTimes(1); + expect(transport.closed).toBe(true); + expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); + + await expect(worker.dump()) + .resolves + .toEqual({ pid: worker.pid, webRtcServerIds: [], routerIds: [ router.id ] }); + + await expect(router.dump()) + .resolves + .toMatchObject( + { + id : router.id, + transportIds : [] + }); +}, 2000); From 839d6b38bb821c1df863ce72822086ac12400159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 21:54:14 +0200 Subject: [PATCH 35/58] WebRtcServer.cpp: cosmetic and add asserts --- worker/src/RTC/WebRtcServer.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index ad43f7b88b..c4911ee46c 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -368,7 +368,7 @@ namespace RTC if (!packet) { - MS_WARN_DEV("ignoring wrong STUN packet received"); + MS_WARN_TAG(ice, "ignoring wrong STUN packet received"); return; } @@ -378,7 +378,7 @@ namespace RTC if (it == this->mapLocalIceUsernameFragmentWebRtcTransport.end()) { - MS_WARN_DEV("ignoring received STUN packet with unknown remote ICE usernameFragment"); + MS_WARN_TAG(ice, "ignoring received STUN packet with unknown remote ICE usernameFragment"); delete packet; @@ -401,7 +401,7 @@ namespace RTC if (it == this->mapTupleWebRtcTransport.end()) { - MS_WARN_DEV("ignoring received non STUN data from unknown tuple"); + MS_WARN_TAG(ice, "ignoring received non STUN data from unknown tuple"); return; } @@ -446,6 +446,11 @@ namespace RTC { MS_TRACE(); + MS_ASSERT( + this->mapLocalIceUsernameFragmentWebRtcTransport.find(usernameFragment) != + this->mapLocalIceUsernameFragmentWebRtcTransport.end(), + "tuple not handled"); + this->mapLocalIceUsernameFragmentWebRtcTransport.erase(usernameFragment); } @@ -462,6 +467,10 @@ namespace RTC { MS_TRACE(); + MS_ASSERT( + this->mapTupleWebRtcTransport.find(tuple->hash) != this->mapTupleWebRtcTransport.end(), + "tuple not handled"); + this->mapTupleWebRtcTransport.erase(tuple->hash); } From 51e70e41a7152943f6c8eb6994906a7984dfb128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 22:52:32 +0200 Subject: [PATCH 36/58] IceServer: Limit max number of tuples per WebRtcTransport --- node/tests/test-WebRtcServer.js | 10 +++---- worker/include/RTC/IceServer.hpp | 5 ++++ worker/include/RTC/TransportTuple.hpp | 8 ++++++ worker/src/RTC/IceServer.cpp | 38 +++++++++++++++++++++++++ worker/src/RTC/TcpServer.cpp | 12 -------- worker/src/RTC/WebRtcServer.cpp | 23 ++++++++------- worker/src/handles/TcpServerHandler.cpp | 2 +- 7 files changed, 70 insertions(+), 28 deletions(-) diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index 1db1e3dd51..8fcc5022e0 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -66,7 +66,7 @@ test('worker.createWebRtcServer() succeeds', async () => ], webRtcTransportIds : [], localIceUsernameFragments : [], - tuples : [] + tupleHahes : [] }); // Private API. @@ -230,7 +230,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is [ { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } ], - tuples : [] + tupleHahes : [] }); transport.close(); @@ -253,7 +253,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is ], webRtcTransportIds : [], localIceUsernameFragments : [], - tuples : [] + tupleHahes : [] }); }, 2000); @@ -320,7 +320,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer [ { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } ], - tuples : [] + tupleHahes : [] }); // Let's restart ICE in the transport so it should add a new entry in @@ -346,7 +346,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer { /* localIceUsernameFragment, */ webRtcTransportId: transport.id }, { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } ], - tuples : [] + tupleHahes : [] }); const onObserverClose = jest.fn(); diff --git a/worker/include/RTC/IceServer.hpp b/worker/include/RTC/IceServer.hpp index 8c428b3b67..51fa85919d 100644 --- a/worker/include/RTC/IceServer.hpp +++ b/worker/include/RTC/IceServer.hpp @@ -71,6 +71,11 @@ namespace RTC } void RestartIce(const std::string& usernameFragment, const std::string& password) { + if (!this->oldUsernameFragment.empty()) + { + this->listener->OnIceServerLocalUsernameFragmentRemoved(this, this->oldUsernameFragment); + } + this->oldUsernameFragment = this->usernameFragment; this->usernameFragment = usernameFragment; diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 9555aea318..04aa9b67e8 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -49,6 +49,14 @@ namespace RTC } public: + void Close() + { + if (this->protocol == Protocol::UDP) + this->udpSocket->Close(); + else + this->tcpConnection->Close(); + } + void FillJson(json& jsonObject) const; void Dump() const; diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index bffd6b2876..e5ac49709b 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -12,6 +12,7 @@ namespace RTC static constexpr size_t StunSerializeBufferSize{ 65536 }; thread_local static uint8_t StunSerializeBuffer[StunSerializeBufferSize]; + static constexpr size_t MaxTuples{ 8 }; /* Instance methods. */ @@ -564,6 +565,43 @@ namespace RTC // Notify the listener. this->listener->OnIceServerTupleAdded(this, storedTuple); + // Don't allow more than MaxTuples. + if (this->tuples.size() > MaxTuples) + { + MS_WARN_TAG(ice, "too many tuples, removing the oldest one that is not the selected one"); + + // Find the older tuple which is neither the added one nor the selected + // one (if any), and remove it. + RTC::TransportTuple* removedTuple{ nullptr }; + auto it = this->tuples.rbegin(); + + for (; it != this->tuples.rend(); ++it) + { + RTC::TransportTuple* otherStoredTuple = std::addressof(*it); + + if (otherStoredTuple != storedTuple && otherStoredTuple != this->selectedTuple) + { + removedTuple = otherStoredTuple; + + break; + } + } + + // This should not happen by design. + MS_ASSERT(removedTuple, "couldn't find any tuple to be removed"); + + // Remove from the list of tuples. + // NOTE: This trick is needed since it is a reverse_iterator and + // erase() requires a iterator, const_iterator or bidirectional_iterator. + this->tuples.erase(std::next(it).base()); + + // Notify the listener. + this->listener->OnIceServerTupleRemoved(this, removedTuple); + + // And close it (which makes special sense for TCP tuples). + removedTuple->Close(); + } + // Return the address of the inserted tuple. return storedTuple; } diff --git a/worker/src/RTC/TcpServer.cpp b/worker/src/RTC/TcpServer.cpp index 9c0579ae00..66a18c179c 100644 --- a/worker/src/RTC/TcpServer.cpp +++ b/worker/src/RTC/TcpServer.cpp @@ -8,10 +8,6 @@ namespace RTC { - /* Static. */ - - static constexpr size_t MaxTcpConnectionsPerServer{ 10 }; - /* Instance methods. */ TcpServer::TcpServer(Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip) @@ -45,14 +41,6 @@ namespace RTC { MS_TRACE(); - // Allow just MaxTcpConnectionsPerServer. - if (GetNumConnections() >= MaxTcpConnectionsPerServer) - { - MS_ERROR("cannot handle more than %zu connections", MaxTcpConnectionsPerServer); - - return; - } - // Allocate a new RTC::TcpConnection for the TcpServer to handle it. auto* connection = new RTC::TcpConnection(this->connListener, 65536); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index c4911ee46c..412474de08 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -235,21 +235,21 @@ namespace RTC ++idx; } - // Add tuples. - jsonObject["tuples"] = json::array(); - auto jsonTuplesIt = jsonObject.find("tuples"); + // Add tupleHashes. + jsonObject["tupleHashes"] = json::array(); + auto jsonTupleHashesIt = jsonObject.find("tupleHashes"); idx = 0; for (auto& kv : this->mapTupleWebRtcTransport) { - const auto& tuple = kv.first; + const auto& tupleHash = kv.first; const auto* webRtcTransport = kv.second; - jsonTuplesIt->emplace_back(json::value_t::object); + jsonTupleHashesIt->emplace_back(json::value_t::object); - auto& jsonEntry = (*jsonTuplesIt)[idx]; + auto& jsonEntry = (*jsonTupleHashesIt)[idx]; - jsonEntry["tuple"] = tuple; + jsonEntry["tupleHash"] = tupleHash; jsonEntry["webRtcTransportId"] = webRtcTransport->id; ++idx; @@ -491,11 +491,14 @@ namespace RTC RTC::TransportTuple tuple(connection); + // NOTE: We cannot assert whether this tuple is still in our + // mapTupleWebRtcTransport because this event may be called after the tuple + // was removed from it. + auto it = this->mapTupleWebRtcTransport.find(tuple.hash); - MS_ASSERT( - it != this->mapTupleWebRtcTransport.end(), - "closed TCP connection not managed by this WebRtcServer"); + if (it == this->mapTupleWebRtcTransport.end()) + return; auto* webRtcTransport = it->second; diff --git a/worker/src/handles/TcpServerHandler.cpp b/worker/src/handles/TcpServerHandler.cpp index 50f8418845..a3213d709e 100644 --- a/worker/src/handles/TcpServerHandler.cpp +++ b/worker/src/handles/TcpServerHandler.cpp @@ -8,7 +8,7 @@ /* Static. */ -static constexpr int ListenBacklog{ 256 }; +static constexpr int ListenBacklog{ 512 }; /* Static methods for UV callbacks. */ From dd0b31ca979465a80232cbdb51f977b7a5a34484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 17 Jun 2022 23:20:40 +0200 Subject: [PATCH 37/58] upps --- node/tests/test-WebRtcServer.js | 10 +++++----- worker/src/RTC/IceServer.cpp | 11 +++++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index 8fcc5022e0..fb6739cf44 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -66,7 +66,7 @@ test('worker.createWebRtcServer() succeeds', async () => ], webRtcTransportIds : [], localIceUsernameFragments : [], - tupleHahes : [] + tupleHashes : [] }); // Private API. @@ -230,7 +230,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is [ { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } ], - tupleHahes : [] + tupleHashes : [] }); transport.close(); @@ -253,7 +253,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is ], webRtcTransportIds : [], localIceUsernameFragments : [], - tupleHahes : [] + tupleHashes : [] }); }, 2000); @@ -320,7 +320,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer [ { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } ], - tupleHahes : [] + tupleHashes : [] }); // Let's restart ICE in the transport so it should add a new entry in @@ -346,7 +346,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer { /* localIceUsernameFragment, */ webRtcTransportId: transport.id }, { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } ], - tupleHahes : [] + tupleHashes : [] }); const onObserverClose = jest.fn(); diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index e5ac49709b..5dc5cef923 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -43,7 +43,11 @@ namespace RTC { auto* storedTuple = const_cast(std::addressof(it)); + // Notify the listener. this->listener->OnIceServerTupleRemoved(this, storedTuple); + + // And close it (which makes special sense for TCP tuples). + storedTuple->Close(); } } @@ -293,7 +297,7 @@ namespace RTC if (!removedTuple) return; - // Remove from the list of tuples. + // Remove it from the list of tuples. this->tuples.erase(it); // If this is the selected tuple, do things. @@ -318,6 +322,9 @@ namespace RTC // Notify the listener. this->listener->OnIceServerTupleRemoved(this, removedTuple); + + // And close it (which makes special sense for TCP tuples). + removedTuple->Close(); } void IceServer::ForceSelectedTuple(const RTC::TransportTuple* tuple) @@ -590,7 +597,7 @@ namespace RTC // This should not happen by design. MS_ASSERT(removedTuple, "couldn't find any tuple to be removed"); - // Remove from the list of tuples. + // Remove it from the list of tuples. // NOTE: This trick is needed since it is a reverse_iterator and // erase() requires a iterator, const_iterator or bidirectional_iterator. this->tuples.erase(std::next(it).base()); From dee74b70eeefd4341a45037d0735488e1e67ab37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 00:21:03 +0200 Subject: [PATCH 38/58] Fix terrible regression --- worker/include/RTC/TransportTuple.hpp | 8 ++++++++ worker/include/handles/TcpConnectionHandler.hpp | 8 ++++---- worker/include/handles/UdpSocketHandler.hpp | 4 ++++ worker/src/RTC/IceServer.cpp | 9 --------- worker/src/RTC/WebRtcTransport.cpp | 4 ++++ 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 04aa9b67e8..1fb885f7ba 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -57,6 +57,14 @@ namespace RTC this->tcpConnection->Close(); } + bool IsClosed() + { + if (this->protocol == Protocol::UDP) + return this->udpSocket->IsClosed(); + else + return this->tcpConnection->IsClosed(); + } + void FillJson(json& jsonObject) const; void Dump() const; diff --git a/worker/include/handles/TcpConnectionHandler.hpp b/worker/include/handles/TcpConnectionHandler.hpp index db5874d91d..0b536225ba 100644 --- a/worker/include/handles/TcpConnectionHandler.hpp +++ b/worker/include/handles/TcpConnectionHandler.hpp @@ -51,16 +51,16 @@ class TcpConnectionHandler public: void Close(); + bool IsClosed() const + { + return this->closed; + } virtual void Dump() const; void Setup( Listener* listener, struct sockaddr_storage* localAddr, const std::string& localIp, uint16_t localPort); - bool IsClosed() const - { - return this->closed; - } uv_tcp_t* GetUvHandle() const { return this->uvHandle; diff --git a/worker/include/handles/UdpSocketHandler.hpp b/worker/include/handles/UdpSocketHandler.hpp index beadfd76e0..188f23b4fa 100644 --- a/worker/include/handles/UdpSocketHandler.hpp +++ b/worker/include/handles/UdpSocketHandler.hpp @@ -44,6 +44,10 @@ class UdpSocketHandler public: void Close(); + bool IsClosed() const + { + return this->closed; + } virtual void Dump() const; void Send( const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketHandler::onSendCallback* cb); diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index 5dc5cef923..bdc3f3f7ad 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -45,9 +45,6 @@ namespace RTC // Notify the listener. this->listener->OnIceServerTupleRemoved(this, storedTuple); - - // And close it (which makes special sense for TCP tuples). - storedTuple->Close(); } } @@ -322,9 +319,6 @@ namespace RTC // Notify the listener. this->listener->OnIceServerTupleRemoved(this, removedTuple); - - // And close it (which makes special sense for TCP tuples). - removedTuple->Close(); } void IceServer::ForceSelectedTuple(const RTC::TransportTuple* tuple) @@ -604,9 +598,6 @@ namespace RTC // Notify the listener. this->listener->OnIceServerTupleRemoved(this, removedTuple); - - // And close it (which makes special sense for TCP tuples). - removedTuple->Close(); } // Return the address of the inserted tuple. diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index 1e889e7e36..abf390e12f 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -1258,6 +1258,10 @@ namespace RTC { this->webRtcTransportListener->OnWebRtcTransportTransportTupleRemoved(this, tuple); } + + // If this is a TCP tuple, close its underlaying TCP connection. + if (tuple->GetProtocol() == RTC::TransportTuple::Protocol::TCP && !tuple->IsClosed()) + tuple->Close(); } inline void WebRtcTransport::OnIceServerSelectedTuple( From 034ad91f176bc0e3987dd61600c445b9a3ad851c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 00:25:28 +0200 Subject: [PATCH 39/58] Ready for review --- TODO_WEBRTC_SERVER.md | 79 ------------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 TODO_WEBRTC_SERVER.md diff --git a/TODO_WEBRTC_SERVER.md b/TODO_WEBRTC_SERVER.md deleted file mode 100644 index 75101f0b69..0000000000 --- a/TODO_WEBRTC_SERVER.md +++ /dev/null @@ -1,79 +0,0 @@ -# TODO WebRtcServer - - -### Issue obtainining `usernameFragment:password` from received STUN packets - -When we create a ICE server we decide the mediasoup side `usernameFragment` and `password` and pass them to the `IceServer` constructor. - -However, when a STUN packet is received from a client, if we check `packet->GetUsername()` it doesn't return the mediasoup side `usernameFragment:password` values but instead `mediasoupUsernameFragment:clientUsernameFragment`. - -I've added some logs to show the problem: - -``` -mediasoup:ERROR:Channel [pid:35897 RTC::IceServer::IceServer() | ----------- IceServer constructor | usernameFragment:bxuwysb0l2hltk2h, password:0275z9opi3uiql3apboece5qrgvffm03 +6ms - -mediasoup:ERROR:Channel [pid:35897 RTC::WebRtcTransport::OnStunDataReceived() | ----------- stunPacket->GetUsername(): bxuwysb0l2hltk2h:1dRN +36ms -```` - -In fact, if we show the local SDP of the client it clearly shows: - -``` -a=ice-ufrag:1dRN -``` - -So how to match received STUN packets against the credentials of our `IceServer`? We may just compare the "usernameFragment" component but unclear if this is good. Obviously the `usernameFragmet` is chosen by mediasoup `WebRtcTransport` constructor by doing `Utils::Crypto::GetRandomString(16)` so it could be good enough but still... The thing is that mediasoup-client does NOT signal the client `a=ice-ufrag` to mediasoup because being mediasoup ICE-Lite it doesn't need it. - -STUN RFC: See https://datatracker.ietf.org/doc/html/rfc5389 - -Suggested solution: use a 32 bytes mediasoup side `usernameFragment`. - -However, there is no rule in RFC 5389 telling that `USERNAME` attribute should contain `remoteUsernameFragment:localUsernameFragment`. Anyway, in `StunPacket::CheckAuthentication()` we already rely on `USERNAME` starting by our local username fragment followed by ":". - -Done. - - -### What happens with its WebRtcTransports when closing a WebRtcServer? - -This is hard. And there must be a parallelism between TS/Rust and C++. - -Proposal: - -* `webRtcServer.close()` iterates its `Set` of `WebRtcTransports` and calls `webRtcTransport.mustClose()`. -* `Transport::MustClose()` calls a new `this->listener->OnTransportMustClose(this)`. -* `Router.OnTransportMustClose(transport)` does: - - Call `transport->CloseProducersAndConsumers()` so `Router` is notified about closed `Producers` and `Consumers` and can remove them from its maps. - - Remove the `transport` from it map. - - Call `delete transport`. - -Note that the destructor of `WebRtcTransport` will invoke `delete this->iceServer` which will trigger may callbacks called in `WebRtcServer` that will remove the `transport` from its maps. - -NOTE: All the above is done in the branch. - -And let's see how to do it in TS/Rust for things to be similar. - - -### Remove limit of TcpConnections per TcpServer - -Also increase `backlog(int)` in `uv_listen`(POSIX argument): - - -> The backlog argument defines the maximum length to which the -> queue of pending connections for sockfd may grow. If a connection -> request arrives when the queue is full, the client may receive an -> error with an indication of ECONNREFUSED or, if the underlying -> protocol supports retransmission, the request may be ignored so -> that a later reattempt at connection succeeds. - -No matter the value is super high, in Linux it's limited by `/proc/sys/net/core/somaxconn`. - -Done by just hardcoding it to 256 since it's irrelevant after investigating it. - - -### Handle limit of UDP/TCP tuples in WebRtcTransport - -This is needed no matter `WebRtcServer` is used or not. Each `WebRtcTransport` should manage max number of UDP and TCP tuples and remove old one (non selected one) etc when a new one is created or reject new one, let's see. - - -### Use the new TransportTuple.id - -In `IceServer` we use `tuple.compare()` but now we have `tuple->id` to match things. We should use it and usage in `WebRtcServer.cpp`. See `GenerateId()` in `TransportTuple.hpp`. From 4987b68a3d156a1174c3e5caedca79186f45b6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 00:33:06 +0200 Subject: [PATCH 40/58] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38f2e90147..b6b45e277d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### WIP +* `WebRtcServer`: A new class that brings the ability to listen in a single UDP/TCP port for in `WebRtcTransports (PR #834). * `TransportCongestionControlClient`: Allow setting max outgoing bitrate before created (PR #833). From 09153128bca85cffff6b4118ad5a0aa0a8c1cabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 00:41:38 +0200 Subject: [PATCH 41/58] fix comments --- node/lib/WebRtcServer.d.ts | 4 ++-- node/lib/WebRtcServer.js | 4 ++-- node/src/WebRtcServer.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/node/lib/WebRtcServer.d.ts b/node/lib/WebRtcServer.d.ts index 79056a9f85..7464e9ecc4 100644 --- a/node/lib/WebRtcServer.d.ts +++ b/node/lib/WebRtcServer.d.ts @@ -51,11 +51,11 @@ export declare class WebRtcServer extends EnhancedEventEmitter; }); /** - * Router id. + * WebRtcServer id. */ get id(): string; /** - * Whether the Router is closed. + * Whether the WebRtcServer is closed. */ get closed(): boolean; /** diff --git a/node/lib/WebRtcServer.js b/node/lib/WebRtcServer.js index 22548506aa..a794a98abc 100644 --- a/node/lib/WebRtcServer.js +++ b/node/lib/WebRtcServer.js @@ -30,13 +30,13 @@ class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { this.#appData = appData || {}; } /** - * Router id. + * WebRtcServer id. */ get id() { return this.#internal.webRtcServerId; } /** - * Whether the Router is closed. + * Whether the WebRtcServer is closed. */ get closed() { return this.#closed; diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 33fe697a26..06d933288c 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -105,7 +105,7 @@ export class WebRtcServer extends EnhancedEventEmitter } /** - * Router id. + * WebRtcServer id. */ get id(): string { @@ -113,7 +113,7 @@ export class WebRtcServer extends EnhancedEventEmitter } /** - * Whether the Router is closed. + * Whether the WebRtcServer is closed. */ get closed(): boolean { From 4d6e1e80948c21b9fdd5f00666e859487810b344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 00:43:29 +0200 Subject: [PATCH 42/58] fix comment --- node/lib/WebRtcTransport.d.ts | 2 +- node/src/WebRtcTransport.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/node/lib/WebRtcTransport.d.ts b/node/lib/WebRtcTransport.d.ts index 813c00417f..6bf6307692 100644 --- a/node/lib/WebRtcTransport.d.ts +++ b/node/lib/WebRtcTransport.d.ts @@ -3,7 +3,7 @@ import { WebRtcServer } from './WebRtcServer'; import { SctpParameters, NumSctpStreams } from './SctpParameters'; export declare type WebRtcTransportOptions = { /** - * Instance of WebRtcServer. Mandatory unless lisntenIps is given. + * Instance of WebRtcServer. Mandatory unless listenIps is given. */ webRtcServer?: WebRtcServer; /** diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 8f413ce713..698286c434 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -15,7 +15,7 @@ import { SctpParameters, NumSctpStreams } from './SctpParameters'; export type WebRtcTransportOptions = { /** - * Instance of WebRtcServer. Mandatory unless lisntenIps is given. + * Instance of WebRtcServer. Mandatory unless listenIps is given. */ webRtcServer?: WebRtcServer; /** From c0ef9f6dcde4ed0b10f78261490c296fb8d7b24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 00:46:58 +0200 Subject: [PATCH 43/58] cosmetic --- worker/src/Worker.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index c344bdb80c..30dbbca76d 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -64,15 +64,6 @@ void Worker::Close() // Delete the SignalsHandler. delete this->signalsHandler; - // Delete all WebRtcServers. - for (auto& kv : this->mapWebRtcServers) - { - auto* webRtcServer = kv.second; - - delete webRtcServer; - } - this->mapWebRtcServers.clear(); - // Delete all Routers. for (auto& kv : this->mapRouters) { @@ -82,6 +73,15 @@ void Worker::Close() } this->mapRouters.clear(); + // Delete all WebRtcServers. + for (auto& kv : this->mapWebRtcServers) + { + auto* webRtcServer = kv.second; + + delete webRtcServer; + } + this->mapWebRtcServers.clear(); + // Close the Checker instance in DepUsrSCTP. DepUsrSCTP::CloseChecker(); From 06a43326b71aab39984827f709e642014989e127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 00:54:50 +0200 Subject: [PATCH 44/58] router.createWebRtcTransport(): pass webRtcServerId in internal object rather than in data object --- node/lib/Router.d.ts.map | 2 +- node/lib/Router.js | 7 +++++-- node/src/Router.ts | 11 ++++++++--- worker/src/RTC/Router.cpp | 9 ++++++--- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/node/lib/Router.d.ts.map b/node/lib/Router.d.ts.map index 5268910021..e532ea0d42 100644 --- a/node/lib/Router.d.ts.map +++ b/node/lib/Router.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node/lib/Router.js b/node/lib/Router.js index 33077cccad..91739e8541 100644 --- a/node/lib/Router.js +++ b/node/lib/Router.js @@ -183,9 +183,12 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { } }); } - const internal = { ...this.#internal, transportId: (0, uuid_1.v4)() }; + const internal = { + ...this.#internal, + transportId: (0, uuid_1.v4)(), + webRtcServerId: webRtcServer ? webRtcServer.id : undefined + }; const reqData = { - webRtcServerId: webRtcServer ? webRtcServer.id : undefined, listenIps, port, enableUdp, diff --git a/node/src/Router.ts b/node/src/Router.ts index e52e2c172d..f6f3ca4940 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -393,9 +393,14 @@ export class Router extends EnhancedEventEmitter }); } - const internal = { ...this.#internal, transportId: uuidv4() }; + const internal = + { + ...this.#internal, + transportId : uuidv4(), + webRtcServerId : webRtcServer ? webRtcServer.id : undefined + }; + const reqData = { - webRtcServerId : webRtcServer ? webRtcServer.id : undefined, listenIps, port, enableUdp, @@ -407,7 +412,7 @@ export class Router extends EnhancedEventEmitter numSctpStreams, maxSctpMessageSize, sctpSendBufferSize, - isDataChannel : true + isDataChannel : true }; const data = webRtcServer diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index 84bc72681a..f29871b3eb 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -209,17 +209,20 @@ namespace RTC // This may throw. SetNewTransportIdFromInternal(request->internal, transportId); - auto jsonWebRtcServerIdIt = request->data.find("webRtcServerId"); + auto jsonWebRtcServerIdIt = request->internal.find("webRtcServerId"); - if (jsonWebRtcServerIdIt == request->data.end() || !jsonWebRtcServerIdIt->is_string()) + if (jsonWebRtcServerIdIt == request->internal.end() || !jsonWebRtcServerIdIt->is_string()) { - MS_THROW_TYPE_ERROR("wrong webRtcServerId (not a string)"); + MS_THROW_ERROR("missing internal.webRtcServerId"); } std::string webRtcServerId = jsonWebRtcServerIdIt->get(); auto* webRtcServer = this->listener->OnRouterNeedWebRtcServer(this, webRtcServerId); + if (!webRtcServer) + MS_THROW_ERROR("wrong internal.webRtcServerId (no associated WebRtcServer found)"); + bool enableUdp{ true }; auto jsonEnableUdpIt = request->data.find("enableUdp"); From ad12b95cbb5dd830da74c5c5945f442f9583837c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 12:17:49 +0200 Subject: [PATCH 45/58] Address feedback --- CHANGELOG.md | 2 +- worker/include/RTC/TransportTuple.hpp | 4 +--- worker/src/RTC/IceServer.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6b45e277d..d9f6f00a9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ### WIP -* `WebRtcServer`: A new class that brings the ability to listen in a single UDP/TCP port for in `WebRtcTransports (PR #834). +* `WebRtcServer`: A new class that brings to `WebRtcTransports` the ability to listen on a single UDP/TCP port (PR #834). * `TransportCongestionControlClient`: Allow setting max outgoing bitrate before created (PR #833). diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 1fb885f7ba..727ff3a7f9 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -38,12 +38,10 @@ namespace RTC } explicit TransportTuple(const TransportTuple* tuple) - : udpSocket(tuple->udpSocket), udpRemoteAddr(tuple->udpRemoteAddr), + : hash(tuple->hash), udpSocket(tuple->udpSocket), udpRemoteAddr(tuple->udpRemoteAddr), tcpConnection(tuple->tcpConnection), localAnnouncedIp(tuple->localAnnouncedIp), protocol(tuple->protocol) { - this->hash = tuple->hash; - if (protocol == TransportTuple::Protocol::UDP) StoreUdpRemoteAddress(); } diff --git a/worker/src/RTC/IceServer.cpp b/worker/src/RTC/IceServer.cpp index bdc3f3f7ad..27db36344b 100644 --- a/worker/src/RTC/IceServer.cpp +++ b/worker/src/RTC/IceServer.cpp @@ -29,8 +29,8 @@ namespace RTC { MS_TRACE(); - // Here we must notify to the listener about the removal of all handled - // tuples and usernameFragment (including the old one if any). + // Here we must notify the listener about the removal of current + // usernameFragments (and also the old one if any) and all tuples. this->listener->OnIceServerLocalUsernameFragmentRemoved(this, usernameFragment); @@ -569,9 +569,9 @@ namespace RTC // Don't allow more than MaxTuples. if (this->tuples.size() > MaxTuples) { - MS_WARN_TAG(ice, "too many tuples, removing the oldest one that is not the selected one"); + MS_WARN_TAG(ice, "too too many tuples, removing the oldest non selected one"); - // Find the older tuple which is neither the added one nor the selected + // Find the oldest tuple which is neither the added one nor the selected // one (if any), and remove it. RTC::TransportTuple* removedTuple{ nullptr }; auto it = this->tuples.rbegin(); From b7420b09ae9041e27ce6848a7611bd124f7bcf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 12:26:12 +0200 Subject: [PATCH 46/58] cosmetic --- node/tests/test-WebRtcServer.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index fb6739cf44..7d768f7e5b 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -228,7 +228,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is webRtcTransportIds : [ transport.id ], localIceUsernameFragments : [ - { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } + { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id } ], tupleHashes : [] }); @@ -318,7 +318,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer webRtcTransportIds : [ transport.id ], localIceUsernameFragments : [ - { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } + { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id } ], tupleHashes : [] }); @@ -343,8 +343,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer webRtcTransportIds : [ transport.id ], localIceUsernameFragments : [ - { /* localIceUsernameFragment, */ webRtcTransportId: transport.id }, - { /* localIceUsernameFragment, */ webRtcTransportId: transport.id } + { /* localIceUsernameFragment: xxx, */ webRtcTransportId: transport.id }, + { /* localIceUsernameFragment: yyy, */ webRtcTransportId: transport.id } ], tupleHashes : [] }); From 1bce071d7eb9b9a61473760661219647f71db5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 17:45:43 +0200 Subject: [PATCH 47/58] Have a generic transport.on('listenserverclose') event --- node/lib/Router.d.ts | 5 ++++ node/lib/Router.d.ts.map | 2 +- node/lib/Router.js | 11 +++++++++ node/lib/Transport.d.ts | 9 +++++--- node/lib/Transport.d.ts.map | 2 +- node/lib/Transport.js | 15 ++++++++---- node/lib/WebRtcServer.js | 4 ++-- node/lib/WebRtcTransport.d.ts | 4 +--- node/lib/WebRtcTransport.d.ts.map | 2 +- node/lib/WebRtcTransport.js | 6 ++--- node/src/Router.ts | 13 +++++++++++ node/src/Transport.ts | 20 ++++++++++++---- node/src/WebRtcServer.ts | 4 ++-- node/src/WebRtcTransport.ts | 8 ++----- node/tests/test-WebRtcServer.js | 10 +++++--- worker/include/RTC/Router.hpp | 2 +- worker/include/RTC/Transport.hpp | 6 ++--- worker/src/RTC/Router.cpp | 38 +++++++++++++++---------------- worker/src/RTC/Transport.cpp | 16 ++++++------- worker/src/RTC/WebRtcServer.cpp | 2 +- 20 files changed, 112 insertions(+), 67 deletions(-) diff --git a/node/lib/Router.d.ts b/node/lib/Router.d.ts index 02f5f17155..f435199a12 100644 --- a/node/lib/Router.d.ts +++ b/node/lib/Router.d.ts @@ -130,6 +130,11 @@ export declare class Router extends EnhancedEventEmitter { * @emits newrtpobserver - (rtpObserver: RtpObserver) */ get observer(): EnhancedEventEmitter; + /** + * @private + * Just for testing purposes. + */ + get transportsForTesting(): Map; /** * Close the Router. */ diff --git a/node/lib/Router.d.ts.map b/node/lib/Router.d.ts.map index e532ea0d42..5d602b7d6d 100644 --- a/node/lib/Router.d.ts.map +++ b/node/lib/Router.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node/lib/Router.js b/node/lib/Router.js index 91739e8541..3419fcb3e7 100644 --- a/node/lib/Router.js +++ b/node/lib/Router.js @@ -93,6 +93,13 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { get observer() { return this.#observer; } + /** + * @private + * Just for testing purposes. + */ + get transportsForTesting() { + return this.#transports; + } /** * Close the Router. */ @@ -217,6 +224,7 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer) => (this.#dataProducers.set(dataProducer.id, dataProducer))); @@ -276,6 +284,7 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer) => (this.#dataProducers.set(dataProducer.id, dataProducer))); @@ -338,6 +347,7 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer) => (this.#dataProducers.set(dataProducer.id, dataProducer))); @@ -368,6 +378,7 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { }); this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer) => (this.#dataProducers.set(dataProducer.id, dataProducer))); diff --git a/node/lib/Transport.d.ts b/node/lib/Transport.d.ts index b2862a7621..8dba70eb15 100644 --- a/node/lib/Transport.d.ts +++ b/node/lib/Transport.d.ts @@ -56,6 +56,7 @@ export interface TransportTraceEventData { export declare type SctpState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed'; export declare type TransportEvents = { routerclose: []; + listenserverclose: []; trace: [TransportTraceEventData]; }; export declare type TransportObserverEvents = { @@ -83,11 +84,13 @@ export declare class Transport { }); // Close every WebRtcTransport. for (const webRtcTransport of this.#webRtcTransports.values()) { - webRtcTransport.mustClose(); + webRtcTransport.listenServerClosed(); } this.#webRtcTransports.clear(); this.emit('@close'); @@ -100,7 +100,7 @@ class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { this.#closed = true; // Close every WebRtcTransport. for (const webRtcTransport of this.#webRtcTransports.values()) { - webRtcTransport.mustClose(); + webRtcTransport.listenServerClosed(); } this.#webRtcTransports.clear(); this.safeEmit('workerclose'); diff --git a/node/lib/WebRtcTransport.d.ts b/node/lib/WebRtcTransport.d.ts index 6bf6307692..b68119120d 100644 --- a/node/lib/WebRtcTransport.d.ts +++ b/node/lib/WebRtcTransport.d.ts @@ -122,7 +122,6 @@ export declare type WebRtcTransportEvents = TransportEvents & { iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; sctpstatechange: [SctpState]; - webrtcserverclose: []; }; export declare type WebRtcTransportObserverEvents = TransportObserverEvents & { icestatechange: [IceState]; @@ -213,9 +212,8 @@ export declare class WebRtcTransport extends Transport return this.#observer; } + /** + * @private + * Just for testing purposes. + */ + get transportsForTesting(): Map + { + return this.#transports; + } + /** * Close the Router. */ @@ -437,6 +446,7 @@ export class Router extends EnhancedEventEmitter this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer: DataProducer) => ( @@ -534,6 +544,7 @@ export class Router extends EnhancedEventEmitter this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer: DataProducer) => ( @@ -637,6 +648,7 @@ export class Router extends EnhancedEventEmitter this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer: DataProducer) => ( @@ -691,6 +703,7 @@ export class Router extends EnhancedEventEmitter this.#transports.set(transport.id, transport); transport.on('@close', () => this.#transports.delete(transport.id)); + transport.on('@listenserverclose', () => this.#transports.delete(transport.id)); transport.on('@newproducer', (producer: Producer) => this.#producers.set(producer.id, producer)); transport.on('@producerclose', (producer: Producer) => this.#producers.delete(producer.id)); transport.on('@newdataproducer', (dataProducer: DataProducer) => ( diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 7259b535b9..65386cd65a 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -83,7 +83,8 @@ export type SctpState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed' export type TransportEvents = { - routerclose: []; + routerclose: []; + listenserverclose: []; trace: [TransportTraceEventData]; } @@ -169,11 +170,13 @@ export class Transport // Close every WebRtcTransport. for (const webRtcTransport of this.#webRtcTransports.values()) { - webRtcTransport.mustClose(); + webRtcTransport.listenServerClosed(); } this.#webRtcTransports.clear(); @@ -201,7 +201,7 @@ export class WebRtcServer extends EnhancedEventEmitter // Close every WebRtcTransport. for (const webRtcTransport of this.#webRtcTransports.values()) { - webRtcTransport.mustClose(); + webRtcTransport.listenServerClosed(); } this.#webRtcTransports.clear(); diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 698286c434..f4e4809556 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -162,7 +162,6 @@ export type WebRtcTransportEvents = TransportEvents & iceselectedtuplechange: [TransportTuple]; dtlsstatechange: [DtlsState]; sctpstatechange: [SctpState]; - webrtcserverclose: []; } export type WebRtcTransportObserverEvents = TransportObserverEvents & @@ -368,9 +367,8 @@ export class WebRtcTransport extends * Called when closing the associated WebRtcServer. * * @private - * @override */ - mustClose(): void + webRtcServerClosed(): void { if (this.closed) return; @@ -382,9 +380,7 @@ export class WebRtcTransport extends if (this.#data.sctpState) this.#data.sctpState = 'closed'; - super.mustClose(); - - this.safeEmit('webrtcserverclose'); + super.listenServerClosed(); } /** diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index 7d768f7e5b..6ebc7e38c4 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -211,6 +211,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(transport.iceSelectedTuple).toBeUndefined(); expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); + expect(router.transportsForTesting.size).toBe(1); await expect(webRtcServer.dump()) .resolves @@ -237,6 +238,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(transport.closed).toBe(true); expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); + expect(router.transportsForTesting.size).toBe(0); await expect(webRtcServer.dump()) .resolves @@ -301,6 +303,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(transport.iceSelectedTuple).toBeUndefined(); expect(webRtcServer.webRtcTransportsForTesting.size).toBe(1); + expect(router.transportsForTesting.size).toBe(1); await expect(webRtcServer.dump()) .resolves @@ -353,17 +356,18 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer webRtcServer.observer.once('close', onObserverClose); - const onWebRtcServerClose = jest.fn(); + const onListenServerClose = jest.fn(); - transport.once('webrtcserverclose', onWebRtcServerClose); + transport.once('listenserverclose', onListenServerClose); webRtcServer.close(); expect(webRtcServer.closed).toBe(true); expect(onObserverClose).toHaveBeenCalledTimes(1); - expect(onWebRtcServerClose).toHaveBeenCalledTimes(1); + expect(onListenServerClose).toHaveBeenCalledTimes(1); expect(transport.closed).toBe(true); expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); + expect(router.transportsForTesting.size).toBe(0); await expect(worker.dump()) .resolves diff --git a/worker/include/RTC/Router.hpp b/worker/include/RTC/Router.hpp index d7c7cc16a1..2e333522d6 100644 --- a/worker/include/RTC/Router.hpp +++ b/worker/include/RTC/Router.hpp @@ -55,7 +55,6 @@ namespace RTC /* Pure virtual methods inherited from RTC::Transport::Listener. */ public: - void OnTransportMustClose(RTC::Transport* transport) override; void OnTransportNewProducer(RTC::Transport* transport, RTC::Producer* producer) override; void OnTransportProducerClosed(RTC::Transport* transport, RTC::Producer* producer) override; void OnTransportProducerPaused(RTC::Transport* transport, RTC::Producer* producer) override; @@ -99,6 +98,7 @@ namespace RTC void OnTransportDataConsumerClosed(RTC::Transport* transport, RTC::DataConsumer* dataConsumer) override; void OnTransportDataConsumerDataProducerClosed( RTC::Transport* transport, RTC::DataConsumer* dataConsumer) override; + void OnTransportListenServerClosed(RTC::Transport* transport) override; public: // Passed by argument. diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index b5ad926123..32d4876c8d 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -57,7 +57,6 @@ namespace RTC virtual ~Listener() = default; public: - virtual void OnTransportMustClose(RTC::Transport* transport) = 0; virtual void OnTransportNewProducer(RTC::Transport* transport, RTC::Producer* producer) = 0; virtual void OnTransportProducerClosed(RTC::Transport* transport, RTC::Producer* producer) = 0; virtual void OnTransportProducerPaused(RTC::Transport* transport, RTC::Producer* producer) = 0; @@ -104,7 +103,8 @@ namespace RTC virtual void OnTransportDataConsumerClosed( RTC::Transport* transport, RTC::DataConsumer* dataConsumer) = 0; virtual void OnTransportDataConsumerDataProducerClosed( - RTC::Transport* transport, RTC::DataConsumer* dataConsumer) = 0; + RTC::Transport* transport, RTC::DataConsumer* dataConsumer) = 0; + virtual void OnTransportListenServerClosed(RTC::Transport* transport) = 0; }; private: @@ -119,8 +119,8 @@ namespace RTC virtual ~Transport(); public: - void MustClose(); void CloseProducersAndConsumers(); + void ListenServerClosed(); // Subclasses must also invoke the parent Close(). virtual void FillJson(json& jsonObject) const; virtual void FillJsonStats(json& jsonArray); diff --git a/worker/src/RTC/Router.cpp b/worker/src/RTC/Router.cpp index f29871b3eb..fe06136ee4 100644 --- a/worker/src/RTC/Router.cpp +++ b/worker/src/RTC/Router.cpp @@ -620,25 +620,6 @@ namespace RTC return producer; } - inline void Router::OnTransportMustClose(RTC::Transport* transport) - { - MS_TRACE(); - - MS_ASSERT( - this->mapTransports.find(transport->id) != this->mapTransports.end(), - "Transport not present in mapTransports"); - - // Tell the Transport to close all its Producers and Consumers so it will - // notify us about their closures. - transport->CloseProducersAndConsumers(); - - // Remove it from the map. - this->mapTransports.erase(transport->id); - - // Delete it. - delete transport; - } - inline void Router::OnTransportNewProducer(RTC::Transport* /*transport*/, RTC::Producer* producer) { MS_TRACE(); @@ -1099,4 +1080,23 @@ namespace RTC // Remove the DataConsumer from the map. this->mapDataConsumerDataProducer.erase(mapDataConsumerDataProducerIt); } + + inline void Router::OnTransportListenServerClosed(RTC::Transport* transport) + { + MS_TRACE(); + + MS_ASSERT( + this->mapTransports.find(transport->id) != this->mapTransports.end(), + "Transport not present in mapTransports"); + + // Tell the Transport to close all its Producers and Consumers so it will + // notify us about their closures. + transport->CloseProducersAndConsumers(); + + // Remove it from the map. + this->mapTransports.erase(transport->id); + + // Delete it. + delete transport; + } } // namespace RTC diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 14d4a34024..78c9dbe355 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -246,14 +246,6 @@ namespace RTC #endif } - void Transport::MustClose() - { - MS_TRACE(); - - // Ask our parent Router to close/delete us. - this->listener->OnTransportMustClose(this); - } - void Transport::CloseProducersAndConsumers() { MS_TRACE(); @@ -315,6 +307,14 @@ namespace RTC this->mapDataConsumers.clear(); } + void Transport::ListenServerClosed() + { + MS_TRACE(); + + // Ask our parent Router to close/delete us. + this->listener->OnTransportListenServerClosed(this); + } + void Transport::FillJson(json& jsonObject) const { MS_TRACE(); diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 412474de08..9ae25f2c61 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -157,7 +157,7 @@ namespace RTC for (auto* webRtcTransport : this->webRtcTransports) { - webRtcTransport->MustClose(); + webRtcTransport->ListenServerClosed(); } this->webRtcTransports.clear(); } From 63bc1f0ee3e0f5db410514ffcf33d6137b1fdb97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 18:18:01 +0200 Subject: [PATCH 48/58] Add more tests --- node/lib/WebRtcServer.d.ts.map | 2 +- node/lib/WebRtcServer.js | 7 ++--- node/src/WebRtcServer.ts | 8 ++---- node/tests/test-WebRtcServer.js | 51 +++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/node/lib/WebRtcServer.d.ts.map b/node/lib/WebRtcServer.d.ts.map index 65b26bb744..b1b102f965 100644 --- a/node/lib/WebRtcServer.d.ts.map +++ b/node/lib/WebRtcServer.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;CACtC,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;;;OAIG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAG7D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAsBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAQ7D"} \ No newline at end of file +{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;CACtC,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;;;OAIG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAG7D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAkBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAQ7D"} \ No newline at end of file diff --git a/node/lib/WebRtcServer.js b/node/lib/WebRtcServer.js index 7be1505b8f..136e7a2077 100644 --- a/node/lib/WebRtcServer.js +++ b/node/lib/WebRtcServer.js @@ -98,11 +98,8 @@ class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { return; logger.debug('workerClosed()'); this.#closed = true; - // Close every WebRtcTransport. - for (const webRtcTransport of this.#webRtcTransports.values()) { - webRtcTransport.listenServerClosed(); - } - this.#webRtcTransports.clear(); + // NOTE: No need to close WebRtcTransports since they are closed by their + // respective Router parents. this.safeEmit('workerclose'); // Emit observer event. this.#observer.safeEmit('close'); diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 0a910bb8a2..81b84a67f8 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -198,12 +198,8 @@ export class WebRtcServer extends EnhancedEventEmitter this.#closed = true; - // Close every WebRtcTransport. - for (const webRtcTransport of this.#webRtcTransports.values()) - { - webRtcTransport.listenServerClosed(); - } - this.#webRtcTransports.clear(); + // NOTE: No need to close WebRtcTransports since they are closed by their + // respective Router parents. this.safeEmit('workerclose'); diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index 6ebc7e38c4..b8286ecae2 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -104,6 +104,57 @@ test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', worker.close(); }, 2000); +test('worker.createWebRtcServer() with unavailable listenInfos rejects with Error', async () => +{ + worker = await createWorker(); + + const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port2 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + + // Using an unavailable listen IP. + await expect(worker.createWebRtcServer( + { + listenInfos : + [ + { + protocol : 'udp', + ip : '127.0.0.1', + port : port1 + }, + { + protocol : 'udp', + ip : '1.2.3.4', + port : port2 + } + ] + })) + .rejects + .toThrow(Error); + + // Using the same UDP port in two listenInfos. + await expect(worker.createWebRtcServer( + { + listenInfos : + [ + { + protocol : 'udp', + ip : '127.0.0.1', + port : port1 + }, + { + protocol : 'udp', + ip : '0.0.0.0', + announcedIp : '1.2.3.4', + port : port1 + } + ] + })) + .rejects + .toThrow(Error); + + worker.close(); +}, 2000); + test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => { worker = await createWorker(); From facf73a99d61bfc3090bbcdbd7cb006c13023ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 18:18:56 +0200 Subject: [PATCH 49/58] cosmetic --- node/lib/WebRtcServer.d.ts.map | 2 +- node/lib/WebRtcServer.js | 1 + node/src/WebRtcServer.ts | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/node/lib/WebRtcServer.d.ts.map b/node/lib/WebRtcServer.d.ts.map index b1b102f965..e27aafb342 100644 --- a/node/lib/WebRtcServer.d.ts.map +++ b/node/lib/WebRtcServer.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;CACtC,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;;;OAIG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAG7D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAkBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAQ7D"} \ No newline at end of file +{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;CAChB,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,kBAAkB,EAAE,CAAC,eAAe,CAAC,CAAC;CACtC,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;;;OAIG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAG7D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAmBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAQ7D"} \ No newline at end of file diff --git a/node/lib/WebRtcServer.js b/node/lib/WebRtcServer.js index 136e7a2077..53612e2bca 100644 --- a/node/lib/WebRtcServer.js +++ b/node/lib/WebRtcServer.js @@ -100,6 +100,7 @@ class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { this.#closed = true; // NOTE: No need to close WebRtcTransports since they are closed by their // respective Router parents. + this.#webRtcTransports.clear(); this.safeEmit('workerclose'); // Emit observer event. this.#observer.safeEmit('close'); diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 81b84a67f8..ae50c55239 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -200,6 +200,7 @@ export class WebRtcServer extends EnhancedEventEmitter // NOTE: No need to close WebRtcTransports since they are closed by their // respective Router parents. + this.#webRtcTransports.clear(); this.safeEmit('workerclose'); From 2b7a18348a971aebc82af35ea09f38c4cd069b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 18:26:34 +0200 Subject: [PATCH 50/58] more tests --- node/tests/test-WebRtcServer.js | 38 ++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index b8286ecae2..3705085133 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -106,13 +106,13 @@ test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', test('worker.createWebRtcServer() with unavailable listenInfos rejects with Error', async () => { - worker = await createWorker(); - + const worker1 = await createWorker(); + const worker2 = await createWorker(); const port1 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); const port2 = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); // Using an unavailable listen IP. - await expect(worker.createWebRtcServer( + await expect(worker1.createWebRtcServer( { listenInfos : [ @@ -132,7 +132,7 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro .toThrow(Error); // Using the same UDP port in two listenInfos. - await expect(worker.createWebRtcServer( + await expect(worker1.createWebRtcServer( { listenInfos : [ @@ -152,7 +152,35 @@ test('worker.createWebRtcServer() with unavailable listenInfos rejects with Erro .rejects .toThrow(Error); - worker.close(); + await worker1.createWebRtcServer( + { + listenInfos : + [ + { + protocol : 'udp', + ip : '127.0.0.1', + port : port1 + } + ] + }); + + // Using the same UDP port in a second Worker. + await expect(worker1.createWebRtcServer( + { + listenInfos : + [ + { + protocol : 'udp', + ip : '127.0.0.1', + port : port1 + } + ] + })) + .rejects + .toThrow(Error); + + worker1.close(); + worker2.close(); }, 2000); test('worker.createWebRtcServer() rejects with InvalidStateError if Worker is closed', async () => From a989157320572cabd8a5b02145c757aa58a2aa8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 18:35:05 +0200 Subject: [PATCH 51/58] TransportTuple.hpp: rename GenerateHash() to SetHash() --- worker/include/RTC/TransportTuple.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 727ff3a7f9..eacee1a2da 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -28,13 +28,13 @@ namespace RTC TransportTuple(RTC::UdpSocket* udpSocket, const struct sockaddr* udpRemoteAddr) : udpSocket(udpSocket), udpRemoteAddr((struct sockaddr*)udpRemoteAddr), protocol(Protocol::UDP) { - GenerateHash(); + SetHash(); } explicit TransportTuple(RTC::TcpConnection* tcpConnection) : tcpConnection(tcpConnection), protocol(Protocol::TCP) { - GenerateHash(); + SetHash(); } explicit TransportTuple(const TransportTuple* tuple) @@ -131,7 +131,7 @@ namespace RTC } private: - void GenerateHash() + void SetHash() { const std::string protocol = this->protocol == Protocol::UDP ? "udp" : "tcp"; int family; From 00e2ff0fc626897e11799325ba0703bde244e722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sat, 18 Jun 2022 23:56:48 +0200 Subject: [PATCH 52/58] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9f6f00a9a..a5d860170b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### WIP +* Improve `EnhancedEventEmitter` (PR #836). * `WebRtcServer`: A new class that brings to `WebRtcTransports` the ability to listen on a single UDP/TCP port (PR #834). * `TransportCongestionControlClient`: Allow setting max outgoing bitrate before created (PR #833). From de5275c3384ca434acbc4be4600e7b90b244781d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 19 Jun 2022 00:59:10 +0200 Subject: [PATCH 53/58] cosmetic --- node/lib/Router.d.ts.map | 2 +- node/lib/Router.js | 4 +++- node/src/Router.ts | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/node/lib/Router.d.ts.map b/node/lib/Router.d.ts.map index 95eae49a90..0ab7ce4fb9 100644 --- a/node/lib/Router.d.ts.map +++ b/node/lib/Router.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,oBAAY,aAAa,GACzB;IACC;;OAEG;IACH,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAEnC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IAEtC;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC;;OAEG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAC;IAExB;;OAEG;IACH,gBAAgB,CAAC,EAAE,YAAY,CAAC;IAEhC;;OAEG;IACH,gBAAgB,CAAC,EAAE,YAAY,CAAC;CAChC,CAAA;AAED,aAAK,iBAAiB,GACtB;IACC,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC;CAC7B,CAAC;AAEF,oBAAY,YAAY,GACxB;IACC,WAAW,EAAE,EAAE,CAAC;IAEhB,QAAQ,EAAE,EAAE,CAAC;CACb,CAAA;AAED,oBAAY,oBAAoB,GAChC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,YAAY,EAAE,CAAC,SAAS,CAAC,CAAC;IAC1B,cAAc,EAAE,CAAC,WAAW,CAAC,CAAC;CAC9B,CAAA;AAID,qBAAa,MAAO,SAAQ,oBAAoB,CAAC,YAAY,CAAC;;IA8C7D;;OAEG;gBAEF,EACC,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,cAAc,EACd,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,IAAI,EAAE,GAAG,CAAC;QACV,OAAO,EAAE,OAAO,CAAC;QACjB,cAAc,EAAE,cAAc,CAAC;QAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAcF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,eAAe,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,oBAAoB,CAAC,CAGzD;IAED;;;OAGG;IACH,IAAI,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAGjD;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAsCb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAmCpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACG,qBAAqB,CAC1B,EACC,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,SAAgB,EAChB,SAAiB,EACjB,SAAiB,EACjB,SAAiB,EACjB,+BAAwC,EACxC,UAAkB,EAClB,cAAwC,EACxC,kBAA2B,EAC3B,kBAA2B,EAC3B,OAAO,EACP,EAAE,sBAAsB,GACvB,OAAO,CAAC,eAAe,CAAC;IAoG3B;;OAEG;IACG,oBAAoB,CACzB,EACC,QAAQ,EACR,IAAI,EACJ,OAAc,EACd,OAAe,EACf,UAAkB,EAClB,cAAwC,EACxC,kBAA2B,EAC3B,kBAA2B,EAC3B,UAAkB,EAClB,eAA2C,EAC3C,OAAO,EACP,EAAE,qBAAqB,GACtB,OAAO,CAAC,cAAc,CAAC;IA8E1B;;OAEG;IACG,uBAAuB,CAC5B,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,cAAc,CAAC;IAQ1B;;OAEG;IACG,mBAAmB,CACxB,EACC,QAAQ,EACR,IAAI,EACJ,UAAkB,EAClB,cAAwC,EACxC,kBAA8B,EAC9B,kBAA8B,EAC9B,SAAiB,EACjB,UAAkB,EAClB,OAAO,EACP,EAAE,oBAAoB,GACrB,OAAO,CAAC,aAAa,CAAC;IA4EzB;;OAEG;IACG,qBAAqB,CAC1B,EACC,cAAuB,EACvB,OAAO,EACP,GAAE,sBAGF,GACC,OAAO,CAAC,eAAe,CAAC;IA4C3B;;OAEG;IACG,YAAY,CACjB,EACC,UAAU,EACV,cAAc,EACd,MAAM,EACN,QAAsB,EACtB,UAAiB,EACjB,cAAwC,EACxC,SAAiB,EACjB,UAAkB,EAClB,EAAE,mBAAmB,GACpB,OAAO,CAAC,kBAAkB,CAAC;IA8O9B;;OAEG;IACH,oBAAoB,CACnB,oBAAoB,EAAE,MAAM,EAC5B,wBAAwB,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAClD,IAAI;IA+BP;;OAEG;IACG,2BAA2B,CAChC,EACC,QAAc,EACd,OAAO,EACP,GAAE,4BAAiC,GAClC,OAAO,CAAC,qBAAqB,CAAC;IAmCjC;;OAEG;IACG,wBAAwB,CAC7B,EACC,UAAc,EACd,SAAe,EACf,QAAe,EACf,OAAO,EACP,GAAE,yBAA8B,GAC/B,OAAO,CAAC,kBAAkB,CAAC;IAmC9B;;OAEG;IACH,UAAU,CACT,EACC,UAAU,EACV,eAAe,EACf,EACD;QACC,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,eAAe,CAAC;KACjC,GACC,OAAO;CAuBV"} \ No newline at end of file diff --git a/node/lib/Router.js b/node/lib/Router.js index ad1c313a75..a76b5fb084 100644 --- a/node/lib/Router.js +++ b/node/lib/Router.js @@ -166,8 +166,10 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { throw new TypeError('missing webRtcServer and listenIps (one of them is mandatory)'); else if (appData && typeof appData !== 'object') throw new TypeError('if given, appData must be an object'); - if (webRtcServer) + if (webRtcServer) { listenIps = undefined; + port = undefined; + } if (listenIps) { listenIps = listenIps.map((listenIp) => { if (typeof listenIp === 'string' && listenIp) { diff --git a/node/src/Router.ts b/node/src/Router.ts index 2b9dff21f6..b0d7c927f1 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -374,7 +374,10 @@ export class Router extends EnhancedEventEmitter throw new TypeError('if given, appData must be an object'); if (webRtcServer) + { listenIps = undefined; + port = undefined; + } if (listenIps) { From 11e01326abb79a8d5249b44a5b8f25e0c2c3b2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 19 Jun 2022 17:02:59 +0200 Subject: [PATCH 54/58] Remove deprecated router.createPlainRtpTransport() method --- node/lib/Router.d.ts | 4 ---- node/lib/Router.d.ts.map | 2 +- node/lib/Router.js | 7 ------- node/src/Router.ts | 13 ------------- 4 files changed, 1 insertion(+), 25 deletions(-) diff --git a/node/lib/Router.d.ts b/node/lib/Router.d.ts index 2fea6e1c6a..cda4a22f5c 100644 --- a/node/lib/Router.d.ts +++ b/node/lib/Router.d.ts @@ -152,10 +152,6 @@ export declare class Router extends EnhancedEventEmitter { * Create a PlainTransport. */ createPlainTransport({ listenIp, port, rtcpMux, comedia, enableSctp, numSctpStreams, maxSctpMessageSize, sctpSendBufferSize, enableSrtp, srtpCryptoSuite, appData }: PlainTransportOptions): Promise; - /** - * DEPRECATED: Use createPlainTransport(). - */ - createPlainRtpTransport(options: PlainTransportOptions): Promise; /** * Create a PipeTransport. */ diff --git a/node/lib/Router.d.ts.map b/node/lib/Router.d.ts.map index 0ab7ce4fb9..a2a6b961d7 100644 --- a/node/lib/Router.d.ts.map +++ b/node/lib/Router.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node/lib/Router.js b/node/lib/Router.js index a76b5fb084..95fbfe0c60 100644 --- a/node/lib/Router.js +++ b/node/lib/Router.js @@ -289,13 +289,6 @@ class Router extends EnhancedEventEmitter_1.EnhancedEventEmitter { this.#observer.safeEmit('newtransport', transport); return transport; } - /** - * DEPRECATED: Use createPlainTransport(). - */ - async createPlainRtpTransport(options) { - logger.warn('createPlainRtpTransport() is DEPRECATED, use createPlainTransport()'); - return this.createPlainTransport(options); - } /** * Create a PipeTransport. */ diff --git a/node/src/Router.ts b/node/src/Router.ts index b0d7c927f1..674464394e 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -559,19 +559,6 @@ export class Router extends EnhancedEventEmitter return transport; } - /** - * DEPRECATED: Use createPlainTransport(). - */ - async createPlainRtpTransport( - options: PlainTransportOptions - ): Promise - { - logger.warn( - 'createPlainRtpTransport() is DEPRECATED, use createPlainTransport()'); - - return this.createPlainTransport(options); - } - /** * Create a PipeTransport. */ From 9ff885cefeb55391ad665fe50e503fea31abfcf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 19 Jun 2022 20:15:42 +0200 Subject: [PATCH 55/58] WebRtcServer: add observer 'webrtctransporthandled' and 'webrtctransportunhandled' events --- node/lib/WebRtcServer.d.ts | 2 ++ node/lib/WebRtcServer.d.ts.map | 2 +- node/lib/WebRtcServer.js | 10 +++++++++- node/src/WebRtcServer.ts | 17 ++++++++++++++++- node/tests/test-WebRtcServer.js | 25 ++++++++++++++++++++++++- 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/node/lib/WebRtcServer.d.ts b/node/lib/WebRtcServer.d.ts index fb4e88ae4b..796da30111 100644 --- a/node/lib/WebRtcServer.d.ts +++ b/node/lib/WebRtcServer.d.ts @@ -37,6 +37,8 @@ export declare type WebRtcServerEvents = { }; export declare type WebRtcServerObserverEvents = { close: []; + webrtctransporthandled: [WebRtcTransport]; + webrtctransportunhandled: [WebRtcTransport]; }; export declare class WebRtcServer extends EnhancedEventEmitter { #private; diff --git a/node/lib/WebRtcServer.d.ts.map b/node/lib/WebRtcServer.d.ts.map index 190c2467fb..c57f843e32 100644 --- a/node/lib/WebRtcServer.d.ts.map +++ b/node/lib/WebRtcServer.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;IAEhB,QAAQ,EAAE,EAAE,CAAC;CACb,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;CACV,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;OAEG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAG7D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAyBb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAmBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAK7D"} \ No newline at end of file +{"version":3,"file":"WebRtcServer.d.ts","sourceRoot":"","sources":["../src/WebRtcServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IAEtC;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,mBAAmB,GAC/B;IACC;;OAEG;IACH,WAAW,EAAE,sBAAsB,EAAE,CAAC;IAEtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAA;AAED,oBAAY,kBAAkB,GAC9B;IACC,WAAW,EAAE,EAAE,CAAC;IAEhB,QAAQ,EAAE,EAAE,CAAC;CACb,CAAA;AAED,oBAAY,0BAA0B,GACtC;IACC,KAAK,EAAE,EAAE,CAAC;IACV,sBAAsB,EAAE,CAAC,eAAe,CAAC,CAAC;IAC1C,wBAAwB,EAAE,CAAC,eAAe,CAAC,CAAC;CAC5C,CAAA;AAID,qBAAa,YAAa,SAAQ,oBAAoB,CAAC,kBAAkB,CAAC;;IAuBzE;;OAEG;gBAEF,EACC,QAAQ,EACR,OAAO,EACP,OAAO,EACP,EACD;QACC,QAAQ,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC;IAYF;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,CAGf;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrC;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAG3C;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,oBAAoB,CAAC,0BAA0B,CAAC,CAG/D;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAG7D;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IA4Bb;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAmBpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAO1B;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;CAe7D"} \ No newline at end of file diff --git a/node/lib/WebRtcServer.js b/node/lib/WebRtcServer.js index d76e2af51c..fc860ed164 100644 --- a/node/lib/WebRtcServer.js +++ b/node/lib/WebRtcServer.js @@ -77,6 +77,8 @@ class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { // Close every WebRtcTransport. for (const webRtcTransport of this.#webRtcTransports.values()) { webRtcTransport.listenServerClosed(); + // Emit observer event. + this.#observer.safeEmit('webrtctransportunhandled', webRtcTransport); } this.#webRtcTransports.clear(); this.emit('@close'); @@ -112,7 +114,13 @@ class WebRtcServer extends EnhancedEventEmitter_1.EnhancedEventEmitter { */ handleWebRtcTransport(webRtcTransport) { this.#webRtcTransports.set(webRtcTransport.id, webRtcTransport); - webRtcTransport.on('@close', () => this.#webRtcTransports.delete(webRtcTransport.id)); + // Emit observer event. + this.#observer.safeEmit('webrtctransporthandled', webRtcTransport); + webRtcTransport.on('@close', () => { + this.#webRtcTransports.delete(webRtcTransport.id); + // Emit observer event. + this.#observer.safeEmit('webrtctransportunhandled', webRtcTransport); + }); } } exports.WebRtcServer = WebRtcServer; diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 581f18e526..9c1ec86c92 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -51,6 +51,8 @@ export type WebRtcServerEvents = export type WebRtcServerObserverEvents = { close: []; + webrtctransporthandled: [WebRtcTransport]; + webrtctransportunhandled: [WebRtcTransport]; } const logger = new Logger('WebRtcServer'); @@ -171,6 +173,9 @@ export class WebRtcServer extends EnhancedEventEmitter for (const webRtcTransport of this.#webRtcTransports.values()) { webRtcTransport.listenServerClosed(); + + // Emit observer event. + this.#observer.safeEmit('webrtctransportunhandled', webRtcTransport); } this.#webRtcTransports.clear(); @@ -220,6 +225,16 @@ export class WebRtcServer extends EnhancedEventEmitter handleWebRtcTransport(webRtcTransport: WebRtcTransport): void { this.#webRtcTransports.set(webRtcTransport.id, webRtcTransport); - webRtcTransport.on('@close', () => this.#webRtcTransports.delete(webRtcTransport.id)); + + // Emit observer event. + this.#observer.safeEmit('webrtctransporthandled', webRtcTransport); + + webRtcTransport.on('@close', () => + { + this.#webRtcTransports.delete(webRtcTransport.id); + + // Emit observer event. + this.#observer.safeEmit('webrtctransportunhandled', webRtcTransport); + }); } } diff --git a/node/tests/test-WebRtcServer.js b/node/tests/test-WebRtcServer.js index 3705085133..26c0f73b55 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/tests/test-WebRtcServer.js @@ -254,6 +254,13 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is { protocol: 'tcp', ip: '127.0.0.1', port: port2 } ] }); + + const onObserverWebRtcTransportHandled = jest.fn(); + const onObserverWebRtcTransportUnhandled = jest.fn(); + + webRtcServer.observer.once('webrtctransporthandled', onObserverWebRtcTransportHandled); + webRtcServer.observer.once('webrtctransportunhandled', onObserverWebRtcTransportUnhandled); + const router = await worker.createRouter(); const onObserverNewTransport = jest.fn(); @@ -271,6 +278,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is .resolves .toMatchObject({ transportIds: [ transport.id ] }); + expect(onObserverWebRtcTransportHandled).toHaveBeenCalledTimes(1); + expect(onObserverWebRtcTransportHandled).toHaveBeenCalledWith(transport); expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(transport); expect(transport.id).toBeType('string'); @@ -314,8 +323,10 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is }); transport.close(); - expect(transport.closed).toBe(true); + expect(transport.closed).toBe(true); + expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledTimes(1); + expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledWith(transport); expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); expect(router.transportsForTesting.size).toBe(0); @@ -352,6 +363,13 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer { protocol: 'tcp', ip: '127.0.0.1', port: port2 } ] }); + + const onObserverWebRtcTransportHandled = jest.fn(); + const onObserverWebRtcTransportUnhandled = jest.fn(); + + webRtcServer.observer.once('webrtctransporthandled', onObserverWebRtcTransportHandled); + webRtcServer.observer.once('webrtctransportunhandled', onObserverWebRtcTransportUnhandled); + const router = await worker.createRouter(); const transport = await router.createWebRtcTransport( { @@ -361,6 +379,9 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer appData : { foo: 'bar' } }); + expect(onObserverWebRtcTransportHandled).toHaveBeenCalledTimes(1); + expect(onObserverWebRtcTransportHandled).toHaveBeenCalledWith(transport); + await expect(router.dump()) .resolves .toMatchObject({ transportIds: [ transport.id ] }); @@ -444,6 +465,8 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer expect(webRtcServer.closed).toBe(true); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(onListenServerClose).toHaveBeenCalledTimes(1); + expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledTimes(1); + expect(onObserverWebRtcTransportUnhandled).toHaveBeenCalledWith(transport); expect(transport.closed).toBe(true); expect(webRtcServer.webRtcTransportsForTesting.size).toBe(0); expect(router.transportsForTesting.size).toBe(0); From 86881e846ed390870a4315cfaa9b58991a82d0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Jun 2022 18:36:49 +0200 Subject: [PATCH 56/58] WebRtcServer.cpp: don't assert tuple.hash in the table since a malicious user may produce 2 identical hashes. Also, match tuple first when a STUN binding request is received since it's faster (we already computed the tuple.hash anyway). --- worker/src/RTC/WebRtcServer.cpp | 44 +++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 9ae25f2c61..4e80c8e3a5 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -373,10 +373,25 @@ namespace RTC return; } + // First try doing lookup in the tuples table. + auto it1 = this->mapTupleWebRtcTransport.find(tuple->hash); + + if (it1 != this->mapTupleWebRtcTransport.end()) + { + auto* webRtcTransport = it1->second; + + webRtcTransport->ProcessStunPacketFromWebRtcServer(tuple, packet); + + delete packet; + + return; + } + + // Otherwise try to match the local ICE username fragment. auto key = GetLocalIceUsernameFragmentFromReceivedStunPacket(packet); - auto it = this->mapLocalIceUsernameFragmentWebRtcTransport.find(key); + auto it2 = this->mapLocalIceUsernameFragmentWebRtcTransport.find(key); - if (it == this->mapLocalIceUsernameFragmentWebRtcTransport.end()) + if (it2 == this->mapLocalIceUsernameFragmentWebRtcTransport.end()) { MS_WARN_TAG(ice, "ignoring received STUN packet with unknown remote ICE usernameFragment"); @@ -385,7 +400,7 @@ namespace RTC return; } - auto* webRtcTransport = it->second; + auto* webRtcTransport = it2->second; webRtcTransport->ProcessStunPacketFromWebRtcServer(tuple, packet); @@ -438,6 +453,11 @@ namespace RTC { MS_TRACE(); + MS_ASSERT( + this->mapLocalIceUsernameFragmentWebRtcTransport.find(usernameFragment) == + this->mapLocalIceUsernameFragmentWebRtcTransport.end(), + "local ICE username fragment already exists in the table"); + this->mapLocalIceUsernameFragmentWebRtcTransport[usernameFragment] = webRtcTransport; } @@ -449,7 +469,7 @@ namespace RTC MS_ASSERT( this->mapLocalIceUsernameFragmentWebRtcTransport.find(usernameFragment) != this->mapLocalIceUsernameFragmentWebRtcTransport.end(), - "tuple not handled"); + "local ICE username fragment not found in the table"); this->mapLocalIceUsernameFragmentWebRtcTransport.erase(usernameFragment); } @@ -459,6 +479,13 @@ namespace RTC { MS_TRACE(); + if (this->mapTupleWebRtcTransport.find(tuple->hash) != this->mapTupleWebRtcTransport.end()) + { + MS_WARN_TAG(ice, "tuple hash already exists in the table, this should not happen"); + + return; + } + this->mapTupleWebRtcTransport[tuple->hash] = webRtcTransport; } @@ -467,9 +494,12 @@ namespace RTC { MS_TRACE(); - MS_ASSERT( - this->mapTupleWebRtcTransport.find(tuple->hash) != this->mapTupleWebRtcTransport.end(), - "tuple not handled"); + if (this->mapTupleWebRtcTransport.find(tuple->hash) == this->mapTupleWebRtcTransport.end()) + { + MS_WARN_TAG(ice, "tuple hash not found in the table, this should not happen"); + + return; + } this->mapTupleWebRtcTransport.erase(tuple->hash); } From 1caf223a87737d99fb6600cb4f2fb26c18788e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 20 Jun 2022 18:38:50 +0200 Subject: [PATCH 57/58] cosmetic --- worker/src/RTC/WebRtcServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 4e80c8e3a5..95c8b067d4 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -481,7 +481,7 @@ namespace RTC if (this->mapTupleWebRtcTransport.find(tuple->hash) != this->mapTupleWebRtcTransport.end()) { - MS_WARN_TAG(ice, "tuple hash already exists in the table, this should not happen"); + MS_WARN_TAG(ice, "tuple hash already exists in the table"); return; } @@ -496,7 +496,7 @@ namespace RTC if (this->mapTupleWebRtcTransport.find(tuple->hash) == this->mapTupleWebRtcTransport.end()) { - MS_WARN_TAG(ice, "tuple hash not found in the table, this should not happen"); + MS_WARN_TAG(ice, "tuple hash not found in the table"); return; } From 4671cac5cd02cb7f3e91d4596a76729506e673a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 21 Jun 2022 23:05:24 +0200 Subject: [PATCH 58/58] New TransportTuple.hash uint64_t implementation (#839) --- worker/include/RTC/TransportTuple.hpp | 76 ++++++++++++++++++++++----- worker/include/RTC/WebRtcServer.hpp | 2 +- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index eacee1a2da..535d221a68 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -131,26 +131,78 @@ namespace RTC } private: + /* + * Hash for IPv4 + * + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PORT | IP | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | IP | |F|P| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Hash for IPv6 + * + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PORT | IP[0] ^ IP[1] ^ IP[2] ^ IP[3]| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | IP[0] >> 16 |F|P| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ void SetHash() { - const std::string protocol = this->protocol == Protocol::UDP ? "udp" : "tcp"; - int family; - std::string localIp; - uint16_t localPort; - std::string remoteIp; - uint16_t remotePort; + const struct sockaddr* remoteSockAddr = GetRemoteAddress(); - Utils::IP::GetAddressInfo(GetLocalAddress(), family, localIp, localPort); - Utils::IP::GetAddressInfo(GetRemoteAddress(), family, remoteIp, remotePort); + switch (remoteSockAddr->sa_family) + { + case AF_INET: + { + auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); - std::string id = remoteIp + std::to_string(remotePort) + localIp + std::to_string(localPort) + - std::to_string(family) + protocol; + const uint64_t address = ntohl(remoteSockAddrIn->sin_addr.s_addr); + const uint64_t port = (ntohs(remoteSockAddrIn->sin_port)); - this->hash = std::hash{}(id); + this->hash = port << 48; + this->hash |= address << 16; + this->hash |= 0x0000; // AF_INET. + + break; + } + + case AF_INET6: + { + auto* remoteSockAddrIn6 = reinterpret_cast(remoteSockAddr); + auto* a = reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); + + const auto address1 = a[0] ^ a[1] ^ a[2] ^ a[3]; + const auto address2 = a[0]; + const uint64_t port = ntohs(remoteSockAddrIn6->sin6_port); + + this->hash = port << 48; + this->hash |= static_cast(address1) << 16; + this->hash |= address2 >> 16 & 0xFFFC; + this->hash |= 0x0002; // AF_INET6. + + break; + } + } + + // Override least significant bit with protocol information: + // - If UDP, start with 0. + // - If TCP, start with 1. + if (this->protocol == Protocol::UDP) + { + this->hash |= 0x0000; + } + else + { + this->hash |= 0x0001; + } } public: - size_t hash; + uint64_t hash{ 0u }; private: // Passed by argument. diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 504ff18f81..cb53233c4f 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -100,7 +100,7 @@ namespace RTC // Map of WebRtcTransports indexed by local ICE usernameFragment. absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransport; // Map of WebRtcTransports indexed by TransportTuple.hash. - absl::flat_hash_map mapTupleWebRtcTransport; + absl::flat_hash_map mapTupleWebRtcTransport; }; } // namespace RTC