@webex/plugin-meetings 3.10.0 → 3.11.0
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/annotation/annotation.types.js.map +1 -1
- package/dist/annotation/constants.js.map +1 -1
- package/dist/annotation/index.js +19 -22
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +6 -6
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/collection.js.map +1 -1
- package/dist/breakouts/edit-lock-error.js +9 -11
- package/dist/breakouts/edit-lock-error.js.map +1 -1
- package/dist/breakouts/events.js.map +1 -1
- package/dist/breakouts/index.js +126 -127
- package/dist/breakouts/index.js.map +1 -1
- package/dist/breakouts/request.js +6 -8
- package/dist/breakouts/request.js.map +1 -1
- package/dist/breakouts/utils.js.map +1 -1
- package/dist/common/browser-detection.js.map +1 -1
- package/dist/common/collection.js +1 -2
- package/dist/common/collection.js.map +1 -1
- package/dist/common/config.js.map +1 -1
- package/dist/common/errors/captcha-error.js +9 -11
- package/dist/common/errors/captcha-error.js.map +1 -1
- package/dist/common/errors/intent-to-join.js +10 -12
- package/dist/common/errors/intent-to-join.js.map +1 -1
- package/dist/common/errors/join-forbidden-error.js +10 -12
- package/dist/common/errors/join-forbidden-error.js.map +1 -1
- package/dist/common/errors/join-meeting.js +10 -12
- package/dist/common/errors/join-meeting.js.map +1 -1
- package/dist/common/errors/join-webinar-error.js +9 -11
- package/dist/common/errors/join-webinar-error.js.map +1 -1
- package/dist/common/errors/media.js +9 -11
- package/dist/common/errors/media.js.map +1 -1
- package/dist/common/errors/multistream-not-supported-error.js +9 -11
- package/dist/common/errors/multistream-not-supported-error.js.map +1 -1
- package/dist/common/errors/no-meeting-info.js +9 -11
- package/dist/common/errors/no-meeting-info.js.map +1 -1
- package/dist/common/errors/parameter.js +11 -14
- package/dist/common/errors/parameter.js.map +1 -1
- package/dist/common/errors/password-error.js +9 -11
- package/dist/common/errors/password-error.js.map +1 -1
- package/dist/common/errors/permission.js +9 -11
- package/dist/common/errors/permission.js.map +1 -1
- package/dist/common/errors/reclaim-host-role-errors.js +32 -38
- package/dist/common/errors/reclaim-host-role-errors.js.map +1 -1
- package/dist/common/errors/reconnection-not-started.js +5 -6
- package/dist/common/errors/reconnection-not-started.js.map +1 -1
- package/dist/common/errors/reconnection.js +9 -11
- package/dist/common/errors/reconnection.js.map +1 -1
- package/dist/common/errors/stats.js +9 -11
- package/dist/common/errors/stats.js.map +1 -1
- package/dist/common/errors/webex-errors.js +38 -27
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/errors/webex-meetings-error.js +9 -12
- package/dist/common/errors/webex-meetings-error.js.map +1 -1
- package/dist/common/events/events-scope.js +9 -10
- package/dist/common/events/events-scope.js.map +1 -1
- package/dist/common/events/events.js +9 -10
- package/dist/common/events/events.js.map +1 -1
- package/dist/common/events/trigger-proxy.js.map +1 -1
- package/dist/common/events/util.js.map +1 -1
- package/dist/common/logs/logger-config.js.map +1 -1
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +17 -17
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +1 -2
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/constants.js +13 -8
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +1 -2
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +1 -2
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/hashTree/constants.js +20 -0
- package/dist/hashTree/constants.js.map +1 -0
- package/dist/hashTree/hashTree.js +515 -0
- package/dist/hashTree/hashTree.js.map +1 -0
- package/dist/hashTree/hashTreeParser.js +1250 -0
- package/dist/hashTree/hashTreeParser.js.map +1 -0
- package/dist/hashTree/types.js +23 -0
- package/dist/hashTree/types.js.map +1 -0
- package/dist/hashTree/utils.js +59 -0
- package/dist/hashTree/utils.js.map +1 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/locusRetry.js +6 -8
- package/dist/interceptors/locusRetry.js.map +1 -1
- package/dist/interceptors/locusRouteToken.js +33 -13
- package/dist/interceptors/locusRouteToken.js.map +1 -1
- package/dist/interpretation/collection.js.map +1 -1
- package/dist/interpretation/index.js +1 -2
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/interpretation/siLanguage.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +5 -3
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/hostUtils.js.map +1 -1
- package/dist/locus-info/index.js +619 -177
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +3 -4
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/locus-info/types.js +7 -0
- package/dist/locus-info/types.js.map +1 -0
- package/dist/media/MediaConnectionAwaiter.js +1 -2
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/index.js +5 -2
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +15 -17
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.js.map +1 -1
- package/dist/meeting/brbState.js +8 -9
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/connectionStateHandler.js +10 -13
- package/dist/meeting/connectionStateHandler.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1632 -1535
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +13 -17
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +11 -12
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +101 -104
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/state.js.map +1 -1
- package/dist/meeting/type.js.map +1 -1
- package/dist/meeting/util.js +24 -23
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting/voicea-meeting.js +3 -3
- package/dist/meeting/voicea-meeting.js.map +1 -1
- package/dist/meeting-info/collection.js +7 -10
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.js +1 -2
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +135 -146
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.js +1 -2
- package/dist/meeting-info/request.js.map +1 -1
- package/dist/meeting-info/util.js +36 -37
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +30 -31
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +6 -8
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +200 -148
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js.map +1 -1
- package/dist/meetings/request.js +6 -8
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +36 -30
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +1 -2
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +6 -3
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +1 -2
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +18 -21
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +8 -11
- package/dist/members/request.js.map +1 -1
- package/dist/members/types.js.map +1 -1
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +4 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +3 -4
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -2
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +34 -45
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +8 -9
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +12 -15
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +1 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +122 -123
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +29 -30
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/personal-meeting-room/index.js +16 -19
- package/dist/personal-meeting-room/index.js.map +1 -1
- package/dist/personal-meeting-room/request.js +7 -10
- package/dist/personal-meeting-room/request.js.map +1 -1
- package/dist/personal-meeting-room/util.js.map +1 -1
- package/dist/reachability/clusterReachability.js +188 -352
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +206 -206
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +14 -1
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/reachability/reachabilityPeerConnection.js +445 -0
- package/dist/reachability/reachabilityPeerConnection.js.map +1 -0
- package/dist/reachability/request.js.map +1 -1
- package/dist/reachability/util.js.map +1 -1
- package/dist/reactions/constants.js.map +1 -1
- package/dist/reactions/reactions.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +178 -176
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.js +1 -2
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +12 -15
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +24 -26
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +75 -76
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js.map +1 -1
- package/dist/transcription/index.js +4 -5
- package/dist/transcription/index.js.map +1 -1
- package/dist/types/common/errors/webex-errors.d.ts +12 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/constants.d.ts +27 -21
- package/dist/types/hashTree/constants.d.ts +8 -0
- package/dist/types/hashTree/hashTree.d.ts +129 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +250 -0
- package/dist/types/hashTree/types.d.ts +33 -0
- package/dist/types/hashTree/utils.d.ts +16 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/interceptors/locusRouteToken.d.ts +2 -0
- package/dist/types/locus-info/index.d.ts +98 -80
- package/dist/types/locus-info/types.d.ts +54 -0
- package/dist/types/meeting/index.d.ts +35 -9
- package/dist/types/meetings/index.d.ts +9 -2
- package/dist/types/metrics/constants.d.ts +3 -0
- package/dist/types/reachability/clusterReachability.d.ts +33 -84
- package/dist/types/reachability/reachability.types.d.ts +12 -1
- package/dist/types/reachability/reachabilityPeerConnection.d.ts +111 -0
- package/dist/webinar/collection.js +1 -2
- package/dist/webinar/collection.js.map +1 -1
- package/dist/webinar/index.js +148 -158
- package/dist/webinar/index.js.map +1 -1
- package/package.json +24 -23
- package/src/common/errors/webex-errors.ts +19 -0
- package/src/config.ts +1 -0
- package/src/constants.ts +15 -2
- package/src/hashTree/constants.ts +9 -0
- package/src/hashTree/hashTree.ts +463 -0
- package/src/hashTree/hashTreeParser.ts +1143 -0
- package/src/hashTree/types.ts +39 -0
- package/src/hashTree/utils.ts +53 -0
- package/src/index.ts +2 -0
- package/src/interceptors/locusRouteToken.ts +22 -5
- package/src/locus-info/controlsUtils.ts +6 -0
- package/src/locus-info/index.ts +641 -164
- package/src/locus-info/types.ts +53 -0
- package/src/media/index.ts +6 -0
- package/src/meeting/index.ts +137 -28
- package/src/meeting/util.ts +1 -0
- package/src/meetings/index.ts +119 -59
- package/src/meetings/util.ts +10 -9
- package/src/metrics/constants.ts +3 -0
- package/src/reachability/clusterReachability.ts +159 -330
- package/src/reachability/index.ts +6 -1
- package/src/reachability/reachability.types.ts +15 -1
- package/src/reachability/reachabilityPeerConnection.ts +418 -0
- package/test/unit/spec/hashTree/hashTree.ts +655 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +1524 -0
- package/test/unit/spec/hashTree/utils.ts +140 -0
- package/test/unit/spec/interceptors/locusRouteToken.ts +44 -0
- package/test/unit/spec/locus-info/controlsUtils.js +27 -1
- package/test/unit/spec/locus-info/index.js +879 -16
- package/test/unit/spec/media/index.ts +140 -9
- package/test/unit/spec/meeting/index.js +299 -94
- package/test/unit/spec/meeting/utils.js +78 -1
- package/test/unit/spec/meetings/index.js +263 -29
- package/test/unit/spec/meetings/utils.js +51 -1
- package/test/unit/spec/reachability/clusterReachability.ts +404 -137
- package/test/unit/spec/reachability/index.ts +3 -3
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {Defer} from '@webex/common';
|
|
2
|
-
|
|
3
|
-
import LoggerProxy from '../common/logs/logger-proxy';
|
|
4
1
|
import {ClusterNode} from './request';
|
|
5
|
-
import {convertStunUrlToTurn, convertStunUrlToTurnTls} from './util';
|
|
6
2
|
import EventsScope from '../common/events/events-scope';
|
|
3
|
+
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
4
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import {Enum} from '../constants';
|
|
6
|
+
import {
|
|
7
|
+
ClusterReachabilityResult,
|
|
8
|
+
NatType,
|
|
9
|
+
ReachabilityPeerConnectionEvents,
|
|
10
|
+
} from './reachability.types';
|
|
11
|
+
import {ReachabilityPeerConnection} from './reachabilityPeerConnection';
|
|
10
12
|
|
|
11
13
|
// data for the Events.resultReady event
|
|
12
14
|
export type ResultEventData = {
|
|
@@ -36,398 +38,225 @@ export type Events = Enum<typeof Events>;
|
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
40
|
* A class that handles reachability checks for a single cluster.
|
|
39
|
-
*
|
|
41
|
+
* Creates and orchestrates ReachabilityPeerConnection instance(s).
|
|
42
|
+
* Listens to events and emits them to consumers.
|
|
43
|
+
*
|
|
44
|
+
* When enablePerUdpUrlReachability is true:
|
|
45
|
+
* - Creates one ReachabilityPeerConnection for each UDP URL
|
|
46
|
+
* - Creates one ReachabilityPeerConnection for all TCP and TLS URLs together
|
|
47
|
+
* Otherwise:
|
|
48
|
+
* - Creates a single ReachabilityPeerConnection for all URLs
|
|
40
49
|
*/
|
|
41
50
|
export class ClusterReachability extends EventsScope {
|
|
42
|
-
private
|
|
43
|
-
private
|
|
44
|
-
|
|
45
|
-
private result: ClusterReachabilityResult;
|
|
46
|
-
private pc?: RTCPeerConnection;
|
|
47
|
-
private defer: Defer; // this defer is resolved once reachability checks for this cluster are completed
|
|
48
|
-
private startTimestamp: number;
|
|
49
|
-
private srflxIceCandidates: RTCIceCandidate[] = [];
|
|
51
|
+
private reachabilityPeerConnection: ReachabilityPeerConnection | null = null;
|
|
52
|
+
private reachabilityPeerConnectionsForUdp: ReachabilityPeerConnection[] = [];
|
|
53
|
+
|
|
50
54
|
public readonly isVideoMesh: boolean;
|
|
51
55
|
public readonly name;
|
|
52
56
|
public readonly reachedSubnets: Set<string> = new Set();
|
|
53
57
|
|
|
58
|
+
private enablePerUdpUrlReachability: boolean;
|
|
59
|
+
private udpResultEmitted = false;
|
|
60
|
+
|
|
54
61
|
/**
|
|
55
62
|
* Constructor for ClusterReachability
|
|
56
63
|
* @param {string} name cluster name
|
|
57
64
|
* @param {ClusterNode} clusterInfo information about the media cluster
|
|
65
|
+
* @param {boolean} enablePerUdpUrlReachability whether to create separate peer connections per UDP URL
|
|
58
66
|
*/
|
|
59
|
-
constructor(name: string, clusterInfo: ClusterNode) {
|
|
67
|
+
constructor(name: string, clusterInfo: ClusterNode, enablePerUdpUrlReachability = false) {
|
|
60
68
|
super();
|
|
61
69
|
this.name = name;
|
|
62
70
|
this.isVideoMesh = clusterInfo.isVideoMesh;
|
|
63
|
-
this.
|
|
64
|
-
this.numTcpUrls = clusterInfo.tcp.length;
|
|
65
|
-
this.numXTlsUrls = clusterInfo.xtls.length;
|
|
71
|
+
this.enablePerUdpUrlReachability = enablePerUdpUrlReachability;
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
result: 'untested',
|
|
73
|
-
},
|
|
74
|
-
tcp: {
|
|
75
|
-
result: 'untested',
|
|
76
|
-
},
|
|
77
|
-
xtls: {
|
|
78
|
-
result: 'untested',
|
|
79
|
-
},
|
|
80
|
-
};
|
|
73
|
+
if (this.enablePerUdpUrlReachability) {
|
|
74
|
+
this.initializePerUdpUrlReachabilityCheck(clusterInfo);
|
|
75
|
+
} else {
|
|
76
|
+
this.initializeSingleReachabilityPeerConnection(clusterInfo);
|
|
77
|
+
}
|
|
81
78
|
}
|
|
82
79
|
|
|
83
80
|
/**
|
|
84
|
-
*
|
|
85
|
-
* @
|
|
81
|
+
* Initializes a single ReachabilityPeerConnection for all protocols
|
|
82
|
+
* @param {ClusterNode} clusterInfo information about the media cluster
|
|
83
|
+
* @returns {void}
|
|
86
84
|
*/
|
|
87
|
-
private
|
|
88
|
-
|
|
85
|
+
private initializeSingleReachabilityPeerConnection(clusterInfo: ClusterNode) {
|
|
86
|
+
this.reachabilityPeerConnection = new ReachabilityPeerConnection(this.name, clusterInfo);
|
|
87
|
+
this.setupReachabilityPeerConnectionEventListeners(this.reachabilityPeerConnection);
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
91
|
+
* Initializes per-URL UDP reachability checks:
|
|
92
|
+
* - One ReachabilityPeerConnection per UDP URL
|
|
93
|
+
* - One ReachabilityPeerConnection for all TCP and TLS URLs together
|
|
94
|
+
* @param {ClusterNode} clusterInfo information about the media cluster
|
|
95
|
+
* @returns {void}
|
|
95
96
|
*/
|
|
96
|
-
private
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
username: 'webexturnreachuser',
|
|
109
|
-
credential: 'webexturnreachpwd',
|
|
110
|
-
urls: [convertStunUrlToTurn(urlString, 'tcp')],
|
|
97
|
+
private initializePerUdpUrlReachabilityCheck(clusterInfo: ClusterNode) {
|
|
98
|
+
LoggerProxy.logger.log(
|
|
99
|
+
`ClusterReachability#initializePerUdpUrlReachabilityCheck --> cluster: ${this.name}, performing per-URL UDP reachability for ${clusterInfo.udp.length} URLs`
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Create one ReachabilityPeerConnection for each UDP URL
|
|
103
|
+
clusterInfo.udp.forEach((udpUrl) => {
|
|
104
|
+
const singleUdpClusterInfo: ClusterNode = {
|
|
105
|
+
isVideoMesh: clusterInfo.isVideoMesh,
|
|
106
|
+
udp: [udpUrl],
|
|
107
|
+
tcp: [],
|
|
108
|
+
xtls: [],
|
|
111
109
|
};
|
|
110
|
+
const rpc = new ReachabilityPeerConnection(this.name, singleUdpClusterInfo);
|
|
111
|
+
this.setupReachabilityPeerConnectionEventListeners(rpc, true);
|
|
112
|
+
this.reachabilityPeerConnectionsForUdp.push(rpc);
|
|
112
113
|
});
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
// Create one ReachabilityPeerConnection for all TCP and TLS URLs together
|
|
116
|
+
if (clusterInfo.tcp.length > 0 || clusterInfo.xtls.length > 0) {
|
|
117
|
+
const tcpTlsClusterInfo: ClusterNode = {
|
|
118
|
+
isVideoMesh: clusterInfo.isVideoMesh,
|
|
119
|
+
udp: [],
|
|
120
|
+
tcp: clusterInfo.tcp,
|
|
121
|
+
xtls: clusterInfo.xtls,
|
|
119
122
|
};
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
iceServers: [...udpIceServers, ...tcpIceServers, ...turnTlsIceServers],
|
|
124
|
-
iceCandidatePoolSize: 0,
|
|
125
|
-
iceTransportPolicy: 'all',
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Creates an RTCPeerConnection
|
|
131
|
-
* @param {ClusterNode} clusterInfo information about the media cluster
|
|
132
|
-
* @returns {RTCPeerConnection} peerConnection
|
|
133
|
-
*/
|
|
134
|
-
private createPeerConnection(clusterInfo: ClusterNode) {
|
|
135
|
-
try {
|
|
136
|
-
const config = this.buildPeerConnectionConfig(clusterInfo);
|
|
137
|
-
|
|
138
|
-
const peerConnection = new RTCPeerConnection(config);
|
|
139
|
-
|
|
140
|
-
return peerConnection;
|
|
141
|
-
} catch (peerConnectionError) {
|
|
142
|
-
LoggerProxy.logger.warn(
|
|
143
|
-
`Reachability:index#createPeerConnection --> Error creating peerConnection:`,
|
|
144
|
-
peerConnectionError
|
|
123
|
+
this.reachabilityPeerConnection = new ReachabilityPeerConnection(
|
|
124
|
+
this.name,
|
|
125
|
+
tcpTlsClusterInfo
|
|
145
126
|
);
|
|
146
|
-
|
|
147
|
-
return undefined;
|
|
127
|
+
this.setupReachabilityPeerConnectionEventListeners(this.reachabilityPeerConnection);
|
|
148
128
|
}
|
|
149
129
|
}
|
|
150
130
|
|
|
151
131
|
/**
|
|
152
|
-
*
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return this.result;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Closes the peerConnection
|
|
160
|
-
*
|
|
132
|
+
* Sets up event listeners for a ReachabilityPeerConnection instance
|
|
133
|
+
* @param {ReachabilityPeerConnection} rpc the ReachabilityPeerConnection instance
|
|
134
|
+
* @param {boolean} isUdpPerUrl whether this is a per-URL UDP instance
|
|
161
135
|
* @returns {void}
|
|
162
136
|
*/
|
|
163
|
-
private
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
*/
|
|
176
|
-
private finishReachabilityCheck() {
|
|
177
|
-
this.defer.resolve();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Aborts the cluster reachability checks by closing the peer connection
|
|
182
|
-
*
|
|
183
|
-
* @returns {void}
|
|
184
|
-
*/
|
|
185
|
-
public abort() {
|
|
186
|
-
const {CLOSED} = CONNECTION_STATE;
|
|
187
|
-
|
|
188
|
-
if (this.pc.connectionState !== CLOSED) {
|
|
189
|
-
this.closePeerConnection();
|
|
190
|
-
this.finishReachabilityCheck();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Adds public IP (client media IPs)
|
|
196
|
-
* @param {string} protocol
|
|
197
|
-
* @param {string} publicIP
|
|
198
|
-
* @returns {void}
|
|
199
|
-
*/
|
|
200
|
-
private addPublicIP(protocol: 'udp' | 'tcp' | 'xtls', publicIP?: string | null) {
|
|
201
|
-
const result = this.result[protocol];
|
|
202
|
-
|
|
203
|
-
if (publicIP) {
|
|
204
|
-
let ipAdded = false;
|
|
205
|
-
|
|
206
|
-
if (result.clientMediaIPs) {
|
|
207
|
-
if (!result.clientMediaIPs.includes(publicIP)) {
|
|
208
|
-
result.clientMediaIPs.push(publicIP);
|
|
209
|
-
ipAdded = true;
|
|
137
|
+
private setupReachabilityPeerConnectionEventListeners(
|
|
138
|
+
rpc: ReachabilityPeerConnection,
|
|
139
|
+
isUdpPerUrl = false
|
|
140
|
+
) {
|
|
141
|
+
rpc.on(ReachabilityPeerConnectionEvents.resultReady, (data) => {
|
|
142
|
+
// For per-URL UDP checks, only emit the first successful UDP result
|
|
143
|
+
if (isUdpPerUrl && data.protocol === 'udp') {
|
|
144
|
+
if (this.udpResultEmitted) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (data.result === 'reachable') {
|
|
148
|
+
this.udpResultEmitted = true;
|
|
210
149
|
}
|
|
211
|
-
} else {
|
|
212
|
-
result.clientMediaIPs = [publicIP];
|
|
213
|
-
ipAdded = true;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (ipAdded)
|
|
217
|
-
this.emit(
|
|
218
|
-
{
|
|
219
|
-
file: 'clusterReachability',
|
|
220
|
-
function: 'addPublicIP',
|
|
221
|
-
},
|
|
222
|
-
Events.clientMediaIpsUpdated,
|
|
223
|
-
{
|
|
224
|
-
protocol,
|
|
225
|
-
clientMediaIPs: result.clientMediaIPs,
|
|
226
|
-
}
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Registers a listener for the iceGatheringStateChange event
|
|
233
|
-
*
|
|
234
|
-
* @returns {void}
|
|
235
|
-
*/
|
|
236
|
-
private registerIceGatheringStateChangeListener() {
|
|
237
|
-
this.pc.onicegatheringstatechange = () => {
|
|
238
|
-
if (this.pc.iceGatheringState === ICE_GATHERING_STATE.COMPLETE) {
|
|
239
|
-
this.closePeerConnection();
|
|
240
|
-
this.finishReachabilityCheck();
|
|
241
150
|
}
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Saves the latency in the result for the given protocol and marks it as reachable,
|
|
247
|
-
* emits the "resultReady" event if this is the first result for that protocol,
|
|
248
|
-
* emits the "clientMediaIpsUpdated" event if we already had a result and only found
|
|
249
|
-
* a new client IP
|
|
250
|
-
*
|
|
251
|
-
* @param {string} protocol
|
|
252
|
-
* @param {number} latency
|
|
253
|
-
* @param {string|null} [publicIp]
|
|
254
|
-
* @param {string|null} [serverIp]
|
|
255
|
-
* @returns {void}
|
|
256
|
-
*/
|
|
257
|
-
private saveResult(
|
|
258
|
-
protocol: 'udp' | 'tcp' | 'xtls',
|
|
259
|
-
latency: number,
|
|
260
|
-
publicIp?: string | null,
|
|
261
|
-
serverIp?: string | null
|
|
262
|
-
) {
|
|
263
|
-
const result = this.result[protocol];
|
|
264
151
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
152
|
+
this.emit(
|
|
153
|
+
{
|
|
154
|
+
file: 'clusterReachability',
|
|
155
|
+
function: 'setupReachabilityPeerConnectionEventListeners',
|
|
156
|
+
},
|
|
157
|
+
Events.resultReady,
|
|
158
|
+
data
|
|
269
159
|
);
|
|
270
|
-
|
|
271
|
-
result.result = 'reachable';
|
|
272
|
-
if (publicIp) {
|
|
273
|
-
result.clientMediaIPs = [publicIp];
|
|
274
|
-
}
|
|
160
|
+
});
|
|
275
161
|
|
|
162
|
+
rpc.on(ReachabilityPeerConnectionEvents.clientMediaIpsUpdated, (data) => {
|
|
276
163
|
this.emit(
|
|
277
164
|
{
|
|
278
165
|
file: 'clusterReachability',
|
|
279
|
-
function: '
|
|
166
|
+
function: 'setupReachabilityPeerConnectionEventListeners',
|
|
280
167
|
},
|
|
281
|
-
Events.
|
|
168
|
+
Events.clientMediaIpsUpdated,
|
|
169
|
+
data
|
|
170
|
+
);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
rpc.on(ReachabilityPeerConnectionEvents.natTypeUpdated, (data) => {
|
|
174
|
+
this.emit(
|
|
282
175
|
{
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
176
|
+
file: 'clusterReachability',
|
|
177
|
+
function: 'setupReachabilityPeerConnectionEventListeners',
|
|
178
|
+
},
|
|
179
|
+
Events.natTypeUpdated,
|
|
180
|
+
data
|
|
286
181
|
);
|
|
287
|
-
}
|
|
288
|
-
this.addPublicIP(protocol, publicIp);
|
|
289
|
-
}
|
|
182
|
+
});
|
|
290
183
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
184
|
+
rpc.on(ReachabilityPeerConnectionEvents.reachedSubnets, (data) => {
|
|
185
|
+
data.subnets.forEach((subnet: string) => {
|
|
186
|
+
this.reachedSubnets.add(subnet);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
294
189
|
}
|
|
295
190
|
|
|
296
191
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* @param {RTCIceCandidate} candidate
|
|
300
|
-
* @returns {void}
|
|
192
|
+
* Gets the aggregated reachability result for this cluster.
|
|
193
|
+
* @returns {ClusterReachabilityResult} reachability result for this cluster
|
|
301
194
|
*/
|
|
302
|
-
|
|
303
|
-
this.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
const key = `${c.address}:${c.relatedPort}`;
|
|
310
|
-
if (!portsFound[key]) {
|
|
311
|
-
portsFound[key] = new Set();
|
|
312
|
-
}
|
|
313
|
-
portsFound[key].add(c.port);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
Object.entries(portsFound).forEach(([, ports]) => {
|
|
317
|
-
if (ports.size > 1) {
|
|
318
|
-
// Found candidates with the same address and relatedPort, but different ports
|
|
319
|
-
this.emit(
|
|
320
|
-
{
|
|
321
|
-
file: 'clusterReachability',
|
|
322
|
-
function: 'determineNatType',
|
|
323
|
-
},
|
|
324
|
-
Events.natTypeUpdated,
|
|
325
|
-
{
|
|
326
|
-
natType: NatType.SymmetricNat,
|
|
327
|
-
}
|
|
328
|
-
);
|
|
195
|
+
getResult(): ClusterReachabilityResult {
|
|
196
|
+
if (!this.enablePerUdpUrlReachability) {
|
|
197
|
+
return (
|
|
198
|
+
this.reachabilityPeerConnection?.getResult() ?? {
|
|
199
|
+
udp: {result: 'untested'},
|
|
200
|
+
tcp: {result: 'untested'},
|
|
201
|
+
xtls: {result: 'untested'},
|
|
329
202
|
}
|
|
330
|
-
|
|
203
|
+
);
|
|
331
204
|
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Registers a listener for the icecandidate event
|
|
336
|
-
*
|
|
337
|
-
* @returns {void}
|
|
338
|
-
*/
|
|
339
|
-
private registerIceCandidateListener() {
|
|
340
|
-
this.pc.onicecandidate = (e) => {
|
|
341
|
-
const TURN_TLS_PORT = 443;
|
|
342
|
-
const CANDIDATE_TYPES = {
|
|
343
|
-
SERVER_REFLEXIVE: 'srflx',
|
|
344
|
-
RELAY: 'relay',
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
const latencyInMilliseconds = this.getElapsedTime();
|
|
348
|
-
|
|
349
|
-
if (e.candidate) {
|
|
350
|
-
if (e.candidate.type === CANDIDATE_TYPES.SERVER_REFLEXIVE) {
|
|
351
|
-
let serverIp = null;
|
|
352
|
-
if ('url' in e.candidate) {
|
|
353
|
-
const stunServerUrlRegex = /stun:([\d.]+):\d+/;
|
|
354
205
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
206
|
+
const result: ClusterReachabilityResult = {
|
|
207
|
+
udp: {result: 'untested'},
|
|
208
|
+
tcp: {result: 'untested'},
|
|
209
|
+
xtls: {result: 'untested'},
|
|
210
|
+
};
|
|
361
211
|
|
|
362
|
-
|
|
212
|
+
// Get the first reachable UDP result from per-URL instances
|
|
213
|
+
for (const rpc of this.reachabilityPeerConnectionsForUdp) {
|
|
214
|
+
const rpcResult = rpc.getResult();
|
|
215
|
+
if (rpcResult.udp.result === 'reachable') {
|
|
216
|
+
result.udp = rpcResult.udp;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
if (rpcResult.udp.result === 'unreachable' && result.udp.result === 'untested') {
|
|
220
|
+
result.udp = rpcResult.udp;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
363
223
|
|
|
364
|
-
|
|
365
|
-
|
|
224
|
+
// Get TCP and TLS results from the main peer connection
|
|
225
|
+
if (this.reachabilityPeerConnection) {
|
|
226
|
+
const mainResult = this.reachabilityPeerConnection.getResult();
|
|
227
|
+
result.tcp = mainResult.tcp;
|
|
228
|
+
result.xtls = mainResult.xtls;
|
|
229
|
+
}
|
|
366
230
|
|
|
367
|
-
|
|
368
|
-
const protocol = e.candidate.port === TURN_TLS_PORT ? 'xtls' : 'tcp';
|
|
369
|
-
this.saveResult(protocol, latencyInMilliseconds, null, e.candidate.address);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
};
|
|
231
|
+
return result;
|
|
373
232
|
}
|
|
374
233
|
|
|
375
234
|
/**
|
|
376
|
-
* Starts the process of doing UDP and
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
* @returns {Promise}
|
|
235
|
+
* Starts the process of doing UDP, TCP, and XTLS reachability checks on the media cluster.
|
|
236
|
+
* @returns {Promise<ClusterReachabilityResult>}
|
|
380
237
|
*/
|
|
381
238
|
async start(): Promise<ClusterReachabilityResult> {
|
|
382
|
-
|
|
383
|
-
LoggerProxy.logger.warn(
|
|
384
|
-
`Reachability:ClusterReachability#start --> Error: peerConnection is undefined`
|
|
385
|
-
);
|
|
386
|
-
|
|
387
|
-
return this.result;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Initialize this.result as saying that nothing is reachable.
|
|
391
|
-
// It will get updated as we go along and successfully gather ICE candidates.
|
|
392
|
-
this.result.udp = {
|
|
393
|
-
result: this.numUdpUrls > 0 ? 'unreachable' : 'untested',
|
|
394
|
-
};
|
|
395
|
-
this.result.tcp = {
|
|
396
|
-
result: this.numTcpUrls > 0 ? 'unreachable' : 'untested',
|
|
397
|
-
};
|
|
398
|
-
this.result.xtls = {
|
|
399
|
-
result: this.numXTlsUrls > 0 ? 'unreachable' : 'untested',
|
|
400
|
-
};
|
|
239
|
+
const startPromises: Promise<ClusterReachabilityResult>[] = [];
|
|
401
240
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
this.startTimestamp = performance.now();
|
|
406
|
-
|
|
407
|
-
// Set up the state change listeners before triggering the ICE gathering
|
|
408
|
-
const gatherIceCandidatePromise = this.gatherIceCandidates();
|
|
409
|
-
|
|
410
|
-
// not awaiting the next call on purpose, because we're not sending the offer anywhere and there won't be any answer
|
|
411
|
-
// we just need to make this call to trigger the ICE gathering process
|
|
412
|
-
this.pc.setLocalDescription(offer);
|
|
241
|
+
this.reachabilityPeerConnectionsForUdp.forEach((rpc) => {
|
|
242
|
+
startPromises.push(rpc.start());
|
|
243
|
+
});
|
|
413
244
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
LoggerProxy.logger.warn(`Reachability:ClusterReachability#start --> Error: `, error);
|
|
245
|
+
if (this.reachabilityPeerConnection) {
|
|
246
|
+
startPromises.push(this.reachabilityPeerConnection.start());
|
|
417
247
|
}
|
|
418
248
|
|
|
419
|
-
|
|
249
|
+
await Promise.all(startPromises);
|
|
250
|
+
|
|
251
|
+
return this.getResult();
|
|
420
252
|
}
|
|
421
253
|
|
|
422
254
|
/**
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
* @returns {Promise} promise that's resolved once reachability checks for this cluster are completed or timeout is reached
|
|
255
|
+
* Aborts the cluster reachability checks
|
|
256
|
+
* @returns {void}
|
|
426
257
|
*/
|
|
427
|
-
|
|
428
|
-
this.
|
|
429
|
-
this.
|
|
430
|
-
|
|
431
|
-
return this.defer.promise;
|
|
258
|
+
public abort() {
|
|
259
|
+
this.reachabilityPeerConnectionsForUdp.forEach((rpc) => rpc.abort());
|
|
260
|
+
this.reachabilityPeerConnection?.abort();
|
|
432
261
|
}
|
|
433
262
|
}
|
|
@@ -961,7 +961,12 @@ export default class Reachability extends EventsScope {
|
|
|
961
961
|
Object.keys(clusterList).forEach((key) => {
|
|
962
962
|
const cluster = clusterList[key];
|
|
963
963
|
|
|
964
|
-
this.clusterReachability[key] = new ClusterReachability(
|
|
964
|
+
this.clusterReachability[key] = new ClusterReachability(
|
|
965
|
+
key,
|
|
966
|
+
cluster,
|
|
967
|
+
// @ts-ignore
|
|
968
|
+
this.webex.config.meetings.enablePerUdpUrlReachability
|
|
969
|
+
);
|
|
965
970
|
this.clusterReachability[key].on(Events.resultReady, async (data: ResultEventData) => {
|
|
966
971
|
const {protocol, result, clientMediaIPs, latencyInMilliseconds} = data;
|
|
967
972
|
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
import {IP_VERSION} from '../constants';
|
|
1
|
+
import {IP_VERSION, Enum} from '../constants';
|
|
2
|
+
|
|
3
|
+
export type Protocol = 'udp' | 'tcp' | 'xtls';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Events emitted by ReachabilityPeerConnection
|
|
7
|
+
*/
|
|
8
|
+
export const ReachabilityPeerConnectionEvents = {
|
|
9
|
+
resultReady: 'resultReady', // emitted when successfully reached over a protocol
|
|
10
|
+
clientMediaIpsUpdated: 'clientMediaIpsUpdated', // emitted when new public IPs are found
|
|
11
|
+
natTypeUpdated: 'natTypeUpdated', // emitted when NAT type is determined
|
|
12
|
+
reachedSubnets: 'reachedSubnets', // emitted when server IP (subnet) is discovered
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export type ReachabilityPeerConnectionEvents = Enum<typeof ReachabilityPeerConnectionEvents>;
|
|
2
16
|
|
|
3
17
|
// result for a specific transport protocol (like udp or tcp)
|
|
4
18
|
export type TransportResult = {
|