@webex/plugin-meetings 3.8.0 → 3.8.1-next.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 (360) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +70 -6
  3. package/dist/breakouts/index.js.map +1 -1
  4. package/dist/common/errors/webex-errors.js +12 -2
  5. package/dist/common/errors/webex-errors.js.map +1 -1
  6. package/dist/config.js +5 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/constants.js +23 -123
  9. package/dist/constants.js.map +1 -1
  10. package/dist/controls-options-manager/enums.js +2 -0
  11. package/dist/controls-options-manager/enums.js.map +1 -1
  12. package/dist/controls-options-manager/types.js.map +1 -1
  13. package/dist/controls-options-manager/util.js +52 -0
  14. package/dist/controls-options-manager/util.js.map +1 -1
  15. package/dist/interpretation/index.js +4 -4
  16. package/dist/interpretation/index.js.map +1 -1
  17. package/dist/interpretation/siLanguage.js +1 -1
  18. package/dist/locus-info/controlsUtils.js +31 -11
  19. package/dist/locus-info/controlsUtils.js.map +1 -1
  20. package/dist/locus-info/index.js +83 -12
  21. package/dist/locus-info/index.js.map +1 -1
  22. package/dist/locus-info/selfUtils.js +432 -418
  23. package/dist/locus-info/selfUtils.js.map +1 -1
  24. package/dist/media/index.js +17 -17
  25. package/dist/media/index.js.map +1 -1
  26. package/dist/media/properties.js +94 -6
  27. package/dist/media/properties.js.map +1 -1
  28. package/dist/meeting/brbState.js +9 -2
  29. package/dist/meeting/brbState.js.map +1 -1
  30. package/dist/meeting/in-meeting-actions.js +17 -1
  31. package/dist/meeting/in-meeting-actions.js.map +1 -1
  32. package/dist/meeting/index.js +661 -334
  33. package/dist/meeting/index.js.map +1 -1
  34. package/dist/meeting/locusMediaRequest.js +21 -22
  35. package/dist/meeting/locusMediaRequest.js.map +1 -1
  36. package/dist/meeting/muteState.js +4 -4
  37. package/dist/meeting/muteState.js.map +1 -1
  38. package/dist/meeting/request.js +30 -0
  39. package/dist/meeting/request.js.map +1 -1
  40. package/dist/meeting/request.type.js.map +1 -1
  41. package/dist/meeting/util.js +13 -2
  42. package/dist/meeting/util.js.map +1 -1
  43. package/dist/meeting-info/meeting-info-v2.js +373 -68
  44. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  45. package/dist/meeting-info/utilv2.js +5 -1
  46. package/dist/meeting-info/utilv2.js.map +1 -1
  47. package/dist/meetings/index.js +136 -1
  48. package/dist/meetings/index.js.map +1 -1
  49. package/dist/meetings/util.js +14 -0
  50. package/dist/meetings/util.js.map +1 -1
  51. package/dist/member/index.js +55 -9
  52. package/dist/member/index.js.map +1 -1
  53. package/dist/member/types.js +3 -0
  54. package/dist/member/types.js.map +1 -1
  55. package/dist/member/util.js +335 -353
  56. package/dist/member/util.js.map +1 -1
  57. package/dist/members/collection.js.map +1 -1
  58. package/dist/members/index.js +137 -29
  59. package/dist/members/index.js.map +1 -1
  60. package/dist/members/request.js +38 -0
  61. package/dist/members/request.js.map +1 -1
  62. package/dist/members/util.js +36 -1
  63. package/dist/members/util.js.map +1 -1
  64. package/dist/metrics/constants.js +10 -0
  65. package/dist/metrics/constants.js.map +1 -1
  66. package/dist/multistream/remoteMediaManager.js +40 -8
  67. package/dist/multistream/remoteMediaManager.js.map +1 -1
  68. package/dist/reachability/clusterReachability.js +63 -27
  69. package/dist/reachability/clusterReachability.js.map +1 -1
  70. package/dist/reachability/index.js +112 -47
  71. package/dist/reachability/index.js.map +1 -1
  72. package/dist/reachability/reachability.types.js +14 -0
  73. package/dist/reachability/reachability.types.js.map +1 -1
  74. package/dist/reachability/request.js +19 -3
  75. package/dist/reachability/request.js.map +1 -1
  76. package/dist/reconnection-manager/index.js +2 -2
  77. package/dist/reconnection-manager/index.js.map +1 -1
  78. package/dist/recording-controller/util.js +5 -5
  79. package/dist/recording-controller/util.js.map +1 -1
  80. package/dist/roap/index.js.map +1 -1
  81. package/dist/roap/turnDiscovery.js +45 -27
  82. package/dist/roap/turnDiscovery.js.map +1 -1
  83. package/dist/roap/types.js +17 -0
  84. package/dist/roap/types.js.map +1 -0
  85. package/dist/types/common/errors/webex-errors.d.ts +7 -1
  86. package/dist/types/config.d.ts +3 -0
  87. package/dist/types/constants.d.ts +16 -85
  88. package/dist/types/controls-options-manager/enums.d.ts +3 -1
  89. package/dist/types/controls-options-manager/types.d.ts +7 -1
  90. package/dist/types/locus-info/index.d.ts +3 -3
  91. package/dist/types/locus-info/selfUtils.d.ts +216 -1
  92. package/dist/types/media/properties.d.ts +15 -0
  93. package/dist/types/meeting/in-meeting-actions.d.ts +16 -0
  94. package/dist/types/meeting/index.d.ts +65 -1
  95. package/dist/types/meeting/muteState.d.ts +0 -1
  96. package/dist/types/meeting/request.d.ts +12 -1
  97. package/dist/types/meeting/request.type.d.ts +6 -0
  98. package/dist/types/meeting/util.d.ts +3 -1
  99. package/dist/types/meeting-info/meeting-info-v2.d.ts +82 -1
  100. package/dist/types/meetings/index.d.ts +57 -0
  101. package/dist/types/member/index.d.ts +21 -6
  102. package/dist/types/member/types.d.ts +73 -14
  103. package/dist/types/member/util.d.ts +156 -1
  104. package/dist/types/members/collection.d.ts +6 -5
  105. package/dist/types/members/index.d.ts +32 -43
  106. package/dist/types/members/request.d.ts +26 -0
  107. package/dist/types/members/util.d.ts +27 -0
  108. package/dist/types/metrics/constants.d.ts +10 -0
  109. package/dist/types/multistream/remoteMediaManager.d.ts +10 -1
  110. package/dist/types/reachability/clusterReachability.d.ts +15 -7
  111. package/dist/types/reachability/index.d.ts +10 -1
  112. package/dist/types/reachability/reachability.types.d.ts +5 -0
  113. package/dist/types/roap/index.d.ts +3 -2
  114. package/dist/types/roap/turnDiscovery.d.ts +5 -17
  115. package/dist/types/roap/types.d.ts +16 -0
  116. package/dist/webinar/index.js +2 -2
  117. package/dist/webinar/index.js.map +1 -1
  118. package/package.json +24 -23
  119. package/src/breakouts/index.ts +69 -0
  120. package/src/common/errors/webex-errors.ts +8 -1
  121. package/src/config.ts +3 -0
  122. package/src/constants.ts +24 -90
  123. package/src/controls-options-manager/enums.ts +2 -0
  124. package/src/controls-options-manager/types.ts +11 -1
  125. package/src/controls-options-manager/util.ts +62 -0
  126. package/src/interpretation/index.ts +3 -3
  127. package/src/locus-info/controlsUtils.ts +50 -14
  128. package/src/locus-info/index.ts +88 -13
  129. package/src/locus-info/selfUtils.ts +496 -442
  130. package/src/media/index.ts +23 -21
  131. package/src/media/properties.ts +96 -0
  132. package/src/meeting/brbState.ts +11 -2
  133. package/src/meeting/in-meeting-actions.ts +32 -0
  134. package/src/meeting/index.ts +449 -95
  135. package/src/meeting/locusMediaRequest.ts +27 -22
  136. package/src/meeting/muteState.ts +4 -4
  137. package/src/meeting/request.ts +36 -1
  138. package/src/meeting/request.type.ts +7 -0
  139. package/src/meeting/util.ts +11 -2
  140. package/src/meeting-info/meeting-info-v2.ts +254 -8
  141. package/src/meeting-info/utilv2.ts +5 -0
  142. package/src/meetings/index.ts +148 -1
  143. package/src/meetings/util.ts +18 -0
  144. package/src/member/index.ts +68 -22
  145. package/src/member/types.ts +82 -16
  146. package/src/member/util.ts +357 -350
  147. package/src/members/collection.ts +4 -3
  148. package/src/members/index.ts +137 -18
  149. package/src/members/request.ts +44 -0
  150. package/src/members/util.ts +43 -1
  151. package/src/metrics/constants.ts +10 -0
  152. package/src/multistream/remoteMediaManager.ts +32 -10
  153. package/src/reachability/clusterReachability.ts +73 -26
  154. package/src/reachability/index.ts +70 -1
  155. package/src/reachability/reachability.types.ts +6 -0
  156. package/src/reachability/request.ts +7 -0
  157. package/src/reconnection-manager/index.ts +2 -2
  158. package/src/recording-controller/util.ts +17 -13
  159. package/src/roap/index.ts +3 -7
  160. package/src/roap/turnDiscovery.ts +34 -39
  161. package/src/roap/types.ts +23 -0
  162. package/src/webinar/index.ts +1 -1
  163. package/test/unit/spec/breakouts/index.ts +167 -95
  164. package/test/unit/spec/controls-options-manager/util.js +120 -0
  165. package/test/unit/spec/interpretation/index.ts +39 -1
  166. package/test/unit/spec/locus-info/controlsUtils.js +139 -9
  167. package/test/unit/spec/locus-info/index.js +195 -73
  168. package/test/unit/spec/locus-info/selfUtils.js +98 -24
  169. package/test/unit/spec/media/index.ts +150 -18
  170. package/test/unit/spec/media/properties.ts +130 -0
  171. package/test/unit/spec/meeting/brbState.ts +40 -2
  172. package/test/unit/spec/meeting/in-meeting-actions.ts +19 -4
  173. package/test/unit/spec/meeting/index.js +754 -139
  174. package/test/unit/spec/meeting/locusMediaRequest.ts +95 -87
  175. package/test/unit/spec/meeting/muteState.js +73 -2
  176. package/test/unit/spec/meeting/request.js +32 -1
  177. package/test/unit/spec/meeting/utils.js +119 -18
  178. package/test/unit/spec/meeting-info/meetinginfov2.js +484 -114
  179. package/test/unit/spec/meeting-info/utilv2.js +19 -0
  180. package/test/unit/spec/meetings/index.js +146 -2
  181. package/test/unit/spec/member/index.js +7 -0
  182. package/test/unit/spec/member/util.js +24 -0
  183. package/test/unit/spec/members/index.js +304 -78
  184. package/test/unit/spec/members/request.js +68 -22
  185. package/test/unit/spec/members/utils.js +75 -0
  186. package/test/unit/spec/multistream/remoteMediaManager.ts +397 -118
  187. package/test/unit/spec/reachability/clusterReachability.ts +88 -56
  188. package/test/unit/spec/reachability/index.ts +101 -0
  189. package/test/unit/spec/reachability/request.js +47 -2
  190. package/test/unit/spec/reconnection-manager/index.js +4 -4
  191. package/test/unit/spec/roap/turnDiscovery.ts +110 -28
  192. package/test/unit/spec/webinar/index.ts +5 -0
  193. package/dist/annotation/annotation.types.d.ts +0 -42
  194. package/dist/annotation/constants.d.ts +0 -31
  195. package/dist/annotation/index.d.ts +0 -117
  196. package/dist/breakouts/breakout.d.ts +0 -8
  197. package/dist/breakouts/collection.d.ts +0 -5
  198. package/dist/breakouts/edit-lock-error.d.ts +0 -15
  199. package/dist/breakouts/events.d.ts +0 -8
  200. package/dist/breakouts/index.d.ts +0 -5
  201. package/dist/breakouts/request.d.ts +0 -22
  202. package/dist/breakouts/utils.d.ts +0 -15
  203. package/dist/common/browser-detection.d.ts +0 -9
  204. package/dist/common/collection.d.ts +0 -48
  205. package/dist/common/config.d.ts +0 -2
  206. package/dist/common/errors/captcha-error.d.ts +0 -15
  207. package/dist/common/errors/intent-to-join.d.ts +0 -16
  208. package/dist/common/errors/join-meeting.d.ts +0 -17
  209. package/dist/common/errors/media.d.ts +0 -15
  210. package/dist/common/errors/no-meeting-info.d.ts +0 -14
  211. package/dist/common/errors/parameter.d.ts +0 -15
  212. package/dist/common/errors/password-error.d.ts +0 -15
  213. package/dist/common/errors/permission.d.ts +0 -14
  214. package/dist/common/errors/reclaim-host-role-error.js +0 -149
  215. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  216. package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
  217. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  218. package/dist/common/errors/reconnection-in-progress.js +0 -33
  219. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  220. package/dist/common/errors/reconnection.d.ts +0 -15
  221. package/dist/common/errors/stats.d.ts +0 -15
  222. package/dist/common/errors/webex-errors.d.ts +0 -93
  223. package/dist/common/errors/webex-meetings-error.d.ts +0 -20
  224. package/dist/common/events/events-scope.d.ts +0 -17
  225. package/dist/common/events/events.d.ts +0 -12
  226. package/dist/common/events/trigger-proxy.d.ts +0 -2
  227. package/dist/common/events/util.d.ts +0 -2
  228. package/dist/common/logs/logger-config.d.ts +0 -2
  229. package/dist/common/logs/logger-proxy.d.ts +0 -2
  230. package/dist/common/logs/request.d.ts +0 -36
  231. package/dist/common/queue.d.ts +0 -34
  232. package/dist/config.d.ts +0 -72
  233. package/dist/constants.d.ts +0 -1088
  234. package/dist/controls-options-manager/constants.d.ts +0 -4
  235. package/dist/controls-options-manager/enums.d.ts +0 -15
  236. package/dist/controls-options-manager/index.d.ts +0 -136
  237. package/dist/controls-options-manager/types.d.ts +0 -43
  238. package/dist/controls-options-manager/util.d.ts +0 -1
  239. package/dist/index.d.ts +0 -7
  240. package/dist/interceptors/index.d.ts +0 -2
  241. package/dist/interceptors/locusRetry.d.ts +0 -27
  242. package/dist/interpretation/collection.d.ts +0 -5
  243. package/dist/interpretation/index.d.ts +0 -5
  244. package/dist/interpretation/siLanguage.d.ts +0 -5
  245. package/dist/locus-info/controlsUtils.d.ts +0 -2
  246. package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
  247. package/dist/locus-info/fullState.d.ts +0 -2
  248. package/dist/locus-info/hostUtils.d.ts +0 -2
  249. package/dist/locus-info/index.d.ts +0 -322
  250. package/dist/locus-info/infoUtils.d.ts +0 -2
  251. package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
  252. package/dist/locus-info/parser.d.ts +0 -272
  253. package/dist/locus-info/selfUtils.d.ts +0 -2
  254. package/dist/media/index.d.ts +0 -34
  255. package/dist/media/properties.d.ts +0 -93
  256. package/dist/media/util.d.ts +0 -2
  257. package/dist/mediaQualityMetrics/config.d.ts +0 -241
  258. package/dist/mediaQualityMetrics/config.js +0 -502
  259. package/dist/mediaQualityMetrics/config.js.map +0 -1
  260. package/dist/meeting/effectsState.js +0 -260
  261. package/dist/meeting/effectsState.js.map +0 -1
  262. package/dist/meeting/in-meeting-actions.d.ts +0 -167
  263. package/dist/meeting/index.d.ts +0 -1825
  264. package/dist/meeting/locusMediaRequest.d.ts +0 -74
  265. package/dist/meeting/muteState.d.ts +0 -178
  266. package/dist/meeting/request.d.ts +0 -295
  267. package/dist/meeting/request.type.d.ts +0 -11
  268. package/dist/meeting/state.d.ts +0 -9
  269. package/dist/meeting/util.d.ts +0 -119
  270. package/dist/meeting/voicea-meeting.d.ts +0 -16
  271. package/dist/meeting-info/collection.d.ts +0 -20
  272. package/dist/meeting-info/index.d.ts +0 -69
  273. package/dist/meeting-info/meeting-info-v2.d.ts +0 -123
  274. package/dist/meeting-info/request.d.ts +0 -22
  275. package/dist/meeting-info/util.d.ts +0 -2
  276. package/dist/meeting-info/utilv2.d.ts +0 -2
  277. package/dist/meetings/collection.d.ts +0 -40
  278. package/dist/meetings/index.d.ts +0 -390
  279. package/dist/meetings/meetings.types.d.ts +0 -4
  280. package/dist/meetings/request.d.ts +0 -27
  281. package/dist/meetings/util.d.ts +0 -18
  282. package/dist/member/index.d.ts +0 -160
  283. package/dist/member/member.types.js +0 -17
  284. package/dist/member/member.types.js.map +0 -1
  285. package/dist/member/types.d.ts +0 -32
  286. package/dist/member/util.d.ts +0 -2
  287. package/dist/members/collection.d.ts +0 -29
  288. package/dist/members/index.d.ts +0 -353
  289. package/dist/members/request.d.ts +0 -114
  290. package/dist/members/types.d.ts +0 -25
  291. package/dist/members/util.d.ts +0 -215
  292. package/dist/metrics/config.js +0 -276
  293. package/dist/metrics/config.js.map +0 -1
  294. package/dist/metrics/constants.d.ts +0 -70
  295. package/dist/metrics/index.d.ts +0 -45
  296. package/dist/multistream/mediaRequestManager.d.ts +0 -119
  297. package/dist/multistream/receiveSlot.d.ts +0 -68
  298. package/dist/multistream/receiveSlotManager.d.ts +0 -56
  299. package/dist/multistream/remoteMedia.d.ts +0 -72
  300. package/dist/multistream/remoteMediaGroup.d.ts +0 -49
  301. package/dist/multistream/remoteMediaManager.d.ts +0 -300
  302. package/dist/multistream/sendSlotManager.d.ts +0 -69
  303. package/dist/networkQualityMonitor/index.d.ts +0 -70
  304. package/dist/networkQualityMonitor/index.js +0 -221
  305. package/dist/networkQualityMonitor/index.js.map +0 -1
  306. package/dist/peer-connection-manager/index.js +0 -671
  307. package/dist/peer-connection-manager/index.js.map +0 -1
  308. package/dist/peer-connection-manager/util.js +0 -109
  309. package/dist/peer-connection-manager/util.js.map +0 -1
  310. package/dist/personal-meeting-room/index.d.ts +0 -47
  311. package/dist/personal-meeting-room/request.d.ts +0 -14
  312. package/dist/personal-meeting-room/util.d.ts +0 -2
  313. package/dist/reachability/clusterReachability.d.ts +0 -109
  314. package/dist/reachability/index.d.ts +0 -105
  315. package/dist/reachability/request.d.ts +0 -39
  316. package/dist/reachability/util.d.ts +0 -8
  317. package/dist/reactions/constants.d.ts +0 -3
  318. package/dist/reactions/reactions.d.ts +0 -4
  319. package/dist/reactions/reactions.type.d.ts +0 -52
  320. package/dist/reconnection-manager/index.d.ts +0 -136
  321. package/dist/recording-controller/enums.d.ts +0 -7
  322. package/dist/recording-controller/index.d.ts +0 -207
  323. package/dist/recording-controller/util.d.ts +0 -14
  324. package/dist/roap/collection.js +0 -62
  325. package/dist/roap/collection.js.map +0 -1
  326. package/dist/roap/handler.js +0 -275
  327. package/dist/roap/handler.js.map +0 -1
  328. package/dist/roap/index.d.ts +0 -86
  329. package/dist/roap/request.d.ts +0 -39
  330. package/dist/roap/state.js +0 -126
  331. package/dist/roap/state.js.map +0 -1
  332. package/dist/roap/turnDiscovery.d.ts +0 -155
  333. package/dist/roap/util.js +0 -75
  334. package/dist/roap/util.js.map +0 -1
  335. package/dist/rtcMetrics/constants.d.ts +0 -4
  336. package/dist/rtcMetrics/constants.js +0 -11
  337. package/dist/rtcMetrics/constants.js.map +0 -1
  338. package/dist/rtcMetrics/index.d.ts +0 -61
  339. package/dist/rtcMetrics/index.js +0 -197
  340. package/dist/rtcMetrics/index.js.map +0 -1
  341. package/dist/statsAnalyzer/global.d.ts +0 -36
  342. package/dist/statsAnalyzer/global.js +0 -126
  343. package/dist/statsAnalyzer/global.js.map +0 -1
  344. package/dist/statsAnalyzer/index.d.ts +0 -217
  345. package/dist/statsAnalyzer/index.js +0 -1013
  346. package/dist/statsAnalyzer/index.js.map +0 -1
  347. package/dist/statsAnalyzer/mqaUtil.d.ts +0 -48
  348. package/dist/statsAnalyzer/mqaUtil.js +0 -179
  349. package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
  350. package/dist/transcription/index.d.ts +0 -64
  351. package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
  352. package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
  353. package/dist/types/networkQualityMonitor/index.d.ts +0 -70
  354. package/dist/types/rtcMetrics/constants.d.ts +0 -4
  355. package/dist/types/rtcMetrics/index.d.ts +0 -71
  356. package/dist/types/statsAnalyzer/global.d.ts +0 -36
  357. package/dist/types/statsAnalyzer/index.d.ts +0 -217
  358. package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
  359. package/dist/webinar/collection.d.ts +0 -16
  360. package/dist/webinar/index.d.ts +0 -5
