-
Notifications
You must be signed in to change notification settings - Fork 290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Simplify the sdp sending timeout protocol #4534
Conversation
e81d5ea
to
9a653f1
Compare
I am actually not sure what is the link with AVS? To me, as long as the SDP contains some relay servers, AVS should be happy, am I wrong? |
The link with AVS is that we want to align the behavior as much as possible. The whole calling protocol is timeout driven and clients are supposed to behave the same. You are not wrong in your assumption that the call "should" work. Firefox is just really slow in gathering the ICE candidate routes. It "should" be as fast as Chrome. But it is not and gathers more routes. There is no point in having 15 routes in the SDP. That's why they warn against the use of more than 2 TURN serves and strictly advice against the use of 5 or more TURN servers. The slowness is exactly the reason why we have the 5 second timeout BUT still check that there is a TURN based candidate in the SDP at that point. If we want to change the behavior we will need to align in with AVS in order to not diverge the protocol and client behavior down the line. |
Also, I ran a bunch of tests last week and I discovered that everytime Firefox finds all the candidates very quick (actually as quickly as Chrome or just a bit slower), but just take a looooottt of time confirming that info (sending the the timeline looks like this :
So two things:
|
@thomas But you were always on a decent network. The gathering will and can take much longer in other network conditions. Just tether your computer with a mobile device or similar. We need an approach that suits all environments. That's were the 5 second timeout from AVS on mobile stems from. I fully agree that we can and should decrease it but we have to be clever on checking that the SDP contains not just any TURN candidate but the ones we want it to contain we do not have a subsequent ICE candidate trickling in place. |
9a653f1
to
735dfea
Compare
Bug submitted to Mozilla for the 13 seconds timeout https://bugzilla.mozilla.org/show_bug.cgi?id=1490672 |
d196974
to
5603133
Compare
const logMessage = `No relay ICE candidates in local SDP. Timeout reset\n${iceCandidates}`; | ||
this.callLogger.warn(logMessage, iceCandidates); | ||
return this._setSendSdpTimeout(false); | ||
const MIN_NUMBER_OF_RELAY_SERVERS = 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also move this to the config at the topic at the file
if (!typeMatches) { | ||
return types; | ||
} | ||
const candidateType = typeMatches[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const [, candidateType] = typeMatches;
return types; | ||
} | ||
const candidateType = typeMatches[1]; | ||
types[candidateType] = types[candidateType] ? types[candidateType] + 1 : 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a ternary:
types[candidateType] = types[candidateType] + 1 || 1;
should give you the same result as underfined + 1
is NaN
which is not truthy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok works, but feels a little cryptic...
const iceCandidateTypesLog = Object.keys(iceCandidateTypes) | ||
.map(candidateType => { | ||
return `${iceCandidateTypes[candidateType]} ${candidateType}`; | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Single line?
.map(candidateType => `${iceCandidateTypes[candidateType]} ${candidateType}`)
obfuscated: [ | ||
localSdp.type, | ||
iceCandidates.length, | ||
this.callLogger.obfuscate(this.remoteUser.id), | ||
this.callLogger.obfuscateSdp(this.localSdp().sdp), | ||
], | ||
}, | ||
message: `Sending local '{0}' SDP containing '{1}' ICE candidates for flow with '{2}'\n{3}`, | ||
message: `Sending local '{0}' SDP containing '{1}' ICE candidates ('{2}') for flow with '{3}'\n{4}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's get rid of the '
from within ('{2}')
as it would be a double indication of the expected variable content.
return iceCandidates.reduce((count, iceCandidate) => { | ||
const isRelay = iceCandidate.toLowerCase().includes('relay'); | ||
return isRelay ? count + 1 : count; | ||
}, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need a reduce here or does Array.filter().length
do the trick as well?
return iceCandidates.filter(iceCandidate => iceCandidate.toLowerCase().includes('relay')).length;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very true
this.callLogger.warn(logMessage, iceCandidates); | ||
return this._setSendSdpTimeout(false); | ||
const MIN_NUMBER_OF_RELAY_SERVERS = 2; | ||
if (this._getNumberOfRelayCandidates(iceCandidates) < MIN_NUMBER_OF_RELAY_SERVERS) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also pull this into a const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback to send SDP after 5s no matter what is missing.
3a420ec
to
0e2ce8a
Compare
@@ -500,6 +501,7 @@ z.calling.entities.FlowEntity = class FlowEntity { | |||
_createPeerConnection() { | |||
return this._createPeerConnectionConfiguration().then(pcConfiguration => { | |||
this.peerConnection = new window.RTCPeerConnection(pcConfiguration); | |||
this.iceCandidatesGatheringAttempts = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's reset this to 0 in the reset method and put a default in the constructor.
const hasReachMaxGatheringAttempts = attempts >= FlowEntity.CONFIG.MAX_ICE_CANDIDATE_GATHERING_ATTEMPTS; | ||
if (!hasReachMaxGatheringAttempts && !isValidGathering) { | ||
const logMessage = `Not enough ICE candidates gathered (attempt '${attempts}'). Restarting timeout\n${iceCandidates}`; | ||
this.iceCandidatesGatheringAttempts++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it would send it after 6 seconds and not 5
c8cc238
to
8228a7c
Compare
Single timeout with a lower value
8228a7c
to
93cbfb5
Compare
Previous behavior:
New behavior:
This PR also adds a log with the types of candidates we have gathered