Re: Issue 170: Response to connectivity checks prior to calling iceTransport.start()?

Robin said:

"@pthatcher<https://github.com/pthatcher> proposed on the last CG to add a factory method like RTCIceTransport.createOrObtainExistingTransport(remoteUFrag) to solve the race that can happen when an ice transport is auto-filled at the same moment when an ice transport is being assigned a remote ufrag/password."

[BA] I am trying to piece together the various suggestions.  As I recall, there was an "onunhandledcheck" Event handler to be added the IceGatherer, which could provide information about an incoming connectivity check.   There was also a potential "earlyStart" method for the IceTransport which could be called to allow an IceTransport to respond to such an incoming check (and presumably to also set the IceTransport role).

Is that correct?

Based on the above, I believe the missing piece is to deal with the possibility that the ICE remoteParameters signaled to the local peer were consistent with the connectivity check (e.g.  connectivity check could indicate "controlling" when the signaling indicates that the remote peer is actually "controlled").  I guess there is also the possibility that an incoming connectivity check could come in *while* iceTransport.start() is being executed.

Is this generally where we are going or is it totally off the mark?

Some potential example code:

// Example to demonstrate forking when RTP and RTCP are not multiplexed,
// so that both RTP and RTCP IceGatherer and IceTransport objects are needed.
// Create ICE gather options
var gatherOptions = new RTCIceGatherOptions();
gatherOptions.gatherPolicy = RTCIceGatherPolicy.relay;
gatherOptions.iceservers = ... ;
// Create ICE gatherer objects
var iceRtpGatherer = new RTCIceGatherer(gatherOptions);
var iceRtcpGatherer = iceRtpGatherer.createAssociatedGatherer();
// Create the ICE RTP and RTCP transports
var iceRtpTransport = new RTCIceTransport(iceRtpGatherer);
var iceRtcpTransport = iceRtpTransport.createAssociatedTransport();
// Prepare to handle incoming connectivity checks
iceRtpGatherer.onunhandledcheck = function (event){iceRtpTransport.earlyStart(iceRtpGatherer,event.remoteUfrag,event.remoteRole);};
iceRtcpGatherer.onunhandledcheck = function (event) {iceRtcpTransport.earlyStart(iceRtcpGatherer,event.remoteUfrag,event.remoteRole);};
// Prepare to signal local candidates
iceRtpGatherer.onlocalcandidate = function (event) {mySendLocalCandidate(RTCIceComponent.RTP, event.candidate)};
iceRtcpGatherer.onlocalcandidate = function (event) {mySendLocalCandidate(RTCIceComponent.RTCP, event.candidate)};

mySendInitiate({
"icertp": iceRtpGatherer.getLocalParameters(),
"icertcp": iceRtcpGatherer.getLocalParameters()
},
function(response) {
// Assume we are only getting a single response...
// Create the ICE Transport Controller object and add the RTP Ice Transport to it
var controller = new RTCIceTransportController();
controller.addTransport(iceRtpTransport);
// It is possible that the RTP and/or RTCP ICE transports were "early started" so do not call start if
// the role is already set.
if (!iceRtpTransport.role) {iceRtpTransport.start(iceRtpGatherer, response.icertp, RTCIceRole.controlling);};
if (!iceRtcpTransport.role){iceRtcpTransport.start(iceRtcpGatherer, response.icertcp, RTCIceRole.controlling);};
// Prepare to add ICE candidates signalled by the remote peer
mySignaller.onRemoteCandidate = function(remote) {
if (remote.component == RTCIceComponent.RTP){
iceRtpTransport.addRemoteCandidate(remote.candidate);
} else {
iceRtcpTransport.addRemoteCandidate(remote.candidate);
};
}

// ... setup DTLS, RTP, SCTP, etc.
});

function mySendLocalCandidate(component, candidate){
mySignaller.mySendLocalCandidate({
"candidate": candidate,
"component": component
});
}









On April 29, Robin said:


The only solution to this is to associate an RTPIceGatherer to an RTCIceTransport prior to calling start which would mean incoming non-associated remote username fragment could become auto-attached to the RTCIceTransport prior to calling start.

To know this association has happened, we would need an event on the RTCIceGatherer to know about the incoming remote username fragment. We would also need an attribute RTCIceTransport.usernameFragment on the transport to indicate that attribute got filled and the RTCIceTransport.role would need to contain the correct role as determine by the incoming connectivity check (which could not be overridden by the RTCIceTransport.start() method.

This allows incoming connectivity checks to be responded to immediate if an RTCIceTransport has been attached to the RTCIceGatherer without RTCIceTransport.start() having been called.

If no RTCIceTransport is attached then we need to event about the new remoteUsernameFragment from the RTCIceGatherer as we already do and buffer the incoming connectivity check until a new RTCIceTransport has been attached to the RTCIceGatherer [to become auto-attached post connectivity check] or RTCIceTransport.start is called with the usernameFragement on a non-associated RTCIceTransport with that remote username fragment specified in the RTCIceTransport.start() method.

Received on Tuesday, 2 June 2015 22:06:27 UTC