@@ -60,11 +60,8 @@ import {
60
60
  import LoggerProxy from '../common/logs/logger-proxy';
61
61
  import EventsUtil from '../common/events/util';
62
62
  import Trigger from '../common/events/trigger-proxy';
63
- import Roap, {
64
- type TurnDiscoveryResult,
65
- type TurnServerInfo,
66
- type TurnDiscoverySkipReason,
67
- } from '../roap/index';
63
+ import Roap, {type TurnDiscoveryResult, type TurnDiscoverySkipReason} from '../roap/index';
64
+ import {type TurnServerInfo} from '../roap/types';
68
65
  import Media, {type BundlePolicy} from '../media';
69
66
  import MediaProperties from '../media/properties';
70
67
  import MeetingStateMachine from './state';
@@ -103,7 +100,6 @@ import {
103
100
  MEETING_STATE_MACHINE,
104
101
  MEETING_STATE,
105
102
  MEETINGS,
106
- MQA_STATS,
107
103
  NETWORK_STATUS,
108
104
  ONLINE,
109
105
  OFFLINE,
@@ -167,6 +163,7 @@ import Member from '../member';
167
163
  import {BrbState, createBrbState} from './brbState';
168
164
  import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
169
165
  import JoinForbiddenError from '../common/errors/join-forbidden-error';
166
+ import {ReachabilityMetrics} from '../reachability/reachability.types';
170
167
 
171
168
  // default callback so we don't call an undefined function, but in practice it should never be used
172
169
  const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
@@ -241,6 +238,8 @@ export type CallStateForMetrics = {
241
238
  sessionCorrelationId?: string;
242
239
  joinTrigger?: string;
243
240
  loginType?: string;
241
+ userNameInput?: string;
242
+ emailInput?: string;
244
243
  };
245
244
 
246
245
  export const MEDIA_UPDATE_TYPE = {
@@ -263,6 +262,11 @@ type FetchMeetingInfoParams = {
263
262
  sendCAevents?: boolean;
264
263
  };
265
264
 
265
+ type MediaReachabilityMetrics = ReachabilityMetrics & {
266
+ isSubnetReachable: boolean;
267
+ selectedCluster: string | null;
268
+ };
269
+
266
270
  /**
267
271
  * MediaDirection
268
272
  * @typedef {Object} MediaDirection
@@ -648,6 +652,13 @@ export default class Meeting extends StatelessWebexPlugin {
648
652
  allowMediaInLobby: boolean;
649
653
  localShareInstanceId: string;
650
654
  remoteShareInstanceId: string;
655
+ shareCAEventSentStatus: {
656
+ transmitStart: boolean;
657
+ transmitStop: boolean;
658
+ receiveStart: boolean;
659
+ receiveStop: boolean;
660
+ };
661
+
651
662
  turnDiscoverySkippedReason: TurnDiscoverySkipReason;
652
663
  turnServerUsed: boolean;
653
664
  areVoiceaEventsSetup = false;
@@ -716,6 +727,7 @@ export default class Meeting extends StatelessWebexPlugin {
716
727
  private rtcMetrics?: RtcMetrics;
717
728
  private uploadLogsTimer?: ReturnType<typeof setTimeout>;
718
729
  private logUploadIntervalIndex: number;
730
+ private mediaServerIp: string;
719
731
 
720
732
  /**
721
733
  * @param {Object} attrs
@@ -1332,7 +1344,7 @@ export default class Meeting extends StatelessWebexPlugin {
1332
1344
  captions: [],
1333
1345
  isListening: false,
1334
1346
  commandText: '',
1335
- languageOptions: {},
1347
+ languageOptions: {currentSpokenLanguage: 'en'},
1336
1348
  showCaptionBox: false,
1337
1349
  transcribingRequestStatus: 'INACTIVE',
1338
1350
  isCaptioning: false,
@@ -1420,6 +1432,19 @@ export default class Meeting extends StatelessWebexPlugin {
1420
1432
  */
1421
1433
  this.remoteShareInstanceId = null;
1422
1434
 
1435
+ /**
1436
+ * Status used for ensuring we do not oversend metrics
1437
+ * @instance
1438
+ * @private
1439
+ * @memberof Meeting
1440
+ */
1441
+ this.shareCAEventSentStatus = {
1442
+ transmitStart: false,
1443
+ transmitStop: false,
1444
+ receiveStart: false,
1445
+ receiveStop: false,
1446
+ };
1447
+
1423
1448
  /**
1424
1449
  * The class that helps to control recording functions: start, stop, pause, resume, etc
1425
1450
  * @instance
@@ -1579,6 +1604,19 @@ export default class Meeting extends StatelessWebexPlugin {
1579
1604
  * @memberof Meeting
1580
1605
  */
1581
1606
  this.#isoLocalClientMeetingJoinTime = undefined;
1607
+
1608
+ // We clear the error cache of CA events on every new meeting instance
1609
+ // @ts-ignore - Fix type
1610
+ this.webex.internal.newMetrics.callDiagnosticMetrics.clearErrorCache();
1611
+
1612
+ /**
1613
+ * IP Address of the remote media server
1614
+ * @instance
1615
+ * @type {string}
1616
+ * @private
1617
+ * @memberof Meeting
1618
+ */
1619
+ this.mediaServerIp = undefined;
1582
1620
  }
1583
1621
 
1584
1622
  /**
@@ -1627,6 +1665,38 @@ export default class Meeting extends StatelessWebexPlugin {
1627
1665
  this.callStateForMetrics.correlationId = correlationId;
1628
1666
  }
1629
1667
 
1668
+ /**
1669
+ * Getter - Returns callStateForMetrics.userNameInput
1670
+ * @returns {string}
1671
+ */
1672
+ get userNameInput() {
1673
+ return this.callStateForMetrics?.userNameInput;
1674
+ }
1675
+
1676
+ /**
1677
+ * Setter - sets callStateForMetrics.userNameInput
1678
+ * @param {string} userNameInput
1679
+ */
1680
+ set userNameInput(userNameInput: string) {
1681
+ this.callStateForMetrics.userNameInput = userNameInput;
1682
+ }
1683
+
1684
+ /**
1685
+ * Getter - Returns callStateForMetrics.emailInput
1686
+ * @returns {string}
1687
+ */
1688
+ get emailInput() {
1689
+ return this.callStateForMetrics?.emailInput;
1690
+ }
1691
+
1692
+ /**
1693
+ * Setter - sets callStateForMetrics.emailInput
1694
+ * @param {string} emailInput
1695
+ */
1696
+ set emailInput(emailInput: string) {
1697
+ this.callStateForMetrics.emailInput = emailInput;
1698
+ }
1699
+
1630
1700
  /**
1631
1701
  * Getter - Returns callStateForMetrics.sessionCorrelationId
1632
1702
  * @returns {string}
@@ -1652,6 +1722,33 @@ export default class Meeting extends StatelessWebexPlugin {
1652
1722
  return this.#isoLocalClientMeetingJoinTime;
1653
1723
  }
1654
1724
 
1725
+ /**
1726
+ * Setter - sets isoLocalClientMeetingJoinTime
1727
+ * This will be set once on meeting join, and not updated again
1728
+ * this will always produce an ISO string
1729
+ * If the iso string is invalid, it will fallback to the current system time
1730
+ * @param {string | undefined} time
1731
+ */
1732
+ set isoLocalClientMeetingJoinTime(time: string | undefined) {
1733
+ const fallback = new Date().toISOString();
1734
+ if (!time) {
1735
+ this.#isoLocalClientMeetingJoinTime = fallback;
1736
+ } else {
1737
+ const date = new Date(time);
1738
+
1739
+ // Check if the date is valid
1740
+ if (Number.isNaN(date.getTime())) {
1741
+ LoggerProxy.logger.info(
1742
+ // @ts-ignore
1743
+ `Meeting:index#isoLocalClientMeetingJoinTime --> Invalid date provided: ${time}. Falling back to system clock.`
1744
+ );
1745
+ this.#isoLocalClientMeetingJoinTime = fallback;
1746
+ } else {
1747
+ this.#isoLocalClientMeetingJoinTime = date.toISOString();
1748
+ }
1749
+ }
1750
+ }
1751
+
1655
1752
  /**
1656
1753
  * Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
1657
1754
  * @param {any} info
@@ -2543,6 +2640,19 @@ export default class Meeting extends StatelessWebexPlugin {
2543
2640
  this.locusInfo.on(EVENTS.LOCUS_INFO_UPDATE_PARTICIPANTS, (payload) => {
2544
2641
  this.members.locusParticipantsUpdate(payload);
2545
2642
  });
2643
+ this.locusInfo.on(LOCUSINFO.EVENTS.PARTICIPANT_REASON_CHANGED, (payload) => {
2644
+ Trigger.trigger(
2645
+ this,
2646
+ {
2647
+ file: 'meeting/index',
2648
+ function: 'setUpLocusParticipantsListener',
2649
+ },
2650
+ EVENT_TRIGGERS.MEETING_PARTICIPANT_REASON_CHANGED,
2651
+ {
2652
+ payload,
2653
+ }
2654
+ );
2655
+ });
2546
2656
  }
2547
2657
 
2548
2658
  /**
@@ -2643,6 +2753,27 @@ export default class Meeting extends StatelessWebexPlugin {
2643
2753
  }
2644
2754
  );
2645
2755
 
2756
+ this.locusInfo.on(
2757
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
2758
+ ({spokenLanguage}) => {
2759
+ if (spokenLanguage) {
2760
+ this.transcription.languageOptions.currentSpokenLanguage = spokenLanguage;
2761
+ // @ts-ignore
2762
+ this.webex.internal.voicea.onSpokenLanguageUpdate(spokenLanguage);
2763
+
2764
+ Trigger.trigger(
2765
+ this,
2766
+ {
2767
+ file: 'meeting/index',
2768
+ function: 'setupLocusControlsListener',
2769
+ },
2770
+ EVENT_TRIGGERS.MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
2771
+ {spokenLanguage}
2772
+ );
2773
+ }
2774
+ }
2775
+ );
2776
+
2646
2777
  this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_MEETING_MANUAL_CAPTION_UPDATED, ({enable}) => {
2647
2778
  Trigger.trigger(
2648
2779
  this,
@@ -2793,6 +2924,24 @@ export default class Meeting extends StatelessWebexPlugin {
2793
2924
  {state}
2794
2925
  );
2795
2926
  });
2927
+
2928
+ this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED, ({state}) => {
2929
+ Trigger.trigger(
2930
+ this,
2931
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
2932
+ EVENT_TRIGGERS.MEETING_CONTROLS_ANNOTATION_UPDATED,
2933
+ {state}
2934
+ );
2935
+ });
2936
+
2937
+ this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED, ({state}) => {
2938
+ Trigger.trigger(
2939
+ this,
2940
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
2941
+ EVENT_TRIGGERS.MEETING_CONTROLS_REMOTE_DESKTOP_CONTROL_UPDATED,
2942
+ {state}
2943
+ );
2944
+ });
2796
2945
  }
2797
2946
 
2798
2947
  /**
@@ -2965,6 +3114,8 @@ export default class Meeting extends StatelessWebexPlugin {
2965
3114
  case SHARE_STATUS.REMOTE_SHARE_ACTIVE: {
2966
3115
  const sendStartedSharingRemote = () => {
2967
3116
  this.remoteShareInstanceId = contentShare.shareInstanceId;
3117
+ this.shareCAEventSentStatus.receiveStart = false;
3118
+ this.shareCAEventSentStatus.receiveStop = false;
2968
3119
 
2969
3120
  Trigger.trigger(
2970
3121
  this,
@@ -3018,6 +3169,7 @@ export default class Meeting extends StatelessWebexPlugin {
3018
3169
  },
3019
3170
  options: {meetingId: this.id},
3020
3171
  });
3172
+
3021
3173
  break;
3022
3174
 
3023
3175
  case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
@@ -3058,6 +3210,8 @@ export default class Meeting extends StatelessWebexPlugin {
3058
3210
  // if we got here, then some remote participant has stolen
3059
3211
  // the presentation from another remote participant
3060
3212
  this.remoteShareInstanceId = contentShare.shareInstanceId;
3213
+ this.shareCAEventSentStatus.receiveStart = false;
3214
+ this.shareCAEventSentStatus.receiveStop = false;
3061
3215
 
3062
3216
  Trigger.trigger(
3063
3217
  this,
@@ -3686,6 +3840,18 @@ export default class Meeting extends StatelessWebexPlugin {
3686
3840
  return this.members.cancelPhoneInvite(invitee);
3687
3841
  }
3688
3842
 
3843
+ /**
3844
+ * Cancel an SIP call invitation made during a meeting
3845
+ * @param {Object} invitee
3846
+ * @param {String} invitee.memberId
3847
+ * @returns {Promise} see #members.cancelSIPInvite
3848
+ * @public
3849
+ * @memberof Meeting
3850
+ */
3851
+ public cancelSIPInvite(invitee: {memberId: string}) {
3852
+ return this.members.cancelSIPInvite(invitee);
3853
+ }
3854
+
3689
3855
  /**
3690
3856
  * Admit the guest(s) to the call once they are waiting.
3691
3857
  * If the host/cohost is in a breakout session, the locus url
@@ -3741,7 +3907,16 @@ export default class Meeting extends StatelessWebexPlugin {
3741
3907
  return Promise.reject(error);
3742
3908
  }
3743
3909
 
3744
- return this.brbState.enable(enabled, this.sendSlotManager);
3910
+ return this.brbState
3911
+ .enable(enabled, this.sendSlotManager)
3912
+ .then(() => {
3913
+ if (this.audio && enabled) {
3914
+ // locus mutes the participant with brb enabled request,
3915
+ // so we need to explicitly update remote mute for correct logic flow
3916
+ this.audio.handleServerRemoteMuteUpdate(this, enabled);
3917
+ }
3918
+ })
3919
+ .catch((error) => Promise.reject(error));
3745
3920
  }
3746
3921
 
3747
3922
  /**
@@ -3933,7 +4108,10 @@ export default class Meeting extends StatelessWebexPlugin {
3933
4108
  canAdmitParticipant: MeetingUtil.canAdmitParticipant(this.userDisplayHints),
3934
4109
  canLock: MeetingUtil.canUserLock(this.userDisplayHints),
3935
4110
  canUnlock: MeetingUtil.canUserUnlock(this.userDisplayHints),
3936
- canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(this.userDisplayHints),
4111
+ canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
4112
+ this.userDisplayHints,
4113
+ this.selfUserPolicies
4114
+ ),
3937
4115
  canSetDisallowUnmute: ControlsOptionsUtil.canSetDisallowUnmute(this.userDisplayHints),
3938
4116
  canUnsetDisallowUnmute: ControlsOptionsUtil.canUnsetDisallowUnmute(this.userDisplayHints),
3939
4117
  canSetMuteOnEntry: ControlsOptionsUtil.canSetMuteOnEntry(this.userDisplayHints),
@@ -3982,6 +4160,9 @@ export default class Meeting extends StatelessWebexPlugin {
3982
4160
  this.inMeetingActions.canSendReactions,
3983
4161
  this.userDisplayHints
3984
4162
  ),
4163
+ requiresPostMeetingDataConsentPrompt: MeetingUtil.requiresPostMeetingDataConsentPrompt(
4164
+ this.userDisplayHints
4165
+ ),
3985
4166
  canManageBreakout: MeetingUtil.canManageBreakout(this.userDisplayHints),
3986
4167
  canStartBreakout: MeetingUtil.canStartBreakout(this.userDisplayHints),
3987
4168
  canBroadcastMessageToBreakout: MeetingUtil.canBroadcastMessageToBreakout(
@@ -3997,6 +4178,7 @@ export default class Meeting extends StatelessWebexPlugin {
3997
4178
  this.userDisplayHints
3998
4179
  ),
3999
4180
  canUserRenameOthers: MeetingUtil.canUserRenameOthers(this.userDisplayHints),
4181
+ canMoveToLobby: MeetingUtil.canMoveToLobby(this.userDisplayHints),
4000
4182
  canMuteAll: ControlsOptionsUtil.hasHints({
4001
4183
  requiredHints: [DISPLAY_HINTS.MUTE_ALL],
4002
4184
  displayHints: this.userDisplayHints,
@@ -4131,6 +4313,14 @@ export default class Meeting extends StatelessWebexPlugin {
4131
4313
  requiredPolicies: [SELF_POLICY.SUPPORT_FILE_TRANSFER],
4132
4314
  policies: this.selfUserPolicies,
4133
4315
  }),
4316
+ canRealtimeCloseCaption: ControlsOptionsUtil.hasPolicies({
4317
+ requiredPolicies: [SELF_POLICY.SUPPORT_REALTIME_CLOSE_CAPTION],
4318
+ policies: this.selfUserPolicies,
4319
+ }),
4320
+ canRealtimeCloseCaptionManual: ControlsOptionsUtil.hasPolicies({
4321
+ requiredPolicies: [SELF_POLICY.SUPPORT_REALTIME_CLOSE_CAPTION_MANUAL],
4322
+ policies: this.selfUserPolicies,
4323
+ }),
4134
4324
  canChat: ControlsOptionsUtil.hasPolicies({
4135
4325
  requiredPolicies: [SELF_POLICY.SUPPORT_CHAT],
4136
4326
  policies: this.selfUserPolicies,
@@ -4177,6 +4367,22 @@ export default class Meeting extends StatelessWebexPlugin {
4177
4367
  requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
4178
4368
  policies: this.selfUserPolicies,
4179
4369
  }),
4370
+ canEnableAnnotation: ControlsOptionsUtil.hasHints({
4371
+ requiredHints: [DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION],
4372
+ displayHints: this.userDisplayHints,
4373
+ }),
4374
+ canDisableAnnotation: ControlsOptionsUtil.hasHints({
4375
+ requiredHints: [DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION],
4376
+ displayHints: this.userDisplayHints,
4377
+ }),
4378
+ canEnableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
4379
+ requiredHints: [DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION],
4380
+ displayHints: this.userDisplayHints,
4381
+ }),
4382
+ canDisableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
4383
+ requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
4384
+ displayHints: this.userDisplayHints,
4385
+ }),
4180
4386
  }) || changed;
4181
4387
  }
4182
4388
  if (changed) {
@@ -5684,8 +5890,6 @@ export default class Meeting extends StatelessWebexPlugin {
5684
5890
  // @ts-ignore
5685
5891
  this.webex.internal.device.meetingStarted();
5686
5892
 
5687
- this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
5688
-
5689
5893
  LoggerProxy.logger.log('Meeting:index#join --> Success');
5690
5894
 
5691
5895
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
@@ -5794,7 +5998,14 @@ export default class Meeting extends StatelessWebexPlugin {
5794
5998
  return undefined;
5795
5999
  }
5796
6000
  // @ts-ignore - Fix type
5797
- await this.webex.internal.llm.disconnectLLM();
6001
+ await this.webex.internal.llm.disconnectLLM(
6002
+ isJoined
6003
+ ? {
6004
+ code: 3050,
6005
+ reason: 'done (permanent)',
6006
+ }
6007
+ : undefined
6008
+ );
5798
6009
  // @ts-ignore - Fix type
5799
6010
  this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
5800
6011
  }
@@ -6139,10 +6350,18 @@ export default class Meeting extends StatelessWebexPlugin {
6139
6350
  },
6140
6351
  options: {meetingId: this.id, rawError: error},
6141
6352
  });
6142
- } else if (
6143
- error instanceof Errors.SdpOfferHandlingError ||
6144
- error instanceof Errors.SdpAnswerHandlingError
6145
- ) {
6353
+ } else if (error instanceof Errors.SdpOfferHandlingError) {
6354
+ sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
6355
+
6356
+ // @ts-ignore
6357
+ this.webex.internal.newMetrics.submitClientEvent({
6358
+ name: 'client.media-engine.remote-sdp-received',
6359
+ payload: {
6360
+ canProceed: false,
6361
+ },
6362
+ options: {meetingId: this.id, rawError: error},
6363
+ });
6364
+ } else if (error instanceof Errors.SdpAnswerHandlingError) {
6146
6365
  sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
6147
6366
 
6148
6367
  // @ts-ignore
@@ -6153,6 +6372,13 @@ export default class Meeting extends StatelessWebexPlugin {
6153
6372
  },
6154
6373
  options: {meetingId: this.id, rawError: error},
6155
6374
  });
6375
+
6376
+ if (this.deferSDPAnswer) {
6377
+ clearTimeout(this.sdpResponseTimer);
6378
+ this.sdpResponseTimer = undefined;
6379
+
6380
+ this.deferSDPAnswer.reject();
6381
+ }
6156
6382
  } else if (error instanceof Errors.SdpError) {
6157
6383
  // this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
6158
6384
  sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.correlationId);
@@ -6180,6 +6406,11 @@ export default class Meeting extends StatelessWebexPlugin {
6180
6406
  ? MeetingsUtil.getMediaServer(roapMessage.sdp)
6181
6407
  : undefined;
6182
6408
 
6409
+ const mediaServerIp =
6410
+ roapMessage.messageType === 'ANSWER'
6411
+ ? MeetingsUtil.getMediaServerIp(roapMessage.sdp)
6412
+ : undefined;
6413
+
6183
6414
  if (this.isMultistream && mediaServer && mediaServer !== 'homer') {
6184
6415
  throw new MultistreamNotSupportedError(
6185
6416
  `Client asked for multistream backend (Homer), but got ${mediaServer} instead`
@@ -6190,6 +6421,10 @@ export default class Meeting extends StatelessWebexPlugin {
6190
6421
  if (mediaServer) {
6191
6422
  this.mediaProperties.webrtcMediaConnection.mediaServer = mediaServer;
6192
6423
  }
6424
+
6425
+ if (this.isMultistream && mediaServerIp) {
6426
+ this.mediaServerIp = mediaServerIp;
6427
+ }
6193
6428
  };
6194
6429
 
6195
6430
  /**
@@ -6647,20 +6882,20 @@ export default class Meeting extends StatelessWebexPlugin {
6647
6882
  * @memberof Meetings
6648
6883
  */
6649
6884
  setupStatsAnalyzerEventHandlers = () => {
6650
- this.statsAnalyzer.on(StatsAnalyzerEventNames.MEDIA_QUALITY, (options) => {
6651
- // TODO: might have to send the same event to the developer
6652
- // Add ip address info if geo hint is present
6653
- // @ts-ignore fix type
6654
- options.data.intervalMetadata.peerReflexiveIP =
6655
- // @ts-ignore
6656
- this.webex.meetings.geoHintInfo?.clientAddress ||
6657
- options.data.intervalMetadata.peerReflexiveIP ||
6658
- MQA_STATS.DEFAULT_IP;
6885
+ this.statsAnalyzer.on(StatsAnalyzerEventNames.MEDIA_QUALITY, (event) => {
6886
+ // Add IP address from geoHintInfo if missing.
6887
+ if (event.data.intervalMetadata.maskedPeerReflexiveIP === '0.0.0.0') {
6888
+ // @ts-ignore fix type
6889
+ const clientAddressFromGeoHint = this.webex.meetings.geoHintInfo?.clientAddress;
6890
+ if (clientAddressFromGeoHint) {
6891
+ event.data.intervalMetadata.maskedPeerReflexiveIP =
6892
+ CallDiagnosticUtils.anonymizeIPAddress(clientAddressFromGeoHint);
6893
+ }
6894
+ }
6659
6895
 
6896
+ // Count members that are in the meeting.
6660
6897
  const {members} = this.getMembers().membersCollection;
6661
-
6662
- // Count members that are in the meeting
6663
- options.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
6898
+ event.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
6664
6899
  (member: Member) => member.isInMeeting
6665
6900
  ).length;
6666
6901
 
@@ -6669,10 +6904,10 @@ export default class Meeting extends StatelessWebexPlugin {
6669
6904
  name: 'client.mediaquality.event',
6670
6905
  options: {
6671
6906
  meetingId: this.id,
6672
- networkType: options.data.networkType,
6907
+ networkType: this.statsAnalyzer.getNetworkType(),
6673
6908
  },
6674
6909
  payload: {
6675
- intervals: [options.data],
6910
+ intervals: [event.data],
6676
6911
  },
6677
6912
  });
6678
6913
  });
@@ -6687,30 +6922,42 @@ export default class Meeting extends StatelessWebexPlugin {
6687
6922
  EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
6688
6923
  data
6689
6924
  );
6690
- // @ts-ignore
6691
- this.webex.internal.newMetrics.submitClientEvent({
6692
- name: 'client.media.tx.start',
6693
- payload: {
6694
- mediaType: data.mediaType,
6695
- shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6696
- },
6697
- options: {
6698
- meetingId: this.id,
6699
- },
6700
- });
6925
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStart) {
6926
+ // @ts-ignore
6927
+ this.webex.internal.newMetrics.submitClientEvent({
6928
+ name: 'client.media.tx.start',
6929
+ payload: {
6930
+ mediaType: data.mediaType,
6931
+ shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6932
+ },
6933
+ options: {
6934
+ meetingId: this.id,
6935
+ },
6936
+ });
6937
+
6938
+ if (data.mediaType === 'share') {
6939
+ this.shareCAEventSentStatus.transmitStart = true;
6940
+ }
6941
+ }
6701
6942
  });
