@webex/plugin-meetings 3.0.0-beta.33 → 3.0.0-beta.331

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 (378) hide show
  1. package/README.md +46 -8
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +94 -15
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/edit-lock-error.js +52 -0
  11. package/dist/breakouts/edit-lock-error.js.map +1 -0
  12. package/dist/breakouts/events.js +45 -0
  13. package/dist/breakouts/events.js.map +1 -0
  14. package/dist/breakouts/index.js +709 -35
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/utils.js +45 -1
  17. package/dist/breakouts/utils.js.map +1 -1
  18. package/dist/common/errors/no-meeting-info.js +51 -0
  19. package/dist/common/errors/no-meeting-info.js.map +1 -0
  20. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  21. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  22. package/dist/common/errors/webex-errors.js +48 -7
  23. package/dist/common/errors/webex-errors.js.map +1 -1
  24. package/dist/common/logs/logger-proxy.js +1 -1
  25. package/dist/common/logs/logger-proxy.js.map +1 -1
  26. package/dist/common/logs/request.js +5 -1
  27. package/dist/common/logs/request.js.map +1 -1
  28. package/dist/common/queue.js +24 -9
  29. package/dist/common/queue.js.map +1 -1
  30. package/dist/config.js +4 -10
  31. package/dist/config.js.map +1 -1
  32. package/dist/constants.js +233 -29
  33. package/dist/constants.js.map +1 -1
  34. package/dist/controls-options-manager/enums.js +14 -2
  35. package/dist/controls-options-manager/enums.js.map +1 -1
  36. package/dist/controls-options-manager/index.js +109 -15
  37. package/dist/controls-options-manager/index.js.map +1 -1
  38. package/dist/controls-options-manager/types.js +7 -0
  39. package/dist/controls-options-manager/types.js.map +1 -0
  40. package/dist/controls-options-manager/util.js +309 -18
  41. package/dist/controls-options-manager/util.js.map +1 -1
  42. package/dist/index.js +112 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/interpretation/collection.js +23 -0
  45. package/dist/interpretation/collection.js.map +1 -0
  46. package/dist/interpretation/index.js +366 -0
  47. package/dist/interpretation/index.js.map +1 -0
  48. package/dist/interpretation/siLanguage.js +25 -0
  49. package/dist/interpretation/siLanguage.js.map +1 -0
  50. package/dist/locus-info/controlsUtils.js +91 -2
  51. package/dist/locus-info/controlsUtils.js.map +1 -1
  52. package/dist/locus-info/index.js +383 -62
  53. package/dist/locus-info/index.js.map +1 -1
  54. package/dist/locus-info/infoUtils.js +7 -1
  55. package/dist/locus-info/infoUtils.js.map +1 -1
  56. package/dist/locus-info/mediaSharesUtils.js +57 -1
  57. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  58. package/dist/locus-info/parser.js +249 -72
  59. package/dist/locus-info/parser.js.map +1 -1
  60. package/dist/locus-info/selfUtils.js +89 -14
  61. package/dist/locus-info/selfUtils.js.map +1 -1
  62. package/dist/media/index.js +61 -116
  63. package/dist/media/index.js.map +1 -1
  64. package/dist/media/properties.js +73 -124
  65. package/dist/media/properties.js.map +1 -1
  66. package/dist/meeting/in-meeting-actions.js +86 -2
  67. package/dist/meeting/in-meeting-actions.js.map +1 -1
  68. package/dist/meeting/index.js +3917 -2960
  69. package/dist/meeting/index.js.map +1 -1
  70. package/dist/meeting/locusMediaRequest.js +292 -0
  71. package/dist/meeting/locusMediaRequest.js.map +1 -0
  72. package/dist/meeting/muteState.js +230 -124
  73. package/dist/meeting/muteState.js.map +1 -1
  74. package/dist/meeting/request.js +260 -196
  75. package/dist/meeting/request.js.map +1 -1
  76. package/dist/meeting/util.js +601 -417
  77. package/dist/meeting/util.js.map +1 -1
  78. package/dist/meeting-info/index.js +73 -7
  79. package/dist/meeting-info/index.js.map +1 -1
  80. package/dist/meeting-info/meeting-info-v2.js +192 -51
  81. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  82. package/dist/meeting-info/util.js +1 -1
  83. package/dist/meeting-info/util.js.map +1 -1
  84. package/dist/meeting-info/utilv2.js +36 -36
  85. package/dist/meeting-info/utilv2.js.map +1 -1
  86. package/dist/meetings/collection.js +39 -0
  87. package/dist/meetings/collection.js.map +1 -1
  88. package/dist/meetings/index.js +424 -116
  89. package/dist/meetings/index.js.map +1 -1
  90. package/dist/meetings/meetings.types.js +7 -0
  91. package/dist/meetings/meetings.types.js.map +1 -0
  92. package/dist/meetings/request.js +2 -0
  93. package/dist/meetings/request.js.map +1 -1
  94. package/dist/meetings/util.js +72 -6
  95. package/dist/meetings/util.js.map +1 -1
  96. package/dist/member/index.js +58 -0
  97. package/dist/member/index.js.map +1 -1
  98. package/dist/member/types.js +25 -0
  99. package/dist/member/types.js.map +1 -0
  100. package/dist/member/util.js +132 -25
  101. package/dist/member/util.js.map +1 -1
  102. package/dist/members/collection.js +10 -0
  103. package/dist/members/collection.js.map +1 -1
  104. package/dist/members/index.js +102 -6
  105. package/dist/members/index.js.map +1 -1
  106. package/dist/members/request.js +106 -38
  107. package/dist/members/request.js.map +1 -1
  108. package/dist/members/types.js +15 -0
  109. package/dist/members/types.js.map +1 -0
  110. package/dist/members/util.js +326 -232
  111. package/dist/members/util.js.map +1 -1
  112. package/dist/metrics/constants.js +16 -5
  113. package/dist/metrics/constants.js.map +1 -1
  114. package/dist/metrics/index.js +1 -468
  115. package/dist/metrics/index.js.map +1 -1
  116. package/dist/multistream/mediaRequestManager.js +228 -58
  117. package/dist/multistream/mediaRequestManager.js.map +1 -1
  118. package/dist/multistream/receiveSlot.js +29 -16
  119. package/dist/multistream/receiveSlot.js.map +1 -1
  120. package/dist/multistream/receiveSlotManager.js +39 -36
  121. package/dist/multistream/receiveSlotManager.js.map +1 -1
  122. package/dist/multistream/remoteMedia.js +44 -18
  123. package/dist/multistream/remoteMedia.js.map +1 -1
  124. package/dist/multistream/remoteMediaGroup.js +60 -3
  125. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  126. package/dist/multistream/remoteMediaManager.js +209 -59
  127. package/dist/multistream/remoteMediaManager.js.map +1 -1
  128. package/dist/multistream/sendSlotManager.js +233 -0
  129. package/dist/multistream/sendSlotManager.js.map +1 -0
  130. package/dist/reachability/index.js +225 -59
  131. package/dist/reachability/index.js.map +1 -1
  132. package/dist/reachability/request.js +17 -8
  133. package/dist/reachability/request.js.map +1 -1
  134. package/dist/reconnection-manager/index.js +214 -170
  135. package/dist/reconnection-manager/index.js.map +1 -1
  136. package/dist/recording-controller/index.js +21 -2
  137. package/dist/recording-controller/index.js.map +1 -1
  138. package/dist/recording-controller/util.js +9 -8
  139. package/dist/recording-controller/util.js.map +1 -1
  140. package/dist/roap/index.js +62 -32
  141. package/dist/roap/index.js.map +1 -1
  142. package/dist/roap/request.js +112 -97
  143. package/dist/roap/request.js.map +1 -1
  144. package/dist/roap/turnDiscovery.js +95 -36
  145. package/dist/roap/turnDiscovery.js.map +1 -1
  146. package/dist/rtcMetrics/constants.js +12 -0
  147. package/dist/rtcMetrics/constants.js.map +1 -0
  148. package/dist/rtcMetrics/index.js +142 -0
  149. package/dist/rtcMetrics/index.js.map +1 -0
  150. package/dist/statsAnalyzer/index.js +107 -79
  151. package/dist/statsAnalyzer/index.js.map +1 -1
  152. package/dist/statsAnalyzer/mqaUtil.js +27 -26
  153. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  154. package/dist/types/annotation/annotation.types.d.ts +42 -0
  155. package/dist/types/annotation/constants.d.ts +31 -0
  156. package/dist/types/annotation/index.d.ts +117 -0
  157. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  158. package/dist/types/breakouts/events.d.ts +8 -0
  159. package/dist/types/breakouts/utils.d.ts +14 -0
  160. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  161. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  162. package/dist/types/common/errors/webex-errors.d.ts +25 -1
  163. package/dist/types/common/logs/request.d.ts +2 -0
  164. package/dist/types/common/queue.d.ts +9 -7
  165. package/dist/types/config.d.ts +1 -7
  166. package/dist/types/constants.d.ts +201 -30
  167. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  168. package/dist/types/controls-options-manager/index.d.ts +17 -1
  169. package/dist/types/controls-options-manager/types.d.ts +43 -0
  170. package/dist/types/controls-options-manager/util.d.ts +1 -7
  171. package/dist/types/index.d.ts +6 -4
  172. package/dist/types/interpretation/collection.d.ts +5 -0
  173. package/dist/types/interpretation/index.d.ts +5 -0
  174. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  175. package/dist/types/locus-info/index.d.ts +57 -4
  176. package/dist/types/locus-info/parser.d.ts +67 -6
  177. package/dist/types/media/index.d.ts +2 -0
  178. package/dist/types/media/properties.d.ts +34 -48
  179. package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
  180. package/dist/types/meeting/index.d.ts +502 -512
  181. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  182. package/dist/types/meeting/muteState.d.ts +99 -23
  183. package/dist/types/meeting/request.d.ts +72 -43
  184. package/dist/types/meeting/util.d.ts +101 -1
  185. package/dist/types/meeting-info/index.d.ts +13 -1
  186. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  187. package/dist/types/meetings/collection.d.ts +17 -0
  188. package/dist/types/meetings/index.d.ts +101 -21
  189. package/dist/types/meetings/meetings.types.d.ts +4 -0
  190. package/dist/types/member/index.d.ts +14 -0
  191. package/dist/types/member/types.d.ts +32 -0
  192. package/dist/types/members/collection.d.ts +5 -0
  193. package/dist/types/members/index.d.ts +35 -2
  194. package/dist/types/members/request.d.ts +73 -9
  195. package/dist/types/members/types.d.ts +25 -0
  196. package/dist/types/members/util.d.ts +214 -1
  197. package/dist/types/metrics/constants.d.ts +15 -4
  198. package/dist/types/metrics/index.d.ts +4 -119
  199. package/dist/types/multistream/mediaRequestManager.d.ts +72 -5
  200. package/dist/types/multistream/receiveSlot.d.ts +13 -11
  201. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  202. package/dist/types/multistream/remoteMedia.d.ts +8 -29
  203. package/dist/types/multistream/remoteMediaGroup.d.ts +0 -9
  204. package/dist/types/multistream/remoteMediaManager.d.ts +46 -2
  205. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  206. package/dist/types/reachability/index.d.ts +61 -7
  207. package/dist/types/reachability/request.d.ts +7 -3
  208. package/dist/types/reconnection-manager/index.d.ts +19 -0
  209. package/dist/types/recording-controller/index.d.ts +15 -1
  210. package/dist/types/recording-controller/util.d.ts +5 -4
  211. package/dist/types/roap/index.d.ts +2 -1
  212. package/dist/types/roap/request.d.ts +15 -11
  213. package/dist/types/roap/turnDiscovery.d.ts +21 -3
  214. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  215. package/dist/types/rtcMetrics/index.d.ts +54 -0
  216. package/dist/types/statsAnalyzer/index.d.ts +7 -1
  217. package/dist/types/webinar/collection.d.ts +16 -0
  218. package/dist/types/webinar/index.d.ts +5 -0
  219. package/dist/webinar/collection.js +44 -0
  220. package/dist/webinar/collection.js.map +1 -0
  221. package/dist/webinar/index.js +69 -0
  222. package/dist/webinar/index.js.map +1 -0
  223. package/package.json +24 -20
  224. package/src/annotation/annotation.types.ts +50 -0
  225. package/src/annotation/constants.ts +36 -0
  226. package/src/annotation/index.ts +328 -0
  227. package/src/breakouts/README.md +42 -12
  228. package/src/breakouts/breakout.ts +67 -9
  229. package/src/breakouts/edit-lock-error.ts +25 -0
  230. package/src/breakouts/events.ts +56 -0
  231. package/src/breakouts/index.ts +592 -20
  232. package/src/breakouts/utils.ts +42 -0
  233. package/src/common/errors/no-meeting-info.ts +24 -0
  234. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  235. package/src/common/errors/webex-errors.ts +44 -2
  236. package/src/common/logs/logger-proxy.ts +1 -1
  237. package/src/common/logs/request.ts +5 -1
  238. package/src/common/queue.ts +22 -8
  239. package/src/config.ts +3 -9
  240. package/src/constants.ts +224 -20
  241. package/src/controls-options-manager/enums.ts +12 -0
  242. package/src/controls-options-manager/index.ts +116 -21
  243. package/src/controls-options-manager/types.ts +59 -0
  244. package/src/controls-options-manager/util.ts +294 -14
  245. package/src/index.ts +40 -0
  246. package/src/interpretation/README.md +60 -0
  247. package/src/interpretation/collection.ts +19 -0
  248. package/src/interpretation/index.ts +332 -0
  249. package/src/interpretation/siLanguage.ts +18 -0
  250. package/src/locus-info/controlsUtils.ts +108 -0
  251. package/src/locus-info/index.ts +413 -59
  252. package/src/locus-info/infoUtils.ts +10 -2
  253. package/src/locus-info/mediaSharesUtils.ts +64 -0
  254. package/src/locus-info/parser.ts +258 -47
  255. package/src/locus-info/selfUtils.ts +81 -5
  256. package/src/media/index.ts +102 -122
  257. package/src/media/properties.ts +87 -110
  258. package/src/meeting/in-meeting-actions.ts +171 -3
  259. package/src/meeting/index.ts +3267 -2555
  260. package/src/meeting/locusMediaRequest.ts +313 -0
  261. package/src/meeting/muteState.ts +229 -131
  262. package/src/meeting/request.ts +177 -121
  263. package/src/meeting/util.ts +588 -394
  264. package/src/meeting-info/index.ts +81 -8
  265. package/src/meeting-info/meeting-info-v2.ts +170 -14
  266. package/src/meeting-info/util.ts +1 -1
  267. package/src/meeting-info/utilv2.ts +23 -23
  268. package/src/meetings/collection.ts +33 -0
  269. package/src/meetings/index.ts +454 -125
  270. package/src/meetings/meetings.types.ts +12 -0
  271. package/src/meetings/request.ts +2 -0
  272. package/src/meetings/util.ts +80 -11
  273. package/src/member/index.ts +58 -0
  274. package/src/member/types.ts +38 -0
  275. package/src/member/util.ts +141 -25
  276. package/src/members/collection.ts +8 -0
  277. package/src/members/index.ts +134 -8
  278. package/src/members/request.ts +97 -17
  279. package/src/members/types.ts +29 -0
  280. package/src/members/util.ts +333 -240
  281. package/src/metrics/constants.ts +15 -4
  282. package/src/metrics/index.ts +1 -490
  283. package/src/multistream/mediaRequestManager.ts +277 -82
  284. package/src/multistream/receiveSlot.ts +31 -17
  285. package/src/multistream/receiveSlotManager.ts +34 -24
  286. package/src/multistream/remoteMedia.ts +27 -2
  287. package/src/multistream/remoteMediaGroup.ts +59 -0
  288. package/src/multistream/remoteMediaManager.ts +148 -30
  289. package/src/multistream/sendSlotManager.ts +170 -0
  290. package/src/reachability/index.ts +228 -37
  291. package/src/reachability/request.ts +17 -8
  292. package/src/reconnection-manager/index.ts +128 -106
  293. package/src/recording-controller/index.ts +20 -3
  294. package/src/recording-controller/util.ts +26 -9
  295. package/src/roap/index.ts +63 -32
  296. package/src/roap/request.ts +100 -104
  297. package/src/roap/turnDiscovery.ts +48 -26
  298. package/src/rtcMetrics/constants.ts +3 -0
  299. package/src/rtcMetrics/index.ts +124 -0
  300. package/src/statsAnalyzer/index.ts +135 -92
  301. package/src/statsAnalyzer/mqaUtil.ts +30 -28
  302. package/src/webinar/collection.ts +31 -0
  303. package/src/webinar/index.ts +62 -0
  304. package/test/integration/spec/converged-space-meetings.js +60 -3
  305. package/test/integration/spec/journey.js +320 -261
  306. package/test/integration/spec/space-meeting.js +76 -3
  307. package/test/unit/spec/annotation/index.ts +418 -0
  308. package/test/unit/spec/breakouts/breakout.ts +118 -28
  309. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  310. package/test/unit/spec/breakouts/events.ts +89 -0
  311. package/test/unit/spec/breakouts/index.ts +1395 -69
  312. package/test/unit/spec/breakouts/utils.js +52 -1
  313. package/test/unit/spec/common/queue.js +31 -2
  314. package/test/unit/spec/controls-options-manager/index.js +163 -0
  315. package/test/unit/spec/controls-options-manager/util.js +576 -60
  316. package/test/unit/spec/fixture/locus.js +1 -0
  317. package/test/unit/spec/interpretation/collection.ts +15 -0
  318. package/test/unit/spec/interpretation/index.ts +589 -0
  319. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  320. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  321. package/test/unit/spec/locus-info/index.js +1304 -33
  322. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  323. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  324. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  325. package/test/unit/spec/locus-info/parser.js +116 -35
  326. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  327. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  328. package/test/unit/spec/media/index.ts +104 -37
  329. package/test/unit/spec/media/properties.ts +2 -2
  330. package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
  331. package/test/unit/spec/meeting/index.js +5750 -2023
  332. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  333. package/test/unit/spec/meeting/muteState.js +408 -208
  334. package/test/unit/spec/meeting/request.js +483 -49
  335. package/test/unit/spec/meeting/utils.js +679 -64
  336. package/test/unit/spec/meeting-info/index.js +300 -0
  337. package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
  338. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  339. package/test/unit/spec/meetings/collection.js +26 -0
  340. package/test/unit/spec/meetings/index.js +1231 -212
  341. package/test/unit/spec/meetings/utils.js +202 -2
  342. package/test/unit/spec/member/index.js +61 -6
  343. package/test/unit/spec/member/util.js +510 -34
  344. package/test/unit/spec/members/index.js +432 -1
  345. package/test/unit/spec/members/request.js +206 -27
  346. package/test/unit/spec/members/utils.js +210 -0
  347. package/test/unit/spec/metrics/index.js +1 -50
  348. package/test/unit/spec/multistream/mediaRequestManager.ts +776 -162
  349. package/test/unit/spec/multistream/receiveSlot.ts +28 -20
  350. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  351. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  352. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  353. package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
  354. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  355. package/test/unit/spec/reachability/index.ts +549 -9
  356. package/test/unit/spec/reachability/request.js +68 -0
  357. package/test/unit/spec/reconnection-manager/index.js +117 -11
  358. package/test/unit/spec/recording-controller/index.js +294 -218
  359. package/test/unit/spec/recording-controller/util.js +223 -96
  360. package/test/unit/spec/roap/index.ts +178 -64
  361. package/test/unit/spec/roap/request.ts +203 -85
  362. package/test/unit/spec/roap/turnDiscovery.ts +82 -36
  363. package/test/unit/spec/rtcMetrics/index.ts +93 -0
  364. package/test/unit/spec/stats-analyzer/index.js +147 -3
  365. package/test/unit/spec/webinar/collection.ts +13 -0
  366. package/test/unit/spec/webinar/index.ts +60 -0
  367. package/test/utils/integrationTestUtils.js +46 -0
  368. package/test/utils/testUtils.js +0 -52
  369. package/dist/meeting/effectsState.js +0 -262
  370. package/dist/meeting/effectsState.js.map +0 -1
  371. package/dist/metrics/config.js +0 -299
  372. package/dist/metrics/config.js.map +0 -1
  373. package/dist/types/meeting/effectsState.d.ts +0 -42
  374. package/dist/types/metrics/config.d.ts +0 -178
  375. package/src/index.js +0 -16
  376. package/src/meeting/effectsState.ts +0 -211
  377. package/src/metrics/config.ts +0 -495
  378. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -4,9 +4,11 @@
