@webex/plugin-meetings 3.0.0-beta.21 → 3.0.0-beta.211

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 (422) hide show
  1. package/README.md +45 -7
  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 +114 -14
  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 +841 -19
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/request.js +78 -0
  17. package/dist/breakouts/request.js.map +1 -0
  18. package/dist/breakouts/utils.js +67 -0
  19. package/dist/breakouts/utils.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +3 -2
  21. package/dist/common/errors/webex-errors.js.map +1 -1
  22. package/dist/common/logs/logger-proxy.js +1 -1
  23. package/dist/common/logs/logger-proxy.js.map +1 -1
  24. package/dist/common/queue.js +24 -9
  25. package/dist/common/queue.js.map +1 -1
  26. package/dist/config.js +3 -8
  27. package/dist/config.js.map +1 -1
  28. package/dist/constants.js +179 -30
  29. package/dist/constants.js.map +1 -1
  30. package/dist/controls-options-manager/constants.js +14 -0
  31. package/dist/controls-options-manager/constants.js.map +1 -0
  32. package/dist/controls-options-manager/enums.js +27 -0
  33. package/dist/controls-options-manager/enums.js.map +1 -0
  34. package/dist/controls-options-manager/index.js +297 -0
  35. package/dist/controls-options-manager/index.js.map +1 -0
  36. package/dist/controls-options-manager/types.js +7 -0
  37. package/dist/controls-options-manager/types.js.map +1 -0
  38. package/dist/controls-options-manager/util.js +319 -0
  39. package/dist/controls-options-manager/util.js.map +1 -0
  40. package/dist/index.js +106 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/interpretation/collection.js +23 -0
  43. package/dist/interpretation/collection.js.map +1 -0
  44. package/dist/interpretation/index.js +366 -0
  45. package/dist/interpretation/index.js.map +1 -0
  46. package/dist/interpretation/siLanguage.js +25 -0
  47. package/dist/interpretation/siLanguage.js.map +1 -0
  48. package/dist/locus-info/controlsUtils.js +91 -2
  49. package/dist/locus-info/controlsUtils.js.map +1 -1
  50. package/dist/locus-info/index.js +359 -64
  51. package/dist/locus-info/index.js.map +1 -1
  52. package/dist/locus-info/infoUtils.js +7 -1
  53. package/dist/locus-info/infoUtils.js.map +1 -1
  54. package/dist/locus-info/mediaSharesUtils.js +43 -1
  55. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  56. package/dist/locus-info/parser.js +219 -63
  57. package/dist/locus-info/parser.js.map +1 -1
  58. package/dist/locus-info/selfUtils.js +89 -14
  59. package/dist/locus-info/selfUtils.js.map +1 -1
  60. package/dist/media/index.js +48 -135
  61. package/dist/media/index.js.map +1 -1
  62. package/dist/media/properties.js +29 -90
  63. package/dist/media/properties.js.map +1 -1
  64. package/dist/mediaQualityMetrics/config.js +505 -493
  65. package/dist/mediaQualityMetrics/config.js.map +1 -1
  66. package/dist/meeting/in-meeting-actions.js +90 -2
  67. package/dist/meeting/in-meeting-actions.js.map +1 -1
  68. package/dist/meeting/index.js +2770 -2547
  69. package/dist/meeting/index.js.map +1 -1
  70. package/dist/meeting/locusMediaRequest.js +291 -0
  71. package/dist/meeting/locusMediaRequest.js.map +1 -0
  72. package/dist/meeting/muteState.js +229 -124
  73. package/dist/meeting/muteState.js.map +1 -1
  74. package/dist/meeting/request.js +199 -193
  75. package/dist/meeting/request.js.map +1 -1
  76. package/dist/meeting/util.js +532 -414
  77. package/dist/meeting/util.js.map +1 -1
  78. package/dist/meeting-info/index.js +48 -7
  79. package/dist/meeting-info/index.js.map +1 -1
  80. package/dist/meeting-info/meeting-info-v2.js +171 -51
  81. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  82. package/dist/meeting-info/utilv2.js +20 -5
  83. package/dist/meeting-info/utilv2.js.map +1 -1
  84. package/dist/meetings/collection.js +22 -0
  85. package/dist/meetings/collection.js.map +1 -1
  86. package/dist/meetings/index.js +357 -66
  87. package/dist/meetings/index.js.map +1 -1
  88. package/dist/meetings/meetings.types.js +7 -0
  89. package/dist/meetings/meetings.types.js.map +1 -0
  90. package/dist/meetings/request.js +2 -0
  91. package/dist/meetings/request.js.map +1 -1
  92. package/dist/meetings/util.js +88 -1
  93. package/dist/meetings/util.js.map +1 -1
  94. package/dist/member/index.js +49 -0
  95. package/dist/member/index.js.map +1 -1
  96. package/dist/member/types.js +25 -0
  97. package/dist/member/types.js.map +1 -0
  98. package/dist/member/util.js +121 -25
  99. package/dist/member/util.js.map +1 -1
  100. package/dist/members/collection.js +10 -0
  101. package/dist/members/collection.js.map +1 -1
  102. package/dist/members/index.js +86 -5
  103. package/dist/members/index.js.map +1 -1
  104. package/dist/members/request.js +106 -38
  105. package/dist/members/request.js.map +1 -1
  106. package/dist/members/types.js +15 -0
  107. package/dist/members/types.js.map +1 -0
  108. package/dist/members/util.js +316 -233
  109. package/dist/members/util.js.map +1 -1
  110. package/dist/metrics/constants.js +3 -5
  111. package/dist/metrics/constants.js.map +1 -1
  112. package/dist/metrics/index.js +1 -468
  113. package/dist/metrics/index.js.map +1 -1
  114. package/dist/multistream/mediaRequestManager.js +238 -49
  115. package/dist/multistream/mediaRequestManager.js.map +1 -1
  116. package/dist/multistream/receiveSlot.js +49 -16
  117. package/dist/multistream/receiveSlot.js.map +1 -1
  118. package/dist/multistream/receiveSlotManager.js +52 -34
  119. package/dist/multistream/receiveSlotManager.js.map +1 -1
  120. package/dist/multistream/remoteMedia.js +44 -18
  121. package/dist/multistream/remoteMedia.js.map +1 -1
  122. package/dist/multistream/remoteMediaGroup.js +60 -3
  123. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  124. package/dist/multistream/remoteMediaManager.js +173 -59
  125. package/dist/multistream/remoteMediaManager.js.map +1 -1
  126. package/dist/networkQualityMonitor/index.js +4 -2
  127. package/dist/networkQualityMonitor/index.js.map +1 -1
  128. package/dist/reachability/index.js +72 -27
  129. package/dist/reachability/index.js.map +1 -1
  130. package/dist/reachability/request.js +12 -5
  131. package/dist/reachability/request.js.map +1 -1
  132. package/dist/reconnection-manager/index.js +196 -155
  133. package/dist/reconnection-manager/index.js.map +1 -1
  134. package/dist/recording-controller/index.js +21 -2
  135. package/dist/recording-controller/index.js.map +1 -1
  136. package/dist/recording-controller/util.js +9 -8
  137. package/dist/recording-controller/util.js.map +1 -1
  138. package/dist/roap/index.js +21 -29
  139. package/dist/roap/index.js.map +1 -1
  140. package/dist/roap/request.js +110 -89
  141. package/dist/roap/request.js.map +1 -1
  142. package/dist/roap/turnDiscovery.js +93 -36
  143. package/dist/roap/turnDiscovery.js.map +1 -1
  144. package/dist/rtcMetrics/constants.js +12 -0
  145. package/dist/rtcMetrics/constants.js.map +1 -0
  146. package/dist/rtcMetrics/index.js +117 -0
  147. package/dist/rtcMetrics/index.js.map +1 -0
  148. package/dist/statsAnalyzer/global.js +1 -93
  149. package/dist/statsAnalyzer/global.js.map +1 -1
  150. package/dist/statsAnalyzer/index.js +326 -311
  151. package/dist/statsAnalyzer/index.js.map +1 -1
  152. package/dist/statsAnalyzer/mqaUtil.js +90 -53
  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/breakout.d.ts +8 -0
  158. package/dist/types/breakouts/collection.d.ts +5 -0
  159. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  160. package/dist/types/breakouts/events.d.ts +8 -0
  161. package/dist/types/breakouts/index.d.ts +5 -0
  162. package/dist/types/breakouts/request.d.ts +22 -0
  163. package/dist/types/breakouts/utils.d.ts +15 -0
  164. package/dist/types/common/browser-detection.d.ts +9 -0
  165. package/dist/types/common/collection.d.ts +48 -0
  166. package/dist/types/common/config.d.ts +2 -0
  167. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  168. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  169. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  170. package/dist/types/common/errors/media.d.ts +15 -0
  171. package/dist/types/common/errors/parameter.d.ts +15 -0
  172. package/dist/types/common/errors/password-error.d.ts +15 -0
  173. package/dist/types/common/errors/permission.d.ts +14 -0
  174. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  175. package/dist/types/common/errors/reconnection.d.ts +15 -0
  176. package/dist/types/common/errors/stats.d.ts +15 -0
  177. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  178. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  179. package/dist/types/common/events/events-scope.d.ts +17 -0
  180. package/dist/types/common/events/events.d.ts +12 -0
  181. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  182. package/dist/types/common/events/util.d.ts +2 -0
  183. package/dist/types/common/logs/logger-config.d.ts +2 -0
  184. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  185. package/dist/types/common/logs/request.d.ts +34 -0
  186. package/dist/types/common/queue.d.ts +34 -0
  187. package/dist/types/config.d.ts +72 -0
  188. package/dist/types/constants.d.ts +1020 -0
  189. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  190. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  191. package/dist/types/controls-options-manager/index.d.ts +136 -0
  192. package/dist/types/controls-options-manager/types.d.ts +43 -0
  193. package/dist/types/controls-options-manager/util.d.ts +1 -0
  194. package/dist/types/index.d.ts +7 -0
  195. package/dist/types/interpretation/collection.d.ts +5 -0
  196. package/dist/types/interpretation/index.d.ts +5 -0
  197. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  198. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  199. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  200. package/dist/types/locus-info/fullState.d.ts +2 -0
  201. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  202. package/dist/types/locus-info/index.d.ts +322 -0
  203. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  204. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  205. package/dist/types/locus-info/parser.d.ts +271 -0
  206. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  207. package/dist/types/media/index.d.ts +34 -0
  208. package/dist/types/media/properties.d.ts +93 -0
  209. package/dist/types/media/util.d.ts +2 -0
  210. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  211. package/dist/types/meeting/in-meeting-actions.d.ts +163 -0
  212. package/dist/types/meeting/index.d.ts +1482 -0
  213. package/dist/types/meeting/locusMediaRequest.d.ts +72 -0
  214. package/dist/types/meeting/muteState.d.ts +184 -0
  215. package/dist/types/meeting/request.d.ts +257 -0
  216. package/dist/types/meeting/request.type.d.ts +11 -0
  217. package/dist/types/meeting/state.d.ts +9 -0
  218. package/dist/types/meeting/util.d.ts +79 -0
  219. package/dist/types/meeting-info/collection.d.ts +20 -0
  220. package/dist/types/meeting-info/index.d.ts +62 -0
  221. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  222. package/dist/types/meeting-info/request.d.ts +22 -0
  223. package/dist/types/meeting-info/util.d.ts +2 -0
  224. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  225. package/dist/types/meetings/collection.d.ts +31 -0
  226. package/dist/types/meetings/index.d.ts +367 -0
  227. package/dist/types/meetings/meetings.types.d.ts +4 -0
  228. package/dist/types/meetings/request.d.ts +27 -0
  229. package/dist/types/meetings/util.d.ts +18 -0
  230. package/dist/types/member/index.d.ts +159 -0
  231. package/dist/types/member/types.d.ts +32 -0
  232. package/dist/types/member/util.d.ts +2 -0
  233. package/dist/types/members/collection.d.ts +29 -0
  234. package/dist/types/members/index.d.ts +353 -0
  235. package/dist/types/members/request.d.ts +114 -0
  236. package/dist/types/members/types.d.ts +24 -0
  237. package/dist/types/members/util.d.ts +210 -0
  238. package/dist/types/metrics/constants.d.ts +55 -0
  239. package/dist/types/metrics/index.d.ts +45 -0
  240. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  241. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  242. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  243. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  244. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  245. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  246. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  247. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  248. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  249. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  250. package/dist/types/reachability/index.d.ts +152 -0
  251. package/dist/types/reachability/request.d.ts +37 -0
  252. package/dist/types/reactions/constants.d.ts +3 -0
  253. package/dist/types/reactions/reactions.d.ts +4 -0
  254. package/dist/types/reactions/reactions.type.d.ts +52 -0
  255. package/dist/types/reconnection-manager/index.d.ts +126 -0
  256. package/dist/types/recording-controller/enums.d.ts +7 -0
  257. package/dist/types/recording-controller/index.d.ts +207 -0
  258. package/dist/types/recording-controller/util.d.ts +14 -0
  259. package/dist/types/roap/index.d.ts +77 -0
  260. package/dist/types/roap/request.d.ts +36 -0
  261. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  262. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  263. package/dist/types/rtcMetrics/index.d.ts +46 -0
  264. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  265. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  266. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  267. package/dist/types/transcription/index.d.ts +64 -0
  268. package/package.json +23 -20
  269. package/src/annotation/annotation.types.ts +50 -0
  270. package/src/annotation/constants.ts +36 -0
  271. package/src/annotation/index.ts +328 -0
  272. package/src/breakouts/README.md +44 -14
  273. package/src/breakouts/breakout.ts +87 -9
  274. package/src/breakouts/edit-lock-error.ts +25 -0
  275. package/src/breakouts/events.ts +56 -0
  276. package/src/breakouts/index.ts +710 -10
  277. package/src/breakouts/request.ts +55 -0
  278. package/src/breakouts/utils.ts +57 -0
  279. package/src/common/errors/webex-errors.ts +6 -2
  280. package/src/common/logs/logger-proxy.ts +1 -1
  281. package/src/common/queue.ts +22 -8
  282. package/src/config.ts +2 -7
  283. package/src/constants.ts +165 -21
  284. package/src/controls-options-manager/constants.ts +5 -0
  285. package/src/controls-options-manager/enums.ts +18 -0
  286. package/src/controls-options-manager/index.ts +278 -0
  287. package/src/controls-options-manager/types.ts +59 -0
  288. package/src/controls-options-manager/util.ts +300 -0
  289. package/src/index.ts +39 -0
  290. package/src/interpretation/README.md +60 -0
  291. package/src/interpretation/collection.ts +19 -0
  292. package/src/interpretation/index.ts +332 -0
  293. package/src/interpretation/siLanguage.ts +18 -0
  294. package/src/locus-info/controlsUtils.ts +108 -0
  295. package/src/locus-info/index.ts +383 -61
  296. package/src/locus-info/infoUtils.ts +10 -2
  297. package/src/locus-info/mediaSharesUtils.ts +48 -0
  298. package/src/locus-info/parser.ts +224 -39
  299. package/src/locus-info/selfUtils.ts +81 -5
  300. package/src/media/index.ts +87 -140
  301. package/src/media/properties.ts +49 -90
  302. package/src/mediaQualityMetrics/config.ts +379 -377
  303. package/src/meeting/in-meeting-actions.ts +179 -3
  304. package/src/meeting/index.ts +2099 -2083
  305. package/src/meeting/locusMediaRequest.ts +311 -0
  306. package/src/meeting/muteState.ts +228 -132
  307. package/src/meeting/request.ts +105 -115
  308. package/src/meeting/util.ts +511 -397
  309. package/src/meeting-info/index.ts +54 -8
  310. package/src/meeting-info/meeting-info-v2.ts +148 -14
  311. package/src/meeting-info/utilv2.ts +13 -3
  312. package/src/meetings/collection.ts +20 -0
  313. package/src/meetings/index.ts +392 -84
  314. package/src/meetings/meetings.types.ts +12 -0
  315. package/src/meetings/request.ts +2 -0
  316. package/src/meetings/util.ts +103 -4
  317. package/src/member/index.ts +49 -0
  318. package/src/member/types.ts +38 -0
  319. package/src/member/util.ts +127 -25
  320. package/src/members/collection.ts +8 -0
  321. package/src/members/index.ts +107 -6
  322. package/src/members/request.ts +97 -17
  323. package/src/members/types.ts +28 -0
  324. package/src/members/util.ts +319 -240
  325. package/src/metrics/constants.ts +2 -4
  326. package/src/metrics/index.ts +1 -490
  327. package/src/multistream/mediaRequestManager.ts +289 -79
  328. package/src/multistream/receiveSlot.ts +55 -18
  329. package/src/multistream/receiveSlotManager.ts +46 -24
  330. package/src/multistream/remoteMedia.ts +27 -2
  331. package/src/multistream/remoteMediaGroup.ts +59 -0
  332. package/src/multistream/remoteMediaManager.ts +113 -32
  333. package/src/networkQualityMonitor/index.ts +6 -6
  334. package/src/reachability/index.ts +62 -15
  335. package/src/reachability/request.ts +10 -5
  336. package/src/reconnection-manager/index.ts +68 -43
  337. package/src/recording-controller/index.ts +20 -3
  338. package/src/recording-controller/util.ts +26 -9
  339. package/src/roap/index.ts +21 -30
  340. package/src/roap/request.ts +101 -95
  341. package/src/roap/turnDiscovery.ts +47 -25
  342. package/src/rtcMetrics/constants.ts +3 -0
  343. package/src/rtcMetrics/index.ts +100 -0
  344. package/src/statsAnalyzer/global.ts +1 -94
  345. package/src/statsAnalyzer/index.ts +376 -386
  346. package/src/statsAnalyzer/mqaUtil.ts +100 -99
  347. package/test/integration/spec/converged-space-meetings.js +233 -0
  348. package/test/integration/spec/journey.js +336 -259
  349. package/test/integration/spec/space-meeting.js +77 -4
  350. package/test/unit/spec/annotation/index.ts +418 -0
  351. package/test/unit/spec/breakouts/breakout.ts +142 -24
  352. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  353. package/test/unit/spec/breakouts/events.ts +89 -0
  354. package/test/unit/spec/breakouts/index.ts +1545 -48
  355. package/test/unit/spec/breakouts/request.ts +104 -0
  356. package/test/unit/spec/breakouts/utils.js +72 -0
  357. package/test/unit/spec/common/queue.js +31 -2
  358. package/test/unit/spec/controls-options-manager/index.js +287 -0
  359. package/test/unit/spec/controls-options-manager/util.js +582 -0
  360. package/test/unit/spec/fixture/locus.js +1 -0
  361. package/test/unit/spec/interpretation/collection.ts +15 -0
  362. package/test/unit/spec/interpretation/index.ts +589 -0
  363. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  364. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  365. package/test/unit/spec/locus-info/index.js +1169 -36
  366. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  367. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  368. package/test/unit/spec/locus-info/parser.js +62 -22
  369. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  370. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  371. package/test/unit/spec/media/index.ts +138 -28
  372. package/test/unit/spec/meeting/in-meeting-actions.ts +89 -3
  373. package/test/unit/spec/meeting/index.js +3573 -1663
  374. package/test/unit/spec/meeting/locusMediaRequest.ts +438 -0
  375. package/test/unit/spec/meeting/muteState.js +370 -208
  376. package/test/unit/spec/meeting/request.js +339 -44
  377. package/test/unit/spec/meeting/utils.js +456 -53
  378. package/test/unit/spec/meeting-info/index.js +181 -0
  379. package/test/unit/spec/meeting-info/meetinginfov2.js +383 -5
  380. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  381. package/test/unit/spec/meetings/collection.js +14 -0
  382. package/test/unit/spec/meetings/index.js +867 -125
  383. package/test/unit/spec/meetings/utils.js +206 -2
  384. package/test/unit/spec/member/index.js +58 -4
  385. package/test/unit/spec/member/util.js +479 -35
  386. package/test/unit/spec/members/index.js +319 -1
  387. package/test/unit/spec/members/request.js +206 -27
  388. package/test/unit/spec/members/utils.js +184 -0
  389. package/test/unit/spec/metrics/index.js +1 -50
  390. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  391. package/test/unit/spec/multistream/receiveSlot.ts +72 -13
  392. package/test/unit/spec/multistream/receiveSlotManager.ts +58 -28
  393. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  394. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  395. package/test/unit/spec/multistream/remoteMediaManager.ts +318 -0
  396. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  397. package/test/unit/spec/reachability/index.ts +125 -8
  398. package/test/unit/spec/reachability/request.js +66 -0
  399. package/test/unit/spec/reconnection-manager/index.js +59 -6
  400. package/test/unit/spec/recording-controller/index.js +294 -218
  401. package/test/unit/spec/recording-controller/util.js +223 -96
  402. package/test/unit/spec/roap/index.ts +26 -51
  403. package/test/unit/spec/roap/request.ts +196 -85
  404. package/test/unit/spec/roap/turnDiscovery.ts +30 -7
  405. package/test/unit/spec/rtcMetrics/index.ts +60 -0
  406. package/test/unit/spec/stats-analyzer/index.js +92 -41
  407. package/test/utils/constants.js +9 -0
  408. package/test/utils/integrationTestUtils.js +46 -0
  409. package/test/utils/testUtils.js +0 -45
  410. package/test/utils/webex-config.js +4 -0
  411. package/test/utils/webex-test-users.js +6 -3
  412. package/dist/meeting/effectsState.js +0 -262
  413. package/dist/meeting/effectsState.js.map +0 -1
  414. package/dist/metrics/config.js +0 -299
  415. package/dist/metrics/config.js.map +0 -1
  416. package/dist/multistream/multistreamMedia.js +0 -110
  417. package/dist/multistream/multistreamMedia.js.map +0 -1
  418. package/src/index.js +0 -16
  419. package/src/meeting/effectsState.ts +0 -211
  420. package/src/metrics/config.ts +0 -495
  421. package/src/multistream/multistreamMedia.ts +0 -97
  422. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -1,11 +1,13 @@
