Port in transport options

I just found myself needing to have port range for different transports in the same worker.
IP is already an argument on transport level and I can manage available ports in the app as well.

For instance I’d like to use one port range and IP for WebRTC transports and another (much smaller) for Pipe transports.

Did anyone else face this before? Thoughts?

This is something that will be considered for v4

What if I implement optional port parameter for transport options?
This way if you specify port explicitly it will be used instead of randomly selected one from specified port range.

I’m not sure. When a Transport is closed we call PortManager.something() to remove each allocated ip:port. Not sure what would happen if we call that we a port that maybe outside the port range, etc.

Some flag can be stored to distinguish whether that port is manually selected or needs to be freed in the port range.
If the feature makes sense I can try to implement it.

Also specifying manually port that overlaps with port range would be an error, so should be easy to check if port should be freed by PortManager by comparing port against port range.

Not really. We are ready already to look for ports in the range that are available in theory but they are used by other processed.

The problem here is that all this complex logic is done by PortManager and I wouldn’t like to replicate such a complex logic elsewhere just to allow passing a custom port per listenIp when creating a Transport.

What I need to implement is not a “suggestion” for worker, but a direct instruction. The port should be free or else an error must be returned. Hence if you specify a port that collides with port range used otherwise you are looking for trouble. So port that is specified explicitly must be outside of port range by definition.

I don’t think it would be necessary to replicate it, I’m thinking of adding one more method in addition to PortManager::Bind with port argument in it.

Just to be clear, what I’m talking about is just adding single port argument to PipeTransportOptions and others.

It is quite similar to what I have tried to do here Using separate rtcMinPort/rtcMaxPort setting for PlainTransport (Implementing separate rtcMinPort/rtcMaxPort setting for PlainTransport · vpalmisano/mediasoup@bcfb1f8 · GitHub), but with the complication that you need to specify this option for each transport.

I think it is actually a bit simpler. I already have a set of definitely free ports and multi-tenant environment, so it is not hard at all to write a trivial PortManager on app level and dedicate one port for each transport.

Your approach would also work assuming it is extended to pipe transport as well.

So do you want to provide a port number in the Transport configuration. But in this case you will need to track the used ports at the application layer, exposing the used ports information from workers to the app.

Yes, exactly.

Tracking used ports is not a problem and they are already exposed, for instance, via PipeTransport.tuple property or ICE candidates. Assuming ports specified explicitly do not overlap with any of the port ranges used there is no problem.

Mediasoup will error handle in case of duplicate port usage and use the next-best options or error out completely with a limit reached message.

It’s more trouble than its worth to change or add this truthfully, more error handling than necessary with lots of potential for user to insert some bunk ranges/specifics. IMO rely on the portmanager and map what you need “specifically” let it run free-range.

Edit
(Understanding more, some use cases could benefit with an option to bypass and maintain the manager themselves)

I know what port manager does and how it handles already used ports, that is completely orthogonal to what my use case requires. I need some transports to use one IP (listen/public) pair and port range and other transport to use completely different IP pair and port range.

I run software in containers with virtual networks and only some of the networking need to be actually exposed publicly. Currently such control is impossible since there is just one global port range on worker shared with all routers and transports in it. Not even mentioning that exposing large potential port ranges with containers [actually] [leads] [to] [numerous] [problems] (those are the ones I recaled quickly) from OOM and slow startup time when trying to do that with Docker to quickly reaching manifest size limit for pod in kubernetes.

Interesting. I’d favor it. Some kind of bypass in those specific scenarios. I like it, however wasn’t aware of that issue till now. Thanks for the reads.

I don’t run containers so experience less of those issues/needs.

Some other sfu use only one udp port for all webrtc Connection

They distinguish one udp packet belong to which connection by mapping the username of stun packet which exists in sdp with the remote udp ip and port

does mediasoup consider adding the feature?

This would be too good to be true comparing to current setup, but I’d really like to see that if possible.

Though it would only work for WebRTC, not plain/pipe transports if I understood correctly. But situation with port range usage would improve massively.

The actual implementation is based on ICE specifications (RFC 5245 - Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols):

Host candidates are obtained by binding to ports (typically ephemeral) on a IP address attached to an interface (physical or virtual, including VPN interfaces) on the host.

Did you know other ICE implementation that are using the same ip:port for host candidates (without inspecting the RTP packet content)?

I’m not familiar with the rfc5245, so I don’t know the “single udp port” implemention was a hack or not.
I obtained this “single port” information from some blog articles.

This patch implement the feature:

1 Like