4
4
 
5
5
  /* eslint-disable class-methods-use-this */
6
6
  /* globals window */
7
- import _ from 'lodash';
7
+ import {uniq, mapValues, pick} from 'lodash';
8
8
 
9
9
  import LoggerProxy from '../common/logs/logger-proxy';
10
+ import MeetingUtil from '../meeting/util';
11
+
10
12
  import {ICE_GATHERING_STATE, CONNECTION_STATE, REACHABILITY} from '../constants';
11
13
 
12
14
  import ReachabilityRequest from './request';
@@ -14,6 +16,50 @@ import ReachabilityRequest from './request';
14
16
  const DEFAULT_TIMEOUT = 3000;
15
17
  const VIDEO_MESH_TIMEOUT = 1000;
16
18
 
19
+ export type ReachabilityMetrics = {
20
+ reachability_public_udp_success: number;
21
+ reachability_public_udp_failed: number;
22
+ reachability_public_tcp_success: number;
23
+ reachability_public_tcp_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
+ };
29
+
30
+ // result for a specific transport protocol (like udp or tcp)
31
+ export type TransportResult = {
32
+ reachable?: 'true' | 'false';
33
+ latencyInMilliseconds?: string;
34
+ clientMediaIPs?: string[];
35
+ untested?: 'true';
36
+ };
37
+
38
+ // reachability result for a specifc media cluster
39
+ type ReachabilityResult = {
40
+ udp: TransportResult;
41
+ tcp: TransportResult;
42
+ xtls: {
43
+ untested: 'true';
44
+ };
45
+ };
46
+ // this is the type that is required by the backend when we send them reachability results
47
+ export type ReachabilityResults = Record<string, ReachabilityResult>;
48
+
49
+ // this is the type used by Reachability class internally and stored in local storage
50
+ type InternalReachabilityResults = Record<
51
+ string,
52
+ ReachabilityResult & {
53
+ isVideoMesh?: boolean;
54
+ }
55
+ >;
56
+
57
+ export type ICECandidateResult = {
58
+ clusterId: string;
59
+ isVideoMesh: boolean;
60
+ elapsed?: string | null;
61
+ publicIPs?: string[];
62
+ };
17
63
  /**
18
64
  * @class Reachability
19
65
  * @export
@@ -58,16 +104,20 @@ export default class Reachability {
58
104
  * @async
59
105
  * @memberof Reachability
60
106
  */
