@webex/plugin-meetings 3.6.0 → 3.7.0-ipv6-multi-turn-urls.1

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.
Files changed (332) hide show
  1. package/README.md +2 -1
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/common/errors/join-webinar-error.js +50 -0
  5. package/dist/common/errors/join-webinar-error.js.map +1 -0
  6. package/dist/config.js +4 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/constants.js +54 -4
  9. package/dist/constants.js.map +1 -1
  10. package/dist/controls-options-manager/enums.js +1 -0
  11. package/dist/controls-options-manager/enums.js.map +1 -1
  12. package/dist/controls-options-manager/index.js +10 -3
  13. package/dist/controls-options-manager/index.js.map +1 -1
  14. package/dist/controls-options-manager/types.js.map +1 -1
  15. package/dist/controls-options-manager/util.js +12 -0
  16. package/dist/controls-options-manager/util.js.map +1 -1
  17. package/dist/index.js +7 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/interpretation/index.js +1 -1
  20. package/dist/interpretation/siLanguage.js +1 -1
  21. package/dist/locus-info/controlsUtils.js +28 -4
  22. package/dist/locus-info/controlsUtils.js.map +1 -1
  23. package/dist/locus-info/fullState.js +2 -1
  24. package/dist/locus-info/fullState.js.map +1 -1
  25. package/dist/locus-info/index.js +61 -3
  26. package/dist/locus-info/index.js.map +1 -1
  27. package/dist/locus-info/parser.js +5 -1
  28. package/dist/locus-info/parser.js.map +1 -1
  29. package/dist/media/index.js +29 -1
  30. package/dist/media/index.js.map +1 -1
  31. package/dist/meeting/in-meeting-actions.js +29 -1
  32. package/dist/meeting/in-meeting-actions.js.map +1 -1
  33. package/dist/meeting/index.js +807 -540
  34. package/dist/meeting/index.js.map +1 -1
  35. package/dist/meeting/locusMediaRequest.js +2 -6
  36. package/dist/meeting/locusMediaRequest.js.map +1 -1
  37. package/dist/meeting/muteState.js +5 -2
  38. package/dist/meeting/muteState.js.map +1 -1
  39. package/dist/meeting/request.js +21 -29
  40. package/dist/meeting/request.js.map +1 -1
  41. package/dist/meeting/util.js +98 -61
  42. package/dist/meeting/util.js.map +1 -1
  43. package/dist/meeting-info/meeting-info-v2.js +80 -17
  44. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  45. package/dist/meetings/index.js +29 -2
  46. package/dist/meetings/index.js.map +1 -1
  47. package/dist/members/index.js +3 -2
  48. package/dist/members/index.js.map +1 -1
  49. package/dist/members/util.js +13 -7
  50. package/dist/members/util.js.map +1 -1
  51. package/dist/metrics/constants.js +4 -1
  52. package/dist/metrics/constants.js.map +1 -1
  53. package/dist/multistream/remoteMedia.js +34 -15
  54. package/dist/multistream/remoteMedia.js.map +1 -1
  55. package/dist/reachability/clusterReachability.js +12 -15
  56. package/dist/reachability/clusterReachability.js.map +1 -1
  57. package/dist/reachability/index.js +433 -136
  58. package/dist/reachability/index.js.map +1 -1
  59. package/dist/{rtcMetrics/constants.js → reachability/reachability.types.js} +1 -5
  60. package/dist/reachability/reachability.types.js.map +1 -0
  61. package/dist/reachability/request.js +23 -9
  62. package/dist/reachability/request.js.map +1 -1
  63. package/dist/recording-controller/enums.js +8 -4
  64. package/dist/recording-controller/enums.js.map +1 -1
  65. package/dist/recording-controller/index.js +18 -9
  66. package/dist/recording-controller/index.js.map +1 -1
  67. package/dist/recording-controller/util.js +13 -9
  68. package/dist/recording-controller/util.js.map +1 -1
  69. package/dist/roap/index.js +5 -7
  70. package/dist/roap/index.js.map +1 -1
  71. package/dist/roap/request.js +45 -79
  72. package/dist/roap/request.js.map +1 -1
  73. package/dist/roap/turnDiscovery.js +3 -6
  74. package/dist/roap/turnDiscovery.js.map +1 -1
  75. package/dist/{common/errors/parameter.d.ts → types/common/errors/join-webinar-error.d.ts} +4 -5
  76. package/dist/types/config.d.ts +3 -0
  77. package/dist/types/constants.d.ts +43 -0
  78. package/dist/types/controls-options-manager/enums.d.ts +2 -1
  79. package/dist/types/controls-options-manager/index.d.ts +2 -1
  80. package/dist/types/controls-options-manager/types.d.ts +2 -0
  81. package/dist/types/index.d.ts +2 -1
  82. package/dist/types/locus-info/index.d.ts +9 -0
  83. package/dist/types/meeting/in-meeting-actions.d.ts +28 -0
  84. package/dist/types/meeting/index.d.ts +34 -3
  85. package/dist/types/meeting/locusMediaRequest.d.ts +2 -3
  86. package/dist/types/meeting/muteState.d.ts +2 -1
  87. package/dist/types/meeting/request.d.ts +2 -2
  88. package/dist/types/meeting/util.d.ts +2 -2
  89. package/dist/types/meeting-info/meeting-info-v2.d.ts +23 -0
  90. package/dist/types/meetings/index.d.ts +13 -1
  91. package/dist/types/members/index.d.ts +2 -1
  92. package/dist/types/members/util.d.ts +5 -1
  93. package/dist/types/metrics/constants.d.ts +3 -0
  94. package/dist/types/multistream/remoteMedia.d.ts +1 -0
  95. package/dist/types/reachability/clusterReachability.d.ts +1 -10
  96. package/dist/types/reachability/index.d.ts +74 -35
  97. package/dist/types/reachability/reachability.types.d.ts +64 -0
  98. package/dist/types/reachability/request.d.ts +5 -1
  99. package/dist/types/recording-controller/enums.d.ts +5 -2
  100. package/dist/types/recording-controller/index.d.ts +1 -0
  101. package/dist/types/recording-controller/util.d.ts +2 -1
  102. package/dist/types/roap/request.d.ts +1 -13
  103. package/dist/webinar/index.js +382 -19
  104. package/dist/webinar/index.js.map +1 -1
  105. package/package.json +22 -22
  106. package/src/common/errors/join-webinar-error.ts +24 -0
  107. package/src/config.ts +3 -0
  108. package/src/constants.ts +52 -0
  109. package/src/controls-options-manager/enums.ts +1 -0
  110. package/src/controls-options-manager/index.ts +19 -2
  111. package/src/controls-options-manager/types.ts +2 -0
  112. package/src/controls-options-manager/util.ts +12 -0
  113. package/src/index.ts +2 -0
  114. package/src/locus-info/controlsUtils.ts +46 -2
  115. package/src/locus-info/fullState.ts +1 -0
  116. package/src/locus-info/index.ts +60 -0
  117. package/src/locus-info/parser.ts +8 -1
  118. package/src/media/index.ts +15 -0
  119. package/src/meeting/in-meeting-actions.ts +58 -0
  120. package/src/meeting/index.ts +268 -32
  121. package/src/meeting/locusMediaRequest.ts +4 -8
  122. package/src/meeting/muteState.ts +6 -2
  123. package/src/meeting/request.ts +4 -11
  124. package/src/meeting/util.ts +31 -6
  125. package/src/meeting-info/meeting-info-v2.ts +63 -0
  126. package/src/meetings/index.ts +74 -40
  127. package/src/members/index.ts +4 -2
  128. package/src/members/util.ts +4 -1
  129. package/src/metrics/constants.ts +3 -0
  130. package/src/multistream/remoteMedia.ts +33 -15
  131. package/src/reachability/clusterReachability.ts +5 -15
  132. package/src/reachability/index.ts +285 -77
  133. package/src/reachability/reachability.types.ts +85 -0
  134. package/src/reachability/request.ts +55 -30
  135. package/src/recording-controller/enums.ts +5 -2
  136. package/src/recording-controller/index.ts +17 -4
  137. package/src/recording-controller/util.ts +20 -5
  138. package/src/roap/index.ts +4 -5
  139. package/src/roap/request.ts +32 -44
  140. package/src/roap/turnDiscovery.ts +2 -4
  141. package/src/webinar/index.ts +223 -17
  142. package/test/unit/spec/controls-options-manager/index.js +56 -32
  143. package/test/unit/spec/controls-options-manager/util.js +44 -0
  144. package/test/unit/spec/locus-info/controlsUtils.js +80 -4
  145. package/test/unit/spec/locus-info/index.js +88 -2
  146. package/test/unit/spec/meeting/in-meeting-actions.ts +31 -1
  147. package/test/unit/spec/meeting/index.js +407 -82
  148. package/test/unit/spec/meeting/locusMediaRequest.ts +18 -11
  149. package/test/unit/spec/meeting/muteState.js +8 -4
  150. package/test/unit/spec/meeting/request.js +3 -26
  151. package/test/unit/spec/meeting/utils.js +71 -14
  152. package/test/unit/spec/meeting-info/meetinginfov2.js +42 -0
  153. package/test/unit/spec/meetings/index.js +41 -6
  154. package/test/unit/spec/members/index.js +25 -2
  155. package/test/unit/spec/members/request.js +37 -3
  156. package/test/unit/spec/members/utils.js +110 -1
  157. package/test/unit/spec/multistream/remoteMedia.ts +27 -9
  158. package/test/unit/spec/reachability/clusterReachability.ts +7 -0
  159. package/test/unit/spec/reachability/index.ts +265 -1
  160. package/test/unit/spec/reachability/request.js +56 -15
  161. package/test/unit/spec/recording-controller/index.js +61 -5
  162. package/test/unit/spec/recording-controller/util.js +39 -3
  163. package/test/unit/spec/roap/index.ts +1 -1
  164. package/test/unit/spec/roap/request.ts +51 -109
  165. package/test/unit/spec/roap/turnDiscovery.ts +202 -147
  166. package/test/unit/spec/webinar/index.ts +443 -14
  167. package/dist/annotation/annotation.types.d.ts +0 -42
  168. package/dist/annotation/constants.d.ts +0 -31
  169. package/dist/annotation/index.d.ts +0 -117
  170. package/dist/breakouts/breakout.d.ts +0 -8
  171. package/dist/breakouts/collection.d.ts +0 -5
  172. package/dist/breakouts/edit-lock-error.d.ts +0 -15
  173. package/dist/breakouts/events.d.ts +0 -8
  174. package/dist/breakouts/index.d.ts +0 -5
  175. package/dist/breakouts/request.d.ts +0 -22
  176. package/dist/breakouts/utils.d.ts +0 -15
  177. package/dist/common/browser-detection.d.ts +0 -9
  178. package/dist/common/collection.d.ts +0 -48
  179. package/dist/common/config.d.ts +0 -2
  180. package/dist/common/errors/captcha-error.d.ts +0 -15
  181. package/dist/common/errors/intent-to-join.d.ts +0 -16
  182. package/dist/common/errors/join-meeting.d.ts +0 -17
  183. package/dist/common/errors/media.d.ts +0 -15
  184. package/dist/common/errors/no-meeting-info.d.ts +0 -14
  185. package/dist/common/errors/password-error.d.ts +0 -15
  186. package/dist/common/errors/permission.d.ts +0 -14
  187. package/dist/common/errors/reclaim-host-role-error.js +0 -149
  188. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  189. package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
  190. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  191. package/dist/common/errors/reconnection-in-progress.js +0 -33
  192. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  193. package/dist/common/errors/reconnection.d.ts +0 -15
  194. package/dist/common/errors/stats.d.ts +0 -15
  195. package/dist/common/errors/webex-errors.d.ts +0 -93
  196. package/dist/common/errors/webex-meetings-error.d.ts +0 -20
  197. package/dist/common/events/events-scope.d.ts +0 -17
  198. package/dist/common/events/events.d.ts +0 -12
  199. package/dist/common/events/trigger-proxy.d.ts +0 -2
  200. package/dist/common/events/util.d.ts +0 -2
  201. package/dist/common/logs/logger-config.d.ts +0 -2
  202. package/dist/common/logs/logger-proxy.d.ts +0 -2
  203. package/dist/common/logs/request.d.ts +0 -36
  204. package/dist/common/queue.d.ts +0 -34
  205. package/dist/config.d.ts +0 -72
  206. package/dist/constants.d.ts +0 -1088
  207. package/dist/controls-options-manager/constants.d.ts +0 -4
  208. package/dist/controls-options-manager/enums.d.ts +0 -15
  209. package/dist/controls-options-manager/index.d.ts +0 -136
  210. package/dist/controls-options-manager/types.d.ts +0 -43
  211. package/dist/controls-options-manager/util.d.ts +0 -1
  212. package/dist/index.d.ts +0 -7
  213. package/dist/interceptors/index.d.ts +0 -2
  214. package/dist/interceptors/locusRetry.d.ts +0 -27
  215. package/dist/interpretation/collection.d.ts +0 -5
  216. package/dist/interpretation/index.d.ts +0 -5
  217. package/dist/interpretation/siLanguage.d.ts +0 -5
  218. package/dist/locus-info/controlsUtils.d.ts +0 -2
  219. package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
  220. package/dist/locus-info/fullState.d.ts +0 -2
  221. package/dist/locus-info/hostUtils.d.ts +0 -2
  222. package/dist/locus-info/index.d.ts +0 -322
  223. package/dist/locus-info/infoUtils.d.ts +0 -2
  224. package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
  225. package/dist/locus-info/parser.d.ts +0 -272
  226. package/dist/locus-info/selfUtils.d.ts +0 -2
  227. package/dist/media/index.d.ts +0 -34
  228. package/dist/media/properties.d.ts +0 -93
  229. package/dist/media/util.d.ts +0 -2
  230. package/dist/mediaQualityMetrics/config.d.ts +0 -241
  231. package/dist/mediaQualityMetrics/config.js +0 -502
  232. package/dist/mediaQualityMetrics/config.js.map +0 -1
  233. package/dist/meeting/effectsState.js +0 -260
  234. package/dist/meeting/effectsState.js.map +0 -1
  235. package/dist/meeting/in-meeting-actions.d.ts +0 -167
  236. package/dist/meeting/index.d.ts +0 -1825
  237. package/dist/meeting/locusMediaRequest.d.ts +0 -74
  238. package/dist/meeting/muteState.d.ts +0 -178
  239. package/dist/meeting/request.d.ts +0 -295
  240. package/dist/meeting/request.type.d.ts +0 -11
  241. package/dist/meeting/state.d.ts +0 -9
  242. package/dist/meeting/util.d.ts +0 -119
  243. package/dist/meeting/voicea-meeting.d.ts +0 -16
  244. package/dist/meeting-info/collection.d.ts +0 -20
  245. package/dist/meeting-info/index.d.ts +0 -69
  246. package/dist/meeting-info/meeting-info-v2.d.ts +0 -123
  247. package/dist/meeting-info/request.d.ts +0 -22
  248. package/dist/meeting-info/util.d.ts +0 -2
  249. package/dist/meeting-info/utilv2.d.ts +0 -2
  250. package/dist/meetings/collection.d.ts +0 -40
  251. package/dist/meetings/index.d.ts +0 -390
  252. package/dist/meetings/meetings.types.d.ts +0 -4
  253. package/dist/meetings/request.d.ts +0 -27
  254. package/dist/meetings/util.d.ts +0 -18
  255. package/dist/member/index.d.ts +0 -160
  256. package/dist/member/member.types.js +0 -17
  257. package/dist/member/member.types.js.map +0 -1
  258. package/dist/member/types.d.ts +0 -32
  259. package/dist/member/util.d.ts +0 -2
  260. package/dist/members/collection.d.ts +0 -29
  261. package/dist/members/index.d.ts +0 -353
  262. package/dist/members/request.d.ts +0 -114
  263. package/dist/members/types.d.ts +0 -25
  264. package/dist/members/util.d.ts +0 -215
  265. package/dist/metrics/config.js +0 -276
  266. package/dist/metrics/config.js.map +0 -1
  267. package/dist/metrics/constants.d.ts +0 -70
  268. package/dist/metrics/index.d.ts +0 -45
  269. package/dist/multistream/mediaRequestManager.d.ts +0 -119
  270. package/dist/multistream/receiveSlot.d.ts +0 -68
  271. package/dist/multistream/receiveSlotManager.d.ts +0 -56
  272. package/dist/multistream/remoteMedia.d.ts +0 -72
  273. package/dist/multistream/remoteMediaGroup.d.ts +0 -49
  274. package/dist/multistream/remoteMediaManager.d.ts +0 -300
  275. package/dist/multistream/sendSlotManager.d.ts +0 -69
  276. package/dist/networkQualityMonitor/index.d.ts +0 -70
  277. package/dist/networkQualityMonitor/index.js +0 -221
  278. package/dist/networkQualityMonitor/index.js.map +0 -1
  279. package/dist/peer-connection-manager/index.js +0 -671
  280. package/dist/peer-connection-manager/index.js.map +0 -1
  281. package/dist/peer-connection-manager/util.js +0 -109
  282. package/dist/peer-connection-manager/util.js.map +0 -1
  283. package/dist/personal-meeting-room/index.d.ts +0 -47
  284. package/dist/personal-meeting-room/request.d.ts +0 -14
  285. package/dist/personal-meeting-room/util.d.ts +0 -2
  286. package/dist/reachability/clusterReachability.d.ts +0 -109
  287. package/dist/reachability/index.d.ts +0 -105
  288. package/dist/reachability/request.d.ts +0 -39
  289. package/dist/reachability/util.d.ts +0 -8
  290. package/dist/reactions/constants.d.ts +0 -3
  291. package/dist/reactions/reactions.d.ts +0 -4
  292. package/dist/reactions/reactions.type.d.ts +0 -52
  293. package/dist/reconnection-manager/index.d.ts +0 -136
  294. package/dist/recording-controller/enums.d.ts +0 -7
  295. package/dist/recording-controller/index.d.ts +0 -207
  296. package/dist/recording-controller/util.d.ts +0 -14
  297. package/dist/roap/collection.js +0 -62
  298. package/dist/roap/collection.js.map +0 -1
  299. package/dist/roap/handler.js +0 -275
  300. package/dist/roap/handler.js.map +0 -1
  301. package/dist/roap/index.d.ts +0 -86
  302. package/dist/roap/request.d.ts +0 -39
  303. package/dist/roap/state.js +0 -126
  304. package/dist/roap/state.js.map +0 -1
  305. package/dist/roap/turnDiscovery.d.ts +0 -155
  306. package/dist/roap/util.js +0 -75
  307. package/dist/roap/util.js.map +0 -1
  308. package/dist/rtcMetrics/constants.d.ts +0 -4
  309. package/dist/rtcMetrics/constants.js.map +0 -1
  310. package/dist/rtcMetrics/index.d.ts +0 -61
  311. package/dist/rtcMetrics/index.js +0 -197
  312. package/dist/rtcMetrics/index.js.map +0 -1
  313. package/dist/statsAnalyzer/global.d.ts +0 -36
  314. package/dist/statsAnalyzer/global.js +0 -126
  315. package/dist/statsAnalyzer/global.js.map +0 -1
  316. package/dist/statsAnalyzer/index.d.ts +0 -217
  317. package/dist/statsAnalyzer/index.js +0 -1013
  318. package/dist/statsAnalyzer/index.js.map +0 -1
  319. package/dist/statsAnalyzer/mqaUtil.d.ts +0 -48
  320. package/dist/statsAnalyzer/mqaUtil.js +0 -179
  321. package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
  322. package/dist/transcription/index.d.ts +0 -64
  323. package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
  324. package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
  325. package/dist/types/networkQualityMonitor/index.d.ts +0 -70
  326. package/dist/types/rtcMetrics/constants.d.ts +0 -4
  327. package/dist/types/rtcMetrics/index.d.ts +0 -71
  328. package/dist/types/statsAnalyzer/global.d.ts +0 -36
  329. package/dist/types/statsAnalyzer/index.d.ts +0 -217
  330. package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
  331. package/dist/webinar/collection.d.ts +0 -16
  332. package/dist/webinar/index.d.ts +0 -5
