Subject: [MMUSIC] Comments on ICE-TCP specification RFC 6544

From: Nigel Pattinson <[email-masked]>
Date: Fri, 8 Jun 2012 09:37:49 +1200

Hello all

In our company we have just implemented support for ICE-TCP, and in our
opinion there are some areas of the specification which could use some
clarification. Note that our implementation is designed to be used in an
XMPP/Jingle context rather than with SIP, which potentially makes a
difference in some of the areas mentioned below.

The specification makes no mention of foundations for TCP candidates.
4.1.1.3 in [RFC5245] specifies that TCP foundations must be different from
UDP foundations, but it is unclear whether or not passive, active, and
simultaneous open candidates should have distinct foundations. The same is
true for NAT-assisted and tunneled candidate types - should these have
distinct foundations from server-reflexive/relayed candidates ? We have
guessed that in all cases they should be distinct.

4.1.1.4 in [RFC5245] states that server reflexive candidates should be kept
alive until ICE processing completes. 11.2 in RFC 6544 does not contradict
this, but does not clarify it either. This implies that TCP connections to
a STUN server should be kept open for this duration, with STUN binding
requests being sent at intervals. It is not clear to us that doing so would
have any benefit, but we are not NAT experts. Either way it would be good
if the ICE-TCP specification made it clear whether or not this was
necessary or desirable.

When the offerer has relayed candidates obtained from a TURN server, it may
not be possible to ensure that permissions are created for those passive
candidates prior to the peer attempting to connect. This may result in
failure of the peer's active check, and hence possibly in failure of ICE as
a whole. The same basic problem can happen in ICE-UDP, but the UDP check
would almost certainly be retried at a time when the permissions are in
place, and so should succeed eventually. The situation could be exacerbated
by the Jingle recommendation that candidates are sent to the peer as soon
as they are discovered - in this case even the answerer's relayed
candidates may not have the permissions in place when they are needed.
We're not sure if there is a foolproof solution to these problems, but we
do feel that the potential for failures should at least be mentioned.

6.2 states that candidate pairs with a tcp passive local candidate should
be pruned from the checklist. This clearly makes sense, but has some
undesirable consequences in the following situation. Imagine that both
agents are on the same network, so all connectivity checks will succeed.
The top priority candidate pair in each agent's check list will most likely
have a local host active candidate and a remote host passive candidate,
since all pairs with a local passive candidate have been pruned. It is
quite likely that the controlled agents first check request will be
received by the controlling agent before the latter has had a chance to
initiate its first check. If this is the case, the controlling agent will
reply to the check, add a candidate pair with a local passive candidate and
a remote active candidate to its check list, and trigger a check for that
candidate pair. Meanwhile the controlled agent will initiate further
lower-priority checks, all of which will succed and cause the controlling
agent to trigger matching checks. Unless the controlling agent has a
shorter _Ta than the offerer, the result can be that the controlling agent
spends all its time sending triggered checks, and only gets a chance to
initiate checks once the controlled agent has exhausted its check list. The
downside to this is that candidate pairs with a controlling active
candidate and a controlled passive candidate exist only in the controlling
agent's check list, so these will not be checked at all until all pairs in
the controlled agent's check list have been checked. What is worse, with
the suggested priority calculcations, the highest priority pair will be
just such a pair, and since aggressive nomination is not being used, it is
likely that the highest priority check needs to be completed before the ICE
session can be regarded as successful. We do not have an ideal solution for
this, but switching the recommended active and passive direction pref
values would make it unlikely that the highest priority check would have a
controlling active candidate and a controlled passive candidate.

7.1 states that for tcp-active candidates, unallocated ports should be
used. This may result in many port allocations, so we wonder whether it
would be preferable to reuse the same port for all connections made from a
specific tcp-active candidate (where supported by the host OS, of course).

Sections 7.1 and 7.2 both note that a peer-reflexive candidate will
'typically' be produced. In 7.1 this is in reference to a STUN response
received on an active TCP candidate, whereas in 7.2 it is in reference to a
STUN request received on a passive TCP candidate. It is unclear to us
whether the wording is intended to mean that this is different to the
equivalent case in UDP, where a peer-reflexive candidate might, but would
not 'typically', be produced. The only difference between TCP and UDP that
we can see in this area is that the port actually used for active TCP
candidates differs from that advertised, since all active TCP candidates
are offered with 9 as the port number. We assume that this is the core
reason behind the wording used, but think that it would be better if the
specification explicitly stated this. We also believe that it is possible
to correctly identify the correct active TCP candidate despite the lack of
explicit port number information, simply by treating 9 as a wildcard that
matches any port. Doing so has the benefit that all the information held
against the candidate (especially priority and foundation) can be used as
intended, whereas if a new peer-reflexive candidate is created this
information will always be ignored for active TCP candidates. Currently our
implementation does this wildcard matching, so will only produce
peer-reflexive candidates in the same situations it would do if using UDP.

11.1 states that connections should be reopened if they have dropped or
been closed for some reason, and have media that needs to be sent.  This
might make sense in an RTP context, but seems very dubious to us in the
more general TCP case as it violates the normal reliability guarantees that
TCP supplies. We think this requires further thought and at the very least
should be configurable.

Thanks for your time
Nigel Pattinson