From 2aaad6213ee3df24af1be469f6a40a36b0b128e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Jan 2024 13:51:31 +0100 Subject: [PATCH] ListenInfo: Ignore given socket flags if not suitable for given IP family or transport For example, by design `libuv` will throw if a IPv4 socket is created with flag `UV_UDP_IPV6ONLY` or `UV_TCP_IPV6ONLY`. --- CHANGELOG.md | 1 + node/src/tests/test-PlainTransport.ts | 3 ++- node/src/tests/test-WebRtcTransport.ts | 8 ++++-- rust/tests/integration/plain_transport.rs | 3 ++- worker/include/RTC/PortManager.hpp | 3 ++- worker/src/RTC/PortManager.cpp | 33 +++++++++++++++++------ 6 files changed, 38 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12075eba84..38e4fb823d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). * `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). +* `ListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). * Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). * Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). diff --git a/node/src/tests/test-PlainTransport.ts b/node/src/tests/test-PlainTransport.ts index 554d07444a..770d0bbfce 100644 --- a/node/src/tests/test-PlainTransport.ts +++ b/node/src/tests/test-PlainTransport.ts @@ -338,7 +338,8 @@ if (!IS_WINDOWS) protocol : 'udp', ip : multicastIp, port : port, - flags : { udpReusePort: true } + // NOTE: ipv6Only flag will be ignored since ip is IPv4. + flags : { udpReusePort: true, ipv6Only: true } } }); diff --git a/node/src/tests/test-WebRtcTransport.ts b/node/src/tests/test-WebRtcTransport.ts index 7bb950eb08..b08b32c342 100644 --- a/node/src/tests/test-WebRtcTransport.ts +++ b/node/src/tests/test-WebRtcTransport.ts @@ -641,10 +641,14 @@ test('WebRtcTransport methods reject if closed', async () => test('router.createWebRtcTransport() with fixed port succeeds', async () => { - const port = await pickPort({ ip: '127.0.0.1', reserveTimeout: 0 }); + const port = await pickPort({ type: 'tcp', ip: '127.0.0.1', reserveTimeout: 0 }); const webRtcTransport = await router.createWebRtcTransport( { - listenInfos : [ { protocol: 'udp', ip: '127.0.0.1', port } ] + listenInfos : + [ + // NOTE: udpReusePort flag will be ignored since protocol is TCP. + { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } } + ] }); expect(webRtcTransport.iceCandidates[0].port).toEqual(port); diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index 5fc334fca6..e40e79fb2c 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -438,8 +438,9 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee ip: multicast_ip, announced_ip: None, port: Some(port), + // NOTE: ipv6Only flag will be ignored since ip is IPv4. flags: Some(SocketFlags { - ipv6_only: false, + ipv6_only: true, udp_reuse_port: true, }), send_buffer_size: None, diff --git a/worker/include/RTC/PortManager.hpp b/worker/include/RTC/PortManager.hpp index 17294f24ca..f8c102b6b9 100644 --- a/worker/include/RTC/PortManager.hpp +++ b/worker/include/RTC/PortManager.hpp @@ -52,7 +52,8 @@ namespace RTC Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); static void Unbind(Transport transport, std::string& ip, uint16_t port); static std::vector& GetPorts(Transport transport, const std::string& ip); - static uint8_t ConvertSocketFlags(RTC::Transport::SocketFlags& flags); + static uint8_t ConvertSocketFlags( + RTC::Transport::SocketFlags& flags, Transport transport, int family); private: thread_local static absl::flat_hash_map> mapUdpIpPorts; diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index 051a318d45..eea8dbb97c 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -1,4 +1,4 @@ -#define MS_CLASS "RTC::PortManager" +#define MS_CLASS "PortManager" // #define MS_LOG_DEV_LEVEL 3 #include "RTC/PortManager.hpp" @@ -55,7 +55,7 @@ namespace RTC uv_handle_t* uvHandle{ nullptr }; uint16_t port; std::string transportStr; - uint8_t bitFlags = ConvertSocketFlags(flags); + uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); switch (transport) { @@ -378,7 +378,7 @@ namespace RTC struct sockaddr_storage bindAddr; // NOLINT(cppcoreguidelines-pro-type-member-init) uv_handle_t* uvHandle{ nullptr }; std::string transportStr; - uint8_t bitFlags = ConvertSocketFlags(flags); + uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); switch (transport) { @@ -692,19 +692,36 @@ namespace RTC return emptyPorts; } - uint8_t PortManager::ConvertSocketFlags(RTC::Transport::SocketFlags& flags) + uint8_t PortManager::ConvertSocketFlags( + RTC::Transport::SocketFlags& flags, Transport transport, int family) { MS_TRACE(); uint8_t bitFlags{ 0b00000000 }; - if (flags.ipv6Only) + // Ignore ipv6Only in IPv4, otherwise libuv will throw. + if (flags.ipv6Only && family == AF_INET6) { - bitFlags |= UV_UDP_IPV6ONLY; - bitFlags |= UV_TCP_IPV6ONLY; // Same flag number but anyway. + switch (transport) + { + case Transport::UDP: + { + bitFlags |= UV_UDP_IPV6ONLY; + + break; + } + + case Transport::TCP: + { + bitFlags |= UV_TCP_IPV6ONLY; + + break; + } + } } - if (flags.udpReusePort) + // Ignore udpReusePort in TCP, otherwise libuv will throw. + if (flags.udpReusePort && transport == Transport::UDP) { bitFlags |= UV_UDP_REUSEADDR; }