@@ -9,64 +9,31 @@ import {Defer} from '@webex/common';
9
9
  import LoggerProxy from '../common/logs/logger-proxy';
10
10
  import MeetingUtil from '../meeting/util';
11
11
 
12
- import {REACHABILITY} from '../constants';
12
+ import {IP_VERSION, REACHABILITY} from '../constants';
13
13
 
14
14
  import ReachabilityRequest, {ClusterList} from './request';
15
+ import {
16
+ ClusterReachabilityResult,
17
+ TransportResult,
18
+ ClientMediaPreferences,
19
+ ReachabilityMetrics,
20
+ ReachabilityReportV0,
21
+ ReachabilityReportV1,
22
+ ReachabilityResults,
23
+ ReachabilityResultsForBackend,
24
+ TransportResultForBackend,
25
+ GetClustersTrigger,
26
+ } from './reachability.types';
15
27
  import {
16
28
  ClientMediaIpsUpdatedEventData,
17
29
  ClusterReachability,
18
- ClusterReachabilityResult,
19
30
  Events,
20
31
  ResultEventData,
21
- TransportResult,
22
32
  } from './clusterReachability';
23
33
  import EventsScope from '../common/events/events-scope';
24
34
  import BEHAVIORAL_METRICS from '../metrics/constants';
