livekit-client 1.6.4 → 1.6.5

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livekit-client",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "description": "JavaScript/TypeScript client SDK for LiveKit",
5
5
  "main": "./dist/livekit-client.umd.js",
6
6
  "unpkg": "./dist/livekit-client.umd.js",
@@ -5,6 +5,7 @@ import {
5
5
  ClientInfo,
6
6
  DisconnectReason,
7
7
  ParticipantInfo,
8
+ ReconnectReason,
8
9
  Room,
9
10
  SpeakerInfo,
10
11
  VideoLayer,
@@ -40,6 +41,9 @@ interface ConnectOpts {
40
41
  /** internal */
41
42
  reconnect?: boolean;
42
43
 
44
+ /** internal */
45
+ reconnectReason?: number;
46
+
43
47
  /** internal */
44
48
  sid?: string;
45
49
 
@@ -89,6 +93,9 @@ export class SignalClient {
89
93
 
90
94
  useJSON: boolean;
91
95
 
96
+ /** signal rtt in milliseconds */
97
+ rtt: number = 0;
98
+
92
99
  /** simulate signaling latency by delaying messages */
93
100
  signalLatency?: number;
94
101
 
@@ -166,7 +173,12 @@ export class SignalClient {
166
173
  return res as JoinResponse;
167
174
  }
168
175
 
169
- async reconnect(url: string, token: string, sid?: string): Promise<ReconnectResponse | void> {
176
+ async reconnect(
177
+ url: string,
178
+ token: string,
179
+ sid?: string,
180
+ reason?: ReconnectReason,
181
+ ): Promise<ReconnectResponse | void> {
170
182
  if (!this.options) {
171
183
  log.warn('attempted to reconnect without signal options being set, ignoring');
172
184
  return;
@@ -175,7 +187,12 @@ export class SignalClient {
175
187
  // clear ping interval and restart it once reconnected
176
188
  this.clearPingInterval();
177
189
 
178
- const res = await this.connect(url, token, { ...this.options, reconnect: true, sid });
190
+ const res = await this.connect(url, token, {
191
+ ...this.options,
192
+ reconnect: true,
193
+ sid,
194
+ reconnectReason: reason,
195
+ });
179
196
  return res;
180
197
  }
181
198
 
@@ -440,10 +457,18 @@ export class SignalClient {
440
457
  }
441
458
 
442
459
  sendPing() {
460
+ /** send both of ping and pingReq for compatibility to old and new server */
443
461
  this.sendRequest({
444
462
  $case: 'ping',
445
463
  ping: Date.now(),
446
464
  });
465
+ this.sendRequest({
466
+ $case: 'pingReq',
467
+ pingReq: {
468
+ timestamp: Date.now(),
469
+ rtt: this.rtt,
470
+ },
471
+ });
447
472
  }
448
473
 
449
474
  async sendLeave() {
@@ -563,6 +588,9 @@ export class SignalClient {
563
588
  }
564
589
  } else if (msg.$case === 'pong') {
565
590
  this.resetPingTimeout();
591
+ } else if (msg.$case === 'pongResp') {
592
+ this.rtt = Date.now() - msg.pongResp.lastPingTimestamp;
593
+ this.resetPingTimeout();
566
594
  } else {
567
595
  log.debug('unsupported message', msg);
568
596
  }
@@ -582,6 +610,10 @@ export class SignalClient {
582
610
  log.error('websocket error', ev);
583
611
  }
584
612
 
613
+ /**
614
+ * Resets the ping timeout and starts a new timeout.
615
+ * Call this after receiving a pong message
616
+ */
585
617
  private resetPingTimeout() {
586
618
  this.clearPingTimeout();
587
619
  if (!this.pingTimeoutDuration) {
@@ -600,6 +632,9 @@ export class SignalClient {
600
632
  }, this.pingTimeoutDuration * 1000);
601
633
  }
602
634
 
635
+ /**
636
+ * Clears ping timeout (does not start a new timeout)
637
+ */
603
638
  private clearPingTimeout() {
604
639
  if (this.pingTimeout) {
605
640
  CriticalTimers.clearTimeout(this.pingTimeout);
@@ -698,6 +733,10 @@ function createConnectionParams(token: string, info: ClientInfo, opts: ConnectOp
698
733
  params.set('adaptive_stream', '1');
699
734
  }
700
735
 
736
+ if (opts.reconnectReason) {
737
+ params.set('reconnect_reason', opts.reconnectReason.toString());
738
+ }
739
+
701
740
  // @ts-ignore
702
741
  if (navigator.connection?.type) {
703
742
  // @ts-ignore
@@ -287,6 +287,57 @@ export function disconnectReasonToJSON(object: DisconnectReason): string {
287
287
  }
288
288
  }
289
289
 
290
+ export enum ReconnectReason {
291
+ REASON_UNKOWN = 0,
292
+ REASON_SIGNAL_DISCONNECTED = 1,
293
+ REASON_PUBLISHER_FAILED = 2,
294
+ REASON_SUBSCRIBER_FAILED = 3,
295
+ REASON_SWITCH_CANDIDATE = 4,
296
+ UNRECOGNIZED = -1,
297
+ }
298
+
299
+ export function reconnectReasonFromJSON(object: any): ReconnectReason {
300
+ switch (object) {
301
+ case 0:
302
+ case "REASON_UNKOWN":
303
+ return ReconnectReason.REASON_UNKOWN;
304
+ case 1:
305
+ case "REASON_SIGNAL_DISCONNECTED":
306
+ return ReconnectReason.REASON_SIGNAL_DISCONNECTED;
307
+ case 2:
308
+ case "REASON_PUBLISHER_FAILED":
309
+ return ReconnectReason.REASON_PUBLISHER_FAILED;
310
+ case 3:
311
+ case "REASON_SUBSCRIBER_FAILED":
312
+ return ReconnectReason.REASON_SUBSCRIBER_FAILED;
313
+ case 4:
314
+ case "REASON_SWITCH_CANDIDATE":
315
+ return ReconnectReason.REASON_SWITCH_CANDIDATE;
316
+ case -1:
317
+ case "UNRECOGNIZED":
318
+ default:
319
+ return ReconnectReason.UNRECOGNIZED;
320
+ }
321
+ }
322
+
323
+ export function reconnectReasonToJSON(object: ReconnectReason): string {
324
+ switch (object) {
325
+ case ReconnectReason.REASON_UNKOWN:
326
+ return "REASON_UNKOWN";
327
+ case ReconnectReason.REASON_SIGNAL_DISCONNECTED:
328
+ return "REASON_SIGNAL_DISCONNECTED";
329
+ case ReconnectReason.REASON_PUBLISHER_FAILED:
330
+ return "REASON_PUBLISHER_FAILED";
331
+ case ReconnectReason.REASON_SUBSCRIBER_FAILED:
332
+ return "REASON_SUBSCRIBER_FAILED";
333
+ case ReconnectReason.REASON_SWITCH_CANDIDATE:
334
+ return "REASON_SWITCH_CANDIDATE";
335
+ case ReconnectReason.UNRECOGNIZED:
336
+ default:
337
+ return "UNRECOGNIZED";
338
+ }
339
+ }
340
+
290
341
  export interface Room {
291
342
  sid: string;
292
343
  name: string;
@@ -152,7 +152,8 @@ export interface SignalRequest {
152
152
  | { $case: "syncState"; syncState: SyncState }
153
153
  | { $case: "simulate"; simulate: SimulateScenario }
154
154
  | { $case: "ping"; ping: number }
155
- | { $case: "updateMetadata"; updateMetadata: UpdateParticipantMetadata };
155
+ | { $case: "updateMetadata"; updateMetadata: UpdateParticipantMetadata }
156
+ | { $case: "pingReq"; pingReq: Ping };
156
157
  }
157
158
 
158
159
  export interface SignalResponse {
@@ -174,7 +175,8 @@ export interface SignalResponse {
174
175
  | { $case: "refreshToken"; refreshToken: string }
175
176
  | { $case: "trackUnpublished"; trackUnpublished: TrackUnpublishedResponse }
176
177
  | { $case: "pong"; pong: number }
177
- | { $case: "reconnect"; reconnect: ReconnectResponse };
178
+ | { $case: "reconnect"; reconnect: ReconnectResponse }
179
+ | { $case: "pongResp"; pongResp: Pong };
178
180
  }
179
181
 
180
182
  export interface SimulcastCodec {
@@ -241,6 +243,9 @@ export interface JoinResponse {
241
243
  export interface ReconnectResponse {
242
244
  iceServers: ICEServer[];
243
245
  clientConfiguration?: ClientConfiguration;
246
+ room?: Room;
247
+ participant?: ParticipantInfo;
248
+ otherParticipants: ParticipantInfo[];
244
249
  }
245
250
 
246
251
  export interface TrackPublishedResponse {
@@ -404,6 +409,18 @@ export interface SimulateScenario {
404
409
  | { $case: "switchCandidateProtocol"; switchCandidateProtocol: CandidateProtocol };
405
410
  }
406
411
 
412
+ export interface Ping {
413
+ timestamp: number;
414
+ /** rtt in milliseconds calculated by client */
415
+ rtt: number;
416
+ }
417
+
418
+ export interface Pong {
419
+ /** timestamp field of last received ping request */
420
+ lastPingTimestamp: number;
421
+ timestamp: number;
422
+ }
423
+
407
424
  function createBaseSignalRequest(): SignalRequest {
408
425
  return { message: undefined };
409
426
  }
@@ -452,6 +469,9 @@ export const SignalRequest = {
452
469
  if (message.message?.$case === "updateMetadata") {
453
470
  UpdateParticipantMetadata.encode(message.message.updateMetadata, writer.uint32(122).fork()).ldelim();
454
471
  }
472
+ if (message.message?.$case === "pingReq") {
473
+ Ping.encode(message.message.pingReq, writer.uint32(130).fork()).ldelim();
474
+ }
455
475
  return writer;
456
476
  },
457
477
 
@@ -513,6 +533,9 @@ export const SignalRequest = {
513
533
  updateMetadata: UpdateParticipantMetadata.decode(reader, reader.uint32()),
514
534
  };
515
535
  break;
536
+ case 16:
537
+ message.message = { $case: "pingReq", pingReq: Ping.decode(reader, reader.uint32()) };
538
+ break;
516
539
  default:
517
540
  reader.skipType(tag & 7);
518
541
  break;
@@ -554,6 +577,8 @@ export const SignalRequest = {
554
577
  ? { $case: "ping", ping: Number(object.ping) }
555
578
  : isSet(object.updateMetadata)
556
579
  ? { $case: "updateMetadata", updateMetadata: UpdateParticipantMetadata.fromJSON(object.updateMetadata) }
580
+ : isSet(object.pingReq)
581
+ ? { $case: "pingReq", pingReq: Ping.fromJSON(object.pingReq) }
557
582
  : undefined,
558
583
  };
559
584
  },
@@ -593,6 +618,8 @@ export const SignalRequest = {
593
618
  message.message?.$case === "updateMetadata" && (obj.updateMetadata = message.message?.updateMetadata
594
619
  ? UpdateParticipantMetadata.toJSON(message.message?.updateMetadata)
595
620
  : undefined);
621
+ message.message?.$case === "pingReq" &&
622
+ (obj.pingReq = message.message?.pingReq ? Ping.toJSON(message.message?.pingReq) : undefined);
596
623
  return obj;
597
624
  },
598
625
 
@@ -689,6 +716,11 @@ export const SignalRequest = {
689
716
  updateMetadata: UpdateParticipantMetadata.fromPartial(object.message.updateMetadata),
690
717
  };
691
718
  }
719
+ if (
720
+ object.message?.$case === "pingReq" && object.message?.pingReq !== undefined && object.message?.pingReq !== null
721
+ ) {
722
+ message.message = { $case: "pingReq", pingReq: Ping.fromPartial(object.message.pingReq) };
723
+ }
692
724
  return message;
693
725
  },
694
726
  };
@@ -754,6 +786,9 @@ export const SignalResponse = {
754
786
  if (message.message?.$case === "reconnect") {
755
787
  ReconnectResponse.encode(message.message.reconnect, writer.uint32(154).fork()).ldelim();
756
788
  }
789
+ if (message.message?.$case === "pongResp") {
790
+ Pong.encode(message.message.pongResp, writer.uint32(162).fork()).ldelim();
791
+ }
757
792
  return writer;
758
793
  },
759
794
 
@@ -839,6 +874,9 @@ export const SignalResponse = {
839
874
  case 19:
840
875
  message.message = { $case: "reconnect", reconnect: ReconnectResponse.decode(reader, reader.uint32()) };
841
876
  break;
877
+ case 20:
878
+ message.message = { $case: "pongResp", pongResp: Pong.decode(reader, reader.uint32()) };
879
+ break;
842
880
  default:
843
881
  reader.skipType(tag & 7);
844
882
  break;
@@ -891,6 +929,8 @@ export const SignalResponse = {
891
929
  ? { $case: "pong", pong: Number(object.pong) }
892
930
  : isSet(object.reconnect)
893
931
  ? { $case: "reconnect", reconnect: ReconnectResponse.fromJSON(object.reconnect) }
932
+ : isSet(object.pongResp)
933
+ ? { $case: "pongResp", pongResp: Pong.fromJSON(object.pongResp) }
894
934
  : undefined,
895
935
  };
896
936
  },
@@ -940,6 +980,8 @@ export const SignalResponse = {
940
980
  message.message?.$case === "pong" && (obj.pong = Math.round(message.message?.pong));
941
981
  message.message?.$case === "reconnect" &&
942
982
  (obj.reconnect = message.message?.reconnect ? ReconnectResponse.toJSON(message.message?.reconnect) : undefined);
983
+ message.message?.$case === "pongResp" &&
984
+ (obj.pongResp = message.message?.pongResp ? Pong.toJSON(message.message?.pongResp) : undefined);
943
985
  return obj;
944
986
  },
945
987
 
@@ -1064,6 +1106,13 @@ export const SignalResponse = {
1064
1106
  ) {
1065
1107
  message.message = { $case: "reconnect", reconnect: ReconnectResponse.fromPartial(object.message.reconnect) };
1066
1108
  }
1109
+ if (
1110
+ object.message?.$case === "pongResp" &&
1111
+ object.message?.pongResp !== undefined &&
1112
+ object.message?.pongResp !== null
1113
+ ) {
1114
+ message.message = { $case: "pongResp", pongResp: Pong.fromPartial(object.message.pongResp) };
1115
+ }
1067
1116
  return message;
1068
1117
  },
1069
1118
  };
@@ -1626,7 +1675,13 @@ export const JoinResponse = {
1626
1675
  };
1627
1676
 
1628
1677
  function createBaseReconnectResponse(): ReconnectResponse {
1629
- return { iceServers: [], clientConfiguration: undefined };
1678
+ return {
1679
+ iceServers: [],
1680
+ clientConfiguration: undefined,
1681
+ room: undefined,
1682
+ participant: undefined,
1683
+ otherParticipants: [],
1684
+ };
1630
1685
  }
1631
1686
 
1632
1687
  export const ReconnectResponse = {
@@ -1637,6 +1692,15 @@ export const ReconnectResponse = {
1637
1692
  if (message.clientConfiguration !== undefined) {
1638
1693
  ClientConfiguration.encode(message.clientConfiguration, writer.uint32(18).fork()).ldelim();
1639
1694
  }
1695
+ if (message.room !== undefined) {
1696
+ Room.encode(message.room, writer.uint32(26).fork()).ldelim();
1697
+ }
1698
+ if (message.participant !== undefined) {
1699
+ ParticipantInfo.encode(message.participant, writer.uint32(34).fork()).ldelim();
1700
+ }
1701
+ for (const v of message.otherParticipants) {
1702
+ ParticipantInfo.encode(v!, writer.uint32(42).fork()).ldelim();
1703
+ }
1640
1704
  return writer;
1641
1705
  },
1642
1706
 
@@ -1653,6 +1717,15 @@ export const ReconnectResponse = {
1653
1717
  case 2:
1654
1718
  message.clientConfiguration = ClientConfiguration.decode(reader, reader.uint32());
1655
1719
  break;
1720
+ case 3:
1721
+ message.room = Room.decode(reader, reader.uint32());
1722
+ break;
1723
+ case 4:
1724
+ message.participant = ParticipantInfo.decode(reader, reader.uint32());
1725
+ break;
1726
+ case 5:
1727
+ message.otherParticipants.push(ParticipantInfo.decode(reader, reader.uint32()));
1728
+ break;
1656
1729
  default:
1657
1730
  reader.skipType(tag & 7);
1658
1731
  break;
@@ -1667,6 +1740,11 @@ export const ReconnectResponse = {
1667
1740
  clientConfiguration: isSet(object.clientConfiguration)
1668
1741
  ? ClientConfiguration.fromJSON(object.clientConfiguration)
1669
1742
  : undefined,
1743
+ room: isSet(object.room) ? Room.fromJSON(object.room) : undefined,
1744
+ participant: isSet(object.participant) ? ParticipantInfo.fromJSON(object.participant) : undefined,
1745
+ otherParticipants: Array.isArray(object?.otherParticipants)
1746
+ ? object.otherParticipants.map((e: any) => ParticipantInfo.fromJSON(e))
1747
+ : [],
1670
1748
  };
1671
1749
  },
1672
1750
 
@@ -1680,6 +1758,14 @@ export const ReconnectResponse = {
1680
1758
  message.clientConfiguration !== undefined && (obj.clientConfiguration = message.clientConfiguration
1681
1759
  ? ClientConfiguration.toJSON(message.clientConfiguration)
1682
1760
  : undefined);
1761
+ message.room !== undefined && (obj.room = message.room ? Room.toJSON(message.room) : undefined);
1762
+ message.participant !== undefined &&
1763
+ (obj.participant = message.participant ? ParticipantInfo.toJSON(message.participant) : undefined);
1764
+ if (message.otherParticipants) {
1765
+ obj.otherParticipants = message.otherParticipants.map((e) => e ? ParticipantInfo.toJSON(e) : undefined);
1766
+ } else {
1767
+ obj.otherParticipants = [];
1768
+ }
1683
1769
  return obj;
1684
1770
  },
1685
1771
 
@@ -1689,6 +1775,11 @@ export const ReconnectResponse = {
1689
1775
  message.clientConfiguration = (object.clientConfiguration !== undefined && object.clientConfiguration !== null)
1690
1776
  ? ClientConfiguration.fromPartial(object.clientConfiguration)
1691
1777
  : undefined;
1778
+ message.room = (object.room !== undefined && object.room !== null) ? Room.fromPartial(object.room) : undefined;
1779
+ message.participant = (object.participant !== undefined && object.participant !== null)
1780
+ ? ParticipantInfo.fromPartial(object.participant)
1781
+ : undefined;
1782
+ message.otherParticipants = object.otherParticipants?.map((e) => ParticipantInfo.fromPartial(e)) || [];
1692
1783
  return message;
1693
1784
  },
1694
1785
  };
@@ -3388,6 +3479,122 @@ export const SimulateScenario = {
3388
3479
  },
3389
3480
  };
3390
3481
 
3482
+ function createBasePing(): Ping {
3483
+ return { timestamp: 0, rtt: 0 };
3484
+ }
3485
+
3486
+ export const Ping = {
3487
+ encode(message: Ping, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
3488
+ if (message.timestamp !== 0) {
3489
+ writer.uint32(8).int64(message.timestamp);
3490
+ }
3491
+ if (message.rtt !== 0) {
3492
+ writer.uint32(16).int64(message.rtt);
3493
+ }
3494
+ return writer;
3495
+ },
3496
+
3497
+ decode(input: _m0.Reader | Uint8Array, length?: number): Ping {
3498
+ const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
3499
+ let end = length === undefined ? reader.len : reader.pos + length;
3500
+ const message = createBasePing();
3501
+ while (reader.pos < end) {
3502
+ const tag = reader.uint32();
3503
+ switch (tag >>> 3) {
3504
+ case 1:
3505
+ message.timestamp = longToNumber(reader.int64() as Long);
3506
+ break;
3507
+ case 2:
3508
+ message.rtt = longToNumber(reader.int64() as Long);
3509
+ break;
3510
+ default:
3511
+ reader.skipType(tag & 7);
3512
+ break;
3513
+ }
3514
+ }
3515
+ return message;
3516
+ },
3517
+
3518
+ fromJSON(object: any): Ping {
3519
+ return {
3520
+ timestamp: isSet(object.timestamp) ? Number(object.timestamp) : 0,
3521
+ rtt: isSet(object.rtt) ? Number(object.rtt) : 0,
3522
+ };
3523
+ },
3524
+
3525
+ toJSON(message: Ping): unknown {
3526
+ const obj: any = {};
3527
+ message.timestamp !== undefined && (obj.timestamp = Math.round(message.timestamp));
3528
+ message.rtt !== undefined && (obj.rtt = Math.round(message.rtt));
3529
+ return obj;
3530
+ },
3531
+
3532
+ fromPartial<I extends Exact<DeepPartial<Ping>, I>>(object: I): Ping {
3533
+ const message = createBasePing();
3534
+ message.timestamp = object.timestamp ?? 0;
3535
+ message.rtt = object.rtt ?? 0;
3536
+ return message;
3537
+ },
3538
+ };
3539
+
3540
+ function createBasePong(): Pong {
3541
+ return { lastPingTimestamp: 0, timestamp: 0 };
3542
+ }
3543
+
3544
+ export const Pong = {
3545
+ encode(message: Pong, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
3546
+ if (message.lastPingTimestamp !== 0) {
3547
+ writer.uint32(8).int64(message.lastPingTimestamp);
3548
+ }
3549
+ if (message.timestamp !== 0) {
3550
+ writer.uint32(16).int64(message.timestamp);
3551
+ }
3552
+ return writer;
3553
+ },
3554
+
3555
+ decode(input: _m0.Reader | Uint8Array, length?: number): Pong {
3556
+ const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
3557
+ let end = length === undefined ? reader.len : reader.pos + length;
3558
+ const message = createBasePong();
3559
+ while (reader.pos < end) {
3560
+ const tag = reader.uint32();
3561
+ switch (tag >>> 3) {
3562
+ case 1:
3563
+ message.lastPingTimestamp = longToNumber(reader.int64() as Long);
3564
+ break;
3565
+ case 2:
3566
+ message.timestamp = longToNumber(reader.int64() as Long);
3567
+ break;
3568
+ default:
3569
+ reader.skipType(tag & 7);
3570
+ break;
3571
+ }
3572
+ }
3573
+ return message;
3574
+ },
3575
+
3576
+ fromJSON(object: any): Pong {
3577
+ return {
3578
+ lastPingTimestamp: isSet(object.lastPingTimestamp) ? Number(object.lastPingTimestamp) : 0,
3579
+ timestamp: isSet(object.timestamp) ? Number(object.timestamp) : 0,
3580
+ };
3581
+ },
3582
+
3583
+ toJSON(message: Pong): unknown {
3584
+ const obj: any = {};
3585
+ message.lastPingTimestamp !== undefined && (obj.lastPingTimestamp = Math.round(message.lastPingTimestamp));
3586
+ message.timestamp !== undefined && (obj.timestamp = Math.round(message.timestamp));
3587
+ return obj;
3588
+ },
3589
+
3590
+ fromPartial<I extends Exact<DeepPartial<Pong>, I>>(object: I): Pong {
3591
+ const message = createBasePong();
3592
+ message.lastPingTimestamp = object.lastPingTimestamp ?? 0;
3593
+ message.timestamp = object.timestamp ?? 0;
3594
+ return message;
3595
+ },
3596
+ };
3597
+
3391
3598
  declare var self: any | undefined;
3392
3599
  declare var window: any | undefined;
3393
3600
  declare var global: any | undefined;
@@ -9,6 +9,7 @@ import {
9
9
  DataPacket,
10
10
  DataPacket_Kind,
11
11
  DisconnectReason,
12
+ ReconnectReason,
12
13
  SpeakerInfo,
13
14
  TrackInfo,
14
15
  UserPacket,
@@ -305,7 +306,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
305
306
 
306
307
  let primaryPC = this.publisher.pc;
307
308
  let secondaryPC = this.subscriber.pc;
308
- if (joinResponse.subscriberPrimary) {
309
+ let subscriberPrimary = joinResponse.subscriberPrimary;
310
+ if (subscriberPrimary) {
309
311
  primaryPC = this.subscriber.pc;
310
312
  secondaryPC = this.publisher.pc;
311
313
  // in subscriber primary mode, server side opens sub data channels.
@@ -330,7 +332,13 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
330
332
  if (this.pcState === PCState.Connected) {
331
333
  this.pcState = PCState.Disconnected;
332
334
 
333
- this.handleDisconnect('primary peerconnection');
335
+ this.handleDisconnect(
336
+ 'primary peerconnection',
337
+ false,
338
+ subscriberPrimary
339
+ ? ReconnectReason.REASON_SUBSCRIBER_FAILED
340
+ : ReconnectReason.REASON_PUBLISHER_FAILED,
341
+ );
334
342
  }
335
343
  }
336
344
  };
@@ -338,7 +346,13 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
338
346
  log.debug(`secondary PC state changed ${secondaryPC.connectionState}`);
339
347
  // also reconnect if secondary peerconnection fails
340
348
  if (secondaryPC.connectionState === 'failed') {
341
- this.handleDisconnect('secondary peerconnection');
349
+ this.handleDisconnect(
350
+ 'secondary peerconnection',
351
+ false,
352
+ subscriberPrimary
353
+ ? ReconnectReason.REASON_PUBLISHER_FAILED
354
+ : ReconnectReason.REASON_SUBSCRIBER_FAILED,
355
+ );
342
356
  }
343
357
  };
344
358
 
@@ -405,7 +419,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
405
419
  };
406
420
 
407
421
  this.client.onClose = () => {
408
- this.handleDisconnect('signal');
422
+ this.handleDisconnect('signal', false, ReconnectReason.REASON_SIGNAL_DISCONNECTED);
409
423
  };
410
424
 
411
425
  this.client.onLeave = (leave?: LeaveRequest) => {
@@ -676,7 +690,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
676
690
  // websocket reconnect behavior. if websocket is interrupted, and the PeerConnection
677
691
  // continues to work, we can reconnect to websocket to continue the session
678
692
  // after a number of retries, we'll close and give up permanently
679
- private handleDisconnect = (connection: string, signalEvents: boolean = false) => {
693
+ private handleDisconnect = (
694
+ connection: string,
695
+ signalEvents: boolean = false,
696
+ disconnectReason?: ReconnectReason,
697
+ ) => {
680
698
  if (this._isClosed) {
681
699
  return;
682
700
  }
@@ -713,12 +731,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
713
731
 
714
732
  this.clearReconnectTimeout();
715
733
  this.reconnectTimeout = CriticalTimers.setTimeout(
716
- () => this.attemptReconnect(signalEvents),
734
+ () => this.attemptReconnect(signalEvents, disconnectReason),
717
735
  delay,
718
736
  );
719
737
  };
720
738
 
721
- private async attemptReconnect(signalEvents: boolean = false) {
739
+ private async attemptReconnect(signalEvents: boolean = false, reason?: ReconnectReason) {
722
740
  if (this._isClosed) {
723
741
  return;
724
742
  }
@@ -740,7 +758,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
740
758
  if (this.fullReconnectOnNext) {
741
759
  await this.restartConnection(signalEvents);
742
760
  } else {
743
- await this.resumeConnection(signalEvents);
761
+ await this.resumeConnection(signalEvents, reason);
744
762
  }
745
763
  this.clearPendingReconnect();
746
764
  this.fullReconnectOnNext = false;
@@ -766,7 +784,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
766
784
  }
767
785
 
768
786
  if (recoverable) {
769
- this.handleDisconnect('reconnect', requireSignalEvents);
787
+ this.handleDisconnect('reconnect', requireSignalEvents, ReconnectReason.REASON_UNKOWN);
770
788
  } else {
771
789
  log.info(
772
790
  `could not recover connection after ${this.reconnectAttempts} attempts, ${
@@ -831,7 +849,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
831
849
  this.emit(EngineEvent.Restarted, joinResponse);
832
850
  }
833
851
 
834
- private async resumeConnection(emitResuming: boolean = false): Promise<void> {
852
+ private async resumeConnection(
853
+ emitResuming: boolean = false,
854
+ reason?: ReconnectReason,
855
+ ): Promise<void> {
835
856
  if (!this.url || !this.token) {
836
857
  // permanent failure, don't attempt reconnection
837
858
  throw new UnexpectedConnectionState('could not reconnect, url or token not saved');
@@ -847,7 +868,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
847
868
  }
848
869
 
849
870
  try {
850
- const res = await this.client.reconnect(this.url, this.token, this.participantSid);
871
+ const res = await this.client.reconnect(this.url, this.token, this.participantSid, reason);
851
872
  if (res) {
852
873
  const rtcConfig = this.makeRTCConfiguration(res);
853
874
  this.publisher.pc.setConfiguration(rtcConfig);
@@ -1001,7 +1022,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1001
1022
 
1002
1023
  const negotiationTimeout = setTimeout(() => {
1003
1024
  reject('negotiation timed out');
1004
- this.handleDisconnect('negotiation');
1025
+ this.handleDisconnect('negotiation', false, ReconnectReason.REASON_SIGNAL_DISCONNECTED);
1005
1026
  }, this.peerConnectionTimeout);
1006
1027
 
1007
1028
  const cleanup = () => {
@@ -1022,7 +1043,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1022
1043
  if (e instanceof NegotiationError) {
1023
1044
  this.fullReconnectOnNext = true;
1024
1045
  }
1025
- this.handleDisconnect('negotiation');
1046
+ this.handleDisconnect('negotiation', false, ReconnectReason.REASON_UNKOWN);
1026
1047
  });
1027
1048
  });
1028
1049
  }
@@ -1060,7 +1081,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1060
1081
  // in case the engine is currently reconnecting, attempt a reconnect immediately after the browser state has changed to 'onLine'
1061
1082
  if (this.client.isReconnecting) {
1062
1083
  this.clearReconnectTimeout();
1063
- this.attemptReconnect(true);
1084
+ this.attemptReconnect(true, ReconnectReason.REASON_SIGNAL_DISCONNECTED);
1064
1085
  }
1065
1086
  };
1066
1087