6702
6943
  this.statsAnalyzer.on(StatsAnalyzerEventNames.LOCAL_MEDIA_STOPPED, (data) => {
6703
- // @ts-ignore
6704
- this.webex.internal.newMetrics.submitClientEvent({
6705
- name: 'client.media.tx.stop',
6706
- payload: {
6707
- mediaType: data.mediaType,
6708
- shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6709
- },
6710
- options: {
6711
- meetingId: this.id,
6712
- },
6713
- });
6944
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStop) {
6945
+ // @ts-ignore
6946
+ this.webex.internal.newMetrics.submitClientEvent({
6947
+ name: 'client.media.tx.stop',
6948
+ payload: {
6949
+ mediaType: data.mediaType,
6950
+ shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6951
+ },
6952
+ options: {
6953
+ meetingId: this.id,
6954
+ },
6955
+ });
6956
+
6957
+ if (data.mediaType === 'share') {
6958
+ this.shareCAEventSentStatus.transmitStop = true;
6959
+ }
6960
+ }
6714
6961
  });
6715
6962
  this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STARTED, (data) => {
6716
6963
  Trigger.trigger(
@@ -6722,57 +6969,65 @@ export default class Meeting extends StatelessWebexPlugin {
6722
6969
  EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
6723
6970
  data
6724
6971
  );
6725
- // @ts-ignore
6726
- this.webex.internal.newMetrics.submitClientEvent({
6727
- name: 'client.media.rx.start',
6728
- payload: {
6729
- mediaType: data.mediaType,
6730
- shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6731
- },
6732
- options: {
6733
- meetingId: this.id,
6734
- },
6735
- });
6736
-
6737
- if (data.mediaType === 'share') {
6972
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStart) {
6738
6973
  // @ts-ignore
6739
6974
  this.webex.internal.newMetrics.submitClientEvent({
6740
- name: 'client.media.render.start',
6975
+ name: 'client.media.rx.start',
6741
6976
  payload: {
6742
- mediaType: 'share',
6743
- shareInstanceId: this.remoteShareInstanceId,
6977
+ mediaType: data.mediaType,
6978
+ shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6744
6979
  },
6745
6980
  options: {
6746
6981
  meetingId: this.id,
6747
6982
  },
6748
6983
  });
6984
+
6985
+ if (data.mediaType === 'share') {
6986
+ // @ts-ignore
6987
+ this.webex.internal.newMetrics.submitClientEvent({
6988
+ name: 'client.media.render.start',
6989
+ payload: {
6990
+ mediaType: 'share',
6991
+ shareInstanceId: this.remoteShareInstanceId,
6992
+ },
6993
+ options: {
6994
+ meetingId: this.id,
6995
+ },
6996
+ });
6997
+
6998
+ this.shareCAEventSentStatus.receiveStart = true;
6999
+ }
6749
7000
  }
6750
7001
  });
