Pion incorrectly resets the consent timer when sending any traffic.
The consent timer must only be reset on STUN traffic.
RFC 7675
> Consent expires after 30 seconds. That is, if a valid STUN binding
> response has not been received from the remote peer's transport
> address in 30 seconds, the endpoint MUST cease transmission on that
> 5-tuple. STUN consent responses received after consent expiry do not
> re-establish consent and may be discarded or cause an ICMP error.
There could be a mismatch between the two ends in candidate priority
when using peer reflexive. It happens in the following scenario
1. Client has two srflx candidates.
a. The first one gets discovered by LiveKit server as prflx.
b. The second one gets added via ice-trickle first and then
gets a STUN ping. So, it is srflx remote candidate from
server's point-of-view.
2. This leads to a priority issue.
a. Both candidates have same priority from client's point-of-view
(both are srflx).
b. But, from server's point-of-view, the first candidate has
higher priority (prflx).
3. The first candidate establishes connectivity and becomes
the selected pair (client is ICE controlling and server is
ICE controlled, server is in ICE lite).
4. libwebrtc does a sort and switch some time later based on RTT.
As client side has both at same priority, RTT based sorting
could make the second candidate the preferred one.
So, the client sends useCandidate=1 for the second candidate.
pion/ice does not switch because the selected pair is at
higher priority due to prflx candidate.
5. STUN pings do not happen and the ICE connection eventually fails.
ICE controlled agent should accept use-candidate unconditionally if
it is an ICE lite agentt.
Just in case existing behaviour is needed, it can be configured
using `EnableUseCandidateCheckPriority`.
NOTE: With aggressive nomination, the selected pair could change
a few times, but should eventually settle on what the controlling
side wants.
* Add round trip time measurement to candidate pair
Use the round trip time measurement to populate RTT fields in
CandidatePairStats.
Atomic and tests
* Use int64 nanosecnods to make atomic easier
Allow the user to perform custom processing for inbound STUN Binding
requests. This allows users to do some of the following
* Log incoming Binding Requests for debugging
* Implement draft-thatcher-ice-renomination
* Implement custom CandidatePair switching logic
Resolves pion/webrtc#2539
Resolves pion/webrtc#2585
Resolves#623
Deliver Candidates and Selected CandidatePairs using the same queue.
This means that things are delivered in order and we don't have to worry
about blocking
Before we launched a goroutine to announce every ConnectionState change
to users. These could then be sent to the user out of order.
This commit adds a connectionStateNotifier. The connectionStateNotifier
delivers them sequentially to the user.
Resolves#624
* Trace log inbound messages
On an ICE restart in controlled mode, seeing incoming messages
getting discarded to due to username mismatch. That is because the
broswer is still using its old candidate and user name. As the
controlled agent waits for `useCandidate` from the controlling agent,
the controlled agent does not get to connected/nominated state inspite
of getting several success responses. Suspect the controlling side does
not have `useCandidate` for the new pair and it is still sending it for
the old pair. Logging more details in trace to understand it better.
* Fix test
When ICE times out and fails, all candidates are deleted.
That means all the candidates are closed and their underlying
conns are clsoed.
But, the selected pair could still be valid. On a subsequenct
`Write`, ICE transport conn will get the selected pair and
write to the pair. As the pair is still valid, write will
flow through to the local candidate `writeTo`.
But, as all candidates and their underlying conns are closed,
`Write` will return a `io.ErrClosedPipe` error.
There are cases where it is not ignored and causes a broken
pipe after an ICERestart.
When the `Write` error propagates back to sctp/association,
the writeLoop is exited.
So, sending data channel traffic after a successful ICERestart
still fails as the SCTP association errored out and write loop exited.
I have copied the changes that are done when ICERestart happens
to when ICE state is set to failed (except for gathering state
and resetting ufrag/pwd). In my testing, it is working well,
i. e. can continue data channel after ICE Restart whereas
previously it was failing every time. But, I am not sure of all
the implications of this change.
Update authors
Update AUTHORS.txt
This is analogue to GetLocalCandidates() and provides
the user with the ability to get a slice of previously added
remote candidates without keeping track of them in the
application code.
By default TCP candidate type priority is UDP one minus 27 (except
relay), so that UDP+srlfx priority > TCP+host priority. That priority
offset can be configured using AgentConfig.
IPv6 TCP candidates are also supported.