livekit-client 1.6.4 → 1.6.5
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/dist/livekit-client.esm.mjs +264 -33
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +13 -2
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/proto/livekit_models.d.ts +10 -0
- package/dist/src/proto/livekit_models.d.ts.map +1 -1
- package/dist/src/proto/livekit_rtc.d.ts +2395 -384
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/ts4.2/src/api/SignalClient.d.ts +13 -2
- package/dist/ts4.2/src/proto/livekit_models.d.ts +10 -0
- package/dist/ts4.2/src/proto/livekit_rtc.d.ts +2567 -440
- package/package.json +1 -1
- package/src/api/SignalClient.ts +41 -2
- package/src/proto/livekit_models.ts +51 -0
- package/src/proto/livekit_rtc.ts +210 -3
- package/src/room/RTCEngine.ts +35 -14
- package/src/room/Room.ts +8 -4
- package/src/room/participant/LocalParticipant.ts +7 -3
- package/src/room/track/LocalAudioTrack.ts +5 -1
package/package.json
CHANGED
package/src/api/SignalClient.ts
CHANGED
@@ -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(
|
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, {
|
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;
|
package/src/proto/livekit_rtc.ts
CHANGED
@@ -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 {
|
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;
|
package/src/room/RTCEngine.ts
CHANGED
@@ -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
|
-
|
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(
|
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(
|
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 = (
|
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(
|
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
|
|