25
35
  import Metrics from '../metrics';
26
36
 
27
- export type ReachabilityMetrics = {
28
- reachability_public_udp_success: number;
29
- reachability_public_udp_failed: number;
30
- reachability_public_tcp_success: number;
31
- reachability_public_tcp_failed: number;
32
- reachability_public_xtls_success: number;
33
- reachability_public_xtls_failed: number;
34
- reachability_vmn_udp_success: number;
35
- reachability_vmn_udp_failed: number;
36
- reachability_vmn_tcp_success: number;
37
- reachability_vmn_tcp_failed: number;
38
- reachability_vmn_xtls_success: number;
39
- reachability_vmn_xtls_failed: number;
40
- };
41
-
42
- /**
43
- * This is the type that matches what backend expects us to send to them. It is a bit weird, because
44
- * it uses strings instead of booleans and numbers, but that's what they require.
45
- */
46
- export type TransportResultForBackend = {
47
- reachable?: 'true' | 'false';
48
- latencyInMilliseconds?: string;
49
- clientMediaIPs?: string[];
50
- untested?: 'true';
51
- };
52
-
53
- export type ReachabilityResultForBackend = {
54
- udp: TransportResultForBackend;
55
- tcp: TransportResultForBackend;
56
- xtls: TransportResultForBackend;
57
- };
58
-
59
- // this is the type that is required by the backend when we send them reachability results
60
- export type ReachabilityResultsForBackend = Record<string, ReachabilityResultForBackend>;
61
-
62
- // this is the type used by Reachability class internally and stored in local storage
63
- export type ReachabilityResults = Record<
64
- string,
65
- ClusterReachabilityResult & {
66
- isVideoMesh?: boolean;
67
- }
68
- >;
69
-
70
37
  // timeouts in seconds