1
1
  /* eslint-disable valid-jsdoc */
2
2
  /* eslint-disable import/prefer-default-export */
3
- import {MediaType} from '@webex/internal-media-core';
4
-
3
+ import {MediaType, ReceiveSlot as WcmeReceiveSlot} from '@webex/internal-media-core';
5
4
  import LoggerProxy from '../common/logs/logger-proxy';
6
- import Meeting from '../meeting';
7
5
 
8
- import {CSI, ReceiveSlot} from './receiveSlot';
6
+ import {FindMemberIdCallback, ReceiveSlot} from './receiveSlot';
7
+
8
+ export type CreateSlotCallback = (mediaType: MediaType) => Promise<WcmeReceiveSlot>;
9
+
10
+ export type {CSI, FindMemberIdCallback} from './receiveSlot';
9
11
 
10
12
  /**
11
13
  * Manages all receive slots used by a meeting. WMCE receive slots cannot be ever deleted,
@@ -16,13 +18,18 @@ export class ReceiveSlotManager {
16
18
 
17
19
  private freeSlots: {[key in MediaType]: ReceiveSlot[]};
18
20
 
19
- private meeting: Meeting;
21
+ private createSlotCallback: CreateSlotCallback;
22
+
23
+ private findMemberIdByCsiCallback: FindMemberIdCallback;
20
24
 
21
25
  /**
22
26
  * Constructor
23
27
  * @param {Meeting} meeting
24
28
  */
