@stream-io/video-client 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/index.browser.es.js +391 -68
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +391 -68
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +391 -68
- package/dist/index.es.js.map +1 -1
- package/dist/src/StreamSfuClient.d.ts +2 -1
- package/dist/src/__tests__/StreamVideoClient.test.d.ts +1 -1
- package/dist/src/coordinator/connection/client.d.ts +2 -2
- package/dist/src/gen/video/sfu/event/events.d.ts +45 -2
- package/dist/src/gen/video/sfu/models/models.d.ts +12 -0
- package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +9 -1
- package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +42 -0
- package/dist/src/rtc/Publisher.d.ts +10 -2
- package/dist/src/rtc/Subscriber.d.ts +8 -3
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Call.ts +2 -0
- package/src/StreamSfuClient.ts +16 -5
- package/src/__tests__/StreamVideoClient.test.ts +85 -4
- package/src/__tests__/StreamVideoServerClient.test.ts +22 -0
- package/src/coordinator/connection/client.ts +22 -11
- package/src/coordinator/connection/connection.ts +2 -2
- package/src/coordinator/connection/connection_fallback.ts +3 -2
- package/src/gen/google/protobuf/struct.ts +1 -2
- package/src/gen/google/protobuf/timestamp.ts +1 -1
- package/src/gen/video/sfu/event/events.ts +165 -5
- package/src/gen/video/sfu/models/models.ts +13 -1
- package/src/gen/video/sfu/signal_rpc/signal.client.ts +27 -1
- package/src/gen/video/sfu/signal_rpc/signal.ts +194 -1
- package/src/rtc/Dispatcher.ts +1 -0
- package/src/rtc/Publisher.ts +69 -34
- package/src/rtc/Subscriber.ts +74 -7
- package/src/rtc/__tests__/Publisher.test.ts +82 -2
- package/src/rtc/__tests__/Subscriber.test.ts +84 -1
package/dist/index.es.js
CHANGED
|
@@ -372,7 +372,6 @@ class Value$Type extends MessageType {
|
|
|
372
372
|
};
|
|
373
373
|
}
|
|
374
374
|
else {
|
|
375
|
-
Struct.fromJson(json);
|
|
376
375
|
target.kind = {
|
|
377
376
|
oneofKind: 'structValue',
|
|
378
377
|
structValue: Struct.fromJson(json),
|
|
@@ -828,6 +827,18 @@ var ErrorCode;
|
|
|
828
827
|
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MIGRATION_FAILED = 202;
|
|
829
828
|
*/
|
|
830
829
|
ErrorCode[ErrorCode["PARTICIPANT_MIGRATION_FAILED"] = 202] = "PARTICIPANT_MIGRATION_FAILED";
|
|
830
|
+
/**
|
|
831
|
+
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MIGRATING = 203;
|
|
832
|
+
*/
|
|
833
|
+
ErrorCode[ErrorCode["PARTICIPANT_MIGRATING"] = 203] = "PARTICIPANT_MIGRATING";
|
|
834
|
+
/**
|
|
835
|
+
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_RECONNECT_FAILED = 204;
|
|
836
|
+
*/
|
|
837
|
+
ErrorCode[ErrorCode["PARTICIPANT_RECONNECT_FAILED"] = 204] = "PARTICIPANT_RECONNECT_FAILED";
|
|
838
|
+
/**
|
|
839
|
+
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MEDIA_TRANSPORT_FAILURE = 205;
|
|
840
|
+
*/
|
|
841
|
+
ErrorCode[ErrorCode["PARTICIPANT_MEDIA_TRANSPORT_FAILURE"] = 205] = "PARTICIPANT_MEDIA_TRANSPORT_FAILURE";
|
|
831
842
|
/**
|
|
832
843
|
* @generated from protobuf enum value: ERROR_CODE_CALL_NOT_FOUND = 300;
|
|
833
844
|
*/
|
|
@@ -2404,10 +2415,122 @@ var models = /*#__PURE__*/Object.freeze({
|
|
|
2404
2415
|
});
|
|
2405
2416
|
|
|
2406
2417
|
/* eslint-disable */
|
|
2407
|
-
// @generated by protobuf-ts 2.
|
|
2418
|
+
// @generated by protobuf-ts 2.9.0 with parameter long_type_string,client_generic,server_none,eslint_disable
|
|
2408
2419
|
// @generated from protobuf file "video/sfu/signal_rpc/signal.proto" (package "stream.video.sfu.signal", syntax proto3)
|
|
2409
2420
|
// tslint:disable
|
|
2410
2421
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
2422
|
+
class ICERestartRequest$Type extends MessageType {
|
|
2423
|
+
constructor() {
|
|
2424
|
+
super('stream.video.sfu.signal.ICERestartRequest', [
|
|
2425
|
+
{ no: 1, name: 'session_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
2426
|
+
{
|
|
2427
|
+
no: 2,
|
|
2428
|
+
name: 'peer_type',
|
|
2429
|
+
kind: 'enum',
|
|
2430
|
+
T: () => ['stream.video.sfu.models.PeerType', PeerType, 'PEER_TYPE_'],
|
|
2431
|
+
},
|
|
2432
|
+
]);
|
|
2433
|
+
}
|
|
2434
|
+
create(value) {
|
|
2435
|
+
const message = { sessionId: '', peerType: 0 };
|
|
2436
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
2437
|
+
enumerable: false,
|
|
2438
|
+
value: this,
|
|
2439
|
+
});
|
|
2440
|
+
if (value !== undefined)
|
|
2441
|
+
reflectionMergePartial(this, message, value);
|
|
2442
|
+
return message;
|
|
2443
|
+
}
|
|
2444
|
+
internalBinaryRead(reader, length, options, target) {
|
|
2445
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
2446
|
+
while (reader.pos < end) {
|
|
2447
|
+
let [fieldNo, wireType] = reader.tag();
|
|
2448
|
+
switch (fieldNo) {
|
|
2449
|
+
case /* string session_id */ 1:
|
|
2450
|
+
message.sessionId = reader.string();
|
|
2451
|
+
break;
|
|
2452
|
+
case /* stream.video.sfu.models.PeerType peer_type */ 2:
|
|
2453
|
+
message.peerType = reader.int32();
|
|
2454
|
+
break;
|
|
2455
|
+
default:
|
|
2456
|
+
let u = options.readUnknownField;
|
|
2457
|
+
if (u === 'throw')
|
|
2458
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
2459
|
+
let d = reader.skip(wireType);
|
|
2460
|
+
if (u !== false)
|
|
2461
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
return message;
|
|
2465
|
+
}
|
|
2466
|
+
internalBinaryWrite(message, writer, options) {
|
|
2467
|
+
/* string session_id = 1; */
|
|
2468
|
+
if (message.sessionId !== '')
|
|
2469
|
+
writer.tag(1, WireType.LengthDelimited).string(message.sessionId);
|
|
2470
|
+
/* stream.video.sfu.models.PeerType peer_type = 2; */
|
|
2471
|
+
if (message.peerType !== 0)
|
|
2472
|
+
writer.tag(2, WireType.Varint).int32(message.peerType);
|
|
2473
|
+
let u = options.writeUnknownFields;
|
|
2474
|
+
if (u !== false)
|
|
2475
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
2476
|
+
return writer;
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* @generated MessageType for protobuf message stream.video.sfu.signal.ICERestartRequest
|
|
2481
|
+
*/
|
|
2482
|
+
const ICERestartRequest = new ICERestartRequest$Type();
|
|
2483
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
2484
|
+
class ICERestartResponse$Type extends MessageType {
|
|
2485
|
+
constructor() {
|
|
2486
|
+
super('stream.video.sfu.signal.ICERestartResponse', [
|
|
2487
|
+
{ no: 1, name: 'error', kind: 'message', T: () => Error$2 },
|
|
2488
|
+
]);
|
|
2489
|
+
}
|
|
2490
|
+
create(value) {
|
|
2491
|
+
const message = {};
|
|
2492
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
2493
|
+
enumerable: false,
|
|
2494
|
+
value: this,
|
|
2495
|
+
});
|
|
2496
|
+
if (value !== undefined)
|
|
2497
|
+
reflectionMergePartial(this, message, value);
|
|
2498
|
+
return message;
|
|
2499
|
+
}
|
|
2500
|
+
internalBinaryRead(reader, length, options, target) {
|
|
2501
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
2502
|
+
while (reader.pos < end) {
|
|
2503
|
+
let [fieldNo, wireType] = reader.tag();
|
|
2504
|
+
switch (fieldNo) {
|
|
2505
|
+
case /* stream.video.sfu.models.Error error */ 1:
|
|
2506
|
+
message.error = Error$2.internalBinaryRead(reader, reader.uint32(), options, message.error);
|
|
2507
|
+
break;
|
|
2508
|
+
default:
|
|
2509
|
+
let u = options.readUnknownField;
|
|
2510
|
+
if (u === 'throw')
|
|
2511
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
2512
|
+
let d = reader.skip(wireType);
|
|
2513
|
+
if (u !== false)
|
|
2514
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
return message;
|
|
2518
|
+
}
|
|
2519
|
+
internalBinaryWrite(message, writer, options) {
|
|
2520
|
+
/* stream.video.sfu.models.Error error = 1; */
|
|
2521
|
+
if (message.error)
|
|
2522
|
+
Error$2.internalBinaryWrite(message.error, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
2523
|
+
let u = options.writeUnknownFields;
|
|
2524
|
+
if (u !== false)
|
|
2525
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
2526
|
+
return writer;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* @generated MessageType for protobuf message stream.video.sfu.signal.ICERestartResponse
|
|
2531
|
+
*/
|
|
2532
|
+
const ICERestartResponse = new ICERestartResponse$Type();
|
|
2533
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
2411
2534
|
class UpdateMuteStatesRequest$Type extends MessageType {
|
|
2412
2535
|
constructor() {
|
|
2413
2536
|
super('stream.video.sfu.signal.UpdateMuteStatesRequest', [
|
|
@@ -3218,6 +3341,12 @@ const SignalServer = new ServiceType('stream.video.sfu.signal.SignalServer', [
|
|
|
3218
3341
|
I: UpdateMuteStatesRequest,
|
|
3219
3342
|
O: UpdateMuteStatesResponse,
|
|
3220
3343
|
},
|
|
3344
|
+
{
|
|
3345
|
+
name: 'IceRestart',
|
|
3346
|
+
options: {},
|
|
3347
|
+
I: ICERestartRequest,
|
|
3348
|
+
O: ICERestartResponse,
|
|
3349
|
+
},
|
|
3221
3350
|
]);
|
|
3222
3351
|
|
|
3223
3352
|
/**
|
|
@@ -3358,6 +3487,13 @@ class SfuEvent$Type extends MessageType {
|
|
|
3358
3487
|
oneof: 'eventPayload',
|
|
3359
3488
|
T: () => GoAway,
|
|
3360
3489
|
},
|
|
3490
|
+
{
|
|
3491
|
+
no: 21,
|
|
3492
|
+
name: 'ice_restart',
|
|
3493
|
+
kind: 'message',
|
|
3494
|
+
oneof: 'eventPayload',
|
|
3495
|
+
T: () => ICERestart,
|
|
3496
|
+
},
|
|
3361
3497
|
]);
|
|
3362
3498
|
}
|
|
3363
3499
|
create(value) {
|
|
@@ -3471,6 +3607,12 @@ class SfuEvent$Type extends MessageType {
|
|
|
3471
3607
|
goAway: GoAway.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.goAway),
|
|
3472
3608
|
};
|
|
3473
3609
|
break;
|
|
3610
|
+
case /* stream.video.sfu.event.ICERestart ice_restart */ 21:
|
|
3611
|
+
message.eventPayload = {
|
|
3612
|
+
oneofKind: 'iceRestart',
|
|
3613
|
+
iceRestart: ICERestart.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.iceRestart),
|
|
3614
|
+
};
|
|
3615
|
+
break;
|
|
3474
3616
|
default:
|
|
3475
3617
|
let u = options.readUnknownField;
|
|
3476
3618
|
if (u === 'throw')
|
|
@@ -3531,6 +3673,9 @@ class SfuEvent$Type extends MessageType {
|
|
|
3531
3673
|
/* stream.video.sfu.event.GoAway go_away = 20; */
|
|
3532
3674
|
if (message.eventPayload.oneofKind === 'goAway')
|
|
3533
3675
|
GoAway.internalBinaryWrite(message.eventPayload.goAway, writer.tag(20, WireType.LengthDelimited).fork(), options).join();
|
|
3676
|
+
/* stream.video.sfu.event.ICERestart ice_restart = 21; */
|
|
3677
|
+
if (message.eventPayload.oneofKind === 'iceRestart')
|
|
3678
|
+
ICERestart.internalBinaryWrite(message.eventPayload.iceRestart, writer.tag(21, WireType.LengthDelimited).fork(), options).join();
|
|
3534
3679
|
let u = options.writeUnknownFields;
|
|
3535
3680
|
if (u !== false)
|
|
3536
3681
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -3659,6 +3804,61 @@ class ICETrickle$Type extends MessageType {
|
|
|
3659
3804
|
*/
|
|
3660
3805
|
const ICETrickle = new ICETrickle$Type();
|
|
3661
3806
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
3807
|
+
class ICERestart$Type extends MessageType {
|
|
3808
|
+
constructor() {
|
|
3809
|
+
super('stream.video.sfu.event.ICERestart', [
|
|
3810
|
+
{
|
|
3811
|
+
no: 1,
|
|
3812
|
+
name: 'peer_type',
|
|
3813
|
+
kind: 'enum',
|
|
3814
|
+
T: () => ['stream.video.sfu.models.PeerType', PeerType, 'PEER_TYPE_'],
|
|
3815
|
+
},
|
|
3816
|
+
]);
|
|
3817
|
+
}
|
|
3818
|
+
create(value) {
|
|
3819
|
+
const message = { peerType: 0 };
|
|
3820
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
3821
|
+
enumerable: false,
|
|
3822
|
+
value: this,
|
|
3823
|
+
});
|
|
3824
|
+
if (value !== undefined)
|
|
3825
|
+
reflectionMergePartial(this, message, value);
|
|
3826
|
+
return message;
|
|
3827
|
+
}
|
|
3828
|
+
internalBinaryRead(reader, length, options, target) {
|
|
3829
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
3830
|
+
while (reader.pos < end) {
|
|
3831
|
+
let [fieldNo, wireType] = reader.tag();
|
|
3832
|
+
switch (fieldNo) {
|
|
3833
|
+
case /* stream.video.sfu.models.PeerType peer_type */ 1:
|
|
3834
|
+
message.peerType = reader.int32();
|
|
3835
|
+
break;
|
|
3836
|
+
default:
|
|
3837
|
+
let u = options.readUnknownField;
|
|
3838
|
+
if (u === 'throw')
|
|
3839
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
3840
|
+
let d = reader.skip(wireType);
|
|
3841
|
+
if (u !== false)
|
|
3842
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
return message;
|
|
3846
|
+
}
|
|
3847
|
+
internalBinaryWrite(message, writer, options) {
|
|
3848
|
+
/* stream.video.sfu.models.PeerType peer_type = 1; */
|
|
3849
|
+
if (message.peerType !== 0)
|
|
3850
|
+
writer.tag(1, WireType.Varint).int32(message.peerType);
|
|
3851
|
+
let u = options.writeUnknownFields;
|
|
3852
|
+
if (u !== false)
|
|
3853
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
3854
|
+
return writer;
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
/**
|
|
3858
|
+
* @generated MessageType for protobuf message stream.video.sfu.event.ICERestart
|
|
3859
|
+
*/
|
|
3860
|
+
const ICERestart = new ICERestart$Type();
|
|
3861
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
3662
3862
|
class SfuRequest$Type extends MessageType {
|
|
3663
3863
|
constructor() {
|
|
3664
3864
|
super('stream.video.sfu.event.SfuRequest', [
|
|
@@ -4012,10 +4212,21 @@ class JoinRequest$Type extends MessageType {
|
|
|
4012
4212
|
T: () => ClientDetails,
|
|
4013
4213
|
},
|
|
4014
4214
|
{ no: 5, name: 'migration', kind: 'message', T: () => Migration },
|
|
4215
|
+
{
|
|
4216
|
+
no: 6,
|
|
4217
|
+
name: 'fast_reconnect',
|
|
4218
|
+
kind: 'scalar',
|
|
4219
|
+
T: 8 /*ScalarType.BOOL*/,
|
|
4220
|
+
},
|
|
4015
4221
|
]);
|
|
4016
4222
|
}
|
|
4017
4223
|
create(value) {
|
|
4018
|
-
const message = {
|
|
4224
|
+
const message = {
|
|
4225
|
+
token: '',
|
|
4226
|
+
sessionId: '',
|
|
4227
|
+
subscriberSdp: '',
|
|
4228
|
+
fastReconnect: false,
|
|
4229
|
+
};
|
|
4019
4230
|
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
4020
4231
|
enumerable: false,
|
|
4021
4232
|
value: this,
|
|
@@ -4044,6 +4255,9 @@ class JoinRequest$Type extends MessageType {
|
|
|
4044
4255
|
case /* stream.video.sfu.event.Migration migration */ 5:
|
|
4045
4256
|
message.migration = Migration.internalBinaryRead(reader, reader.uint32(), options, message.migration);
|
|
4046
4257
|
break;
|
|
4258
|
+
case /* bool fast_reconnect */ 6:
|
|
4259
|
+
message.fastReconnect = reader.bool();
|
|
4260
|
+
break;
|
|
4047
4261
|
default:
|
|
4048
4262
|
let u = options.readUnknownField;
|
|
4049
4263
|
if (u === 'throw')
|
|
@@ -4071,6 +4285,9 @@ class JoinRequest$Type extends MessageType {
|
|
|
4071
4285
|
/* stream.video.sfu.event.Migration migration = 5; */
|
|
4072
4286
|
if (message.migration)
|
|
4073
4287
|
Migration.internalBinaryWrite(message.migration, writer.tag(5, WireType.LengthDelimited).fork(), options).join();
|
|
4288
|
+
/* bool fast_reconnect = 6; */
|
|
4289
|
+
if (message.fastReconnect !== false)
|
|
4290
|
+
writer.tag(6, WireType.Varint).bool(message.fastReconnect);
|
|
4074
4291
|
let u = options.writeUnknownFields;
|
|
4075
4292
|
if (u !== false)
|
|
4076
4293
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -4167,10 +4384,11 @@ class JoinResponse$Type extends MessageType {
|
|
|
4167
4384
|
constructor() {
|
|
4168
4385
|
super('stream.video.sfu.event.JoinResponse', [
|
|
4169
4386
|
{ no: 1, name: 'call_state', kind: 'message', T: () => CallState$1 },
|
|
4387
|
+
{ no: 2, name: 'reconnected', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
|
|
4170
4388
|
]);
|
|
4171
4389
|
}
|
|
4172
4390
|
create(value) {
|
|
4173
|
-
const message = {};
|
|
4391
|
+
const message = { reconnected: false };
|
|
4174
4392
|
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
4175
4393
|
enumerable: false,
|
|
4176
4394
|
value: this,
|
|
@@ -4187,6 +4405,9 @@ class JoinResponse$Type extends MessageType {
|
|
|
4187
4405
|
case /* stream.video.sfu.models.CallState call_state */ 1:
|
|
4188
4406
|
message.callState = CallState$1.internalBinaryRead(reader, reader.uint32(), options, message.callState);
|
|
4189
4407
|
break;
|
|
4408
|
+
case /* bool reconnected */ 2:
|
|
4409
|
+
message.reconnected = reader.bool();
|
|
4410
|
+
break;
|
|
4190
4411
|
default:
|
|
4191
4412
|
let u = options.readUnknownField;
|
|
4192
4413
|
if (u === 'throw')
|
|
@@ -4202,6 +4423,9 @@ class JoinResponse$Type extends MessageType {
|
|
|
4202
4423
|
/* stream.video.sfu.models.CallState call_state = 1; */
|
|
4203
4424
|
if (message.callState)
|
|
4204
4425
|
CallState$1.internalBinaryWrite(message.callState, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
4426
|
+
/* bool reconnected = 2; */
|
|
4427
|
+
if (message.reconnected !== false)
|
|
4428
|
+
writer.tag(2, WireType.Varint).bool(message.reconnected);
|
|
4205
4429
|
let u = options.writeUnknownFields;
|
|
4206
4430
|
if (u !== false)
|
|
4207
4431
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -5318,6 +5542,7 @@ var events = /*#__PURE__*/Object.freeze({
|
|
|
5318
5542
|
GoAway: GoAway,
|
|
5319
5543
|
HealthCheckRequest: HealthCheckRequest,
|
|
5320
5544
|
HealthCheckResponse: HealthCheckResponse,
|
|
5545
|
+
ICERestart: ICERestart,
|
|
5321
5546
|
ICETrickle: ICETrickle,
|
|
5322
5547
|
JoinRequest: JoinRequest,
|
|
5323
5548
|
JoinResponse: JoinResponse,
|
|
@@ -5434,6 +5659,13 @@ class SignalServerClient {
|
|
|
5434
5659
|
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
|
5435
5660
|
return stackIntercept('unary', this._transport, method, opt, input);
|
|
5436
5661
|
}
|
|
5662
|
+
/**
|
|
5663
|
+
* @generated from protobuf rpc: IceRestart(stream.video.sfu.signal.ICERestartRequest) returns (stream.video.sfu.signal.ICERestartResponse);
|
|
5664
|
+
*/
|
|
5665
|
+
iceRestart(input, options) {
|
|
5666
|
+
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
|
5667
|
+
return stackIntercept('unary', this._transport, method, opt, input);
|
|
5668
|
+
}
|
|
5437
5669
|
}
|
|
5438
5670
|
|
|
5439
5671
|
const defaultOptions = {
|
|
@@ -5668,7 +5900,7 @@ const logLevels = Object.freeze({
|
|
|
5668
5900
|
warn: 3,
|
|
5669
5901
|
error: 4,
|
|
5670
5902
|
});
|
|
5671
|
-
let logger$
|
|
5903
|
+
let logger$4;
|
|
5672
5904
|
let level = 'info';
|
|
5673
5905
|
const logToConsole = (logLevel, message, ...args) => {
|
|
5674
5906
|
let logMethod;
|
|
@@ -5692,7 +5924,7 @@ const logToConsole = (logLevel, message, ...args) => {
|
|
|
5692
5924
|
logMethod(message, ...args);
|
|
5693
5925
|
};
|
|
5694
5926
|
const setLogger = (l, lvl) => {
|
|
5695
|
-
logger$
|
|
5927
|
+
logger$4 = l;
|
|
5696
5928
|
if (lvl) {
|
|
5697
5929
|
setLogLevel(lvl);
|
|
5698
5930
|
}
|
|
@@ -5701,7 +5933,7 @@ const setLogLevel = (l) => {
|
|
|
5701
5933
|
level = l;
|
|
5702
5934
|
};
|
|
5703
5935
|
const getLogger = (withTags) => {
|
|
5704
|
-
const loggerMethod = logger$
|
|
5936
|
+
const loggerMethod = logger$4 || logToConsole;
|
|
5705
5937
|
const tags = (withTags || []).join(':');
|
|
5706
5938
|
const result = (logLevel, message, ...args) => {
|
|
5707
5939
|
if (logLevels[logLevel] >= logLevels[level]) {
|
|
@@ -5808,6 +6040,7 @@ const sfuEventKinds = {
|
|
|
5808
6040
|
error: undefined,
|
|
5809
6041
|
callGrantsUpdated: undefined,
|
|
5810
6042
|
goAway: undefined,
|
|
6043
|
+
iceRestart: undefined,
|
|
5811
6044
|
};
|
|
5812
6045
|
const isSfuEvent = (eventName) => {
|
|
5813
6046
|
return Object.prototype.hasOwnProperty.call(sfuEventKinds, eventName);
|
|
@@ -6033,6 +6266,7 @@ const muteTypeToTrackType = (muteType) => {
|
|
|
6033
6266
|
}
|
|
6034
6267
|
};
|
|
6035
6268
|
|
|
6269
|
+
const logger$3 = getLogger(['Publisher']);
|
|
6036
6270
|
/**
|
|
6037
6271
|
* The `Publisher` is responsible for publishing/unpublishing media streams to/from the SFU
|
|
6038
6272
|
* @internal
|
|
@@ -6044,11 +6278,13 @@ class Publisher {
|
|
|
6044
6278
|
* @param connectionConfig the connection configuration to use.
|
|
6045
6279
|
* @param sfuClient the SFU client to use.
|
|
6046
6280
|
* @param state the call state to use.
|
|
6281
|
+
* @param dispatcher the dispatcher to use.
|
|
6047
6282
|
* @param isDtxEnabled whether DTX is enabled.
|
|
6048
6283
|
* @param isRedEnabled whether RED is enabled.
|
|
6049
6284
|
* @param preferredVideoCodec the preferred video codec.
|
|
6285
|
+
* @param iceRestartDelay the delay in milliseconds to wait before restarting ICE once connection goes to `disconnected` state.
|
|
6050
6286
|
*/
|
|
6051
|
-
constructor({ connectionConfig, sfuClient, state, isDtxEnabled, isRedEnabled, preferredVideoCodec, }) {
|
|
6287
|
+
constructor({ connectionConfig, sfuClient, dispatcher, state, isDtxEnabled, isRedEnabled, preferredVideoCodec, iceRestartDelay = 2500, }) {
|
|
6052
6288
|
this.transceiverRegistry = {
|
|
6053
6289
|
[TrackType.AUDIO]: undefined,
|
|
6054
6290
|
[TrackType.VIDEO]: undefined,
|
|
@@ -6078,7 +6314,7 @@ class Publisher {
|
|
|
6078
6314
|
[TrackType.SCREEN_SHARE_AUDIO]: undefined,
|
|
6079
6315
|
[TrackType.UNSPECIFIED]: undefined,
|
|
6080
6316
|
};
|
|
6081
|
-
this.
|
|
6317
|
+
this.isIceRestarting = false;
|
|
6082
6318
|
this.createPeerConnection = (connectionConfig) => {
|
|
6083
6319
|
const pc = new RTCPeerConnection(connectionConfig);
|
|
6084
6320
|
pc.addEventListener('icecandidate', this.onIceCandidate);
|
|
@@ -6104,6 +6340,7 @@ class Publisher {
|
|
|
6104
6340
|
this.trackLayersCache[trackType] = undefined;
|
|
6105
6341
|
});
|
|
6106
6342
|
}
|
|
6343
|
+
this.unsubscribeOnIceRestart();
|
|
6107
6344
|
this.pc.removeEventListener('negotiationneeded', this.onNegotiationNeeded);
|
|
6108
6345
|
this.pc.close();
|
|
6109
6346
|
};
|
|
@@ -6134,7 +6371,7 @@ class Publisher {
|
|
|
6134
6371
|
* Once the track has ended, it will notify the SFU and update the state.
|
|
6135
6372
|
*/
|
|
6136
6373
|
const handleTrackEnded = () => __awaiter(this, void 0, void 0, function* () {
|
|
6137
|
-
|
|
6374
|
+
logger$3('info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
|
|
6138
6375
|
yield this.notifyTrackMuteStateChanged(mediaStream, track, trackType, true);
|
|
6139
6376
|
// clean-up, this event listener needs to run only once.
|
|
6140
6377
|
track.removeEventListener('ended', handleTrackEnded);
|
|
@@ -6157,11 +6394,11 @@ class Publisher {
|
|
|
6157
6394
|
: undefined,
|
|
6158
6395
|
sendEncodings: videoEncodings,
|
|
6159
6396
|
});
|
|
6160
|
-
|
|
6397
|
+
logger$3('debug', `Added ${TrackType[trackType]} transceiver`);
|
|
6161
6398
|
this.transceiverInitOrder.push(trackType);
|
|
6162
6399
|
this.transceiverRegistry[trackType] = transceiver;
|
|
6163
6400
|
if ('setCodecPreferences' in transceiver && codecPreferences) {
|
|
6164
|
-
|
|
6401
|
+
logger$3('info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
|
|
6165
6402
|
transceiver.setCodecPreferences(codecPreferences);
|
|
6166
6403
|
}
|
|
6167
6404
|
}
|
|
@@ -6229,7 +6466,7 @@ class Publisher {
|
|
|
6229
6466
|
* Stops publishing all tracks and stop all tracks.
|
|
6230
6467
|
*/
|
|
6231
6468
|
this.stopPublishing = () => {
|
|
6232
|
-
|
|
6469
|
+
logger$3('debug', 'Stopping publishing all tracks');
|
|
6233
6470
|
this.pc.getSenders().forEach((s) => {
|
|
6234
6471
|
var _a;
|
|
6235
6472
|
(_a = s.track) === null || _a === void 0 ? void 0 : _a.stop();
|
|
@@ -6240,15 +6477,15 @@ class Publisher {
|
|
|
6240
6477
|
};
|
|
6241
6478
|
this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
6242
6479
|
var _a;
|
|
6243
|
-
|
|
6480
|
+
logger$3('info', 'Update publish quality, requested rids by SFU:', enabledRids);
|
|
6244
6481
|
const videoSender = (_a = this.transceiverRegistry[TrackType.VIDEO]) === null || _a === void 0 ? void 0 : _a.sender;
|
|
6245
6482
|
if (!videoSender) {
|
|
6246
|
-
|
|
6483
|
+
logger$3('warn', 'Update publish quality, no video sender found.');
|
|
6247
6484
|
return;
|
|
6248
6485
|
}
|
|
6249
6486
|
const params = videoSender.getParameters();
|
|
6250
6487
|
if (params.encodings.length === 0) {
|
|
6251
|
-
|
|
6488
|
+
logger$3('warn', 'Update publish quality, No suitable video encoding quality found');
|
|
6252
6489
|
return;
|
|
6253
6490
|
}
|
|
6254
6491
|
let changed = false;
|
|
@@ -6266,10 +6503,10 @@ class Publisher {
|
|
|
6266
6503
|
.join(', ');
|
|
6267
6504
|
if (changed) {
|
|
6268
6505
|
yield videoSender.setParameters(params);
|
|
6269
|
-
|
|
6506
|
+
logger$3('info', `Update publish quality, enabled rids: ${activeRids}`);
|
|
6270
6507
|
}
|
|
6271
6508
|
else {
|
|
6272
|
-
|
|
6509
|
+
logger$3('info', `Update publish quality, no change: ${activeRids}`);
|
|
6273
6510
|
}
|
|
6274
6511
|
});
|
|
6275
6512
|
/**
|
|
@@ -6293,7 +6530,7 @@ class Publisher {
|
|
|
6293
6530
|
this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
|
|
6294
6531
|
const { candidate } = e;
|
|
6295
6532
|
if (!candidate) {
|
|
6296
|
-
|
|
6533
|
+
logger$3('debug', 'null ice candidate');
|
|
6297
6534
|
return;
|
|
6298
6535
|
}
|
|
6299
6536
|
yield this.sfuClient.iceTrickle({
|
|
@@ -6322,7 +6559,12 @@ class Publisher {
|
|
|
6322
6559
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
6323
6560
|
*/
|
|
6324
6561
|
this.restartIce = () => __awaiter(this, void 0, void 0, function* () {
|
|
6325
|
-
|
|
6562
|
+
logger$3('debug', 'Restarting ICE connection');
|
|
6563
|
+
const signalingState = this.pc.signalingState;
|
|
6564
|
+
if (this.isIceRestarting || signalingState === 'have-local-offer') {
|
|
6565
|
+
logger$3('debug', 'ICE restart is already in progress');
|
|
6566
|
+
return;
|
|
6567
|
+
}
|
|
6326
6568
|
yield this.negotiate({ iceRestart: true });
|
|
6327
6569
|
});
|
|
6328
6570
|
this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -6334,6 +6576,8 @@ class Publisher {
|
|
|
6334
6576
|
* @param options the optional offer options to use.
|
|
6335
6577
|
*/
|
|
6336
6578
|
this.negotiate = (options) => __awaiter(this, void 0, void 0, function* () {
|
|
6579
|
+
var _b;
|
|
6580
|
+
this.isIceRestarting = (_b = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _b !== void 0 ? _b : false;
|
|
6337
6581
|
const offer = yield this.pc.createOffer(options);
|
|
6338
6582
|
offer.sdp = this.mungeCodecs(offer.sdp);
|
|
6339
6583
|
const trackInfos = this.getCurrentTrackInfos(offer.sdp);
|
|
@@ -6352,21 +6596,19 @@ class Publisher {
|
|
|
6352
6596
|
});
|
|
6353
6597
|
}
|
|
6354
6598
|
catch (e) {
|
|
6355
|
-
|
|
6599
|
+
logger$3('error', `setRemoteDescription error`, {
|
|
6356
6600
|
sdp: response.sdp,
|
|
6357
6601
|
error: e,
|
|
6358
6602
|
});
|
|
6359
6603
|
}
|
|
6604
|
+
this.isIceRestarting = false;
|
|
6360
6605
|
this.sfuClient.iceTrickleBuffer.publisherCandidates.subscribe((candidate) => __awaiter(this, void 0, void 0, function* () {
|
|
6361
6606
|
try {
|
|
6362
6607
|
const iceCandidate = JSON.parse(candidate.iceCandidate);
|
|
6363
6608
|
yield this.pc.addIceCandidate(iceCandidate);
|
|
6364
6609
|
}
|
|
6365
6610
|
catch (e) {
|
|
6366
|
-
|
|
6367
|
-
error: e,
|
|
6368
|
-
candidate,
|
|
6369
|
-
});
|
|
6611
|
+
logger$3('warn', `ICE candidate error`, [e, candidate]);
|
|
6370
6612
|
}
|
|
6371
6613
|
}));
|
|
6372
6614
|
});
|
|
@@ -6392,10 +6634,10 @@ class Publisher {
|
|
|
6392
6634
|
if (defaultMid)
|
|
6393
6635
|
return defaultMid;
|
|
6394
6636
|
if (!sdp) {
|
|
6395
|
-
|
|
6637
|
+
logger$3('warn', 'No SDP found. Returning empty mid');
|
|
6396
6638
|
return '';
|
|
6397
6639
|
}
|
|
6398
|
-
|
|
6640
|
+
logger$3('debug', `No 'mid' found for track. Trying to find it from the Offer SDP`);
|
|
6399
6641
|
const parsedSdp = SDP.parse(sdp);
|
|
6400
6642
|
const media = parsedSdp.media.find((m) => {
|
|
6401
6643
|
var _a, _b;
|
|
@@ -6404,12 +6646,12 @@ class Publisher {
|
|
|
6404
6646
|
((_b = (_a = m.msid) === null || _a === void 0 ? void 0 : _a.includes(track.id)) !== null && _b !== void 0 ? _b : true));
|
|
6405
6647
|
});
|
|
6406
6648
|
if (typeof (media === null || media === void 0 ? void 0 : media.mid) === 'undefined') {
|
|
6407
|
-
|
|
6649
|
+
logger$3('debug', `No mid found in SDP for track type ${track.kind} and id ${track.id}. Attempting to find a heuristic mid`);
|
|
6408
6650
|
const heuristicMid = this.transceiverInitOrder.indexOf(trackType);
|
|
6409
6651
|
if (heuristicMid !== -1) {
|
|
6410
6652
|
return String(heuristicMid);
|
|
6411
6653
|
}
|
|
6412
|
-
|
|
6654
|
+
logger$3('debug', 'No heuristic mid found. Returning empty mid');
|
|
6413
6655
|
return '';
|
|
6414
6656
|
}
|
|
6415
6657
|
return String(media.mid);
|
|
@@ -6435,7 +6677,7 @@ class Publisher {
|
|
|
6435
6677
|
else {
|
|
6436
6678
|
// we report the last known optimal layers for ended tracks
|
|
6437
6679
|
optimalLayers = this.trackLayersCache[trackType] || [];
|
|
6438
|
-
|
|
6680
|
+
logger$3('debug', `Track ${TrackType[trackType]} is ended. Announcing last known optimal layers`, optimalLayers);
|
|
6439
6681
|
}
|
|
6440
6682
|
const layers = optimalLayers.map((optimalLayer) => ({
|
|
6441
6683
|
rid: optimalLayer.rid || '',
|
|
@@ -6462,38 +6704,41 @@ class Publisher {
|
|
|
6462
6704
|
this.onIceCandidateError = (e) => {
|
|
6463
6705
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
6464
6706
|
`${e.errorCode}: ${e.errorText}`;
|
|
6465
|
-
|
|
6707
|
+
logger$3('error', `ICE Candidate error`, errorMessage);
|
|
6466
6708
|
};
|
|
6467
6709
|
this.onIceConnectionStateChange = () => {
|
|
6468
6710
|
const state = this.pc.iceConnectionState;
|
|
6469
|
-
|
|
6711
|
+
logger$3('debug', `ICE Connection state changed to`, state);
|
|
6470
6712
|
if (state === 'failed') {
|
|
6471
|
-
|
|
6713
|
+
logger$3('warn', `Attempting to restart ICE`);
|
|
6472
6714
|
this.restartIce().catch((e) => {
|
|
6473
|
-
|
|
6715
|
+
logger$3('error', `ICE restart error`, e);
|
|
6474
6716
|
});
|
|
6475
6717
|
}
|
|
6476
6718
|
else if (state === 'disconnected') {
|
|
6477
6719
|
// when in `disconnected` state, the browser may recover automatically,
|
|
6478
6720
|
// hence, we delay the ICE restart
|
|
6479
|
-
|
|
6721
|
+
logger$3('warn', `Scheduling ICE restart in ${this.iceRestartDelay} ms.`);
|
|
6480
6722
|
setTimeout(() => {
|
|
6481
6723
|
// check if the state is still `disconnected` or `failed`
|
|
6482
6724
|
// as the connection may have recovered (or failed) in the meantime
|
|
6483
6725
|
if (this.pc.iceConnectionState === 'disconnected' ||
|
|
6484
6726
|
this.pc.iceConnectionState === 'failed') {
|
|
6485
6727
|
this.restartIce().catch((e) => {
|
|
6486
|
-
|
|
6728
|
+
logger$3('error', `ICE restart error`, e);
|
|
6487
6729
|
});
|
|
6488
6730
|
}
|
|
6489
|
-
|
|
6731
|
+
else {
|
|
6732
|
+
logger$3('debug', `Scheduled ICE restart: connection recovered, canceled.`);
|
|
6733
|
+
}
|
|
6734
|
+
}, this.iceRestartDelay);
|
|
6490
6735
|
}
|
|
6491
6736
|
};
|
|
6492
6737
|
this.onIceGatheringStateChange = () => {
|
|
6493
|
-
|
|
6738
|
+
logger$3('debug', `ICE Gathering State`, this.pc.iceGatheringState);
|
|
6494
6739
|
};
|
|
6495
6740
|
this.onSignalingStateChange = () => {
|
|
6496
|
-
|
|
6741
|
+
logger$3('debug', `Signaling state changed`, this.pc.signalingState);
|
|
6497
6742
|
};
|
|
6498
6743
|
this.ridToVideoQuality = (rid) => {
|
|
6499
6744
|
return rid === 'q'
|
|
@@ -6505,9 +6750,19 @@ class Publisher {
|
|
|
6505
6750
|
this.pc = this.createPeerConnection(connectionConfig);
|
|
6506
6751
|
this.sfuClient = sfuClient;
|
|
6507
6752
|
this.state = state;
|
|
6753
|
+
this.dispatcher = dispatcher;
|
|
6508
6754
|
this.isDtxEnabled = isDtxEnabled;
|
|
6509
6755
|
this.isRedEnabled = isRedEnabled;
|
|
6510
6756
|
this.preferredVideoCodec = preferredVideoCodec;
|
|
6757
|
+
this.iceRestartDelay = iceRestartDelay;
|
|
6758
|
+
this.unsubscribeOnIceRestart = dispatcher.on('iceRestart', (message) => __awaiter(this, void 0, void 0, function* () {
|
|
6759
|
+
if (message.eventPayload.oneofKind !== 'iceRestart')
|
|
6760
|
+
return;
|
|
6761
|
+
const { iceRestart } = message.eventPayload;
|
|
6762
|
+
if (iceRestart.peerType !== PeerType.PUBLISHER_UNSPECIFIED)
|
|
6763
|
+
return;
|
|
6764
|
+
yield this.restartIce();
|
|
6765
|
+
}));
|
|
6511
6766
|
}
|
|
6512
6767
|
}
|
|
6513
6768
|
|
|
@@ -6524,8 +6779,10 @@ class Subscriber {
|
|
|
6524
6779
|
* @param dispatcher the dispatcher to use.
|
|
6525
6780
|
* @param state the state of the call.
|
|
6526
6781
|
* @param connectionConfig the connection configuration to use.
|
|
6782
|
+
* @param iceRestartDelay the delay in milliseconds to wait before restarting ICE when connection goes to `disconnected` state.
|
|
6527
6783
|
*/
|
|
6528
|
-
constructor({ sfuClient, dispatcher, state, connectionConfig, }) {
|
|
6784
|
+
constructor({ sfuClient, dispatcher, state, connectionConfig, iceRestartDelay = 2500, }) {
|
|
6785
|
+
this.isIceRestarting = false;
|
|
6529
6786
|
/**
|
|
6530
6787
|
* Creates a new `RTCPeerConnection` instance with the given configuration.
|
|
6531
6788
|
*
|
|
@@ -6545,6 +6802,7 @@ class Subscriber {
|
|
|
6545
6802
|
*/
|
|
6546
6803
|
this.close = () => {
|
|
6547
6804
|
this.unregisterOnSubscriberOffer();
|
|
6805
|
+
this.unregisterOnIceRestart();
|
|
6548
6806
|
this.pc.close();
|
|
6549
6807
|
};
|
|
6550
6808
|
/**
|
|
@@ -6617,10 +6875,25 @@ class Subscriber {
|
|
|
6617
6875
|
/**
|
|
6618
6876
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
6619
6877
|
*/
|
|
6620
|
-
this.restartIce = () => {
|
|
6878
|
+
this.restartIce = () => __awaiter(this, void 0, void 0, function* () {
|
|
6621
6879
|
logger$2('debug', 'Restarting ICE connection');
|
|
6622
|
-
this.pc.
|
|
6623
|
-
|
|
6880
|
+
if (this.pc.signalingState === 'have-remote-offer') {
|
|
6881
|
+
logger$2('debug', 'ICE restart is already in progress');
|
|
6882
|
+
return;
|
|
6883
|
+
}
|
|
6884
|
+
const previousIsIceRestarting = this.isIceRestarting;
|
|
6885
|
+
try {
|
|
6886
|
+
this.isIceRestarting = true;
|
|
6887
|
+
yield this.sfuClient.iceRestart({
|
|
6888
|
+
peerType: PeerType.SUBSCRIBER,
|
|
6889
|
+
});
|
|
6890
|
+
}
|
|
6891
|
+
catch (e) {
|
|
6892
|
+
// restore the previous state, as our intent for restarting ICE failed
|
|
6893
|
+
this.isIceRestarting = previousIsIceRestarting;
|
|
6894
|
+
throw e;
|
|
6895
|
+
}
|
|
6896
|
+
});
|
|
6624
6897
|
this.handleOnTrack = (e) => {
|
|
6625
6898
|
const [primaryStream] = e.streams;
|
|
6626
6899
|
// example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
|
|
@@ -6684,22 +6957,50 @@ class Subscriber {
|
|
|
6684
6957
|
yield this.pc.addIceCandidate(iceCandidate);
|
|
6685
6958
|
}
|
|
6686
6959
|
catch (e) {
|
|
6687
|
-
logger$2('
|
|
6960
|
+
logger$2('warn', `ICE candidate error`, [e, candidate]);
|
|
6688
6961
|
}
|
|
6689
6962
|
}));
|
|
6690
|
-
// apply ice candidates
|
|
6691
6963
|
const answer = yield this.pc.createAnswer();
|
|
6692
6964
|
yield this.pc.setLocalDescription(answer);
|
|
6693
6965
|
yield this.sfuClient.sendAnswer({
|
|
6694
6966
|
peerType: PeerType.SUBSCRIBER,
|
|
6695
6967
|
sdp: answer.sdp || '',
|
|
6696
6968
|
});
|
|
6969
|
+
this.isIceRestarting = false;
|
|
6697
6970
|
});
|
|
6698
6971
|
this.onIceConnectionStateChange = () => {
|
|
6699
|
-
|
|
6972
|
+
const state = this.pc.iceConnectionState;
|
|
6973
|
+
logger$2('debug', `ICE connection state changed`, state);
|
|
6974
|
+
// do nothing when ICE is restarting
|
|
6975
|
+
if (this.isIceRestarting)
|
|
6976
|
+
return;
|
|
6977
|
+
if (state === 'failed') {
|
|
6978
|
+
logger$2('warn', `Attempting to restart ICE`);
|
|
6979
|
+
this.restartIce().catch((e) => {
|
|
6980
|
+
logger$2('error', `ICE restart failed`, e);
|
|
6981
|
+
});
|
|
6982
|
+
}
|
|
6983
|
+
else if (state === 'disconnected') {
|
|
6984
|
+
// when in `disconnected` state, the browser may recover automatically,
|
|
6985
|
+
// hence, we delay the ICE restart
|
|
6986
|
+
logger$2('warn', `Scheduling ICE restart in ${this.iceRestartDelay} ms.`);
|
|
6987
|
+
setTimeout(() => {
|
|
6988
|
+
// check if the state is still `disconnected` or `failed`
|
|
6989
|
+
// as the connection may have recovered (or failed) in the meantime
|
|
6990
|
+
if (this.pc.iceConnectionState === 'disconnected' ||
|
|
6991
|
+
this.pc.iceConnectionState === 'failed') {
|
|
6992
|
+
this.restartIce().catch((e) => {
|
|
6993
|
+
logger$2('error', `ICE restart failed`, e);
|
|
6994
|
+
});
|
|
6995
|
+
}
|
|
6996
|
+
else {
|
|
6997
|
+
logger$2('debug', `Scheduled ICE restart: connection recovered, canceled.`);
|
|
6998
|
+
}
|
|
6999
|
+
}, 5000);
|
|
7000
|
+
}
|
|
6700
7001
|
};
|
|
6701
7002
|
this.onIceGatheringStateChange = () => {
|
|
6702
|
-
logger$2('
|
|
7003
|
+
logger$2('debug', `ICE gathering state changed`, this.pc.iceGatheringState);
|
|
6703
7004
|
};
|
|
6704
7005
|
this.onIceCandidateError = (e) => {
|
|
6705
7006
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
@@ -6709,6 +7010,7 @@ class Subscriber {
|
|
|
6709
7010
|
this.sfuClient = sfuClient;
|
|
6710
7011
|
this.dispatcher = dispatcher;
|
|
6711
7012
|
this.state = state;
|
|
7013
|
+
this.iceRestartDelay = iceRestartDelay;
|
|
6712
7014
|
this.pc = this.createPeerConnection(connectionConfig);
|
|
6713
7015
|
this.unregisterOnSubscriberOffer = dispatcher.on('subscriberOffer', (message) => __awaiter(this, void 0, void 0, function* () {
|
|
6714
7016
|
if (message.eventPayload.oneofKind !== 'subscriberOffer')
|
|
@@ -6716,6 +7018,14 @@ class Subscriber {
|
|
|
6716
7018
|
const { subscriberOffer } = message.eventPayload;
|
|
6717
7019
|
yield this.negotiate(subscriberOffer);
|
|
6718
7020
|
}));
|
|
7021
|
+
this.unregisterOnIceRestart = dispatcher.on('iceRestart', (message) => __awaiter(this, void 0, void 0, function* () {
|
|
7022
|
+
if (message.eventPayload.oneofKind !== 'iceRestart')
|
|
7023
|
+
return;
|
|
7024
|
+
const { iceRestart } = message.eventPayload;
|
|
7025
|
+
if (iceRestart.peerType !== PeerType.SUBSCRIBER)
|
|
7026
|
+
return;
|
|
7027
|
+
yield this.restartIce();
|
|
7028
|
+
}));
|
|
6719
7029
|
}
|
|
6720
7030
|
}
|
|
6721
7031
|
|
|
@@ -6902,6 +7212,7 @@ class StreamSfuClient {
|
|
|
6902
7212
|
this.pingIntervalInMs = 10 * 1000;
|
|
6903
7213
|
this.unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
|
|
6904
7214
|
this.close = (code = 1000, reason = 'Requested signal connection close') => {
|
|
7215
|
+
this.logger('debug', 'Closing SFU WS connection', code, reason);
|
|
6905
7216
|
this.signalWs.close(code, reason);
|
|
6906
7217
|
this.unsubscribeIceTrickle();
|
|
6907
7218
|
clearInterval(this.keepAliveInterval);
|
|
@@ -6922,6 +7233,9 @@ class StreamSfuClient {
|
|
|
6922
7233
|
this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6923
7234
|
return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6924
7235
|
});
|
|
7236
|
+
this.iceRestart = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
7237
|
+
return retryable(() => this.rpc.iceRestart(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
7238
|
+
});
|
|
6925
7239
|
this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
|
|
6926
7240
|
return this.updateMuteStates({
|
|
6927
7241
|
muteStates: [
|
|
@@ -6973,7 +7287,6 @@ class StreamSfuClient {
|
|
|
6973
7287
|
if (this.lastMessageTimestamp) {
|
|
6974
7288
|
const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
|
|
6975
7289
|
if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
|
|
6976
|
-
this.logger('debug', 'SFU connection unhealthy, closing');
|
|
6977
7290
|
this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
|
|
6978
7291
|
}
|
|
6979
7292
|
}
|
|
@@ -6984,10 +7297,9 @@ class StreamSfuClient {
|
|
|
6984
7297
|
this.edgeName = sfuServer.edge_name;
|
|
6985
7298
|
this.token = token;
|
|
6986
7299
|
this.logger = getLogger(['sfu-client']);
|
|
6987
|
-
const logger = this.logger;
|
|
6988
7300
|
const logInterceptor = {
|
|
6989
|
-
interceptUnary(next, method, input, options) {
|
|
6990
|
-
logger('trace', `Calling SFU RPC method ${method.name}`, {
|
|
7301
|
+
interceptUnary: (next, method, input, options) => {
|
|
7302
|
+
this.logger('trace', `Calling SFU RPC method ${method.name}`, {
|
|
6991
7303
|
input,
|
|
6992
7304
|
options,
|
|
6993
7305
|
});
|
|
@@ -9463,6 +9775,7 @@ class Call {
|
|
|
9463
9775
|
if (!this.publisher) {
|
|
9464
9776
|
this.publisher = new Publisher({
|
|
9465
9777
|
sfuClient,
|
|
9778
|
+
dispatcher: this.dispatcher,
|
|
9466
9779
|
state: this.state,
|
|
9467
9780
|
connectionConfig,
|
|
9468
9781
|
isDtxEnabled,
|
|
@@ -9499,6 +9812,7 @@ class Call {
|
|
|
9499
9812
|
subscriberSdp: sdp || '',
|
|
9500
9813
|
clientDetails: getClientDetails(),
|
|
9501
9814
|
migration,
|
|
9815
|
+
fastReconnect: false,
|
|
9502
9816
|
});
|
|
9503
9817
|
});
|
|
9504
9818
|
// 2. in parallel, wait for the SFU to send us the "joinResponse"
|
|
@@ -10726,6 +11040,7 @@ class StableWSConnection {
|
|
|
10726
11040
|
* @return {ConnectAPIResponse<ConnectedEvent>} Promise that completes once the first health check message is received
|
|
10727
11041
|
*/
|
|
10728
11042
|
_connect() {
|
|
11043
|
+
var _a, _b, _c, _d;
|
|
10729
11044
|
return __awaiter(this, void 0, void 0, function* () {
|
|
10730
11045
|
if (this.isConnecting ||
|
|
10731
11046
|
(this.isDisconnected && this.client.options.enableWSFallback))
|
|
@@ -10762,7 +11077,7 @@ class StableWSConnection {
|
|
|
10762
11077
|
this.isConnecting = false;
|
|
10763
11078
|
if (response) {
|
|
10764
11079
|
this.connectionID = response.connection_id;
|
|
10765
|
-
this.client.resolveConnectionId(this.connectionID);
|
|
11080
|
+
(_b = (_a = this.client).resolveConnectionId) === null || _b === void 0 ? void 0 : _b.call(_a, this.connectionID);
|
|
10766
11081
|
if (this.client.insightMetrics.wsConsecutiveFailures > 0 &&
|
|
10767
11082
|
this.client.options.enableInsights) {
|
|
10768
11083
|
postInsights('ws_success_after_failure', buildWsSuccessAfterFailureInsight(this));
|
|
@@ -10781,7 +11096,7 @@ class StableWSConnection {
|
|
|
10781
11096
|
const insights = buildWsFatalInsight(this, convertErrorToJson(err));
|
|
10782
11097
|
postInsights === null || postInsights === void 0 ? void 0 : postInsights('ws_fatal', insights);
|
|
10783
11098
|
}
|
|
10784
|
-
this.client.rejectConnectionId();
|
|
11099
|
+
(_d = (_c = this.client).rejectConnectionId) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
10785
11100
|
throw err;
|
|
10786
11101
|
}
|
|
10787
11102
|
});
|
|
@@ -11190,6 +11505,7 @@ class WSConnectionFallback {
|
|
|
11190
11505
|
undefined, {
|
|
11191
11506
|
config: Object.assign(Object.assign({}, config), { cancelToken: (_a = this.cancelToken) === null || _a === void 0 ? void 0 : _a.token }),
|
|
11192
11507
|
params,
|
|
11508
|
+
publicEndpoint: true,
|
|
11193
11509
|
});
|
|
11194
11510
|
this.consecutiveFailures = 0; // always reset in case of no error
|
|
11195
11511
|
return res;
|
|
@@ -11246,6 +11562,7 @@ class WSConnectionFallback {
|
|
|
11246
11562
|
* @param reconnect should be false for first call and true for subsequent calls to keep the connection alive and call recoverState
|
|
11247
11563
|
*/
|
|
11248
11564
|
this.connect = (reconnect = false) => __awaiter(this, void 0, void 0, function* () {
|
|
11565
|
+
var _c, _d, _e, _f;
|
|
11249
11566
|
if (this.state === ConnectionState.Connecting) {
|
|
11250
11567
|
this._log('connect() - connecting already in progress', { reconnect }, 'warn');
|
|
11251
11568
|
return;
|
|
@@ -11262,7 +11579,7 @@ class WSConnectionFallback {
|
|
|
11262
11579
|
}, reconnect);
|
|
11263
11580
|
this._setState(ConnectionState.Connected);
|
|
11264
11581
|
this.connectionID = event.connection_id;
|
|
11265
|
-
this.client.resolveConnectionId();
|
|
11582
|
+
(_d = (_c = this.client).resolveConnectionId) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
11266
11583
|
// @ts-expect-error
|
|
11267
11584
|
this.client.dispatchEvent(event);
|
|
11268
11585
|
this._poll();
|
|
@@ -11270,7 +11587,7 @@ class WSConnectionFallback {
|
|
|
11270
11587
|
}
|
|
11271
11588
|
catch (err) {
|
|
11272
11589
|
this._setState(ConnectionState.Closed);
|
|
11273
|
-
this.client.rejectConnectionId();
|
|
11590
|
+
(_f = (_e = this.client).rejectConnectionId) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
11274
11591
|
throw err;
|
|
11275
11592
|
}
|
|
11276
11593
|
});
|
|
@@ -11281,10 +11598,10 @@ class WSConnectionFallback {
|
|
|
11281
11598
|
return !!this.connectionID && this.state === ConnectionState.Connected;
|
|
11282
11599
|
};
|
|
11283
11600
|
this.disconnect = (timeout = 2000) => __awaiter(this, void 0, void 0, function* () {
|
|
11284
|
-
var
|
|
11601
|
+
var _g;
|
|
11285
11602
|
removeConnectionEventListeners(this._onlineStatusChanged);
|
|
11286
11603
|
this._setState(ConnectionState.Disconnected);
|
|
11287
|
-
(
|
|
11604
|
+
(_g = this.cancelToken) === null || _g === void 0 ? void 0 : _g.cancel('disconnect() is called');
|
|
11288
11605
|
this.cancelToken = undefined;
|
|
11289
11606
|
const connection_id = this.connectionID;
|
|
11290
11607
|
this.connectionID = undefined;
|
|
@@ -11321,7 +11638,7 @@ class WSConnectionFallback {
|
|
|
11321
11638
|
}
|
|
11322
11639
|
}
|
|
11323
11640
|
|
|
11324
|
-
const version = '0.1.
|
|
11641
|
+
const version = '0.1.4';
|
|
11325
11642
|
|
|
11326
11643
|
const logger = getLogger(['location']);
|
|
11327
11644
|
const HINT_URL = `https://hint.stream-io-video.com/`;
|
|
@@ -11498,6 +11815,10 @@ class StreamClient {
|
|
|
11498
11815
|
this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
|
|
11499
11816
|
return Promise.resolve();
|
|
11500
11817
|
}
|
|
11818
|
+
this.connectionIdPromise = new Promise((resolve, reject) => {
|
|
11819
|
+
this.resolveConnectionId = resolve;
|
|
11820
|
+
this.rejectConnectionId = reject;
|
|
11821
|
+
});
|
|
11501
11822
|
this.clientID = `${this.userID}--${randomId()}`;
|
|
11502
11823
|
this.wsPromise = this.connect();
|
|
11503
11824
|
return this.wsPromise;
|
|
@@ -11526,11 +11847,19 @@ class StreamClient {
|
|
|
11526
11847
|
this.anonymous = false;
|
|
11527
11848
|
yield this.closeConnection(timeout);
|
|
11528
11849
|
this.tokenManager.reset();
|
|
11850
|
+
this.connectionIdPromise = undefined;
|
|
11851
|
+
this.rejectConnectionId = undefined;
|
|
11852
|
+
this.resolveConnectionId = undefined;
|
|
11529
11853
|
});
|
|
11530
11854
|
/**
|
|
11531
11855
|
* connectAnonymousUser - Set an anonymous user and open a WebSocket connection
|
|
11532
11856
|
*/
|
|
11533
11857
|
this.connectAnonymousUser = (user, tokenOrProvider) => __awaiter(this, void 0, void 0, function* () {
|
|
11858
|
+
var _g;
|
|
11859
|
+
this.connectionIdPromise = new Promise((resolve, reject) => {
|
|
11860
|
+
this.resolveConnectionId = resolve;
|
|
11861
|
+
this.rejectConnectionId = reject;
|
|
11862
|
+
});
|
|
11534
11863
|
this.anonymous = true;
|
|
11535
11864
|
yield this._setToken(user, tokenOrProvider, this.anonymous);
|
|
11536
11865
|
if (this.resolveConnectPromise) {
|
|
@@ -11542,7 +11871,7 @@ class StreamClient {
|
|
|
11542
11871
|
// some endpoints require a connection_id to be resolved.
|
|
11543
11872
|
// as anonymous users aren't allowed to open WS connections, we just
|
|
11544
11873
|
// resolve the connection_id here.
|
|
11545
|
-
this.resolveConnectionId();
|
|
11874
|
+
(_g = this.resolveConnectionId) === null || _g === void 0 ? void 0 : _g.call(this);
|
|
11546
11875
|
});
|
|
11547
11876
|
/**
|
|
11548
11877
|
* on - Listen to events on all channels and users your watching
|
|
@@ -11605,8 +11934,8 @@ class StreamClient {
|
|
|
11605
11934
|
});
|
|
11606
11935
|
};
|
|
11607
11936
|
this.doAxiosRequest = (type, url, data, options = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
11608
|
-
var
|
|
11609
|
-
if (!options.publicEndpoint
|
|
11937
|
+
var _h;
|
|
11938
|
+
if (!options.publicEndpoint) {
|
|
11610
11939
|
if (this.waitForConnectPromise) {
|
|
11611
11940
|
yield this.waitForConnectPromise;
|
|
11612
11941
|
}
|
|
@@ -11647,7 +11976,7 @@ class StreamClient {
|
|
|
11647
11976
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11648
11977
|
}
|
|
11649
11978
|
catch (e /**TODO: generalize error types */) {
|
|
11650
|
-
e.client_request_id = (
|
|
11979
|
+
e.client_request_id = (_h = requestConfig.headers) === null || _h === void 0 ? void 0 : _h['x-client-request-id'];
|
|
11651
11980
|
this._logApiError(type, url, e);
|
|
11652
11981
|
this.consecutiveFailures += 1;
|
|
11653
11982
|
if (e.response) {
|
|
@@ -11912,12 +12241,6 @@ class StreamClient {
|
|
|
11912
12241
|
keepAliveMsecs: 3000,
|
|
11913
12242
|
});
|
|
11914
12243
|
}
|
|
11915
|
-
this.connectionIdPromise = this.secret
|
|
11916
|
-
? undefined
|
|
11917
|
-
: new Promise((resolve, reject) => {
|
|
11918
|
-
this.resolveConnectionId = resolve;
|
|
11919
|
-
this.rejectConnectionId = reject;
|
|
11920
|
-
});
|
|
11921
12244
|
this.setBaseURL(this.options.baseURL || 'https://video.stream-io-api.com/video');
|
|
11922
12245
|
if (typeof process !== 'undefined' && process.env.STREAM_LOCAL_TEST_RUN) {
|
|
11923
12246
|
this.setBaseURL('http://localhost:3030/video');
|