71
38
  const DEFAULT_TIMEOUT = 3;
72
39
  const VIDEO_MESH_TIMEOUT = 1;
@@ -84,6 +51,9 @@ export default class Reachability extends EventsScope {
84
51
  [key: string]: ClusterReachability;
85
52
  };
86
53
 
54
+ minRequiredClusters?: number;
55
+ orpheusApiVersion?: number;
56
+
87
57
  reachabilityDefer?: Defer;
88
58
 
89
59
  vmnTimer?: ReturnType<typeof setTimeout>;
@@ -92,6 +62,8 @@ export default class Reachability extends EventsScope {
92
62
 
93
63
  expectedResultsCount = {videoMesh: {udp: 0}, public: {udp: 0, tcp: 0, xtls: 0}};
94
64
  resultsCount = {videoMesh: {udp: 0}, public: {udp: 0, tcp: 0, xtls: 0}};
65
+ startTime = undefined;
66
+ totalDuration = undefined;
95
67
 
96
68
  protected lastTrigger?: string;
97
69
 
@@ -118,14 +90,35 @@ export default class Reachability extends EventsScope {
118
90
 
119
91
  /**
120
92
  * Fetches the list of media clusters from the backend
93
+ * @param {string} trigger - explains the reason for starting reachability, used by Orpheus
94
+ * @param {Object} previousReport - last reachability report
121
95
  * @param {boolean} isRetry
122
96
  * @private
123
97
  * @returns {Promise<{clusters: ClusterList, joinCookie: any}>}
124
98
  */
125
- async getClusters(isRetry = false): Promise<{clusters: ClusterList; joinCookie: any}> {
99
+ async getClusters(
100
+ trigger: GetClustersTrigger,
101
+ previousReport?: any,
102
+ isRetry = false
103
+ ): Promise<{
104
+ clusters: ClusterList;
105
+ joinCookie: any;
106
+ }> {
126
107
  try {
127
- const {clusters, joinCookie} = await this.reachabilityRequest.getClusters(
128
- MeetingUtil.getIpVersion(this.webex)
108
+ const {clusters, joinCookie, discoveryOptions} = await this.reachabilityRequest.getClusters(
109
+ trigger,
110
+ MeetingUtil.getIpVersion(this.webex),
111
+ previousReport
112
+ );
113
+
114
+ this.minRequiredClusters = discoveryOptions?.['early-call-min-clusters'];
115
+ this.orpheusApiVersion = discoveryOptions?.['report-version'];
116
+
117
+ // @ts-ignore
118
+ await this.webex.boundedStorage.put(
119
+ this.namespace,
120
+ REACHABILITY.localStorageJoinCookie,
121
+ JSON.stringify(joinCookie)
129
122
  );
130
123
 
131
124
  return {clusters, joinCookie};
@@ -138,7 +131,7 @@ export default class Reachability extends EventsScope {
138
131
  `Reachability:index#getClusters --> Failed with error: ${error}, retrying...`
139
132
  );
140
133
 
141
- return this.getClusters(true);
134
+ return this.getClusters(trigger, previousReport, true);
142
135
  }
143
136
  }
144
137
 
@@ -154,19 +147,12 @@ export default class Reachability extends EventsScope {
154
147
  try {
155
148
  this.lastTrigger = trigger;
156
149
 
157
- // kick off ip version detection. For now we don't await it, as we're doing it
158
- // to gather the timings and send them with our reachability metrics
150
+ // kick off ip version detection. We don't await it, as we don't want to waste time
151
+ // and if it fails, that's ok we can still carry on
159
152
  // @ts-ignore
160
- this.webex.internal.device.ipNetworkDetector.detect();
153
+ this.webex.internal.device.ipNetworkDetector.detect(true);
161
154
 
162
- const {clusters, joinCookie} = await this.getClusters();
163
-
164
- // @ts-ignore
165
- await this.webex.boundedStorage.put(
166
- this.namespace,
167
- REACHABILITY.localStorageJoinCookie,
168
- JSON.stringify(joinCookie)
169
- );
155
+ const {clusters} = await this.getClusters('startup');
170
156
 
171
157
  this.reachabilityDefer = new Defer();
172
158
 
@@ -181,6 +167,98 @@ export default class Reachability extends EventsScope {
181
167
  }
182
168
  }
183
169
 
170
+ /**
171
+ * Gets the last join cookie we got from Orpheus
172
+ *
173
+ * @returns {Promise<Object>} join cookie
174
+ */
175
+ async getJoinCookie() {
176
+ // @ts-ignore
177
+ const joinCookieRaw = await this.webex.boundedStorage
178
+ .get(REACHABILITY.namespace, REACHABILITY.localStorageJoinCookie)
179
+ .catch(() => {});
180
+
181
+ let joinCookie;
182
+
183
+ if (joinCookieRaw) {
184
+ try {
185
+ joinCookie = JSON.parse(joinCookieRaw);
186
+ } catch (e) {
187
+ LoggerProxy.logger.error(
188
+ `MeetingRequest#constructor --> Error in parsing join cookie data: ${e}`
189
+ );
190
+ }
191
+ }
192
+
193
+ return joinCookie;
194
+ }
195
+
196
+ /**
197
+ * Returns the reachability report that needs to be attached to the ROAP messages
198
+ * that we send to the backend.
199
+ *
200
+ * @returns {Promise<Object>}
201
+ */
202
+ async getReachabilityReport(): Promise<
203
+ | {
204
+ joinCookie: any;
205
+ reachability?: ReachabilityReportV1;
206
+ }
207
+ | {
208
+ reachability: ReachabilityReportV0;
209
+ }
210
+ > {
211
+ const reachabilityResult = await this.getReachabilityResults();
212
+ const joinCookie = await this.getJoinCookie();
213
+
214
+ // Orpheus API version 0
215
+ if (!this.orpheusApiVersion) {
216
+ return {
217
+ reachability: reachabilityResult,
218
+ };
219
+ }
220
+
221
+ // Orpheus API version 1
222
+ return {
223
+ reachability: {
224
+ version: 1,
225
+ result: {
226
+ usedDiscoveryOptions: {
227
+ 'early-call-min-clusters': this.minRequiredClusters,
228
+ },
229
+ metrics: {
230
+ 'total-duration-ms': this.totalDuration,
231
+ },
232
+ tests: reachabilityResult,
233
+ },
234
+ },
235
+ joinCookie,
236
+ };
237
+ }
238
+
239
+ /**
240
+ * This method is called when we don't succeed in reaching the minimum number of clusters
241
+ * required by Orpheus. It sends the results to Orpheus and gets a new list that it tries to reach again.
242
+ * @returns {Promise<ReachabilityResults>} reachability results
243
+ * @public
244
+ * @memberof Reachability
245
+ */
246
+ public async gatherReachabilityFallback(): Promise<void> {
247
+ try {
248
+ const reachabilityReport = await this.getReachabilityReport();
249
+
250
+ const {clusters} = await this.getClusters('early-call/no-min-reached', reachabilityReport);
251
+
252
+ // stop all previous reachability checks that might still be going on in the background
253
+ this.abortCurrentChecks();
254
+
255
+ // Perform Reachability Check
256
+ await this.performReachabilityChecks(clusters);
257
+ } catch (error) {
258
+ LoggerProxy.logger.error(`Reachability:index#gatherReachabilityFallback --> Error:`, error);
259
+ }
260
+ }
261
+
184
262
  /**
185
263
  * Returns statistics about last reachability results. The returned value is an object
186
264
  * with a flat list of properties so that it can be easily sent with metrics
@@ -304,7 +382,7 @@ export default class Reachability extends EventsScope {
304
382
  } catch (e) {
305
383
  // empty storage, that's ok
306
384
  LoggerProxy.logger.warn(
307
- 'Roap:request#attachReachabilityData --> Error parsing reachability data: ',
385
+ 'Reachability:index#getReachabilityResults --> Error parsing reachability data: ',
308
386
  e
309
387
  );
310
388
  }
@@ -336,7 +414,7 @@ export default class Reachability extends EventsScope {
336
414
  );
337
415
  } catch (e) {
338
416
  LoggerProxy.logger.error(
339
- `Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`
417
+ `Reachability:index#isAnyPublicClusterReachable --> Error in parsing reachability data: ${e}`
340
418
  );
341
419
  }
342
420
  }
@@ -393,7 +471,7 @@ export default class Reachability extends EventsScope {
393
471
  );
394
472
  } catch (e) {
395
473
  LoggerProxy.logger.error(
396
- `Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`
474
+ `Reachability:index#isWebexMediaBackendUnreachable --> Error in parsing reachability data: ${e}`
397
475
  );
398
476
  }
399
477
  }
@@ -427,6 +505,30 @@ export default class Reachability extends EventsScope {
427
505
  return unreachableList;
428
506
  }
429
507
 
508
+ /**
509
+ * Gets the number of reachable clusters from last run reachability check
510
+ * @returns {number} reachable clusters count
511
+ * @private
512
+ * @memberof Reachability
513
+ */
514
+ private getNumberOfReachableClusters(): number {
515
+ let count = 0;
516
+
517
+ Object.entries(this.clusterReachability).forEach(([key, clusterReachability]) => {
518
+ const result = clusterReachability.getResult();
519
+
520
+ if (
521
+ result.udp.result === 'reachable' ||
522
+ result.tcp.result === 'reachable' ||
523
+ result.xtls.result === 'reachable'
524
+ ) {
525
+ count += 1;
526
+ }
527
+ });
528
+
529
+ return count;
530
+ }
531
+
430
532
  /**
431
533
  * Make a log of unreachable clusters.
432
534
  * @returns {undefined}
@@ -465,18 +567,27 @@ export default class Reachability extends EventsScope {
465
567
 
466
568
  /**
467
569
  * Resolves the promise returned by gatherReachability() method
570
+ * @param {boolean} checkMinRequiredClusters - if true, it will check if we have reached the minimum required clusters and do a fallback if needed
468
571
  * @returns {void}
469
572
  */
470
- private resolveReachabilityPromise() {
471
- if (this.vmnTimer) {
472
- clearTimeout(this.vmnTimer);
473
- }
474
- if (this.publicCloudTimer) {
475
- clearTimeout(this.publicCloudTimer);
476
- }
573
+ private resolveReachabilityPromise(checkMinRequiredClusters = true) {
574
+ this.totalDuration = performance.now() - this.startTime;
575
+
576
+ this.clearTimer('vmnTimer');
577
+ this.clearTimer('publicCloudTimer');
477
578
 
478
579
  this.logUnreachableClusters();
479
580
  this.reachabilityDefer?.resolve();
581
+
582
+ if (checkMinRequiredClusters) {
583
+ const numReachableClusters = this.getNumberOfReachableClusters();
584
+ if (this.minRequiredClusters && numReachableClusters < this.minRequiredClusters) {
585
+ LoggerProxy.logger.log(
586
+ `Reachability:index#resolveReachabilityPromise --> minRequiredClusters not reached (${numReachableClusters} < ${this.minRequiredClusters}), doing reachability fallback`
587
+ );
588
+ this.gatherReachabilityFallback();
589
+ }
590
+ }
480
591
  }
481
592
 
482
593
  /**
@@ -591,6 +702,8 @@ export default class Reachability extends EventsScope {
591
702
  `Reachability:index#startTimers --> Reachability checks timed out (${DEFAULT_TIMEOUT}s)`
592
703
  );
593
704
 
705
+ // check against minimum required clusters, do a new call if we don't have enough
706
+
594
707
  // resolve the promise, so that the client won't be blocked waiting on meetings.register() for too long
595
708
  this.resolveReachabilityPromise();
596
709
  }, DEFAULT_TIMEOUT * 1000);
@@ -646,6 +759,32 @@ export default class Reachability extends EventsScope {
646
759
  this.resultsCount.public.xtls = 0;
647
760
  }
648
761
 
762
+ /**
763
+ * Clears the timer
764
+ *
765
+ * @param {string} timer name of the timer to clear
766
+ * @returns {void}
767
+ */
768
+ private clearTimer(timer: string) {
769
+ if (this[timer]) {
770
+ clearTimeout(this[timer]);
771
+ this[timer] = undefined;
772
+ }
773
+ }
774
+
775
+ /**
776
+ * Aborts current checks that are in progress
777
+ *
778
+ * @returns {void}
779
+ */
780
+ private abortCurrentChecks() {
781
+ this.clearTimer('vmnTimer');
782
+ this.clearTimer('publicCloudTimer');
783
+ this.clearTimer('overallTimer');
784
+
785
+ this.abortClusterReachability();
786
+ }
787
+
649
788
  /**
650
789
  * Performs reachability checks for all clusters
651
790
  * @param {ClusterList} clusterList
@@ -656,9 +795,7 @@ export default class Reachability extends EventsScope {
656
795
 
657
796
  this.clusterReachability = {};
658
797
 
659
- if (!clusterList || !Object.keys(clusterList).length) {
660
- return;
661
- }
798
+ this.startTime = performance.now();
662
799
 
663
800
  LoggerProxy.logger.log(
664
801
  `Reachability:index#performReachabilityChecks --> doing UDP${
@@ -671,7 +808,6 @@ export default class Reachability extends EventsScope {
671
808
  );
672
809
 
673
810
  this.resetResultCounters();
674
- this.startTimers();
675
811
 
676
812
  // sanitize the urls in the clusterList
677
813
  Object.keys(clusterList).forEach((key) => {
@@ -721,6 +857,24 @@ export default class Reachability extends EventsScope {
721
857
  // save the initialized results (in case we don't get any "resultReady" events at all)
722
858
  await this.storeResults(results);
723
859
 
860
+ if (!clusterList || !Object.keys(clusterList).length) {
861
+ // nothing to do, finish immediately
862
+ this.resolveReachabilityPromise(false);
863
+
864
+ this.emit(
865
+ {
866
+ file: 'reachability',
867
+ function: 'performReachabilityChecks',
868
+ },
869
+ 'reachability:done',
870
+ {}
871
+ );
872
+
873
+ return;
874
+ }
875
+
876
+ this.startTimers();
877
+
724
878
  // now start the reachability on all the clusters
725
879
  Object.keys(clusterList).forEach((key) => {
726
880
  const cluster = clusterList[key];
@@ -753,8 +907,7 @@ export default class Reachability extends EventsScope {
753
907
  await this.storeResults(results);
754
908
 
755
909
  if (areAllResultsReady) {
756
- clearTimeout(this.overallTimer);
757
- this.overallTimer = undefined;
910
+ this.clearTimer('overallTimer');
758
911
  this.emit(
759
912
  {
760
913
  file: 'reachability',
@@ -785,4 +938,59 @@ export default class Reachability extends EventsScope {
785
938
  this.clusterReachability[key].start(); // not awaiting on purpose
786
939
  });
787
940
  }
941
+
942
+ /**
943
+ * Returns the clientMediaPreferences object that needs to be sent to the backend
944
+ * when joining a meeting
945
+ *
946
+ * @param {boolean} isMultistream
947
+ * @param {IP_VERSION} ipver
948
+ * @returns {Object}
949
+ */
950
+ async getClientMediaPreferences(
951
+ isMultistream: boolean,
952
+ ipver?: IP_VERSION
953
+ ): Promise<ClientMediaPreferences> {
954
+ // if 0 or undefined, we assume version 0 and don't send any reachability in clientMediaPreferences
955
+ if (!this.orpheusApiVersion) {
956
+ return {
957
+ ipver,
958
+ joinCookie: await this.getJoinCookie(),
959
+ preferTranscoding: !isMultistream,
960
+ };
961
+ }
962
+
963
+ // must be version 1
964
+
965
+ // for version 1, the reachability report goes into clientMediaPreferences (and it contains joinCookie)
966
+ const reachabilityReport = (await this.getReachabilityReport()) as {
967
+ joinCookie: any;
968
+ reachability?: ReachabilityReportV1;
969
+ };
970
+
971
+ return {
972
+ ipver,
973
+ preferTranscoding: !isMultistream,
974
+ ...reachabilityReport,
975
+ };
976
+ }
977
+
978
+ /**
979
+ * Returns the reachability report that needs to be attached to the ROAP messages
980
+ * that we send to the backend.
981
+ * It may return undefined, if reachability is not needed to be attached to ROAP messages (that's the case for v1 or Orpheus API)
982
+ *
983
+ * @returns {Promise<ReachabilityReportV0>} object that needs to be attached to Roap messages
984
+ */
985
+ async getReachabilityReportToAttachToRoap(): Promise<ReachabilityReportV0 | undefined> {
986
+ // version 0
987
+ if (!this.orpheusApiVersion) {
988
+ return this.getReachabilityResults();
989
+ }
990
+
991
+ // version 1
992
+
993
+ // for version 1 we don't attach anything to Roap messages, reachability report is sent inside clientMediaPreferences
994
+ return undefined;
995
+ }
788
996
  }
@@ -0,0 +1,85 @@
1
+ import {IP_VERSION} from '../constants';
2
+
3
+ // result for a specific transport protocol (like udp or tcp)
4
+ export type TransportResult = {
5
+ result: 'reachable' | 'unreachable' | 'untested';
6
+ latencyInMilliseconds?: number; // amount of time it took to get the first ICE candidate
7
+ clientMediaIPs?: string[];
8
+ };
9
+
10
+ // reachability result for a specific media cluster
11
+ export type ClusterReachabilityResult = {
12
+ udp: TransportResult;
13
+ tcp: TransportResult;
14
+ xtls: TransportResult;
15
+ };
16
+
17
+ export type ReachabilityMetrics = {
18
+ reachability_public_udp_success: number;
19
+ reachability_public_udp_failed: number;
20
+ reachability_public_tcp_success: number;
21
+ reachability_public_tcp_failed: number;
22
+ reachability_public_xtls_success: number;
23
+ reachability_public_xtls_failed: number;
24
+ reachability_vmn_udp_success: number;
25
+ reachability_vmn_udp_failed: number;
26
+ reachability_vmn_tcp_success: number;
27
+ reachability_vmn_tcp_failed: number;
28
+ reachability_vmn_xtls_success: number;
29
+ reachability_vmn_xtls_failed: number;
30
+ };
31
+
32
+ /**
33
+ * This is the type that matches what backend expects us to send to them. It is a bit weird, because
34
+ * it uses strings instead of booleans and numbers, but that's what they require.
35
+ */
36
+ export type TransportResultForBackend = {
37
+ reachable?: 'true' | 'false';
38
+ latencyInMilliseconds?: string;
39
+ clientMediaIPs?: string[];
40
+ untested?: 'true';
41
+ };
42
+
43
+ export type ReachabilityResultForBackend = {
44
+ udp: TransportResultForBackend;
45
+ tcp: TransportResultForBackend;
46
+ xtls: TransportResultForBackend;
47
+ };
48
+
49
+ // this is the type that is required by the backend when we send them reachability results
50
+ export type ReachabilityResultsForBackend = Record<string, ReachabilityResultForBackend>;
51
+
52
+ // this is the type used by Reachability class internally and stored in local storage
53
+ export type ReachabilityResults = Record<
54
+ string,
55
+ ClusterReachabilityResult & {
56
+ isVideoMesh?: boolean;
57
+ }
58
+ >;
59
+
60
+ export type ReachabilityReportV0 = ReachabilityResultsForBackend;
61
+
62
+ export type ReachabilityReportV1 = {
63
+ version: 1;
64
+ result: {
65
+ usedDiscoveryOptions: {
66
+ 'early-call-min-clusters': number;
67
+ // there are more options, but we don't support them yet
68
+ };
69
+ metrics: {
70
+ 'total-duration-ms': number;
71
+ // there are more metrics, but we don't support them yet
72
+ };
73
+ tests: Record<string, ReachabilityResultForBackend>;
74
+ };
75
+ };
76
+
77
+ export interface ClientMediaPreferences {
78
+ ipver: IP_VERSION;
79
+ joinCookie: any;
80
+ preferTranscoding: boolean;
81
+ reachability?: ReachabilityReportV1; // only present when using Orpheus API version 1
82
+ }
83
+
84
+ /* Orpheus API supports more triggers, but we don't use them yet */
85
+ export type GetClustersTrigger = 'startup' | 'early-call/no-min-reached';
@@ -1,5 +1,6 @@
1
1
  import LoggerProxy from '../common/logs/logger-proxy';
2
2
  import {HTTP_VERBS, RESOURCE, API, IP_VERSION} from '../constants';
3
+ import {GetClustersTrigger} from './reachability.types';
3
4
 
4
5
  export interface ClusterNode {
5
6
  isVideoMesh: boolean;
@@ -30,43 +31,67 @@ class ReachabilityRequest {
30
31
  /**
31
32
  * Gets the cluster information
32
33
  *
34
+ * @param {string} trigger that's passed to Orpheus
33
35
  * @param {IP_VERSION} ipVersion information about current ip network we're on
36
+ * @param {Object} previousReport last reachability result
34
37
  * @returns {Promise}
35
38
  */
36
- getClusters = (ipVersion?: IP_VERSION): Promise<{clusters: ClusterList; joinCookie: any}> =>
37
- this.webex.internal.newMetrics.callDiagnosticLatencies
38
- .measureLatency(
39
- () =>
40
- this.webex.request({
41
- method: HTTP_VERBS.GET,
42
- shouldRefreshAccessToken: false,
43
- api: API.CALLIOPEDISCOVERY,
44
- resource: RESOURCE.CLUSTERS,
45
- qs: {
46
- JCSupport: 1,
47
- ipver: ipVersion,
39
+ getClusters = (
40
+ trigger: GetClustersTrigger,
41
+ ipVersion?: IP_VERSION,
42
+ previousReport?: any
43
+ ): Promise<{
44
+ clusters: ClusterList;
45
+ joinCookie: any;
46
+ discoveryOptions?: Record<string, any>;
47
+ }> => {
48
+ // we only measure latency for the initial startup call, not for other triggers
49
+ const callWrapper =
50
+ trigger === 'startup'
51
+ ? this.webex.internal.newMetrics.callDiagnosticLatencies.measureLatency.bind(
52
+ this.webex.internal.newMetrics.callDiagnosticLatencies
53
+ )
54
+ : (func) => func();
55
+
56
+ return callWrapper(
57
+ () =>
58
+ this.webex.request({
59
+ method: HTTP_VERBS.POST,
60
+ shouldRefreshAccessToken: false,
61
+ api: API.CALLIOPEDISCOVERY,
62
+ resource: RESOURCE.CLUSTERS,
63
+ body: {
64
+ ipver: ipVersion,
65
+ 'supported-options': {
66
+ 'report-version': 1,
67
+ 'early-call-min-clusters': true,
48
68
  },
49
- }),
50
- 'internal.get.cluster.time'
51
- )
52
- .then((res) => {
53
- const {clusters, joinCookie} = res.body;
69
+ 'previous-report': previousReport,
70
+ trigger,
71
+ },
72
+ timeout: this.webex.config.meetings.reachabilityGetClusterTimeout,
73
+ }),
74
+ 'internal.get.cluster.time'
75
+ ).then((res) => {
76
+ const {clusters, joinCookie, discoveryOptions} = res.body;
54
77
 
55
- Object.keys(clusters).forEach((key) => {
56
- clusters[key].isVideoMesh = !!res.body.clusterClasses?.hybridMedia?.includes(key);
57
- });
78
+ Object.keys(clusters).forEach((key) => {
79
+ clusters[key].isVideoMesh = !!res.body.clusterClasses?.hybridMedia?.includes(key);
80
+ });
58
81
 
59
- LoggerProxy.logger.log(
60
- `Reachability:request#getClusters --> get clusters (ipver=${ipVersion}) successful:${JSON.stringify(
61
- clusters
62
- )}`
63
- );
82
+ LoggerProxy.logger.log(
83
+ `Reachability:request#getClusters --> get clusters (ipver=${ipVersion}) successful:${JSON.stringify(
84
+ clusters
85
+ )}`
86
+ );
64
87
 
65
- return {
66
- clusters,
67
- joinCookie,
68
- };
69
- });
88
+ return {
89
+ clusters,
90
+ joinCookie,
91
+ discoveryOptions,
92
+ };
93
+ });
94
+ };
70
95
 
71
96
  /**
72
97
  * gets remote SDP For Clusters