6751
7002
  this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STOPPED, (data) => {
6752
- // @ts-ignore
6753
- this.webex.internal.newMetrics.submitClientEvent({
6754
- name: 'client.media.rx.stop',
6755
- payload: {
6756
- mediaType: data.mediaType,
6757
- shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6758
- },
6759
- options: {
6760
- meetingId: this.id,
6761
- },
6762
- });
6763
-
6764
- if (data.mediaType === 'share') {
7003
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStop) {
6765
7004
  // @ts-ignore
6766
7005
  this.webex.internal.newMetrics.submitClientEvent({
6767
- name: 'client.media.render.stop',
7006
+ name: 'client.media.rx.stop',
6768
7007
  payload: {
6769
- mediaType: 'share',
6770
- shareInstanceId: this.remoteShareInstanceId,
7008
+ mediaType: data.mediaType,
7009
+ shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6771
7010
  },
6772
7011
  options: {
6773
7012
  meetingId: this.id,
6774
7013
  },
6775
7014
  });
7015
+
7016
+ if (data.mediaType === 'share') {
7017
+ // @ts-ignore
7018
+ this.webex.internal.newMetrics.submitClientEvent({
7019
+ name: 'client.media.render.stop',
7020
+ payload: {
7021
+ mediaType: 'share',
7022
+ shareInstanceId: this.remoteShareInstanceId,
7023
+ },
7024
+ options: {
7025
+ meetingId: this.id,
7026
+ },
7027
+ });
7028
+
7029
+ this.shareCAEventSentStatus.receiveStop = true;
7030
+ }
6776
7031
  }
6777
7032
  });
