Skip to content

Commit

Permalink
Handle signal disconnect during reconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasIO committed Jan 16, 2024
1 parent 7ff06f7 commit 4e24145
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 8 deletions.
6 changes: 5 additions & 1 deletion src/api/SignalClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,11 @@ export class SignalClient {
reject(new ConnectionError('Websocket got closed during a (re)connection attempt'));
}

this.log.warn(`websocket closed`, { ...this.logContext, reason: ev.reason });
this.log.warn(`websocket closed`, {
...this.logContext,
reason: ev.reason,
state: this.state,
});
this.handleOnClose(ev.reason);
};
} finally {
Expand Down
9 changes: 9 additions & 0 deletions src/proto/livekit_rtc_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2084,6 +2084,14 @@ export class SimulateScenario extends Message<SimulateScenario> {
*/
value: bigint;
case: "subscriberBandwidth";
} | {
/**
* disconnect signal on resume
*
* @generated from field: bool disconnect_signal_on_resume = 7;
*/
value: boolean;
case: "disconnectSignalOnResume";
} | { case: undefined; value?: undefined } = { case: undefined };

constructor(data?: PartialMessage<SimulateScenario>) {
Expand All @@ -2100,6 +2108,7 @@ export class SimulateScenario extends Message<SimulateScenario> {
{ no: 4, name: "server_leave", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "scenario" },
{ no: 5, name: "switch_candidate_protocol", kind: "enum", T: proto3.getEnumType(CandidateProtocol), oneof: "scenario" },
{ no: 6, name: "subscriber_bandwidth", kind: "scalar", T: 3 /* ScalarType.INT64 */, oneof: "scenario" },
{ no: 7, name: "disconnect_signal_on_resume", kind: "scalar", T: 8 /* ScalarType.BOOL */, oneof: "scenario" },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): SimulateScenario {
Expand Down
13 changes: 13 additions & 0 deletions src/room/RTCEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
}
// guard for attempting reconnection multiple times while one attempt is still not finished
if (this.attemptingReconnect) {
log.warn('already attempting reconnect, returning early', this.logContext);
return;
}
if (
Expand Down Expand Up @@ -948,6 +949,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
this.emit(EngineEvent.SignalRestarted, joinResponse);

await this.waitForPCReconnected();

// re-check signal connection state before setting engine as resumed
if (this.client.currentState !== SignalConnectionState.CONNECTED) {
throw new SignalReconnectError('Signal connection got severed during reconnect');
}

this.regionUrlProvider?.resetAttempts();
// reconnect success
this.emit(EngineEvent.Restarted);
Expand Down Expand Up @@ -1005,6 +1012,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
await this.pcManager.triggerIceRestart();

await this.waitForPCReconnected();

// re-check signal connection state before setting engine as resumed
if (this.client.currentState !== SignalConnectionState.CONNECTED) {
throw new SignalReconnectError('Signal connection got severed during reconnect');
}

this.client.setReconnected();

// recreate publish datachannel if it's id is null
Expand Down
28 changes: 22 additions & 6 deletions src/room/Room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,10 +788,21 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
// @ts-expect-error function is private
await this.engine.client.handleOnClose('simulate resume-disconnect');
break;
case 'disconnect-signal-on-resume':
postAction = async () => {
// @ts-expect-error function is private
await this.engine.client.handleOnClose('simulate resume-disconnect');
};
req = new SimulateScenario({
scenario: {
case: 'disconnectSignalOnResume',
value: true,
},
});
break;
case 'full-reconnect':
this.engine.fullReconnectOnNext = true;
// @ts-expect-error function is private
await this.engine.client.handleOnClose('simulate full-reconnect');

break;
case 'force-tcp':
case 'force-tls':
Expand Down Expand Up @@ -824,11 +835,12 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
},
});
break;

default:
}
if (req) {
this.engine.client.sendSimulateScenario(req);
postAction();
await this.engine.client.sendSimulateScenario(req);
await postAction();
}
}

Expand Down Expand Up @@ -1669,6 +1681,10 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
this.log.warn('detected connection state mismatch', {
...this.logContext,
numFailures: consecutiveFailures,
engine: {
closed: this.engine.isClosed,
transportsConnected: this.engine.verifyTransport(),
},
});
if (consecutiveFailures >= 3) {
this.recreateEngine();
Expand Down Expand Up @@ -1820,7 +1836,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
await window.navigator.mediaDevices.getUserMedia({ video: true })
).getVideoTracks()[0]
: createDummyVideoStreamTrack(
160 * participantOptions.aspectRatios[0] ?? 1,
160 * (participantOptions.aspectRatios[0] ?? 1),
160,
true,
true,
Expand Down Expand Up @@ -1870,7 +1886,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
const p = this.getOrCreateParticipant(info.identity, info);
if (participantOptions.video) {
const dummyVideo = createDummyVideoStreamTrack(
160 * participantOptions.aspectRatios[i % participantOptions.aspectRatios.length] ?? 1,
160 * (participantOptions.aspectRatios[i % participantOptions.aspectRatios.length] ?? 1),
160,
false,
true,
Expand Down
3 changes: 2 additions & 1 deletion src/room/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export type SimulationScenario =
// overrides server-side bandwidth estimator with set bandwidth
// this can be used to test application behavior when congested or
// to disable congestion control entirely (by setting bandwidth to 100Mbps)
| 'subscriber-bandwidth';
| 'subscriber-bandwidth'
| 'disconnect-signal-on-resume';

export type LoggerOptions = {
loggerName?: string;
Expand Down

0 comments on commit 4e24145

Please sign in to comment.