[libnice] Force an external address (srflx) candidate?

Fabrice Bellet fabrice at bellet.info
Mon Oct 19 15:57:18 UTC 2020

Hi Stuart,

On 10/14/20 at 09:22pm, Stuart Marshall wrote:
> In contrast, the ICE candidates emitted by Chrome are stunningly few and precise. I understand that the ICE protocols and the libnice implementation were/are meant to be general case. But they miss obvious efficiencies that can be provided by additional external information. STUN servers facilitate some of that additional information, but introduce a dependency and more latency.
> My knowledge of libnice internals is not great, but I kind of wish we could
>   1.  Feed some particular IP candidate addresses to it,
>   2.  Tell it to skip a bunch of other candidate generation and testing

I think of some optimisations, that could help to limit the number of
candidates, without weakening the versatility of the ice method overall
(except in *rare* cases where the server running libnice uses source
routing, ie chooses the default route based on the source IP address):

We could use a single server reflexive candidate and relay local
candidate, per stream/component.

Generally, there's no gain to send a stun request from each local
interface, because all packets will reach the same stun server by the
same default route. 

The consequence is that we obtain <N> distinct server-reflexive
candidates from <N> distinct source IP addresses. These
server-reflexives candidates are distinct because their IP address will
be the same (this is our public IP address), but the port mapping will
be different. The same applies to turn relay candidates too (including
unnecessary resources reservations on the turn servers BTW).

To avoid that, we could for example:
  1. discard these redundant candidates when we discover them (when
  processing the discovery stun response).
  2. or more radically, just send a single stun and turn discovery request.

In case of 2. the choice of the local interface used as the base address
to send this unique stun/turn discoevry request is normally not
relevant, because the routing table will hopefully make these packets go
out by the same default route again, whatever source interface they come

To summarize, I think that sending a single stun request from a single
network interface during gathering phase to obtain our server-reflexive
address is normally a cheap operation (one RTT when the thr stun server
is available), but what is expensive from libnice point of view is to
deal with many identical reflexive/relay candidates during the
connecting phase, because it creates many possibilities to be tested.
And the more possibilities we have to test, the more time it takes to

Best wishes,

More information about the nice mailing list