6778
7033
  };
@@ -6789,7 +7044,10 @@ export default class Meeting extends StatelessWebexPlugin {
6789
7044
  * @param {AddMediaOptions} [options] Options for enabling/disabling audio/video
6790
7045
  * @returns {RoapMediaConnection | MultistreamRoapMediaConnection}
6791
7046
  */
6792
- private async createMediaConnection(turnServerInfo, bundlePolicy?: BundlePolicy) {
7047
+ private async createMediaConnection(
7048
+ turnServerInfo?: TurnServerInfo,
7049
+ bundlePolicy?: BundlePolicy
7050
+ ) {
6793
7051
  this.rtcMetrics = this.isMultistream
6794
7052
  ? // @ts-ignore
6795
7053
  new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
@@ -6814,6 +7072,13 @@ export default class Meeting extends StatelessWebexPlugin {
6814
7072
  bundlePolicy,
6815
7073
  // @ts-ignore - config coming from registerPlugin
6816
7074
  iceCandidatesTimeout: this.config.iceCandidatesGatheringTimeout,
7075
+ // @ts-ignore - config coming from registerPlugin
7076
+ disableAudioMainDtx: this.config.experimental.disableAudioMainDtx,
7077
+ // @ts-ignore - config coming from registerPlugin
7078
+ enableAudioTwcc: this.config.enableAudioTwccForMultistream,
7079
+ stopIceGatheringAfterFirstRelayCandidate:
7080
+ // @ts-ignore - config coming from registerPlugin
7081
+ this.config.stopIceGatheringAfterFirstRelayCandidate,
6817
7082
  }
6818
7083
  );
6819
7084
 
@@ -6964,12 +7229,18 @@ export default class Meeting extends StatelessWebexPlugin {
6964
7229
  },
6965
7230
  options: {
6966
7231
  meetingId: this.id,
7232
+ rawError: error,
6967
7233
  },
6968
7234
  });
