Open SimonBrandner opened 1 year ago
I guess my question here is exactly what the ICE UDP muxing does - looks like it gathers source addreses based on ice credentials in the check packets and then routes media packets based on the source addresses it matched. I couldn't find out for sure, but I guess this is necessary because otherwise there's no way of knowing which DTLS session to use to decrypt a packet (and since they're DTLSed, you can't just route based on SSRC). In which case, yeah, this is probably something we want to think about a little further down the line.
Something like this, yeah, though I think the issue that you described is rather an implication of a more generic problem, let me explain how I understood it (hope that my understanding is correct).
Imagine we don't use UDP mux, and just use different UDP sockets (each peer connection has its own dedicated socket). Code-wise it means that somewhere inside a PeerConnection
there is a socket
and I imagine that when you read the data it essentially just calls socket.read()
and then passes the data down the line to process the received packet.
Now imagine we enforce the usage of a single UDP port naively (using the same architecture, without changes in code), now 5 separate PeerConnection
s will essentially have the same socket
(bound to the same local address and port). If all of them continue to read from the socket the same way they did it before, each PeerConnection
will end up reading a random datagram from a socket that may not necessarily have been addressed to this particular PeerConnection
. What should PeerConnection
do with it? - Well, the only thing it could do is to either drop it (treating it as an unknown or invalid message) or use some sort of a look-up table to understand which PeerConnection
this packet was meant for (based on e.g. sender's address and port). This "look-up table" must then be some sort of a shared state between PeerConnection
s, so that they know to who the message must be forwarded. Alternatively, the underlying socket must be moved outside of the PeerConnection
and read in a single place while dispatching the messages to the right PeerConnection
based on the addresses. This is exactly what the UDP Muxing in Pion does I suppose (from a quick peek in their code it looks like Pion does indeed something similar though more elaborated).
Exactly - without DTLS this lookup would just be done on the SSRC of the incoming packet so it's trivial, but in a DTLS world you need to know which set of keys to use to decrypt the packet, so you end up guessing based on the sender address.
UPD. An example to try out once we want to implement it: https://github.com/pion/webrtc/blob/master/examples/ice-single-port/main.go#L85
@daniel-abramov:
As discussed during the daily, I'm adding a little bit more context here: we won't be able to achieve the desired effect by just setting a range of UDP ports to a single port, instead, what we need, is to enable a so-called UDP Muxing in Pion.
As we know, UDP (unlike TCP) does not really have a concept of a connection on a protocol level, so it's about sending and receiving datagrams from/to an address. Pion does not have a global WebRTC state out-of-the-box that would allow reading the information from a single UDP socket and then forwarding it to the appropriate peer connection that is meant to be associated with it. So to enable this behavior, we should rely upon
ice.NewMultiUDPMuxFromPort(ourPort)
and then configure the engine accordingly:webrtc.SettingEngine.setICEUDPMux(ourConfig)
(then we can create a new peer connection specifying the configured settings engine).Note, that it's probably not something we want to have before stabilizing the SFU since enabling this option might have some undesired side-effects that must be treated accordingly, there is an open issue about it: https://github.com/pion/ice/issues/518
Perhaps a better idea would be to start with something that LiveKit has, i.e. allow configuration of the range of ports used for the UDP along with the support of the ICE-TCP. This should give us a good starting point. Then we could embed a TURN server into the SFU (the TURN server normally has fixed configured ports for both UDP and TCP) and only after it consider the usage of the UDPMux.