25
- constructor(meeting) {
29
+ constructor(
30
+ createSlotCallback: CreateSlotCallback,
31
+ findMemberIdByCsiCallback: FindMemberIdCallback
32
+ ) {
26
33
  this.allocatedSlots = {
27
34
  [MediaType.AudioMain]: [],
28
35
  [MediaType.VideoMain]: [],
@@ -35,7 +42,8 @@ export class ReceiveSlotManager {
35
42
  [MediaType.AudioSlides]: [],
36
43
  [MediaType.VideoSlides]: [],
37
44
  };
38
- this.meeting = meeting;
45
+ this.createSlotCallback = createSlotCallback;
46
+ this.findMemberIdByCsiCallback = findMemberIdByCsiCallback;
39
47
  }
40
48
 
41
49
  /**
@@ -45,34 +53,24 @@ export class ReceiveSlotManager {
45
53
  * @returns {Promise<ReceiveSlot>}
46
54
  */
47
55
  async allocateSlot(mediaType: MediaType): Promise<ReceiveSlot> {
48
- if (!this.meeting?.mediaProperties?.webrtcMediaConnection) {
49
- return Promise.reject(new Error('Webrtc media connection is missing'));
50
- }
51
-
52
56
  // try to use one of the free ones
53
57
  const availableSlot = this.freeSlots[mediaType].pop();
54
58
 
55
59
  if (availableSlot) {
56
60
  this.allocatedSlots[mediaType].push(availableSlot);
57
61
 
58
- LoggerProxy.logger.log(`receive slot re-used: ${availableSlot.id}`);
62
+ LoggerProxy.logger.log(`${mediaType}: receive slot re-used: ${availableSlot.id}`);
59
63
 
60
64
  return availableSlot;
61
65
  }
62
66
 
63
67
  // we have to create a new one
64
- const wcmeReceiveSlot =
65
- await this.meeting.mediaProperties.webrtcMediaConnection.createReceiveSlot(mediaType);
66
-
67
- const receiveSlot = new ReceiveSlot(
68
- mediaType,
69
- wcmeReceiveSlot,
70
- // @ts-ignore
71
- (csi: CSI) => this.meeting.members.findMemberByCsi(csi)?.id
72
- );
68
+ const wcmeReceiveSlot = await this.createSlotCallback(mediaType);
69
+
70
+ const receiveSlot = new ReceiveSlot(mediaType, wcmeReceiveSlot, this.findMemberIdByCsiCallback);
73
71
 
74
72
  this.allocatedSlots[mediaType].push(receiveSlot);
75
- LoggerProxy.logger.log(`new receive slot allocated: ${receiveSlot.id}`);
73
+ LoggerProxy.logger.log(`${mediaType}: new receive slot allocated: ${receiveSlot.id}`);
76
74
 
77
75
  return receiveSlot;
78
76
  }
@@ -89,10 +87,10 @@ export class ReceiveSlotManager {
89
87
  if (idx >= 0) {
90
88
  this.allocatedSlots[slot.mediaType].splice(idx, 1);
91
89
  this.freeSlots[slot.mediaType].push(slot);
92
- LoggerProxy.logger.log(`receive slot released: ${slot.id}`);
90
+ LoggerProxy.logger.log(`${slot.mediaType}: receive slot released: ${slot.id}`);
93
91
  } else {
94
92
  LoggerProxy.logger.warn(
95
- 'ReceiveSlotManager#releaseSlot --> trying to release a slot that is not managed by this ReceiveSlotManager'
93
+ `ReceiveSlotManager#releaseSlot --> trying to release a ${slot.mediaType}} slot that is not managed by this ReceiveSlotManager`
96
94
  );
97
95
  }
98
96
  }
@@ -141,4 +139,28 @@ export class ReceiveSlotManager {
141
139
  numFreeSlots,
142
140
  };
143
141
  }
142
+
143
+ /**
144
+ * Tries to find the member id on all allocated receive slots
145
+ * This function should be called when new members are added to the meeting.
146
+ */
147
+ updateMemberIds() {
148
+ Object.keys(this.allocatedSlots).forEach((key) => {
149
+ this.allocatedSlots[key].forEach((slot: ReceiveSlot) => {
150
+ slot.findMemberId();
151
+ });
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Find a receive slot by a ssrc.
157
+ *
158
+ * @param ssrc - The ssrc of the receive slot to find.
159
+ * @returns - The receive slot with this ssrc, undefined if not found.
160
+ */
161
+ findReceiveSlotBySsrc(ssrc: number): ReceiveSlot | undefined {
162
+ return Object.values(this.allocatedSlots)
163
+ .flat()
164
+ .find((r) => ssrc && r.wcmeReceiveSlot?.id?.ssrc === ssrc);
165
+ }
144
166
  }
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable valid-jsdoc */
2
- import {MediaType, SourceState} from '@webex/internal-media-core';
2
+ import {MediaType, StreamState} from '@webex/internal-media-core';
3
3
  import LoggerProxy from '../common/logs/logger-proxy';
4
4
  import EventsScope from '../common/events/events-scope';
5
5
 
@@ -102,6 +102,31 @@ export class RemoteMedia extends EventsScope {
102
102
  this.id = `RM${remoteMediaCounter}-${this.receiveSlot.id}`;
103
103
  }
104
104
 
105
+ /**
106
+ * Supply the width and height of the video element
107
+ * to restrict the requested resolution to this size
108
+ * @param width width of the video element
109
+ * @param height height of the video element
110
+ */
111
+ public setSizeHint(width, height) {
112
+ // only base on height for now
113
+ let fs: number;
114
+
115
+ if (height < 135) {
116
+ fs = 60;
117
+ } else if (height < 270) {
118
+ fs = 240;
119
+ } else if (height < 540) {
120
+ fs = 920;
121
+ } else if (height <= 720) {
122
+ fs = 3600;
123
+ } else {
124
+ fs = 8192;
125
+ }
126
+
127
+ this.receiveSlot?.setMaxFs(fs);
128
+ }
129
+
105
130
  /**
106
131
  * Invalidates the remote media by clearing the reference to a receive slot and
107
132
  * cancelling the media request.
@@ -208,7 +233,7 @@ export class RemoteMedia extends EventsScope {
208
233
  /**
209
234
  * Getter for source state
210
235
  */
211
- public get sourceState(): SourceState {
236
+ public get sourceState(): StreamState {
212
237
  return this.receiveSlot?.sourceState;
213
238
  }
214
239
 
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable valid-jsdoc */
2
2
  /* eslint-disable require-jsdoc */
3
3
  /* eslint-disable import/prefer-default-export */
4
+ import {forEach} from 'lodash';
4
5
  import LoggerProxy from '../common/logs/logger-proxy';
5
6
 
6
7
  import {getMaxFs, RemoteMedia, RemoteVideoResolution} from './remoteMedia';
@@ -66,6 +67,53 @@ export class RemoteMediaGroup {
66
67
  return [...this.unpinnedRemoteMedia, ...this.pinnedRemoteMedia];
67
68
  }
68
69
 
70
+ /**
71
+ * Sets CSIs for multiple RemoteMedia instances belonging to this RemoteMediaGroup.
72
+ * For each entry in the remoteMediaCsis array:
73
+ * - if csi is specified, the RemoteMedia instance is pinned to that CSI
74
+ * - if csi is undefined, the RemoteMedia instance is unpinned
75
+ * @internal
76
+ */
77
+ public setActiveSpeakerCsis(
78
+ remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: number}[],
79
+ commit = true
80
+ ): void {
81
+ forEach(remoteMediaCsis, ({csi, remoteMedia}) => {
82
+ if (csi) {
83
+ if (!(this.pinnedRemoteMedia.indexOf(remoteMedia) >= 0)) {
84
+ const unpinId = this.unpinnedRemoteMedia.indexOf(remoteMedia);
85
+ if (unpinId >= 0) {
86
+ this.unpinnedRemoteMedia.splice(unpinId, 1);
87
+ this.pinnedRemoteMedia.push(remoteMedia);
88
+ } else {
89
+ throw new Error(
90
+ `failed to pin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`
91
+ );
92
+ }
93
+ }
94
+ remoteMedia.sendMediaRequest(csi, false);
95
+ } else {
96
+ if (!(this.unpinnedRemoteMedia.indexOf(remoteMedia) >= 0)) {
97
+ const pinId = this.pinnedRemoteMedia.indexOf(remoteMedia);
98
+ if (pinId >= 0) {
99
+ this.pinnedRemoteMedia.splice(pinId, 1);
100
+ this.unpinnedRemoteMedia.push(remoteMedia);
101
+ } else {
102
+ throw new Error(
103
+ `failed to unpin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`
104
+ );
105
+ }
106
+ }
107
+ remoteMedia.cancelMediaRequest(false);
108
+ }
109
+ });
110
+ this.cancelActiveSpeakerMediaRequest(false);
111
+ this.sendActiveSpeakerMediaRequest(false);
112
+ if (commit) {
113
+ this.mediaRequestManager.commit();
114
+ }
115
+ }
116
+
69
117
  /**
70
118
  * Pins a specific remote media instance to a specfic CSI, so the media will
71
119
  * no longer come from active speaker, but from that CSI.
@@ -151,6 +199,17 @@ export class RemoteMediaGroup {
151
199
  throw new Error(`remote media object ${remoteMedia.id} not found in the group`);
152
200
  }
153
201
 
202
+ /**
203
+ * setPreferLiveVideo - sets preferLiveVideo to true/false
204
+ * @internal
205
+ */
206
+ public setPreferLiveVideo(preferLiveVideo: boolean, commit: boolean) {
207
+ if (this.options.preferLiveVideo !== preferLiveVideo) {
208
+ this.options.preferLiveVideo = preferLiveVideo;
209
+ this.sendActiveSpeakerMediaRequest(commit);
210
+ }
211
+ }
212
+
154
213
  private sendActiveSpeakerMediaRequest(commit: boolean) {
155
214
  this.cancelActiveSpeakerMediaRequest(false);
156
215
 
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable valid-jsdoc */
2
- import {cloneDeep, remove} from 'lodash';
2
+ import {cloneDeep, forEach, remove} from 'lodash';
3
3
  import {EventMap} from 'typed-emitter';
4
4
  import {MediaType} from '@webex/internal-media-core';
5
5
 
@@ -96,6 +96,7 @@ const OnePlusFiveLayout: VideoLayout = {
96
96
  };
97
97
 
98
98
  // A layout with 2 big panes for 2 main active speakers and a strip of 6 small panes for other active speakers:
99
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
99
100
  const TwoMainPlusSixSmallLayout: VideoLayout = {
100
101
  activeSpeakerVideoPaneGroups: [
101
102
  {
@@ -115,7 +116,7 @@ const TwoMainPlusSixSmallLayout: VideoLayout = {
115
116
 
116
117
  // A strip of 8 small video panes (thumbnails) displayed at the top of a remote screenshare:
117
118
  const RemoteScreenShareWithSmallThumbnailsLayout: VideoLayout = {
118
- // screenShareVideo: {size: 'best'}, // todo: SPARK-393485: uncomment this once backend supports screen sharing
119
+ screenShareVideo: {size: 'best'},
119
120
  activeSpeakerVideoPaneGroups: [
120
121
  {
121
122
  id: 'thumbnails',
@@ -153,7 +154,7 @@ const Stage2x2With6ThumbnailsLayout: VideoLayout = {
153
154
  export const DefaultConfiguration: Configuration = {
154
155
  audio: {
155
156
  numOfActiveSpeakerStreams: 3,
156
- numOfScreenShareStreams: 0, // todo: SPARK-393485: change to 1 once backend supports screen sharing
157
+ numOfScreenShareStreams: 1,
157
158
  },
158
159
  video: {
159
160
  preferLiveVideo: true,
@@ -490,6 +491,38 @@ export class RemoteMediaManager extends EventsScope {
490
491
  return this.currentLayoutId;
491
492
  }
492
493
 
494
+ /**
495
+ * sets the preferLiveVideo
496
+ */
497
+ public setPreferLiveVideo(preferLiveVideo: boolean) {
498
+ LoggerProxy.logger.log(
499
+ `RemoteMediaManager#setPreferLiveVideo --> setPreferLiveVideo is called to set preferLiveVideo to ${preferLiveVideo}`
500
+ );
501
+ this.config.video.preferLiveVideo = preferLiveVideo;
502
+ Object.values(this.media.video.activeSpeakerGroups).forEach((activeSpeakerGroup) => {
503
+ activeSpeakerGroup.setPreferLiveVideo(preferLiveVideo, false);
504
+ });
505
+ this.mediaRequestManagers.video.commit();
506
+ }
507
+
508
+ /**
509
+ * Sets CSIs for multiple RemoteMedia instances belonging to RemoteMediaGroup.
510
+ * For each entry in the remoteMediaCsis array:
511
+ * - if csi is specified, the RemoteMedia instance is pinned to that CSI
512
+ * - if csi is undefined, the RemoteMedia instance is unpinned
513
+ */
514
+ public setActiveSpeakerCsis(remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: number}[]) {
515
+ Object.values(this.media.video.activeSpeakerGroups).forEach((remoteMediaGroup) => {
516
+ const groupRemoteMediaCsis = remoteMediaCsis.filter(({remoteMedia}) =>
517
+ remoteMediaGroup.includes(remoteMedia)
518
+ );
519
+ if (groupRemoteMediaCsis.length > 0) {
520
+ remoteMediaGroup.setActiveSpeakerCsis(groupRemoteMediaCsis, false);
521
+ }
522
+ });
523
+ this.mediaRequestManagers.video.commit();
524
+ }
525
+
493
526
  /**
494
527
  * Creates the audio slots
495
528
  */
@@ -601,25 +634,37 @@ export class RemoteMediaManager extends EventsScope {
601
634
  }
602
635
 
603
636
  /**
604
- * Allocates receive slots to all video panes in the current selected layout
637
+ * Allocates receive slots to all active speaker video panes
638
+ * in the current selected layout.
639
+ *
640
+ * Allocation tries to keep the same order of the slots between the previous
641
+ * layout and the new one. Sorting helps making sure that highest priority slots
642
+ * go in the same order in the new layout.
605
643
  */
606
- private allocateSlotsToVideoPaneGroups() {
607
- this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};
608
-
609
- this.currentLayout?.activeSpeakerVideoPaneGroups?.forEach((group) => {
610
- this.receiveSlotAllocations.activeSpeaker[group.id] = {slots: []};
611
-
612
- for (let paneIndex = 0; paneIndex < group.numPanes; paneIndex += 1) {
613
- // allocate a slot from the "unused" list
614
- const freeSlot = this.slots.video.unused.pop();
615
-
616
- if (freeSlot) {
617
- this.slots.video.activeSpeaker.push(freeSlot);
618
- this.receiveSlotAllocations.activeSpeaker[group.id].slots.push(freeSlot);
644
+ private allocateSlotsToActiveSpeakerPaneGroups() {
645
+ this.currentLayout?.activeSpeakerVideoPaneGroups
646
+ // sorting in descending order based on group priority
647
+ ?.sort((a, b) => (a.priority < b.priority ? 1 : -1))
648
+ ?.forEach((group) => {
649
+ this.receiveSlotAllocations.activeSpeaker[group.id] = {slots: []};
650
+
651
+ for (let paneIndex = 0; paneIndex < group.numPanes; paneIndex += 1) {
652
+ // allocate a slot from the "unused" list, by grabbing in same order (shift) as previous layout
653
+ const freeSlot = this.slots.video.unused.shift();
654
+
655
+ if (freeSlot) {
656
+ this.slots.video.activeSpeaker.push(freeSlot);
657
+ this.receiveSlotAllocations.activeSpeaker[group.id].slots.push(freeSlot);
658
+ }
619
659
  }
620
- }
621
- });
660
+ });
661
+ }
622
662
 
663
+ /**
664
+ * Allocates receive slots to all receiver selected video panes
665
+ * in the current selected layout
666
+ */
667
+ private allocateSlotsToReceiverSelectedVideoPaneGroups() {
623
668
  this.currentLayout?.memberVideoPanes?.forEach((memberPane) => {
624
669
  // check if there is existing slot for this csi
625
670
  const existingSlot = this.slots.video.receiverSelected.find(
@@ -646,19 +691,15 @@ export class RemoteMediaManager extends EventsScope {
646
691
  }
647
692
 
648
693
  /**
649
- * Makes sure we have the right number of receive slots created for the current layout
650
- * and allocates them to the right video panes / pane groups
651
- *
652
- * @returns {Promise}
694
+ * Ensures that we have enough slots for the current layout.
653
695
  */
654
- private async updateVideoReceiveSlots() {
696
+ private async refillRequiredSlotsIfNeeded() {
655
697
  const requiredNumSlots = this.getRequiredNumVideoSlotsForLayout(this.currentLayout);
656
698
  const totalNumSlots =
657
699
  this.slots.video.unused.length +
658
700
  this.slots.video.activeSpeaker.length +
659
701
  this.slots.video.receiverSelected.length;
660
702
 
661
- // ensure we have enough total slots for current layout
662
703
  if (totalNumSlots < requiredNumSlots) {
663
704
  let numSlotsToCreate = requiredNumSlots - totalNumSlots;
664
705
 
@@ -671,20 +712,60 @@ export class RemoteMediaManager extends EventsScope {
671
712
  numSlotsToCreate -= 1;
672
713
  }
673
714
  }
715
+ }
674
716
 
675
- // move all no longer needed receiver-selected slots to "unused"
676
- this.trimReceiverSelectedSlots();
677
-
678
- // move all active speaker slots to "unused"
717
+ /**
718
+ * Move all active speaker slots to "unused"
719
+ */
720
+ private trimActiveSpeakerSlots() {
679
721
  this.slots.video.unused.push(...this.slots.video.activeSpeaker);
680
722
  this.slots.video.activeSpeaker.length = 0;
723
+ }
681
724
 
682
- // allocate the slots to the right panes / pane groups
683
- this.allocateSlotsToVideoPaneGroups();
725
+ /**
726
+ * Logs the state of the receive slots
727
+ */
728
+ private logReceieveSlots() {
729
+ let logMessage = '';
730
+ forEach(this.receiveSlotAllocations.activeSpeaker, (group, groupName) => {
731
+ logMessage += `group: ${groupName}\n${group.slots.map((slot) => slot.logString).join(' ')}`;
732
+ });
733
+
734
+ logMessage += '\nreceiverSelected:\n';
735
+ forEach(this.receiveSlotAllocations.receiverSelected, (slot, key) => {
736
+ logMessage += ` ${key}: ${slot.logString}\n`;
737
+ });
684
738
 
685
739
  LoggerProxy.logger.log(
686
- `RemoteMediaManager#updateVideoReceiveSlots --> receive slots updated: unused=${this.slots.video.unused.length}, activeSpeaker=${this.slots.video.activeSpeaker.length}, receiverSelected=${this.slots.video.receiverSelected.length}`
740
+ `RemoteMediaManager#updateVideoReceiveSlots --> receive slots updated: unused=${this.slots.video.unused.length}, activeSpeaker=${this.slots.video.activeSpeaker.length}, receiverSelected=${this.slots.video.receiverSelected.length}\n${logMessage}`
687
741
  );
742
+ }
743
+
744
+ /**
745
+ * Makes sure we have the right number of receive slots created for the current layout
746
+ * and allocates them to the right video panes / pane groups
747
+ *
748
+ * @returns {Promise}
749
+ */
750
+ private async updateVideoReceiveSlots() {
751
+ // move all active speaker slots to "unused"
752
+ this.trimActiveSpeakerSlots();
753
+
754
+ // move all no longer needed receiver-selected slots to "unused"
755
+ this.trimReceiverSelectedSlots();
756
+
757
+ // ensure we have enough total slots for current layout
758
+ await this.refillRequiredSlotsIfNeeded();
759
+
760
+ // allocate the slots to the right panes / pane groups
761
+ // reset allocations
762
+ this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};
763
+ // allocate active speaker
764
+ this.allocateSlotsToActiveSpeakerPaneGroups();
765
+ // allocate receiver selected
766
+ this.allocateSlotsToReceiverSelectedVideoPaneGroups();
767
+
768
+ this.logReceieveSlots();
688
769
 
689
770
  // If this is the initial layout, there may be some "unused" slots left because of the preallocation
690
771
  // done in this.preallocateVideoReceiveSlots(), so release them now
@@ -1,5 +1,5 @@
1
1
  import EventsScope from '../common/events/events-scope';
2
- import {EVENT_TRIGGERS, STATS} from '../constants';
2
+ import {EVENT_TRIGGERS} from '../constants';
3
3
 
4
4
  /**
5
5
  * Meeting - network quality event
@@ -49,11 +49,7 @@ export default class NetworkQualityMonitor extends EventsScope {
49
49
  });
50
50
  this.networkQualityScore = 1;
51
51
  this.networkQualityStatus = {
52
- [this.frequencyTypes.UPLINK]: {
53
- [STATS.VIDEO_CORRELATE]: {},
54
- [STATS.AUDIO_CORRELATE]: {},
55
- [STATS.SHARE_CORRELATE]: {},
56
- },
52
+ [this.frequencyTypes.UPLINK]: {},
57
53
  };
58
54
  this.mediaType = null;
59
55
  }
@@ -172,6 +168,10 @@ export default class NetworkQualityMonitor extends EventsScope {
172
168
  const determineIfUndefined = (value: number | undefined) =>
173
169
  typeof value === 'undefined' ? null : value;
174
170
 
171
+ if (!this.networkQualityStatus[UPLINK][mediaType]) {
172
+ this.networkQualityStatus[UPLINK][mediaType] = {};
173
+ }
174
+
175
175
  /**
176
176
  * Values for some browsers specifically Safari will be undefined we explicitly set to null
177
177
  * https://bugs.webkit.org/show_bug.cgi?id=206645
@@ -14,6 +14,7 @@ import ReachabilityRequest from './request';
14
14
  const DEFAULT_TIMEOUT = 3000;
15
15
  const VIDEO_MESH_TIMEOUT = 1000;
16
16
 
17
+ export type ICECandidateResult = {clusterId: string; elapsed?: string | null; publicIPs?: string[]};
17
18
  /**
18
19
  * @class Reachability
19
20
  * @export
@@ -63,11 +64,13 @@ export default class Reachability {
63
64
 
64
65
  // Remove stored reachability results to ensure no stale data
65
66
  // @ts-ignore
66
- await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorage);
67
+ await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageResult);
68
+ // @ts-ignore
69
+ await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageJoinCookie);
67
70
 
68
71
  // Fetch clusters and measure latency
69
72
  try {
70
- const clusters = await this.reachabilityRequest.getClusters();
73
+ const {clusters, joinCookie} = await this.reachabilityRequest.getClusters();
71
74
 
72
75
  // Perform Reachability Check
73
76
  const results = await this.performReachabilityCheck(clusters);
@@ -75,9 +78,15 @@ export default class Reachability {
75
78
  // @ts-ignore
76
79
  await this.webex.boundedStorage.put(
77
80
  this.namespace,
78
- REACHABILITY.localStorage,
81
+ REACHABILITY.localStorageResult,
79
82
  JSON.stringify(results)
80
83
  );
84
+ // @ts-ignore
85
+ await this.webex.boundedStorage.put(
86
+ this.namespace,
87
+ REACHABILITY.localStorageJoinCookie,
88
+ JSON.stringify(joinCookie)
89
+ );
81
90
 
82
91
  LoggerProxy.logger.log(
83
92
  'Reachability:index#gatherReachability --> Reachability checks completed'
@@ -103,7 +112,7 @@ export default class Reachability {
103
112
  let reachable = false;
104
113
  // @ts-ignore
105
114
  const reachabilityData = await this.webex.boundedStorage
106
- .get(this.namespace, REACHABILITY.localStorage)
115
+ .get(this.namespace, REACHABILITY.localStorageResult)
107
116
  .catch(() => {});
108
117
 
109
118
  if (reachabilityData) {
@@ -292,6 +301,8 @@ export default class Reachability {
292
301
  `Reachability:index#onIceCandidate --> Successfully pinged ${peerConnection.key}:`,
293
302
  elapsed
294
303
  );
304
+ // order is important
305
+ this.addPublicIP(peerConnection, e.candidate.address);
295
306
  this.setLatencyAndClose(peerConnection, elapsed);
296
307
  }
297
308
  };
@@ -309,8 +320,9 @@ export default class Reachability {
309
320
  private iceGatheringState(peerConnection: RTCPeerConnection, timeout: number) {
310
321
  const ELAPSED = 'elapsed';
311
322
 
312
- return new Promise((resolve) => {
323
+ return new Promise<ICECandidateResult>((resolve) => {
313
324
  const peerConnectionProxy = new window.Proxy(peerConnection, {
325
+ // eslint-disable-next-line require-jsdoc
314
326
  get(target, property) {
315
327
  const targetMember = target[property];
316
328
 
@@ -324,7 +336,7 @@ export default class Reachability {
324
336
  // only intercept elapsed property
325
337
  if (property === ELAPSED) {
326
338
  // @ts-ignore
327
- resolve({clusterId: peerConnection.key, elapsed: value});
339
+ resolve({clusterId: peerConnection.key, publicIPs: target.publicIPs, elapsed: value});
328
340
 
329
341
  return true;
330
342
  }
@@ -345,6 +357,8 @@ export default class Reachability {
345
357
 
346
358
  // Close any open peerConnections
347
359
  if (peerConnectionProxy.connectionState !== CLOSED) {
360
+ // order is important
361
+ this.addPublicIP(peerConnectionProxy, null);
348
362
  this.setLatencyAndClose(peerConnectionProxy, null);
349
363
  }
350
364
  }, timeout);
@@ -369,24 +383,30 @@ export default class Reachability {
369
383
 
370
384
  /**
371
385
  * Calculates time to establish connection
372
- * @param {array} iceResults iceResults
386
+ * @param {Array<ICECandidateResult>} iceResults iceResults
373
387
  * @returns {object} reachabilityMap
374
- * @private
388
+ * @protected
375
389
  * @memberof Reachability
376
390
  */
377
- private parseIceResultsToReachabilityResults(iceResults: Array<any>) {
391
+ protected parseIceResultsToReachabilityResults(iceResults: Array<ICECandidateResult>) {
378
392
  const reachabilityMap = {};
379
393
 
380
- iceResults.forEach(({clusterId, elapsed}) => {
381
- let latencyResult;
394
+ iceResults.forEach(({clusterId, elapsed, publicIPs}) => {
395
+ const latencyResult = {};
382
396
 
383
- if (elapsed === null) {
384
- latencyResult = {reachable: 'false'};
397
+ if (!elapsed) {
398
+ Object.assign(latencyResult, {reachable: 'false'});
385
399
  } else {
386
- latencyResult = {
400
+ Object.assign(latencyResult, {
387
401
  reachable: 'true',
388
402
  latencyInMilliseconds: elapsed.toString(),
389
- };
403
+ });
404
+ }
405
+
406
+ if (publicIPs) {
407
+ Object.assign(latencyResult, {
408
+ clientMediaIPs: publicIPs,
409
+ });
390
410
  }
391
411
 
392
412
  reachabilityMap[clusterId] = {
@@ -432,6 +452,33 @@ export default class Reachability {
432
452
  });
433
453
  }
434
454
 
455
+ /**
456
+ * Adds public IP (client media IPs)
457
+ * @param {RTCPeerConnection} peerConnection
458
+ * @param {string} publicIP
459
+ * @returns {void}
460
+ */
461
+ protected addPublicIP(peerConnection: RTCPeerConnection, publicIP?: string | null) {
462
+ const modifiedPeerConnection: RTCPeerConnection & {publicIPs?: string[]} = peerConnection;
463
+ const {CLOSED} = CONNECTION_STATE;
464
+
465
+ if (modifiedPeerConnection.connectionState === CLOSED) {
466
+ LoggerProxy.logger.log(
467
+ `Reachability:index#addPublicIP --> Attempting to set publicIP of ${publicIP} on closed peerConnection.`
468
+ );
469
+ }
470
+
471
+ if (publicIP) {
472
+ if (modifiedPeerConnection.publicIPs) {
473
+ modifiedPeerConnection.publicIPs.push(publicIP);
474
+ } else {
475
+ modifiedPeerConnection.publicIPs = [publicIP];
476
+ }
477
+ } else {
478
+ modifiedPeerConnection.publicIPs = null;
479
+ }
480
+ }
481
+
435
482
  /**
436
483
  * Records latency and closes the peerConnection
437
484
  * @param {RTCPeerConnection} peerConnection