6969
7235
  }
6970
- throw new Error(
7236
+
7237
+ const timedOutError = new Error(
6971
7238
  `Timed out waiting for media connection to be connected, correlationId=${this.correlationId}`
6972
7239
  );
7240
+
7241
+ timedOutError.cause = error;
7242
+
7243
+ throw timedOutError;
6973
7244
  }
6974
7245
  }
6975
7246
 
@@ -6990,6 +7261,12 @@ export default class Meeting extends StatelessWebexPlugin {
6990
7261
  networkQualityMonitor: this.networkQualityMonitor,
6991
7262
  isMultistream: this.isMultistream,
6992
7263
  });
7264
+ this.shareCAEventSentStatus = {
7265
+ transmitStart: false,
7266
+ transmitStop: false,
7267
+ receiveStart: false,
7268
+ receiveStop: false,
7269
+ };
6993
7270
  this.setupStatsAnalyzerEventHandlers();
6994
7271
  this.networkQualityMonitor.on(
6995
7272
  NetworkQualityEventNames.NETWORK_QUALITY,
@@ -7024,6 +7301,9 @@ export default class Meeting extends StatelessWebexPlugin {
7024
7301
  ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT / 1000
7025
7302
  } seconds`
7026
7303
  );
7304
+
7305
+ const error = new Error('Timed out waiting for REMOTE SDP ANSWER');
7306
+
7027
7307
  // @ts-ignore
7028
7308
  this.webex.internal.newMetrics.submitClientEvent({
7029
7309
  name: 'client.media-engine.remote-sdp-received',
@@ -7036,10 +7316,10 @@ export default class Meeting extends StatelessWebexPlugin {
7036
7316
  }),
7037
7317
  ],
7038
7318
  },
7039
- options: {meetingId: this.id, rawError: new Error('Timeout waiting for SDP answer')},
7319
+ options: {meetingId: this.id, rawError: error},
7040
7320
  });
7041
7321
 
7042
- deferSDPAnswer.reject(new Error('Timed out waiting for REMOTE SDP ANSWER'));
7322
+ deferSDPAnswer.reject(error);
7043
7323
  }, ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT);
7044
7324
 
7045
7325
  LoggerProxy.logger.info(`${LOG_HEADER} waiting for REMOTE SDP ANSWER...`);
@@ -7144,7 +7424,7 @@ export default class Meeting extends StatelessWebexPlugin {
7144
7424
  error
7145
7425
  );
7146
7426
 
7147
- throw new AddMediaFailed();
7427
+ throw new AddMediaFailed(error);
7148
7428
  }
7149
7429
  }
7150
7430
 
@@ -7557,28 +7837,33 @@ export default class Meeting extends StatelessWebexPlugin {
7557
7837
  await this.enqueueScreenShareFloorRequest();
7558
7838
  }
7559
7839
 
7560
- const {connectionType, selectedCandidatePairChanges, numTransports} =
7840
+ const {connectionType, ipVersion, selectedCandidatePairChanges, numTransports} =
7561
7841
  await this.mediaProperties.getCurrentConnectionInfo();
7562
- // @ts-ignore
7563
- const reachabilityStats = await this.webex.meetings.reachability.getReachabilityMetrics();
7842
+
7564
7843
  const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
7565
7844
 
7845
+ const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
7846
+
7566
7847
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
7567
7848
  correlation_id: this.correlationId,
7568
7849
  locus_id: this.locusUrl.split('/').pop(),
7569
7850
  connectionType,
7851
+ ipVersion,
7570
7852
  selectedCandidatePairChanges,
7571
7853
  numTransports,
7572
7854
  isMultistream: this.isMultistream,
7573
7855
  retriedWithTurnServer: this.addMediaData.retriedWithTurnServer,
7574
7856
  isJoinWithMediaRetry: this.joinWithMediaRetryInfo.isRetry,
7575
- ...reachabilityStats,
7857
+ ...reachabilityMetrics,
7576
7858
  ...iceCandidateErrors,
7577
7859
  iceCandidatesCount: this.iceCandidatesCount,
7578
7860
  });
7579
7861
  // @ts-ignore
7580
7862
  this.webex.internal.newMetrics.submitClientEvent({
7581
7863
  name: 'client.media-engine.ready',
7864
+ payload: {
7865
+ ipVersion,
7866
+ },
7582
7867
  options: {
7583
7868
  meetingId: this.id,
7584
7869
  },
@@ -7594,7 +7879,7 @@ export default class Meeting extends StatelessWebexPlugin {
7594
7879
  LoggerProxy.logger.error(`${LOG_HEADER} failed to establish media connection: `, error);
7595
7880
 
7596
7881
  // @ts-ignore
7597
- const reachabilityMetrics = await this.webex.meetings.reachability.getReachabilityMetrics();
7882
+ const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
7598
7883
 
7599
7884
  const {selectedCandidatePairChanges, numTransports} =
7600
7885
  await this.mediaProperties.getCurrentConnectionInfo();
@@ -8674,6 +8959,9 @@ export default class Meeting extends StatelessWebexPlugin {
8674
8959
  LoggerProxy.logger.log(
8675
8960
  `Meeting:index#handleShareVideoStreamMuteStateChange --> Share video stream mute state changed to muted ${muted}`
8676
8961
  );