61
- public async gatherReachability() {
107
+ public async gatherReachability(): Promise<InternalReachabilityResults> {
62
108
  this.setup();
63
109
 
64
110
  // Remove stored reachability results to ensure no stale data
65
111
  // @ts-ignore
66
- await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorage);
112
+ await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageResult);
113
+ // @ts-ignore
114
+ await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageJoinCookie);
67
115
 
68
116
  // Fetch clusters and measure latency
69
117
  try {
70
- const clusters = await this.reachabilityRequest.getClusters();
118
+ const {clusters, joinCookie} = await this.reachabilityRequest.getClusters(
119
+ MeetingUtil.getIpVersion(this.webex)
120
+ );
71
121
 
72
122
  // Perform Reachability Check
73
123
  const results = await this.performReachabilityCheck(clusters);
@@ -75,9 +125,15 @@ export default class Reachability {
75
125
  // @ts-ignore
76
126
  await this.webex.boundedStorage.put(
77
127
  this.namespace,
78
- REACHABILITY.localStorage,
128
+ REACHABILITY.localStorageResult,
79
129
  JSON.stringify(results)
80
130
  );
131
+ // @ts-ignore
132
+ await this.webex.boundedStorage.put(
133
+ this.namespace,
134
+ REACHABILITY.localStorageJoinCookie,
135
+ JSON.stringify(joinCookie)
136
+ );
81
137
 
82
138
  LoggerProxy.logger.log(
83
139
  'Reachability:index#gatherReachability --> Reachability checks completed'
@@ -93,25 +149,111 @@ export default class Reachability {
93
149
  }
94
150
  }
95
151
 
152
+ /**
153
+ * Returns statistics about last reachability results. The returned value is an object
154
+ * with a flat list of properties so that it can be easily sent with metrics
155
+ *
156
+ * @returns {Promise} Promise with metrics values, it never rejects/throws.
157
+ */
158
+ async getReachabilityMetrics(): Promise<ReachabilityMetrics> {
159
+ const stats: ReachabilityMetrics = {
160
+ reachability_public_udp_success: 0,
161
+ reachability_public_udp_failed: 0,
162
+ reachability_public_tcp_success: 0,
163
+ reachability_public_tcp_failed: 0,
164
+ reachability_vmn_udp_success: 0,
165
+ reachability_vmn_udp_failed: 0,
166
+ reachability_vmn_tcp_success: 0,
167
+ reachability_vmn_tcp_failed: 0,
168
+ };
169
+
170
+ const updateStats = (clusterType: 'public' | 'vmn', result: ReachabilityResult) => {
171
+ if (result.udp?.reachable) {
172
+ const outcome = result.udp.reachable === 'true' ? 'success' : 'failed';
173
+ stats[`reachability_${clusterType}_udp_${outcome}`] += 1;
174
+ }
175
+ if (result.tcp?.reachable) {
176
+ const outcome = result.tcp.reachable === 'true' ? 'success' : 'failed';
177
+ stats[`reachability_${clusterType}_tcp_${outcome}`] += 1;
178
+ }
179
+ };
180
+
181
+ try {
182
+ // @ts-ignore
183
+ const resultsJson = await this.webex.boundedStorage.get(
184
+ REACHABILITY.namespace,
185
+ REACHABILITY.localStorageResult
186
+ );
187
+
188
+ const internalResults: InternalReachabilityResults = JSON.parse(resultsJson);
189
+
190
+ Object.values(internalResults).forEach((result) => {
191
+ updateStats(result.isVideoMesh ? 'vmn' : 'public', result);
192
+ });
193
+ } catch (e) {
194
+ // empty storage, that's ok
195
+ LoggerProxy.logger.warn(
196
+ 'Roap:request#getReachabilityMetrics --> Error parsing reachability data: ',
197
+ e
198
+ );
199
+ }
200
+
201
+ return stats;
202
+ }
203
+
204
+ /**
205
+ * Reachability results as an object in the format that backend expects
206
+ *
207
+ * @returns {any} reachability results that need to be sent to the backend
208
+ */
209
+ async getReachabilityResults(): Promise<ReachabilityResults | undefined> {
210
+ let results: ReachabilityResults;
211
+
212
+ // these are the only props that backend needs in the reachability results:
213
+ const reachabilityResultsProps: Array<keyof ReachabilityResult> = ['udp', 'tcp', 'xtls'];
214
+
215
+ try {
216
+ // @ts-ignore
217
+ const resultsJson = await this.webex.boundedStorage.get(
218
+ REACHABILITY.namespace,
219
+ REACHABILITY.localStorageResult
220
+ );
221
+
222
+ const internalResults: InternalReachabilityResults = JSON.parse(resultsJson);
223
+
224
+ results = mapValues(internalResults, (result) => pick(result, reachabilityResultsProps));
225
+ } catch (e) {
226
+ // empty storage, that's ok
227
+ LoggerProxy.logger.warn(
228
+ 'Roap:request#attachReachabilityData --> Error parsing reachability data: ',
229
+ e
230
+ );
231
+ }
232
+
233
+ return results;
234
+ }
235
+
96
236
  /**
97
237
  * fetches reachability data and checks for cluster reachability
98
238
  * @returns {boolean}
99
239
  * @public
100
240
  * @memberof Reachability
101
241
  */
102
- async isAnyClusterReachable() {
242
+ async isAnyPublicClusterReachable() {
103
243
  let reachable = false;
104
244
  // @ts-ignore
105
245
  const reachabilityData = await this.webex.boundedStorage
106
- .get(this.namespace, REACHABILITY.localStorage)
246
+ .get(this.namespace, REACHABILITY.localStorageResult)
107
247
  .catch(() => {});
108
248
 
109
249
  if (reachabilityData) {
110
250
  try {
111
- const reachabilityResults = JSON.parse(reachabilityData);
251
+ const reachabilityResults: InternalReachabilityResults = JSON.parse(reachabilityData);
112
252
 
113
253
  reachable = Object.values(reachabilityResults).some(
114
- (result: any) => result.udp?.reachable === 'true' || result.tcp?.reachable === 'true'
254
+ (result) =>
255
+ !result.isVideoMesh &&
256
+ (result.udp?.reachable === 'true' || result.tcp?.reachable === 'true')
115
257
  );
116
258
  } catch (e) {
117
259
  LoggerProxy.logger.error(
@@ -131,7 +273,7 @@ export default class Reachability {
131
273
  * @memberof Reachability
132
274
  */
133
275
  private buildPeerConnectionConfig(cluster: any) {
134
- const iceServers = _.uniq([...cluster.udp, ...cluster.tcp]).map((url) => ({
276
+ const iceServers = uniq(cluster.udp).map((url) => ({
135
277
  username: '',
136
278
  credential: '',
137
279
  urls: [url],
@@ -192,7 +334,7 @@ export default class Reachability {
192
334
  * @private
193
335
  * @memberof Reachability
194
336
  */
195
- private getLocalSDPForClusters(clusterList: object) {
337
+ private getLocalSDPForClusters(clusterList: object): Promise<InternalReachabilityResults> {
196
338
  let clusters: any[] = [...Object.keys(clusterList)];
197
339
 
198
340
  clusters = clusters.map(async (key) => {
@@ -205,18 +347,17 @@ export default class Reachability {
205
347
  peerConnection.begin = Date.now();
206
348
  peerConnection.setLocalDescription(description);
207
349
 
208
- return this.iceGatheringState(
209
- peerConnection,
210
- cluster.isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT
211
- ).catch((iceGatheringStateError) => {
212
- LoggerProxy.logger.log(
213
- `Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`
214
- );
215
- });
350
+ return this.iceGatheringState(peerConnection, cluster.isVideoMesh).catch(
351
+ (iceGatheringStateError) => {
352
+ LoggerProxy.logger.log(
353
+ `Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`
354
+ );
355
+ }
356
+ );
216
357
  });
217
358
 
218
359
  return Promise.all(clusters)
219
- .then(this.parseIceResultsToReachabilityResults)
360
+ .then(this.parseIceResultsToInternalReachabilityResults)
220
361
  .then((reachabilityLatencyResults) => {
221
362
  this.logUnreachableClusters();
222
363
 
@@ -292,6 +433,8 @@ export default class Reachability {
292
433
  `Reachability:index#onIceCandidate --> Successfully pinged ${peerConnection.key}:`,
293
434
  elapsed
294
435
  );
436
+ // order is important
437
+ this.addPublicIP(peerConnection, e.candidate.address);
295
438
  this.setLatencyAndClose(peerConnection, elapsed);
296
439
  }
297
440
  };
@@ -303,14 +446,17 @@ export default class Reachability {
303
446
  * speed.
304
447
  * @private
305
448
  * @param {RTCPeerConnection} peerConnection
306
- * @param {number} timeout
449
+ * @param {boolean} isVideoMesh
307
450
  * @returns {Promise}
308
451
  */
309
- private iceGatheringState(peerConnection: RTCPeerConnection, timeout: number) {
452
+ private iceGatheringState(peerConnection: RTCPeerConnection, isVideoMesh: boolean) {
310
453
  const ELAPSED = 'elapsed';
311
454
 
312
- return new Promise((resolve) => {
455
+ const timeout = isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT;
456
+
457
+ return new Promise<ICECandidateResult>((resolve) => {
313
458
  const peerConnectionProxy = new window.Proxy(peerConnection, {
459
+ // eslint-disable-next-line require-jsdoc
314
460
  get(target, property) {
315
461
  const targetMember = target[property];
316
462
 
@@ -323,8 +469,14 @@ export default class Reachability {
323
469
  set: (target, property, value) => {
324
470
  // only intercept elapsed property
325
471
  if (property === ELAPSED) {
326
- // @ts-ignore
327
- resolve({clusterId: peerConnection.key, elapsed: value});
472
+ resolve({
473
+ // @ts-ignore
474
+ clusterId: peerConnection.key,
475
+ isVideoMesh,
476
+ // @ts-ignore
477
+ publicIPs: target.publicIPs,
478
+ elapsed: value,
479
+ });
328
480
 
329
481
  return true;
330
482
  }
@@ -345,6 +497,8 @@ export default class Reachability {
345
497
 
346
498
  // Close any open peerConnections
347
499
  if (peerConnectionProxy.connectionState !== CLOSED) {
500
+ // order is important
501
+ this.addPublicIP(peerConnectionProxy, null);
348
502
  this.setLatencyAndClose(peerConnectionProxy, null);
349
503
  }
350
504
  }, timeout);
@@ -369,29 +523,39 @@ export default class Reachability {
369
523
 
370
524
  /**
371
525
  * Calculates time to establish connection
372
- * @param {array} iceResults iceResults
526
+ * @param {Array<ICECandidateResult>} iceResults iceResults
373
527
  * @returns {object} reachabilityMap
374
- * @private
528
+ * @protected
375
529
  * @memberof Reachability
376
530
  */
377
- private parseIceResultsToReachabilityResults(iceResults: Array<any>) {
531
+ protected parseIceResultsToInternalReachabilityResults(
532
+ iceResults: Array<ICECandidateResult>
533
+ ): InternalReachabilityResults {
378
534
  const reachabilityMap = {};
379
535
 
380
- iceResults.forEach(({clusterId, elapsed}) => {
381
- let latencyResult;
536
+ iceResults.forEach(({clusterId, isVideoMesh, elapsed, publicIPs}) => {
537
+ const latencyResult = {};
382
538
 
383
- if (elapsed === null) {
384
- latencyResult = {reachable: 'false'};
539
+ if (!elapsed) {
540
+ Object.assign(latencyResult, {reachable: 'false'});
385
541
  } else {
386
- latencyResult = {
542
+ Object.assign(latencyResult, {
387
543
  reachable: 'true',
388
544
  latencyInMilliseconds: elapsed.toString(),
389
- };
545
+ });
546
+ }
547
+
548
+ if (publicIPs) {
549
+ Object.assign(latencyResult, {
550
+ clientMediaIPs: publicIPs,
551
+ });
390
552
  }
391
553
 
392
554
  reachabilityMap[clusterId] = {
393
555
  udp: latencyResult,
394
- tcp: latencyResult,
556
+ tcp: {untested: 'true'},
557
+ xtls: {untested: 'true'},
558
+ isVideoMesh,
395
559
  };
396
560
  });
397
561
 
@@ -401,11 +565,11 @@ export default class Reachability {
401
565
  /**
402
566
  * fetches reachability data
403
567
  * @param {object} clusterList
404
- * @returns {Promise<localSDPData>} reachability check results
568
+ * @returns {Promise<InternalReachabilityResults>} reachability check results
405
569
  * @private
406
570
  * @memberof Reachability
407
571
  */
408
- private performReachabilityCheck(clusterList: object) {
572
+ private performReachabilityCheck(clusterList: object): Promise<InternalReachabilityResults> {
409
573
  if (!clusterList || !Object.keys(clusterList).length) {
410
574
  return Promise.resolve({});
411
575
  }
@@ -432,6 +596,33 @@ export default class Reachability {
432
596
  });
433
597
  }
434
598
 
599
+ /**
600
+ * Adds public IP (client media IPs)
601
+ * @param {RTCPeerConnection} peerConnection
602
+ * @param {string} publicIP
603
+ * @returns {void}
604
+ */
605
+ protected addPublicIP(peerConnection: RTCPeerConnection, publicIP?: string | null) {
606
+ const modifiedPeerConnection: RTCPeerConnection & {publicIPs?: string[]} = peerConnection;
607
+ const {CLOSED} = CONNECTION_STATE;
608
+
609
+ if (modifiedPeerConnection.connectionState === CLOSED) {
610
+ LoggerProxy.logger.log(
611
+ `Reachability:index#addPublicIP --> Attempting to set publicIP of ${publicIP} on closed peerConnection.`
612
+ );
613
+ }
614
+
615
+ if (publicIP) {
616
+ if (modifiedPeerConnection.publicIPs) {
617
+ modifiedPeerConnection.publicIPs.push(publicIP);
618
+ } else {
619
+ modifiedPeerConnection.publicIPs = [publicIP];
620
+ }
621
+ } else {
622
+ modifiedPeerConnection.publicIPs = null;
623
+ }
624
+ }
625
+
435
626
  /**
436
627
  * Records latency and closes the peerConnection
437
628
  * @param {RTCPeerConnection} peerConnection
@@ -1,5 +1,5 @@
1
1
  import LoggerProxy from '../common/logs/logger-proxy';
2
- import {HTTP_VERBS, RESOURCE, API} from '../constants';
2
+ import {HTTP_VERBS, RESOURCE, API, IP_VERSION} from '../constants';
3
3
 
4
4
  export interface ClusterNode {
5
5
  isVideoMesh: boolean;
@@ -28,31 +28,40 @@ class ReachabilityRequest {
28
28
  }
29
29
 
30
30
  /**
31
- * gets the cluster information
31
+ * Gets the cluster information
32
32
  *
33
- * @param {boolean} includeVideoMesh whether to include the video mesh clusters in the result or not
33
+ * @param {IP_VERSION} ipVersion information about current ip network we're on
34
34
  * @returns {Promise}
35
35
  */
36
- getClusters = (): Promise<ClusterList> =>
36
+ getClusters = (ipVersion?: IP_VERSION): Promise<{clusters: ClusterList; joinCookie: any}> =>
37
37
  this.webex
38
38
  .request({
39
39
  method: HTTP_VERBS.GET,
40
40
  shouldRefreshAccessToken: false,
41
41
  api: API.CALLIOPEDISCOVERY,
42
42
  resource: RESOURCE.CLUSTERS,
43
+ qs: {
44
+ JCSupport: 1,
45
+ ipver: ipVersion,
46
+ },
43
47
  })
44
48
  .then((res) => {
45
- const {clusters} = res.body;
49
+ const {clusters, joinCookie} = res.body;
46
50
 
47
51
  Object.keys(clusters).forEach((key) => {
48
- clusters[key].isVideoMesh = res.body.clusterClasses?.hybridMedia?.includes(key);
52
+ clusters[key].isVideoMesh = !!res.body.clusterClasses?.hybridMedia?.includes(key);
49
53
  });
50
54
 
51
55
  LoggerProxy.logger.log(
52
- `Reachability:request#getClusters --> get clusters successful:${JSON.stringify(clusters)}`
56
+ `Reachability:request#getClusters --> get clusters (ipver=${ipVersion}) successful:${JSON.stringify(
57
+ clusters
58
+ )}`
53
59
  );
54
60
 
55
- return clusters;
61
+ return {
62
+ clusters,
63
+ joinCookie,
64
+ };
56
65
  });
57
66
 
58
67
  /**