From c74e6777d8ef4c1c83a50c315a5b5eec3f2d10b6 Mon Sep 17 00:00:00 2001 From: CloudWebRTC Date: Tue, 7 Mar 2023 17:54:18 +0800 Subject: [PATCH] feat: Forward leave reason of disconnected events. (#250) * feat: Forward leave reason of disconnected events. * fix analyze. * chore: print room disconnect reason when event.reason != null. * chore: rename InternalDisconnectReason => ClientDisconnectReason. --- example/lib/pages/room.dart | 5 ++++- lib/src/core/engine.dart | 26 +++++++++++++++----------- lib/src/core/room.dart | 2 +- lib/src/core/signal_client.dart | 3 ++- lib/src/events.dart | 7 +++++-- lib/src/extensions.dart | 18 ++++++++++++++++++ lib/src/internal/events.dart | 2 ++ lib/src/types/internal.dart | 11 +++++++++++ lib/src/types/other.dart | 14 ++++++++------ 9 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 lib/src/types/internal.dart diff --git a/example/lib/pages/room.dart b/example/lib/pages/room.dart index 74dfca3..93e8d48 100644 --- a/example/lib/pages/room.dart +++ b/example/lib/pages/room.dart @@ -54,7 +54,10 @@ class _RoomPageState extends State { } void _setUpListeners() => _listener - ..on((_) async { + ..on((event) async { + if (event.reason != null) { + print('Room disconnected: reason => ${event.reason}'); + } WidgetsBindingCompatible.instance ?.addPostFrameCallback((timeStamp) => Navigator.pop(context)); }) diff --git a/lib/src/core/engine.dart b/lib/src/core/engine.dart index 5290885..fb0fa2b 100644 --- a/lib/src/core/engine.dart +++ b/lib/src/core/engine.dart @@ -18,6 +18,7 @@ import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_rtc.pb.dart' as lk_rtc; import '../support/disposable.dart'; import '../support/websocket.dart'; +import '../types/internal.dart'; import '../types/other.dart'; import '../types/video_dimensions.dart'; import '../utils.dart'; @@ -220,7 +221,7 @@ class Engine extends Disposable with EventsEmittable { if (error is NegotiationError) { fullReconnect = true; } - await handleDisconnect(DisconnectReason.negotiationFailed); + await handleDisconnect(ClientDisconnectReason.negotiationFailed); } } @@ -370,9 +371,9 @@ class Engine extends Disposable with EventsEmittable { events.on((event) { if (event.state.isDisconnectedOrFailed()) { - handleDisconnect(DisconnectReason.reconnect); + handleDisconnect(ClientDisconnectReason.reconnect); } else if (event.state.isClosed()) { - handleDisconnect(DisconnectReason.peerConnectionClosed); + handleDisconnect(ClientDisconnectReason.peerConnectionClosed); } }); @@ -536,7 +537,7 @@ class Engine extends Disposable with EventsEmittable { } } - Future handleDisconnect(DisconnectReason reason) async { + Future handleDisconnect(ClientDisconnectReason reason) async { logger .info('onDisconnected state:${_connectionState} reason:${reason.name}'); @@ -544,9 +545,9 @@ class Engine extends Disposable with EventsEmittable { fullReconnect = _clientConfiguration?.resumeConnection == lk_models.ClientConfigSetting.DISABLED || [ - DisconnectReason.leaveReconnect, - DisconnectReason.negotiationFailed, - DisconnectReason.peerConnectionClosed + ClientDisconnectReason.leaveReconnect, + ClientDisconnectReason.negotiationFailed, + ClientDisconnectReason.peerConnectionClosed ].contains(reason); } @@ -732,7 +733,7 @@ class Engine extends Disposable with EventsEmittable { }) ..on((event) async { if (event.newState == ConnectionState.disconnected) { - await handleDisconnect(DisconnectReason.signal); + await handleDisconnect(ClientDisconnectReason.signal); } }) ..on((event) async { @@ -788,14 +789,15 @@ class Engine extends Disposable with EventsEmittable { // reconnect immediately instead of waiting for next attempt _connectionState = ConnectionState.reconnecting; _updateConnectionState(ConnectionState.reconnecting); - await handleDisconnect(DisconnectReason.leaveReconnect); + await handleDisconnect(ClientDisconnectReason.leaveReconnect); } else { if (_connectionState == ConnectionState.reconnecting) { logger.warning( '[Signal] Received Leave while engine is reconnecting, ignoring...'); return; } - _updateConnectionState(ConnectionState.disconnected); + _updateConnectionState(ConnectionState.disconnected, + reason: event.reason.toSDKType()); await cleanUp(); } }); @@ -811,7 +813,8 @@ extension EnginePrivateMethods on Engine { _publisherDataChannel(reliability)?.state ?? rtc.RTCDataChannelState.RTCDataChannelClosed; - void _updateConnectionState(ConnectionState newValue) { + void _updateConnectionState(ConnectionState newValue, + {DisconnectReason? reason}) { if (_connectionState == newValue) return; logger.fine('Engine ConnectionState ' @@ -828,6 +831,7 @@ extension EnginePrivateMethods on Engine { oldState: oldState, didReconnect: didReconnect, fullReconnect: fullReconnect, + disconnectReason: reason, )); } } diff --git a/lib/src/core/room.dart b/lib/src/core/room.dart index f35dcae..ca731c6 100644 --- a/lib/src/core/room.dart +++ b/lib/src/core/room.dart @@ -314,7 +314,7 @@ class Room extends DisposableChangeNotifier with EventsEmittable { } else if (event.newState == ConnectionState.disconnected) { if (!event.fullReconnect) { await _cleanUp(); - events.emit(const RoomDisconnectedEvent()); + events.emit(RoomDisconnectedEvent(reason: event.disconnectReason)); } } // always notify ChangeNotifier diff --git a/lib/src/core/signal_client.dart b/lib/src/core/signal_client.dart index cdef44a..714fb0f 100644 --- a/lib/src/core/signal_client.dart +++ b/lib/src/core/signal_client.dart @@ -210,7 +210,8 @@ class SignalClient extends Disposable with EventsEmittable { )); break; case lk_rtc.SignalResponse_Message.leave: - events.emit(SignalLeaveEvent(canReconnect: msg.leave.canReconnect)); + events.emit(SignalLeaveEvent( + canReconnect: msg.leave.canReconnect, reason: msg.leave.reason)); break; case lk_rtc.SignalResponse_Message.mute: events.emit(SignalRemoteMuteTrackEvent( diff --git a/lib/src/events.dart b/lib/src/events.dart index 3eb7a8f..cf76d87 100644 --- a/lib/src/events.dart +++ b/lib/src/events.dart @@ -65,10 +65,13 @@ class RoomRestartedEvent with RoomEvent { /// Disconnected from the room /// Emitted by [Room]. class RoomDisconnectedEvent with RoomEvent { - const RoomDisconnectedEvent(); + DisconnectReason? reason; + RoomDisconnectedEvent({ + this.reason, + }); @override - String toString() => '${runtimeType}()'; + String toString() => '${runtimeType}($reason)'; } /// Room metadata has changed. diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index a3dce7a..68c62c0 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -170,3 +170,21 @@ extension WidgetsBindingCompatible on WidgetsBinding { // always return optional type for compatibility with flutter v2 and v3 static WidgetsBinding? get instance => WidgetsBinding.instance; } + +extension DisconnectReasonExt on lk_models.DisconnectReason { + DisconnectReason toSDKType() => { + lk_models.DisconnectReason.UNKNOWN_REASON: DisconnectReason.unknown, + lk_models.DisconnectReason.CLIENT_INITIATED: + DisconnectReason.clientInitiated, + lk_models.DisconnectReason.DUPLICATE_IDENTITY: + DisconnectReason.duplicateIdentity, + lk_models.DisconnectReason.SERVER_SHUTDOWN: + DisconnectReason.serverShutdown, + lk_models.DisconnectReason.PARTICIPANT_REMOVED: + DisconnectReason.participantRemoved, + lk_models.DisconnectReason.ROOM_DELETED: DisconnectReason.roomDeleted, + lk_models.DisconnectReason.STATE_MISMATCH: + DisconnectReason.stateMismatch, + lk_models.DisconnectReason.JOIN_FAILURE: DisconnectReason.joinFailure, + }[this]!; +} diff --git a/lib/src/internal/events.dart b/lib/src/internal/events.dart index 615497a..b64b4e5 100644 --- a/lib/src/internal/events.dart +++ b/lib/src/internal/events.dart @@ -247,8 +247,10 @@ class EngineActiveSpeakersUpdateEvent with EngineEvent, InternalEvent { @internal class SignalLeaveEvent with SignalEvent, InternalEvent { final bool canReconnect; + final lk_models.DisconnectReason reason; const SignalLeaveEvent({ required this.canReconnect, + required this.reason, }); } diff --git a/lib/src/types/internal.dart b/lib/src/types/internal.dart new file mode 100644 index 0000000..273c905 --- /dev/null +++ b/lib/src/types/internal.dart @@ -0,0 +1,11 @@ +import 'package:meta/meta.dart'; + +@internal +enum ClientDisconnectReason { + user, + peerConnectionClosed, + negotiationFailed, + signal, + reconnect, + leaveReconnect, +} diff --git a/lib/src/types/other.dart b/lib/src/types/other.dart index 8af1a35..7f5636e 100644 --- a/lib/src/types/other.dart +++ b/lib/src/types/other.dart @@ -61,12 +61,14 @@ enum StreamState { } enum DisconnectReason { - user, - peerConnectionClosed, - negotiationFailed, - signal, - reconnect, - leaveReconnect, + unknown, + clientInitiated, + duplicateIdentity, + serverShutdown, + participantRemoved, + roomDeleted, + stateMismatch, + joinFailure, } /// The reason why a track failed to publish.