8962
+
8963
+ const shareVideoStreamSettings = this.mediaProperties?.shareVideoStream?.getSettings();
8964
+
8677
8965
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
8678
8966
  correlationId: this.correlationId,
8679
8967
  muted,
@@ -8682,8 +8970,9 @@ export default class Meeting extends StatelessWebexPlugin {
8682
8970
  // SDK to TypeScript 5, which may affect other packages, use bracket notation for now, since
8683
8971
  // all we're doing here is adding metrics.
8684
8972
  // eslint-disable-next-line dot-notation
8685
- displaySurface: this.mediaProperties?.shareVideoStream?.getSettings()['displaySurface'],
8973
+ displaySurface: shareVideoStreamSettings?.['displaySurface'],
8686
8974
  isMultistream: this.isMultistream,
8975
+ frameRate: shareVideoStreamSettings?.frameRate,
8687
8976
  });
8688
8977
  };
8689
8978
 
@@ -9010,6 +9299,23 @@ export default class Meeting extends StatelessWebexPlugin {
9010
9299
  });
9011
9300
  }
9012
9301
 
9302
+ /**
9303
+ * Method to set post meeting data consent.
9304
+ *
9305
+ * @param {boolean} accept - whether consent accepted or declined
9306
+ * @returns {Promise}
9307
+ * @public
9308
+ * @memberof Meeting
9309
+ */
9310
+ public setPostMeetingDataConsent(accept: boolean) {
9311
+ return this.meetingRequest.setPostMeetingDataConsent({
9312
+ postMeetingDataConsent: accept,
9313
+ locusUrl: this.locusUrl,
9314
+ deviceUrl: this.deviceUrl,
9315
+ selfId: this.members.selfId,
9316
+ });
9317
+ }
9318
+
9013
9319
  /**
9014
9320
  * Throws if we don't have a media connection created
9015
9321
  *
@@ -9250,6 +9556,8 @@ export default class Meeting extends StatelessWebexPlugin {
9250
9556
 
9251
9557
  if (floorRequestNeeded) {
9252
9558
  this.localShareInstanceId = uuid.v4();
9559
+ this.shareCAEventSentStatus.transmitStart = false;
9560
+ this.shareCAEventSentStatus.transmitStop = false;
9253
9561
 
9254
9562
  // @ts-ignore
9255
9563
  this.webex.internal.newMetrics.submitClientEvent({
@@ -9377,4 +9685,50 @@ export default class Meeting extends StatelessWebexPlugin {
9377
9685
 
9378
9686
  return Promise.resolve();
9379
9687
  }
9688
+
9689
+ /**
9690
+ * Gets the media reachability metrics
9691
+ *
9692
+ * @returns {Promise<MediaReachabilityMetrics>}
9693
+ */
9694
+ private async getMediaReachabilityMetricFields(): Promise<MediaReachabilityMetrics> {
9695
+ const reachabilityMetrics: ReachabilityMetrics =
9696
+ // @ts-ignore
9697
+ await this.webex.meetings.reachability.getReachabilityMetrics();
9698
+
9699
+ const successKeys: Array<keyof ReachabilityMetrics> = [
9700
+ 'reachability_public_udp_success',
9701
+ 'reachability_public_tcp_success',
9702
+ 'reachability_public_xtls_success',
9703
+ 'reachability_vmn_udp_success',
9704
+ 'reachability_vmn_tcp_success',
9705
+ 'reachability_vmn_xtls_success',
9706
+ ];
9707
+
9708
+ const totalSuccessCases = successKeys.reduce((total, key) => {
9709
+ const value = reachabilityMetrics[key];
9710
+ if (typeof value === 'number') {
9711
+ return total + value;
9712
+ }
9713
+
9714
+ return total;
9715
+ }, 0);
9716
+
9717
+ let isSubnetReachable = null;
9718
+ if (totalSuccessCases > 0) {
9719
+ // @ts-ignore
9720
+ isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
9721
+ }
9722
+
9723
+ let selectedCluster = null;
9724
+ if (this.mediaConnections && this.mediaConnections.length > 0) {
9725
+ selectedCluster = this.mediaConnections[0].mediaAgentCluster;
9726
+ }
9727
+
9728
+ return {
9729
+ ...reachabilityMetrics,
9730
+ isSubnetReachable,
9731
+ selectedCluster,
9732
+ };
9733
+ }
9380
9734
  }