Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TransportListenInfo: Add portRange (deprecate worker port range) #1365

Merged
merged 17 commits into from
Apr 8, 2024

Conversation

ibc
Copy link
Member

@ibc ibc commented Apr 7, 2024

Details

  • New optional portRange field (an object with min and max keys) has been added in TransportListenInfo, so it's available in router.createWebRtcTransport(), router.createPlainTransport(), router.createPipeTransport() and worker.createWebRtcServer() methods.
  • If portRange is given, then a free random port in that range (and given ip and protocol) will be chosen.
  • This feature deprecates worker ports range (rtcMinPort and rtcMaxPort in WorkerSettings given to createWorker() method). Rationale is that it doesn't make any sense to have a unique port range for different listening IPs (for example: an app may want to use different port ranges for public connections (public internet) and private connections (private network).

TODO

  • Documentation in website and proper announcement.

@ibc ibc marked this pull request as ready for review April 7, 2024 23:35
@ibc ibc requested a review from jmillan April 7, 2024 23:41
@@ -1,5 +1,6 @@
import * as os from 'node:os';
import { Duplex } from 'node:stream';
import { info, warn } from 'node:console';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to avoid that Jest mangles the output of MS_DUMP().

Comment on lines 200 to 216
test('router.createWebRtcTransport() with fixed port succeeds', async () => {
const port = await pickPort({
type: 'tcp',
ip: '127.0.0.1',
reserveTimeout: 0,
});
const webRtcTransport = await ctx.router!.createWebRtcTransport({
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);

webRtcTransport.close();
}, 2000);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to keep a proper order.

@@ -14,50 +13,72 @@ namespace RTC
class PortManager
{
private:
enum class Transport : uint8_t
enum class Protocol : uint8_t
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consistency

|IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | IP[0] >> 16 |F|P|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
void SetHash()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to .cpp

: // This may throw.
::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, port, flags)), listener(listener),
fixedPort(true)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had a critical BUG here! We marked UdpSocket with fixedPort: true, meaning that the port was never removed from PortManager's maps when this UdpSocket was closed!!!

uint16_t minPort,
uint16_t maxPort,
RTC::Transport::SocketFlags& flags,
uint64_t& portRangeHash)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that portRangeHash is passed as a reference to uint64_t, so the parent constructor (in the initializer list) calls RTC::PortManager::BindUdp() and also passes portRangeHash to it as a reference to uint64_t, so PortManager will change the value of portRangeHash and the new value will be also visible here.

@ibc ibc changed the title ListenInfo: Add minPort and maxPort (deprecate worker port range) TransportListenInfo: Add minPort and maxPort (deprecate worker port range) Apr 7, 2024
Copy link
Member

@jmillan jmillan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍 . If I had a comment to add is that it would be IMHO a bit cleaner adding a new type portRange rather than two minPort and maxPort.

type PortRange = {
  min: number;  
  max: number;
};

@ibc ibc changed the title TransportListenInfo: Add minPort and maxPort (deprecate worker port range) TransportListenInfo: Add portRange (deprecate worker port range) Apr 8, 2024
@@ -52,7 +52,7 @@ impl AppData {
/// # Notes on usage
/// If you use "0.0.0.0" or "::" as ip value, then you need to also provide
/// `announced_address`.
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to remove Ord and PartialOrd because RangeInclusive doesn't implement them. No downsides AFAIS.

rust/src/data_structures.rs Outdated Show resolved Hide resolved
@ibc
Copy link
Member Author

ibc commented Apr 8, 2024

@jmillan, minPort and maxPort now moved to portRange.

@ibc ibc requested a review from nazar-pc April 8, 2024 10:35
@ibc ibc merged commit 62d2731 into v3 Apr 8, 2024
31 checks passed
@ibc ibc deleted the dynamic-port-ranges branch April 8, 2024 14:24
@CosmosisT
Copy link

CosmosisT commented Apr 10, 2024

Why not allowedPorts and provide ability for min/max and static ports. That way everyone is settled. I would assume if isolated processes are ran the min/max range would still be affective skipping used ports for an available one when initiating connections.

The parameter would look a little like this allowedPorts: {min: 20000, max: 30000, static:[443, 3923, 10293]}

This way no matter the setup it's simplified and in one spot and for people who want specifics between TCP/UDP connections this would suffice.

@ibc
Copy link
Member Author

ibc commented Apr 10, 2024

We allow passing a static port (so the app must manage ports by itself) or a port range. IMHO is more than enough. In addition the PortRange C++ class is optimized to avoid trying already used ports.

Also, it doesn't make sense that the app passes some static ports plus a port range. If the app passes a static port then the app is supposed to manage ports. mediasoup is not gonna try first your "maybe available or not" static ports and then, of all fail, choose a random one in the given range. It doesn't make sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants