Skip to content

Commit d81f476

Browse files
authored
fix(llc): fix for anonymous user joining the call (#827)
* fix for anonymous user joining the call * wip * fix(llc): fixed enabling/disabling cloned tracks (#828) * fixed cloned track disabling/enabling * tweak
1 parent 2fd8ccc commit d81f476

File tree

10 files changed

+219
-82
lines changed

10 files changed

+219
-82
lines changed

packages/stream_video/lib/src/call/call.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,8 @@ class Call {
970970
_logger.v(() => '[startSession] applying connect options');
971971
await _applyConnectOptions();
972972
},
973+
isAnonymousUser:
974+
_streamVideo.state.currentUser.type == UserType.anonymous,
973975
);
974976

975977
_subscriptions.add(

packages/stream_video/lib/src/call/session/call_session.dart

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,13 @@ class CallSession extends Disposable {
221221
})>> start({
222222
sfu_events.ReconnectDetails? reconnectDetails,
223223
FutureOr<void> Function(RtcManager)? onRtcManagerCreatedCallback,
224+
bool isAnonymousUser = false,
224225
}) async {
225226
try {
226-
_logger.d(() => '[start] no args');
227+
_logger.d(
228+
() => '[start] reconnectDetails: $reconnectDetails, '
229+
'isAnonymousUser: $isAnonymousUser',
230+
);
227231

228232
await _ensureClientDetails();
229233

@@ -304,25 +308,35 @@ class CallSession extends Disposable {
304308
);
305309

306310
_logger.v(() => '[start] sfu joined: $event');
307-
final currentUserId = stateManager.callState.currentUserId;
308-
final localParticipant = event.callState.participants.firstWhere(
309-
(it) => it.userId == currentUserId,
310-
);
311-
final localTrackId = localParticipant.trackLookupPrefix;
312-
313-
_logger.v(() => '[start] localTrackId: $localTrackId');
314-
rtcManager = await rtcManagerFactory.makeRtcManager(
315-
publisherId: localTrackId,
316-
publishOptions: event.publishOptions,
317-
)
318-
..onPublisherIceCandidate = _onLocalIceCandidate
319-
..onSubscriberIceCandidate = _onLocalIceCandidate
320-
..onPublisherIssue = onPeerConnectionIssue
321-
..onSubscriberIssue = onPeerConnectionIssue
322-
..onLocalTrackMuted = _onLocalTrackMuted
323-
..onLocalTrackPublished = _onLocalTrackPublished
324-
..onRenegotiationNeeded = _onRenegotiationNeeded
325-
..onRemoteTrackReceived = _onRemoteTrackReceived;
311+
312+
if (isAnonymousUser) {
313+
rtcManager = await rtcManagerFactory.makeRtcManager()
314+
..onSubscriberIceCandidate = _onLocalIceCandidate
315+
..onSubscriberIssue = onPeerConnectionIssue
316+
..onRenegotiationNeeded = _onRenegotiationNeeded
317+
..onRemoteTrackReceived = _onRemoteTrackReceived;
318+
} else {
319+
final currentUserId = stateManager.callState.currentUserId;
320+
final localParticipant = event.callState.participants.firstWhere(
321+
(it) => it.userId == currentUserId,
322+
);
323+
final localTrackId = localParticipant.trackLookupPrefix;
324+
325+
_logger.v(() => '[start] localTrackId: $localTrackId');
326+
327+
rtcManager = await rtcManagerFactory.makeRtcManager(
328+
publisherId: localTrackId,
329+
publishOptions: event.publishOptions,
330+
)
331+
..onPublisherIceCandidate = _onLocalIceCandidate
332+
..onSubscriberIceCandidate = _onLocalIceCandidate
333+
..onPublisherIssue = onPeerConnectionIssue
334+
..onSubscriberIssue = onPeerConnectionIssue
335+
..onLocalTrackMuted = _onLocalTrackMuted
336+
..onLocalTrackPublished = _onLocalTrackPublished
337+
..onRenegotiationNeeded = _onRenegotiationNeeded
338+
..onRemoteTrackReceived = _onRemoteTrackReceived;
339+
}
326340

327341
await onRtcManagerCreatedCallback?.call(rtcManager!);
328342
_rtcManagerSubject!.add(rtcManager!);
@@ -404,13 +418,13 @@ class CallSession extends Disposable {
404418
'[fastReconnect] fast-reconnect possible - requesting ICE restarts',
405419
);
406420

407-
await rtcManager?.publisher.pc.restartIce();
421+
await rtcManager?.publisher?.pc.restartIce();
408422

409423
final remoteTracks =
410424
rtcManager!.tracks.values.whereType<RtcRemoteTrack>().toList();
411425

412426
for (final track in remoteTracks) {
413-
await _onRemoteTrackReceived(rtcManager!.publisher, track);
427+
await _onRemoteTrackReceived(rtcManager!.subscriber, track);
414428
}
415429

416430
_logger.d(() => '[fastReconnect] completed');

packages/stream_video/lib/src/call/sfu_stats_reporter.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class SfuStatsReporter {
6666
SfuReconnectionStrategy? reconnectionStrategy,
6767
}) async {
6868
final publisherStatsBundle =
69-
await callSession.rtcManager?.publisher.getStats();
69+
await callSession.rtcManager?.publisher?.getStats();
7070
final subscriberStatsBundle =
7171
await callSession.rtcManager?.subscriber.getStats();
7272

packages/stream_video/lib/src/call/stats_reporter.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import '../webrtc/model/stats/rtc_codec.dart';
77
import '../webrtc/model/stats/rtc_ice_candidate_pair.dart';
88
import '../webrtc/model/stats/rtc_inbound_rtp_video_stream.dart';
99
import '../webrtc/model/stats/rtc_outbound_rtp_video_stream.dart';
10+
import '../webrtc/model/stats/rtc_printable_stats.dart';
1011
import '../webrtc/peer_type.dart';
1112
import '../webrtc/rtc_manager.dart';
1213
import 'state/call_state_notifier.dart';
@@ -33,14 +34,15 @@ class StatsReporter {
3334

3435
Future<({CallStats publisherStats, CallStats subscriberStats})>
3536
collectStats() async {
36-
final publisherStatsBundle = await rtcManager.publisher.getStats();
37+
final publisherStatsBundle = await rtcManager.publisher?.getStats();
3738
final subscriberStatsBundle = await rtcManager.subscriber.getStats();
3839

3940
final publisherStats = CallStats(
4041
peerType: StreamPeerType.publisher,
41-
stats: publisherStatsBundle.rtcStats,
42-
printable: publisherStatsBundle.printable,
43-
raw: publisherStatsBundle.rawStats,
42+
stats: publisherStatsBundle?.rtcStats ?? [],
43+
printable: publisherStatsBundle?.printable ??
44+
const RtcPrintableStats(local: '', remote: ''),
45+
raw: publisherStatsBundle?.rawStats ?? [],
4446
);
4547

4648
final subscriberStats = CallStats(

packages/stream_video/lib/src/coordinator/open_api/coordinator_client_open_api.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class CoordinatorClientOpenApi extends CoordinatorClient {
3838
required TokenManager tokenManager,
3939
required LatencyService latencyService,
4040
required RetryPolicy retryPolicy,
41+
this.isAnonymous = false,
4142
}) : _rpcUrl = rpcUrl,
4243
_wsUrl = wsUrl,
4344
_apiKey = apiKey,
@@ -54,6 +55,8 @@ class CoordinatorClientOpenApi extends CoordinatorClient {
5455
final LatencyService _latencyService;
5556
final RetryPolicy _retryPolicy;
5657

58+
final bool isAnonymous;
59+
5760
late final open.ApiClient _apiClient = open.ApiClient(
5861
basePath: _rpcUrl,
5962
authentication: _Authentication(
@@ -142,7 +145,14 @@ class CoordinatorClientOpenApi extends CoordinatorClient {
142145
}
143146

144147
Future<Result<None>> _waitUntilConnected() async {
145-
_logger.w(() => '[waitUntilConnected] user.id: ${_user?.id}');
148+
if (isAnonymous) {
149+
_logger.d(
150+
() => '[waitUntilConnected] anonymous user does not require connection',
151+
);
152+
return const Result.success(none);
153+
}
154+
155+
_logger.d(() => '[waitUntilConnected] user.id: ${_user?.id}');
146156
return _connectionState
147157
.firstWhere(
148158
(it) => it.isConnected,

packages/stream_video/lib/src/stream_video.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class StreamVideo extends Disposable {
137137
}) : _options = options,
138138
_state = MutableClientState(user) {
139139
_client = buildCoordinatorClient(
140+
user: user,
140141
apiKey: apiKey,
141142
tokenManager: _tokenManager,
142143
latencySettings: _options.latencySettings,
@@ -270,10 +271,12 @@ class StreamVideo extends Disposable {
270271
'Cannot connect anonymous user to the WS due to Missing Permissions',
271272
);
272273
}
274+
273275
_connectOperation ??= _connect(
274276
includeUserDetails: includeUserDetails,
275277
registerPushDevice: registerPushDevice,
276278
).asCancelable();
279+
277280
return _connectOperation!
278281
.valueOrDefault(Result.error('connect was cancelled'))
279282
.whenComplete(() {
@@ -298,6 +301,7 @@ class StreamVideo extends Disposable {
298301
bool registerPushDevice = true,
299302
}) async {
300303
_logger.i(() => '[connect] currentUser.id: ${_state.currentUser.id}');
304+
301305
if (_connectionState.isConnected) {
302306
_logger.w(() => '[connect] rejected (already connected)');
303307
final token = _tokenManager.getCachedToken();
@@ -306,9 +310,11 @@ class StreamVideo extends Disposable {
306310
}
307311
return Result.success(token);
308312
}
313+
309314
_connectionState = ConnectionState.connecting(
310315
_state.currentUser.id,
311316
);
317+
312318
// guest user will be updated when token gets fetched
313319
final tokenResult = await _tokenManager.getToken();
314320
if (tokenResult is! Success<UserToken>) {
@@ -319,6 +325,7 @@ class StreamVideo extends Disposable {
319325
);
320326
return tokenResult;
321327
}
328+
322329
final user = _state.user.value;
323330
_logger.v(() => '[connect] currentUser.id : ${user.id}');
324331
try {
@@ -857,6 +864,7 @@ class StreamVideo extends Disposable {
857864
}
858865

859866
CoordinatorClient buildCoordinatorClient({
867+
required User user,
860868
required String rpcUrl,
861869
required String wsUrl,
862870
required String apiKey,
@@ -876,6 +884,7 @@ CoordinatorClient buildCoordinatorClient({
876884
retryPolicy: retryPolicy,
877885
rpcUrl: rpcUrl,
878886
wsUrl: wsUrl,
887+
isAnonymous: user.type == UserType.anonymous,
879888
),
880889
);
881890
}

0 commit comments

Comments
 (0)