@@ -343,7 +343,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
343
343
// possible
344
344
private candidateSendQueue : Array < RTCIceCandidate > = [ ] ;
345
345
private candidateSendTries = 0 ;
346
- private sentEndOfCandidates = false ;
346
+ private candidatesEnded = false ;
347
347
private feeds : Array < CallFeed > = [ ] ;
348
348
private usermediaSenders : Array < RTCRtpSender > = [ ] ;
349
349
private screensharingSenders : Array < RTCRtpSender > = [ ] ;
@@ -1597,6 +1597,11 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
1597
1597
*/
1598
1598
private gotLocalIceCandidate = ( event : RTCPeerConnectionIceEvent ) : Promise < void > => {
1599
1599
if ( event . candidate ) {
1600
+ if ( this . candidatesEnded ) {
1601
+ logger . warn ( "Got candidate after candidates have ended - ignoring!" ) ;
1602
+ return ;
1603
+ }
1604
+
1600
1605
logger . debug (
1601
1606
"Call " + this . callId + " got local ICE " + event . candidate . sdpMid + " candidate: " +
1602
1607
event . candidate . candidate ,
@@ -1606,29 +1611,18 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
1606
1611
1607
1612
// As with the offer, note we need to make a copy of this object, not
1608
1613
// pass the original: that broke in Chrome ~m43.
1609
- if ( event . candidate . candidate !== '' || ! this . sentEndOfCandidates ) {
1614
+ if ( event . candidate . candidate === '' ) {
1615
+ this . queueCandidate ( null ) ;
1616
+ } else {
1610
1617
this . queueCandidate ( event . candidate ) ;
1611
-
1612
- if ( event . candidate . candidate === '' ) this . sentEndOfCandidates = true ;
1613
1618
}
1614
1619
}
1615
1620
} ;
1616
1621
1617
1622
private onIceGatheringStateChange = ( event : Event ) : void => {
1618
1623
logger . debug ( `Call ${ this . callId } ice gathering state changed to ${ this . peerConn . iceGatheringState } ` ) ;
1619
- if ( this . peerConn . iceGatheringState === 'complete' && ! this . sentEndOfCandidates ) {
1620
- // If we didn't get an empty-string candidate to signal the end of candidates,
1621
- // create one ourselves now gathering has finished.
1622
- // We cast because the interface lists all the properties as required but we
1623
- // only want to send 'candidate'
1624
- // XXX: We probably want to send either sdpMid or sdpMLineIndex, as it's not strictly
1625
- // correct to have a candidate that lacks both of these. We'd have to figure out what
1626
- // previous candidates had been sent with and copy them.
1627
- const c = {
1628
- candidate : '' ,
1629
- } as RTCIceCandidate ;
1630
- this . queueCandidate ( c ) ;
1631
- this . sentEndOfCandidates = true ;
1624
+ if ( this . peerConn . iceGatheringState === 'complete' ) {
1625
+ this . queueCandidate ( null ) ;
1632
1626
}
1633
1627
} ;
1634
1628
@@ -2247,7 +2241,12 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
2247
2241
}
2248
2242
}
2249
2243
2250
- private queueCandidate ( content : RTCIceCandidate ) : void {
2244
+ /**
2245
+ * Queue a candidate to be sent
2246
+ * @param content The candidate to queue up, or null if candidates have finished being generated
2247
+ * and end-of-candidates should be signalled
2248
+ */
2249
+ private queueCandidate ( content : RTCIceCandidate | null ) : void {
2251
2250
// We partially de-trickle candidates by waiting for `delay` before sending them
2252
2251
// amalgamated, in order to avoid sending too many m.call.candidates events and hitting
2253
2252
// rate limits in Matrix.
@@ -2257,7 +2256,11 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
2257
2256
// currently proposes as the way to indicate that candidate gathering is complete.
2258
2257
// This will hopefully be changed to an explicit rather than implicit notification
2259
2258
// shortly.
2260
- this . candidateSendQueue . push ( content ) ;
2259
+ if ( content ) {
2260
+ this . candidateSendQueue . push ( content ) ;
2261
+ } else {
2262
+ this . candidatesEnded = true ;
2263
+ }
2261
2264
2262
2265
// Don't send the ICE candidates yet if the call is in the ringing state: this
2263
2266
// means we tried to pick (ie. started generating candidates) and then failed to
@@ -2446,6 +2449,12 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
2446
2449
this . candidateSendQueue = [ ] ;
2447
2450
++ this . candidateSendTries ;
2448
2451
const content = { candidates : candidates . map ( candidate => candidate . toJSON ( ) ) } ;
2452
+ if ( this . candidatesEnded ) {
2453
+ // If there are no more candidates, signal this by adding an empty string candidate
2454
+ content . candidates . push ( {
2455
+ candidate : '' ,
2456
+ } ) ;
2457
+ }
2449
2458
logger . debug ( `Call ${ this . callId } attempting to send ${ candidates . length } candidates` ) ;
2450
2459
try {
2451
2460
await this . sendVoipEvent ( EventType . CallCandidates , content ) ;
0 commit comments