roc-streaming / roc-toolkit

Real-time audio streaming over the network.
https://roc-streaming.org
Mozilla Public License 2.0
1.03k stars 205 forks source link

Allow configuring outgoing port range of sender #556

Open gavv opened 9 months ago

gavv commented 9 months ago

Problem

We already allow to configure outgoing sender address using roc_sender_configure() function via outgoing_address field of roc_interface_config struct.

Now we should also allow to configure outgoing port. Currently we always use zero port, which means "select random free ephemeral port".

The user may want to specify specific port or a port range, which would mean "select random free port from the range".

The typical usage of this feature will be restricting sender to ports which are open in the firewall. The user just tells us what ports Roc can use and doesn't bother with the housekeeping needed to track what ports are free.

Solution

When a port range is given, we can't delegate the selection of a random free port to kernel and should do it by ourselves.

We could do a linear search and try all ports in range one by one until we successfully bind one. Or we could try to bind to a random port from range in a loop until bind succeeds. Both approaches are not efficient, and the second one can even cause a hang.

I suggest the following approach (but feel free to suggest something better!):

With this approach, port allocation will be efficient if the user uses a unique port range for each context (roc_context), and thus for each netio::NetworkLoop, which I think is a reasonable requirement. If the requirement is not met, port selection wouldn't be so efficient, but at least it won't hang.

Note that alloc_random_port() does not have to be truly random, but some degree of randomization will help if the port range is also used by someone else. E.g. if the implementation of PortAllocator splits bitmask into chunks, it could randomly select a chunk, and then do a linear search inside the chunk.

If we chose this approach, we should mention its requirements in comments for roc_interface_config.