e2e: fix resume/full-reconnect. (#194)

* fix: full re-connect.

* chore: Reset fullReConnect state after ConnectionState is emitted.

* Support full reconnect, fix Migration, NodeFailure, FullReconnect test cases.

* revert Timeouts.connection.

* update.

* Refactor the resume/reconnect implementation.

* more changes.

* update.

* Changed to simpler reconnect/recovery logic.

* update.

* update.

* code format.

* tidy.

* bump version for flutter-webrtc.

* chore: Remove unused exception class (SignalReconnectError).

* chore: rename `fullReconnectOnNext` to `fullReconnect`.

* update.

* chore: Revert changes for `unpublishTrack`.

* chore: Reconnect signalClient when resumeConnection.

* revert `rethrow` in engine.connect.

* Use removePublishedTrack instead of unpublishTrack (RemoteParticipant).

* chore: Correctly handle PeerConnectionState for resume/full-reconnect.

* tidy.
This commit is contained in:
CloudWebRTC
2022-11-08 16:06:09 +08:00
committed by GitHub
parent 9b0f0604e1
commit 0d8441ebfb
17 changed files with 300 additions and 144 deletions
+56 -20
View File
@@ -74,7 +74,7 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
// suppport for multiple event listeners
late final EventsListener<EngineEvent> _engineListener;
//
late final EventsListener<SignalEvent> _signalListener;
late EventsListener<SignalEvent> _signalListener;
Room({
ConnectOptions connectOptions = const ConnectOptions(),
@@ -140,11 +140,15 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
logger.fine('[Engine] Received JoinResponse, '
'serverVersion: ${event.response.serverVersion}');
_localParticipant = LocalParticipant(
_localParticipant ??= LocalParticipant(
room: this,
info: event.response.participant,
);
if (engine.fullReconnect) {
_localParticipant!.updateFromInfo(event.response.participant);
}
if (connectOptions.protocolVersion.index >= ProtocolVersion.v8.index &&
engine.fastConnectOptions != null) {
var options = engine.fastConnectOptions!;
@@ -264,19 +268,47 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
void _setUpEngineListeners() => _engineListener
..on<EngineConnectionStateUpdatedEvent>((event) async {
if (event.didReconnect) {
events.emit(const RoomReconnectedEvent());
// re-send tracks permissions
localParticipant?.sendTrackSubscriptionPermissions();
events.emit(const RoomReconnectedEvent());
await _handlePostReconnect(false);
} else if (event.fullReconnect &&
event.newState == ConnectionState.connecting) {
events.emit(const RoomRestartingEvent());
// clean up RemoteParticipants
for (final participant in _participants.values) {
events.emit(ParticipantDisconnectedEvent(participant: participant));
await participant.dispose();
}
_participants.clear();
_activeSpeakers.clear();
// reset params
_name = null;
_sid = null;
_metadata = null;
_serverVersion = null;
_serverRegion = null;
} else if (event.fullReconnect &&
event.newState == ConnectionState.connected) {
events.emit(const RoomRestartedEvent());
// recreate signal listener.
await _signalListener.cancelAll();
await _signalListener.dispose();
_signalListener = engine.signalClient.createListener();
_setUpSignalListeners();
await _handlePostReconnect(event.fullReconnect);
} else if (event.newState == ConnectionState.reconnecting) {
events.emit(const RoomReconnectingEvent());
} else if (event.newState == ConnectionState.disconnected) {
await _cleanUp();
events.emit(const RoomDisconnectedEvent());
if (!event.fullReconnect) {
await _cleanUp();
events.emit(const RoomDisconnectedEvent());
}
}
// always notify ChangeNotifier
notifyListeners();
})
..on<RoomRestartingEvent>((event) {})
..on<RoomRestartedEvent>((event) {})
..on<EngineActiveSpeakersUpdateEvent>(
(event) => _onEngineActiveSpeakersUpdateEvent(event.speakers))
..on<EngineDataPacketReceivedEvent>(_onDataMessageEvent)
@@ -319,7 +351,7 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
}
Future<void> reconnect() async {
await engine.reconnect();
await engine.restartConnection();
}
RemoteParticipant _getOrCreateRemoteParticipant(
@@ -528,13 +560,13 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
Future<void> _handlePostReconnect(bool isFullReconnect) async {
if (isFullReconnect) {
// TODO republish tracks on full reconnect
} else {
for (var participant in participants.values) {
for (var pub in participant.trackPublications.values) {
if (pub.subscribed) {
pub.sendUpdateTrackSettings();
}
// re-publish all tracks
await localParticipant?.rePublishAllTracks();
}
for (var participant in participants.values) {
for (var pub in participant.trackPublications.values) {
if (pub.subscribed) {
pub.sendUpdateTrackSettings();
}
}
}
@@ -585,13 +617,17 @@ extension RoomDebugMethods on Room {
bool? migration,
bool? serverLeave,
bool? switchCandidate,
bool? signalReconnect,
}) async {
if (signalReconnect != null && signalReconnect) {
await engine.signalClient.cleanUp();
return;
}
engine.signalClient.sendSimulateScenario(
speakerUpdate: speakerUpdate,
nodeFailure: nodeFailure,
migration: migration,
serverLeave: serverLeave,
switchCandidate: switchCandidate,
);
speakerUpdate: speakerUpdate,
nodeFailure: nodeFailure,
migration: migration,
serverLeave: serverLeave,
switchCandidate: switchCandidate);
}
}