Fix: re-publish tracks after re connect (#238)
* fix republish local tracks after reconnect. * update flutter-webrtc. * remove unused import. * add dart_webrtc. * cleanup. * fix: Fix sendSyncState timing error, when reconnecting is sending. * Adjust the re-connect logic to ensure that the publisher negotiates and reconnects correctly. * Update room.dart
This commit is contained in:
@@ -216,18 +216,6 @@ class _ControlsWidgetState extends State<ControlsWidget> {
|
||||
if (result == true) await widget.room.disconnect();
|
||||
}
|
||||
|
||||
void _onTapReconnect() async {
|
||||
final result = await context.showReconnectDialog();
|
||||
if (result == true) {
|
||||
try {
|
||||
await widget.room.reconnect();
|
||||
await context.showReconnectSuccessDialog();
|
||||
} catch (error) {
|
||||
await context.showErrorDialog(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _onTapUpdateSubscribePermission() async {
|
||||
final result = await context.showSubscribePermissionDialog();
|
||||
if (result != null) {
|
||||
@@ -440,11 +428,6 @@ class _ControlsWidgetState extends State<ControlsWidget> {
|
||||
icon: const Icon(EvaIcons.paperPlane),
|
||||
tooltip: 'send demo data',
|
||||
),
|
||||
IconButton(
|
||||
onPressed: _onTapReconnect,
|
||||
icon: const Icon(EvaIcons.refresh),
|
||||
tooltip: 're-connect',
|
||||
),
|
||||
IconButton(
|
||||
onPressed: _onTapUpdateSubscribePermission,
|
||||
icon: const Icon(EvaIcons.settings2),
|
||||
|
||||
@@ -60,6 +60,8 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
|
||||
// this is helpful to know if we need to restart ICE on the publisher connection
|
||||
bool _hasPublished = false;
|
||||
|
||||
bool _restarting = false;
|
||||
|
||||
lk_models.ClientConfiguration? _clientConfiguration;
|
||||
|
||||
// remember url and token for reconnect
|
||||
@@ -548,7 +550,8 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
|
||||
].contains(reason);
|
||||
}
|
||||
|
||||
if (_connectionState == ConnectionState.reconnecting && !fullReconnect) {
|
||||
if (_restarting ||
|
||||
(_connectionState == ConnectionState.reconnecting && !fullReconnect)) {
|
||||
logger.fine('[$objectId] Already reconnecting...');
|
||||
return;
|
||||
}
|
||||
@@ -566,6 +569,7 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
|
||||
}
|
||||
}
|
||||
|
||||
@internal
|
||||
Future<void> resumeConnection() async {
|
||||
if (_connectionState == ConnectionState.disconnected) {
|
||||
logger.fine('resumeConnection: Already closed.');
|
||||
@@ -633,10 +637,15 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
|
||||
}
|
||||
}
|
||||
|
||||
@internal
|
||||
Future<void> restartConnection([bool signalEvents = false]) async {
|
||||
if (_restarting) {
|
||||
logger.fine('restartConnection: Already restarting...');
|
||||
return;
|
||||
}
|
||||
_restarting = true;
|
||||
await publisher?.dispose();
|
||||
publisher = null;
|
||||
_hasPublished = false;
|
||||
|
||||
await subscriber?.dispose();
|
||||
subscriber = null;
|
||||
@@ -646,6 +655,7 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
|
||||
_lossyDCSub = null;
|
||||
_lossyDCPub = null;
|
||||
await _signalListener.cancelAll();
|
||||
await events.cancelAll();
|
||||
_signalListener = signalClient.createListener(synchronized: true);
|
||||
_setUpSignalListeners();
|
||||
|
||||
@@ -657,7 +667,17 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
|
||||
fastConnectOptions: fastConnectOptions,
|
||||
);
|
||||
|
||||
if (_hasPublished) {
|
||||
await negotiate();
|
||||
logger.fine('restartConnection: Waiting for publisher to ice-connect...');
|
||||
await events.waitFor<EnginePublisherPeerStateUpdatedEvent>(
|
||||
filter: (event) => event.state.isConnected(),
|
||||
duration: connectOptions.timeouts.peerConnection,
|
||||
);
|
||||
}
|
||||
|
||||
fullReconnect = false;
|
||||
_restarting = false;
|
||||
}
|
||||
|
||||
@internal
|
||||
@@ -767,6 +787,7 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
|
||||
fullReconnect = true;
|
||||
// reconnect immediately instead of waiting for next attempt
|
||||
_connectionState = ConnectionState.reconnecting;
|
||||
_updateConnectionState(ConnectionState.reconnecting);
|
||||
await handleDisconnect(DisconnectReason.leaveReconnect);
|
||||
} else {
|
||||
if (_connectionState == ConnectionState.reconnecting) {
|
||||
|
||||
+3
-11
@@ -166,7 +166,8 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
|
||||
}
|
||||
|
||||
if (connectOptions.protocolVersion.index >= ProtocolVersion.v8.index &&
|
||||
engine.fastConnectOptions != null) {
|
||||
engine.fastConnectOptions != null &&
|
||||
!engine.fullReconnect) {
|
||||
var options = engine.fastConnectOptions!;
|
||||
|
||||
var audio = options.microphone;
|
||||
@@ -263,7 +264,7 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
|
||||
})
|
||||
..on<SignalConnectionStateUpdatedEvent>((event) {
|
||||
// during reconnection, need to send sync state upon signal connection.
|
||||
if (event.didReconnect) {
|
||||
if (event.newState == ConnectionState.reconnecting) {
|
||||
logger.fine('Sending syncState');
|
||||
_sendSyncState();
|
||||
}
|
||||
@@ -306,11 +307,6 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
|
||||
} 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());
|
||||
@@ -366,10 +362,6 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
|
||||
await _cleanUp();
|
||||
}
|
||||
|
||||
Future<void> reconnect() async {
|
||||
await engine.restartConnection();
|
||||
}
|
||||
|
||||
RemoteParticipant _getOrCreateRemoteParticipant(
|
||||
String sid, lk_models.ParticipantInfo? info) {
|
||||
RemoteParticipant? participant = _participants[sid];
|
||||
|
||||
@@ -37,6 +37,7 @@ class Transport extends Disposable {
|
||||
pc.onRenegotiationNeeded = null;
|
||||
pc.onIceCandidate = null;
|
||||
pc.onConnectionState = null;
|
||||
pc.onIceConnectionState = null;
|
||||
pc.onTrack = null;
|
||||
|
||||
// Remove all senders
|
||||
|
||||
@@ -124,6 +124,7 @@ extension LocalVideoTrackExt on LocalVideoTrack {
|
||||
}
|
||||
|
||||
if (fastSwitch) {
|
||||
currentOptions = options.copyWith(deviceId: deviceId);
|
||||
await rtc.Helper.switchCamera(mediaStreamTrack, deviceId, mediaStream);
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,9 +25,9 @@ dependencies:
|
||||
protobuf: ^2.1.0
|
||||
flutter_webrtc: 0.9.22
|
||||
flutter_window_close: ^0.2.2
|
||||
dart_webrtc: 1.0.15
|
||||
device_info_plus: ^8.0.0
|
||||
webrtc_interface: 1.0.11
|
||||
dart_webrtc: 1.0.15
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user