@webex/plugin-meetings 3.0.0-beta.39 → 3.0.0-beta.391

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 (393) hide show
  1. package/README.md +58 -8
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +94 -15
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/events.js +45 -0
  11. package/dist/breakouts/events.js.map +1 -0
  12. package/dist/breakouts/index.js +671 -81
  13. package/dist/breakouts/index.js.map +1 -1
  14. package/dist/breakouts/utils.js +45 -1
  15. package/dist/breakouts/utils.js.map +1 -1
  16. package/dist/common/errors/no-meeting-info.js +51 -0
  17. package/dist/common/errors/no-meeting-info.js.map +1 -0
  18. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  19. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +48 -7
  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/logs/request.js +5 -1
  25. package/dist/common/logs/request.js.map +1 -1
  26. package/dist/common/queue.js +24 -9
  27. package/dist/common/queue.js.map +1 -1
  28. package/dist/config.js +5 -10
  29. package/dist/config.js.map +1 -1
  30. package/dist/constants.js +242 -33
  31. package/dist/constants.js.map +1 -1
  32. package/dist/controls-options-manager/enums.js +14 -2
  33. package/dist/controls-options-manager/enums.js.map +1 -1
  34. package/dist/controls-options-manager/index.js +109 -15
  35. package/dist/controls-options-manager/index.js.map +1 -1
  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 +309 -18
  39. package/dist/controls-options-manager/util.js.map +1 -1
  40. package/dist/index.js +110 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/interceptors/index.js +15 -0
  43. package/dist/interceptors/index.js.map +1 -0
  44. package/dist/interceptors/locusRetry.js +93 -0
  45. package/dist/interceptors/locusRetry.js.map +1 -0
  46. package/dist/interpretation/collection.js +23 -0
  47. package/dist/interpretation/collection.js.map +1 -0
  48. package/dist/interpretation/index.js +380 -0
  49. package/dist/interpretation/index.js.map +1 -0
  50. package/dist/interpretation/siLanguage.js +25 -0
  51. package/dist/interpretation/siLanguage.js.map +1 -0
  52. package/dist/locus-info/controlsUtils.js +91 -2
  53. package/dist/locus-info/controlsUtils.js.map +1 -1
  54. package/dist/locus-info/index.js +386 -62
  55. package/dist/locus-info/index.js.map +1 -1
  56. package/dist/locus-info/infoUtils.js +7 -1
  57. package/dist/locus-info/infoUtils.js.map +1 -1
  58. package/dist/locus-info/mediaSharesUtils.js +71 -1
  59. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  60. package/dist/locus-info/parser.js +249 -72
  61. package/dist/locus-info/parser.js.map +1 -1
  62. package/dist/locus-info/selfUtils.js +89 -14
  63. package/dist/locus-info/selfUtils.js.map +1 -1
  64. package/dist/media/index.js +65 -102
  65. package/dist/media/index.js.map +1 -1
  66. package/dist/media/properties.js +73 -124
  67. package/dist/media/properties.js.map +1 -1
  68. package/dist/mediaQualityMetrics/config.js +135 -330
  69. package/dist/mediaQualityMetrics/config.js.map +1 -1
  70. package/dist/meeting/in-meeting-actions.js +86 -2
  71. package/dist/meeting/in-meeting-actions.js.map +1 -1
  72. package/dist/meeting/index.js +4075 -2827
  73. package/dist/meeting/index.js.map +1 -1
  74. package/dist/meeting/locusMediaRequest.js +292 -0
  75. package/dist/meeting/locusMediaRequest.js.map +1 -0
  76. package/dist/meeting/muteState.js +224 -136
  77. package/dist/meeting/muteState.js.map +1 -1
  78. package/dist/meeting/request.js +177 -152
  79. package/dist/meeting/request.js.map +1 -1
  80. package/dist/meeting/util.js +672 -417
  81. package/dist/meeting/util.js.map +1 -1
  82. package/dist/meeting-info/index.js +73 -7
  83. package/dist/meeting-info/index.js.map +1 -1
  84. package/dist/meeting-info/meeting-info-v2.js +192 -51
  85. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  86. package/dist/meeting-info/util.js +1 -1
  87. package/dist/meeting-info/util.js.map +1 -1
  88. package/dist/meeting-info/utilv2.js +36 -36
  89. package/dist/meeting-info/utilv2.js.map +1 -1
  90. package/dist/meetings/collection.js +39 -0
  91. package/dist/meetings/collection.js.map +1 -1
  92. package/dist/meetings/index.js +484 -119
  93. package/dist/meetings/index.js.map +1 -1
  94. package/dist/meetings/meetings.types.js +7 -0
  95. package/dist/meetings/meetings.types.js.map +1 -0
  96. package/dist/meetings/request.js +2 -0
  97. package/dist/meetings/request.js.map +1 -1
  98. package/dist/meetings/util.js +73 -7
  99. package/dist/meetings/util.js.map +1 -1
  100. package/dist/member/index.js +58 -0
  101. package/dist/member/index.js.map +1 -1
  102. package/dist/member/types.js +25 -0
  103. package/dist/member/types.js.map +1 -0
  104. package/dist/member/util.js +132 -25
  105. package/dist/member/util.js.map +1 -1
  106. package/dist/members/collection.js +10 -0
  107. package/dist/members/collection.js.map +1 -1
  108. package/dist/members/index.js +102 -6
  109. package/dist/members/index.js.map +1 -1
  110. package/dist/members/request.js +106 -38
  111. package/dist/members/request.js.map +1 -1
  112. package/dist/members/types.js +15 -0
  113. package/dist/members/types.js.map +1 -0
  114. package/dist/members/util.js +326 -232
  115. package/dist/members/util.js.map +1 -1
  116. package/dist/metrics/constants.js +18 -1
  117. package/dist/metrics/constants.js.map +1 -1
  118. package/dist/metrics/index.js +1 -446
  119. package/dist/metrics/index.js.map +1 -1
  120. package/dist/multistream/mediaRequestManager.js +223 -32
  121. package/dist/multistream/mediaRequestManager.js.map +1 -1
  122. package/dist/multistream/receiveSlot.js +10 -0
  123. package/dist/multistream/receiveSlot.js.map +1 -1
  124. package/dist/multistream/receiveSlotManager.js +39 -36
  125. package/dist/multistream/receiveSlotManager.js.map +1 -1
  126. package/dist/multistream/remoteMedia.js +3 -1
  127. package/dist/multistream/remoteMedia.js.map +1 -1
  128. package/dist/multistream/remoteMediaGroup.js +76 -5
  129. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  130. package/dist/multistream/remoteMediaManager.js +366 -104
  131. package/dist/multistream/remoteMediaManager.js.map +1 -1
  132. package/dist/multistream/sendSlotManager.js +255 -0
  133. package/dist/multistream/sendSlotManager.js.map +1 -0
  134. package/dist/reachability/clusterReachability.js +356 -0
  135. package/dist/reachability/clusterReachability.js.map +1 -0
  136. package/dist/reachability/index.js +263 -390
  137. package/dist/reachability/index.js.map +1 -1
  138. package/dist/reachability/request.js +6 -4
  139. package/dist/reachability/request.js.map +1 -1
  140. package/dist/reachability/util.js +29 -0
  141. package/dist/reachability/util.js.map +1 -0
  142. package/dist/reconnection-manager/index.js +266 -202
  143. package/dist/reconnection-manager/index.js.map +1 -1
  144. package/dist/recording-controller/index.js +21 -2
  145. package/dist/recording-controller/index.js.map +1 -1
  146. package/dist/recording-controller/util.js +9 -8
  147. package/dist/recording-controller/util.js.map +1 -1
  148. package/dist/roap/index.js +51 -28
  149. package/dist/roap/index.js.map +1 -1
  150. package/dist/roap/request.js +48 -64
  151. package/dist/roap/request.js.map +1 -1
  152. package/dist/roap/turnDiscovery.js +220 -70
  153. package/dist/roap/turnDiscovery.js.map +1 -1
  154. package/dist/rtcMetrics/constants.js +12 -0
  155. package/dist/rtcMetrics/constants.js.map +1 -0
  156. package/dist/rtcMetrics/index.js +179 -0
  157. package/dist/rtcMetrics/index.js.map +1 -0
  158. package/dist/statsAnalyzer/index.js +357 -295
  159. package/dist/statsAnalyzer/index.js.map +1 -1
  160. package/dist/statsAnalyzer/mqaUtil.js +296 -156
  161. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  162. package/dist/types/annotation/annotation.types.d.ts +42 -0
  163. package/dist/types/annotation/constants.d.ts +31 -0
  164. package/dist/types/annotation/index.d.ts +117 -0
  165. package/dist/types/breakouts/events.d.ts +8 -0
  166. package/dist/types/breakouts/utils.d.ts +14 -0
  167. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  168. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  169. package/dist/types/common/errors/webex-errors.d.ts +25 -1
  170. package/dist/types/common/logs/request.d.ts +2 -0
  171. package/dist/types/common/queue.d.ts +9 -7
  172. package/dist/types/config.d.ts +2 -7
  173. package/dist/types/constants.d.ts +203 -31
  174. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  175. package/dist/types/controls-options-manager/index.d.ts +17 -1
  176. package/dist/types/controls-options-manager/types.d.ts +43 -0
  177. package/dist/types/controls-options-manager/util.d.ts +1 -7
  178. package/dist/types/index.d.ts +6 -5
  179. package/dist/types/interceptors/index.d.ts +2 -0
  180. package/dist/types/interceptors/locusRetry.d.ts +27 -0
  181. package/dist/types/interpretation/collection.d.ts +5 -0
  182. package/dist/types/interpretation/index.d.ts +5 -0
  183. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  184. package/dist/types/locus-info/index.d.ts +57 -4
  185. package/dist/types/locus-info/parser.d.ts +66 -6
  186. package/dist/types/media/index.d.ts +2 -0
  187. package/dist/types/media/properties.d.ts +34 -49
  188. package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
  189. package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
  190. package/dist/types/meeting/index.d.ts +567 -496
  191. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  192. package/dist/types/meeting/muteState.d.ts +93 -25
  193. package/dist/types/meeting/request.d.ts +64 -43
  194. package/dist/types/meeting/util.d.ts +117 -1
  195. package/dist/types/meeting-info/index.d.ts +13 -1
  196. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  197. package/dist/types/meetings/collection.d.ts +17 -0
  198. package/dist/types/meetings/index.d.ts +113 -21
  199. package/dist/types/meetings/meetings.types.d.ts +4 -0
  200. package/dist/types/member/index.d.ts +14 -0
  201. package/dist/types/member/types.d.ts +32 -0
  202. package/dist/types/members/collection.d.ts +5 -0
  203. package/dist/types/members/index.d.ts +35 -2
  204. package/dist/types/members/request.d.ts +73 -9
  205. package/dist/types/members/types.d.ts +25 -0
  206. package/dist/types/members/util.d.ts +214 -1
  207. package/dist/types/metrics/constants.d.ts +17 -0
  208. package/dist/types/metrics/index.d.ts +4 -111
  209. package/dist/types/multistream/mediaRequestManager.d.ts +72 -3
  210. package/dist/types/multistream/receiveSlot.d.ts +7 -3
  211. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  212. package/dist/types/multistream/remoteMedia.d.ts +3 -31
  213. package/dist/types/multistream/remoteMediaGroup.d.ts +2 -9
  214. package/dist/types/multistream/remoteMediaManager.d.ts +62 -2
  215. package/dist/types/multistream/sendSlotManager.d.ts +70 -0
  216. package/dist/types/reachability/clusterReachability.d.ts +109 -0
  217. package/dist/types/reachability/index.d.ts +60 -95
  218. package/dist/types/reachability/request.d.ts +3 -1
  219. package/dist/types/reachability/util.d.ts +8 -0
  220. package/dist/types/reconnection-manager/index.d.ts +19 -0
  221. package/dist/types/recording-controller/index.d.ts +15 -1
  222. package/dist/types/recording-controller/util.d.ts +5 -4
  223. package/dist/types/roap/index.d.ts +2 -1
  224. package/dist/types/roap/request.d.ts +9 -8
  225. package/dist/types/roap/turnDiscovery.d.ts +39 -5
  226. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  227. package/dist/types/rtcMetrics/index.d.ts +61 -0
  228. package/dist/types/statsAnalyzer/index.d.ts +34 -12
  229. package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
  230. package/dist/types/webinar/collection.d.ts +16 -0
  231. package/dist/types/webinar/index.d.ts +5 -0
  232. package/dist/webinar/collection.js +44 -0
  233. package/dist/webinar/collection.js.map +1 -0
  234. package/dist/webinar/index.js +69 -0
  235. package/dist/webinar/index.js.map +1 -0
  236. package/package.json +22 -19
  237. package/src/annotation/annotation.types.ts +50 -0
  238. package/src/annotation/constants.ts +36 -0
  239. package/src/annotation/index.ts +328 -0
  240. package/src/breakouts/README.md +35 -11
  241. package/src/breakouts/breakout.ts +67 -9
  242. package/src/breakouts/events.ts +56 -0
  243. package/src/breakouts/index.ts +558 -59
  244. package/src/breakouts/utils.ts +42 -0
  245. package/src/common/errors/no-meeting-info.ts +24 -0
  246. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  247. package/src/common/errors/webex-errors.ts +44 -2
  248. package/src/common/logs/logger-proxy.ts +1 -1
  249. package/src/common/logs/request.ts +5 -1
  250. package/src/common/queue.ts +22 -8
  251. package/src/config.ts +4 -9
  252. package/src/constants.ts +229 -21
  253. package/src/controls-options-manager/enums.ts +12 -0
  254. package/src/controls-options-manager/index.ts +116 -21
  255. package/src/controls-options-manager/types.ts +59 -0
  256. package/src/controls-options-manager/util.ts +294 -14
  257. package/src/index.ts +44 -0
  258. package/src/interceptors/index.ts +3 -0
  259. package/src/interceptors/locusRetry.ts +67 -0
  260. package/src/interpretation/README.md +60 -0
  261. package/src/interpretation/collection.ts +19 -0
  262. package/src/interpretation/index.ts +349 -0
  263. package/src/interpretation/siLanguage.ts +18 -0
  264. package/src/locus-info/controlsUtils.ts +108 -0
  265. package/src/locus-info/index.ts +417 -59
  266. package/src/locus-info/infoUtils.ts +10 -2
  267. package/src/locus-info/mediaSharesUtils.ts +80 -0
  268. package/src/locus-info/parser.ts +258 -47
  269. package/src/locus-info/selfUtils.ts +81 -5
  270. package/src/media/index.ts +100 -108
  271. package/src/media/properties.ts +88 -117
  272. package/src/mediaQualityMetrics/config.ts +103 -238
  273. package/src/meeting/in-meeting-actions.ts +171 -3
  274. package/src/meeting/index.ts +3411 -2435
  275. package/src/meeting/locusMediaRequest.ts +313 -0
  276. package/src/meeting/muteState.ts +223 -136
  277. package/src/meeting/request.ts +155 -120
  278. package/src/meeting/util.ts +685 -395
  279. package/src/meeting-info/index.ts +81 -8
  280. package/src/meeting-info/meeting-info-v2.ts +170 -14
  281. package/src/meeting-info/util.ts +1 -1
  282. package/src/meeting-info/utilv2.ts +23 -23
  283. package/src/meetings/collection.ts +33 -0
  284. package/src/meetings/index.ts +507 -127
  285. package/src/meetings/meetings.types.ts +12 -0
  286. package/src/meetings/request.ts +2 -0
  287. package/src/meetings/util.ts +81 -12
  288. package/src/member/index.ts +58 -0
  289. package/src/member/types.ts +38 -0
  290. package/src/member/util.ts +141 -25
  291. package/src/members/collection.ts +8 -0
  292. package/src/members/index.ts +134 -8
  293. package/src/members/request.ts +97 -17
  294. package/src/members/types.ts +29 -0
  295. package/src/members/util.ts +333 -240
  296. package/src/metrics/constants.ts +17 -0
  297. package/src/metrics/index.ts +1 -469
  298. package/src/multistream/mediaRequestManager.ts +271 -56
  299. package/src/multistream/receiveSlot.ts +11 -4
  300. package/src/multistream/receiveSlotManager.ts +34 -24
  301. package/src/multistream/remoteMedia.ts +5 -3
  302. package/src/multistream/remoteMediaGroup.ts +78 -0
  303. package/src/multistream/remoteMediaManager.ts +248 -44
  304. package/src/multistream/sendSlotManager.ts +199 -0
  305. package/src/reachability/clusterReachability.ts +320 -0
  306. package/src/reachability/index.ts +229 -346
  307. package/src/reachability/request.ts +8 -4
  308. package/src/reachability/util.ts +24 -0
  309. package/src/reconnection-manager/index.ts +128 -97
  310. package/src/recording-controller/index.ts +20 -3
  311. package/src/recording-controller/util.ts +26 -9
  312. package/src/roap/index.ts +52 -23
  313. package/src/roap/request.ts +48 -67
  314. package/src/roap/turnDiscovery.ts +147 -49
  315. package/src/rtcMetrics/constants.ts +3 -0
  316. package/src/rtcMetrics/index.ts +166 -0
  317. package/src/statsAnalyzer/index.ts +457 -416
  318. package/src/statsAnalyzer/mqaUtil.ts +317 -170
  319. package/src/webinar/collection.ts +31 -0
  320. package/src/webinar/index.ts +62 -0
  321. package/test/integration/spec/converged-space-meetings.js +60 -3
  322. package/test/integration/spec/journey.js +320 -261
  323. package/test/integration/spec/space-meeting.js +76 -3
  324. package/test/unit/spec/annotation/index.ts +418 -0
  325. package/test/unit/spec/breakouts/breakout.ts +118 -28
  326. package/test/unit/spec/breakouts/events.ts +89 -0
  327. package/test/unit/spec/breakouts/index.ts +1349 -114
  328. package/test/unit/spec/breakouts/utils.js +52 -1
  329. package/test/unit/spec/common/queue.js +31 -2
  330. package/test/unit/spec/controls-options-manager/index.js +163 -0
  331. package/test/unit/spec/controls-options-manager/util.js +576 -60
  332. package/test/unit/spec/fixture/locus.js +1 -0
  333. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  334. package/test/unit/spec/interpretation/collection.ts +15 -0
  335. package/test/unit/spec/interpretation/index.ts +625 -0
  336. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  337. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  338. package/test/unit/spec/locus-info/index.js +1363 -37
  339. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  340. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  341. package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
  342. package/test/unit/spec/locus-info/parser.js +116 -35
  343. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  344. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  345. package/test/unit/spec/media/index.ts +173 -81
  346. package/test/unit/spec/media/properties.ts +2 -2
  347. package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
  348. package/test/unit/spec/meeting/index.js +6821 -2172
  349. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  350. package/test/unit/spec/meeting/muteState.js +402 -212
  351. package/test/unit/spec/meeting/request.js +473 -54
  352. package/test/unit/spec/meeting/utils.js +773 -67
  353. package/test/unit/spec/meeting-info/index.js +300 -0
  354. package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
  355. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  356. package/test/unit/spec/meetings/collection.js +26 -0
  357. package/test/unit/spec/meetings/index.js +1415 -213
  358. package/test/unit/spec/meetings/utils.js +229 -2
  359. package/test/unit/spec/member/index.js +61 -6
  360. package/test/unit/spec/member/util.js +510 -34
  361. package/test/unit/spec/members/index.js +432 -1
  362. package/test/unit/spec/members/request.js +206 -27
  363. package/test/unit/spec/members/utils.js +210 -0
  364. package/test/unit/spec/metrics/index.js +1 -50
  365. package/test/unit/spec/multistream/mediaRequestManager.ts +781 -114
  366. package/test/unit/spec/multistream/receiveSlot.ts +9 -1
  367. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  368. package/test/unit/spec/multistream/remoteMedia.ts +2 -0
  369. package/test/unit/spec/multistream/remoteMediaGroup.ts +345 -0
  370. package/test/unit/spec/multistream/remoteMediaManager.ts +525 -0
  371. package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
  372. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  373. package/test/unit/spec/reachability/index.ts +551 -14
  374. package/test/unit/spec/reachability/request.js +3 -1
  375. package/test/unit/spec/reachability/util.ts +40 -0
  376. package/test/unit/spec/reconnection-manager/index.js +171 -11
  377. package/test/unit/spec/recording-controller/index.js +294 -218
  378. package/test/unit/spec/recording-controller/util.js +223 -96
  379. package/test/unit/spec/roap/index.ts +180 -83
  380. package/test/unit/spec/roap/request.ts +100 -62
  381. package/test/unit/spec/roap/turnDiscovery.ts +388 -96
  382. package/test/unit/spec/rtcMetrics/index.ts +122 -0
  383. package/test/unit/spec/stats-analyzer/index.js +1252 -12
  384. package/test/unit/spec/webinar/collection.ts +13 -0
  385. package/test/unit/spec/webinar/index.ts +60 -0
  386. package/test/utils/integrationTestUtils.js +46 -0
  387. package/test/utils/testUtils.js +0 -57
  388. package/test/utils/webex-test-users.js +12 -4
  389. package/dist/metrics/config.js +0 -289
  390. package/dist/metrics/config.js.map +0 -1
  391. package/dist/types/metrics/config.d.ts +0 -169
  392. package/src/index.js +0 -18
  393. package/src/metrics/config.ts +0 -485
@@ -1,5 +1,5 @@
1
1
  import LoggerProxy from '../common/logs/logger-proxy';
2
- import {HTTP_VERBS, RESOURCE, API} from '../constants';
2
+ import {HTTP_VERBS, RESOURCE, API, IP_VERSION} from '../constants';
3
3
 
4
4
  export interface ClusterNode {
5
5
  isVideoMesh: boolean;
@@ -30,9 +30,10 @@ class ReachabilityRequest {
30
30
  /**
31
31
  * Gets the cluster information
32
32
  *
33
+ * @param {IP_VERSION} ipVersion information about current ip network we're on
33
34
  * @returns {Promise}
34
35
  */
35
- getClusters = (): Promise<{clusters: ClusterList; joinCookie: any}> =>
36
+ getClusters = (ipVersion?: IP_VERSION): Promise<{clusters: ClusterList; joinCookie: any}> =>
36
37
  this.webex
37
38
  .request({
38
39
  method: HTTP_VERBS.GET,
@@ -41,17 +42,20 @@ class ReachabilityRequest {
41
42
  resource: RESOURCE.CLUSTERS,
42
43
  qs: {
43
44
  JCSupport: 1,
45
+ ipver: ipVersion,
44
46
  },
45
47
  })
46
48
  .then((res) => {
47
49
  const {clusters, joinCookie} = res.body;
48
50
 
49
51
  Object.keys(clusters).forEach((key) => {
50
- clusters[key].isVideoMesh = res.body.clusterClasses?.hybridMedia?.includes(key);
52
+ clusters[key].isVideoMesh = !!res.body.clusterClasses?.hybridMedia?.includes(key);
51
53
  });
52
54
 
53
55
  LoggerProxy.logger.log(
54
- `Reachability:request#getClusters --> get clusters successful:${JSON.stringify(clusters)}`
56
+ `Reachability:request#getClusters --> get clusters (ipver=${ipVersion}) successful:${JSON.stringify(
57
+ clusters
58
+ )}`
55
59
  );
56
60
 
57
61
  return {
@@ -0,0 +1,24 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ /**
3
+ * Converts a stun url to a turn url
4
+ *
5
+ * @param {string} stunUrl url of a stun server
6
+ * @param {'tcp'|'udp'} protocol what protocol to use for the turn server
7
+ * @returns {string} url of a turn server
8
+ */
9
+ export function convertStunUrlToTurn(stunUrl: string, protocol: 'udp' | 'tcp') {
10
+ // stunUrl looks like this: "stun:external-media91.public.wjfkm-a-10.prod.infra.webex.com:5004"
11
+ // and we need it to be like this: "turn:external-media91.public.wjfkm-a-10.prod.infra.webex.com:5004?transport=tcp"
12
+ const url = new URL(stunUrl);
13
+
14
+ if (url.protocol !== 'stun:') {
15
+ throw new Error(`Not a STUN URL: ${stunUrl}`);
16
+ }
17
+
18
+ url.protocol = 'turn:';
19
+ if (protocol === 'tcp') {
20
+ url.searchParams.append('transport', 'tcp');
21
+ }
22
+
23
+ return url.toString();
24
+ }
@@ -14,14 +14,14 @@ import {
14
14
  _CALL_,
15
15
  _LEFT_,
16
16
  _ID_,
17
+ RECONNECTION_STATE,
17
18
  } from '../constants';
18
19
  import BEHAVIORAL_METRICS from '../metrics/constants';
19
- import ReconnectionError from '../common/errors/reconnection';
20
20
  import ReconnectInProgress from '../common/errors/reconnection-in-progress';
21
- import {eventType, reconnection, errorObjects} from '../metrics/config';
22
- import Media from '../media';
23
21
  import Metrics from '../metrics';
24
22
  import Meeting from '../meeting';
23
+ import {MediaRequestManager} from '../multistream/mediaRequestManager';
24
+ import ReconnectionError from '../common/errors/reconnection';
25
25
 
26
26
  /**
27
27
  * Used to indicate that the reconnect logic needs to be retried.
@@ -97,7 +97,7 @@ export default class ReconnectionManager {
97
97
 
98
98
  /**
99
99
  * @instance
100
- * @type {String}
100
+ * @type {RECONNECTION_STATE}
101
101
  * @private
102
102
  * @memberof ReconnectionManager
103
103
  */
@@ -228,7 +228,32 @@ export default class ReconnectionManager {
228
228
  */
229
229
  public cleanUp() {
230
230
  this.reset();
231
- this.meeting = null;
231
+ }
232
+
233
+ /**
234
+ * Stop the local share stream.
235
+ *
236
+ * @param {string} reason a {@link SHARE_STOPPED_REASON}
237
+ * @returns {undefined}
238
+ * @private
239
+ * @memberof ReconnectionManager
240
+ */
241
+ private async stopLocalShareStream(reason: string) {
242
+ await this.meeting.unpublishStreams([
243
+ this.meeting.mediaProperties.shareVideoStream,
244
+ this.meeting.mediaProperties.shareAudioStream,
245
+ ]);
246
+ Trigger.trigger(
247
+ this.meeting,
248
+ {
249
+ file: 'reconnection-manager/index',
250
+ function: 'stopLocalShareStream',
251
+ },
252
+ EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
253
+ {
254
+ reason,
255
+ }
256
+ );
232
257
  }
233
258
 
234
259
  /**
@@ -240,6 +265,18 @@ export default class ReconnectionManager {
240
265
  return this.status === RECONNECTION.STATE.IN_PROGRESS;
241
266
  }
242
267
 
268
+ /**
269
+ * Sets the reconnection status
270
+ *
271
+ * @public
272
+ * @param {RECONNECTION_STATE} status
273
+ * @memberof ReconnectionManager
274
+ * @returns {undefined}
275
+ */
276
+ public setStatus(status: RECONNECTION_STATE) {
277
+ this.status = status;
278
+ }
279
+
243
280
  /**
244
281
  * @returns {Boolean}
245
282
  * @throws {ReconnectionError}
@@ -302,72 +339,76 @@ export default class ReconnectionManager {
302
339
  LoggerProxy.logger.info(
303
340
  'ReconnectionManager:index#reconnect --> Sending reconnect start metric.'
304
341
  );
305
- Metrics.postEvent({
306
- event: eventType.MEDIA_RECONNECTING,
307
- meeting: this.meeting,
342
+
343
+ // @ts-ignore
344
+ this.webex.internal.newMetrics.submitClientEvent({
345
+ name: 'client.media.reconnecting',
346
+ options: {
347
+ meetingId: this.meeting.id,
348
+ },
308
349
  });
309
350
  }
310
351
 
311
- return this.executeReconnection({networkDisconnect})
312
- .then(() => {
313
- LoggerProxy.logger.info('ReconnectionManager:index#reconnect --> Reconnection successful.');
314
- LoggerProxy.logger.info(
315
- 'ReconnectionManager:index#reconnect --> Sending reconnect success metric.'
316
- );
317
- Metrics.postEvent({
318
- event: eventType.MEDIA_RECOVERED,
319
- meeting: this.meeting,
320
- data: {recoveredBy: reconnection.RECOVERED_BY_NEW},
321
- });
322
- })
323
- .catch((reconnectError) => {
324
- if (reconnectError instanceof NeedsRetryError) {
325
- LoggerProxy.logger.info(
326
- 'ReconnectionManager:index#reconnect --> Reconnection not successful, retrying.'
327
- );
328
- // Reset our reconnect status since we are looping back to the beginning
329
- this.status = RECONNECTION.STATE.DEFAULT_STATUS;
330
-
331
- // This is a network retry, so we should not log START metrics again
332
- return this.reconnect({networkDisconnect: true, networkRetry: true});
333
- }
352
+ try {
353
+ await this.webex.meetings.startReachability();
354
+ } catch (err) {
355
+ LoggerProxy.logger.info(
356
+ 'ReconnectionManager:index#reconnect --> Reachability failed, continuing with reconnection attempt, err: ',
357
+ err
358
+ );
359
+ }
334
360
 
335
- // Reconnect has failed
336
- LoggerProxy.logger.error(
337
- 'ReconnectionManager:index#reconnect --> Reconnection failed.',
338
- reconnectError.message
339
- );
361
+ try {
362
+ const media = await this.executeReconnection({networkDisconnect});
363
+
364
+ return media;
365
+ } catch (reconnectError) {
366
+ if (reconnectError instanceof NeedsRetryError) {
340
367
  LoggerProxy.logger.info(
341
- 'ReconnectionManager:index#reconnect --> Sending reconnect abort metric.'
368
+ 'ReconnectionManager:index#reconnect --> Reconnection not successful, retrying.'
342
369
  );
370
+ // Reset our reconnect status since we are looping back to the beginning
371
+ this.status = RECONNECTION.STATE.DEFAULT_STATUS;
343
372
 
344
- const reconnectMetric = {
345
- event: eventType.CALL_ABORTED,
346
- meeting: this.meeting,
347
- data: {
348
- errors: [
349
- {
350
- category: errorObjects.category.expected,
351
- errorCode: 2008,
352
- fatal: true,
353
- name: errorObjects.name.mediaEngine,
354
- shownToUser: false,
355
- },
356
- ],
357
- },
358
- };
359
-
360
- Metrics.postEvent(reconnectMetric);
361
- if (reconnectError instanceof NeedsRejoinError) {
362
- // send call aborded event with catogery as expected as we are trying to rejoin
363
-
364
- if (this.autoRejoinEnabled) {
365
- return this.rejoinMeeting(reconnectError.wasSharing);
366
- }
367
- }
373
+ // This is a network retry, so we should not log START metrics again
374
+ return this.reconnect({networkDisconnect: true, networkRetry: true});
375
+ }
376
+
377
+ // Reconnect has failed
378
+ LoggerProxy.logger.error(
379
+ 'ReconnectionManager:index#reconnect --> Reconnection failed.',
380
+ reconnectError.message
381
+ );
382
+ LoggerProxy.logger.info(
383
+ 'ReconnectionManager:index#reconnect --> Sending reconnect abort metric.'
384
+ );
368
385
 
369
- throw reconnectError;
386
+ // send call aborted event with catogery as expected as we are trying to rejoin
387
+ // @ts-ignore
388
+ this.webex.internal.newMetrics.submitClientEvent({
389
+ name: 'client.call.aborted',
390
+ payload: {
391
+ errors: [
392
+ {
393
+ category: 'expected',
394
+ errorCode: 2008,
395
+ fatal: true,
396
+ name: 'media-engine',
397
+ shownToUser: false,
398
+ },
399
+ ],
400
+ },
401
+ options: {
402
+ meetingId: this.meeting.id,
403
+ },
370
404
  });
405
+
406
+ if (reconnectError instanceof NeedsRejoinError && this.autoRejoinEnabled) {
407
+ return this.rejoinMeeting(reconnectError.wasSharing);
408
+ }
409
+
410
+ throw reconnectError;
411
+ }
371
412
  }
372
413
 
373
414
  /**
@@ -385,6 +426,12 @@ export default class ReconnectionManager {
385
426
  'ReconnectionManager:index#executeReconnection --> Attempting to reconnect to meeting.'
386
427
  );
387
428
 
429
+ const wasSharing = this.meeting.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE;
430
+
431
+ if (wasSharing) {
432
+ await this.stopLocalShareStream(SHARE_STOPPED_REASON.MEDIA_RECONNECTION);
433
+ }
434
+
388
435
  if (networkDisconnect) {
389
436
  try {
390
437
  await this.reconnectMercuryWebSocket();
@@ -401,13 +448,11 @@ export default class ReconnectionManager {
401
448
  }
402
449
  }
403
450
 
404
- const wasSharing = this.meeting.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE;
405
-
406
451
  try {
407
452
  LoggerProxy.logger.info(
408
453
  'ReconnectionManager:index#executeReconnection --> Updating meeting data from server.'
409
454
  );
410
- await this.webex.meetings.syncMeetings();
455
+ await this.webex.meetings.syncMeetings({keepOnlyLocusMeetings: false});
411
456
  } catch (syncError) {
412
457
  LoggerProxy.logger.info(
413
458
  'ReconnectionManager:index#executeReconnection --> Unable to sync meetings, reconnecting.',
@@ -420,10 +465,10 @@ export default class ReconnectionManager {
420
465
  // So that on rejoin it known what parametrs it was using
421
466
  if (!this.meeting || !this.webex.meetings.getMeetingByType(_ID_, this.meeting.id)) {
422
467
  LoggerProxy.logger.info(
423
- 'ReconnectionManager:index#executeReconnection --> Meeting got deleted due to inactivity or ended remotely '
468
+ 'ReconnectionManager:index#executeReconnection --> Meeting got deleted due to inactivity or ended remotely.'
424
469
  );
425
470
 
426
- throw new Error('Unable to rejoin a meeting already ended or inactive .');
471
+ throw new Error('Unable to rejoin a meeting already ended or inactive.');
427
472
  }
428
473
 
429
474
  LoggerProxy.logger.info(
@@ -443,14 +488,13 @@ export default class ReconnectionManager {
443
488
  const media = await this.reconnectMedia();
444
489
 
445
490
  LoggerProxy.logger.log(
446
- 'ReconnectionManager:index#executeReconnection --> Media reestablished'
491
+ 'ReconnectionManager:index#executeReconnection --> webRTC media connection renewed and local sdp offer sent'
447
492
  );
448
- this.status = RECONNECTION.STATE.COMPLETE;
449
493
 
450
494
  return media;
451
495
  } catch (error) {
452
496
  LoggerProxy.logger.error(
453
- 'ReconnectionManager:index#executeReconnection --> Media reestablishment failed'
497
+ 'ReconnectionManager:index#executeReconnection --> failed to renew webRTC media connection or initiate offer'
454
498
  );
455
499
  this.status = RECONNECTION.STATE.FAILURE;
456
500
 
@@ -475,24 +519,7 @@ export default class ReconnectionManager {
475
519
  LoggerProxy.logger.info('ReconnectionManager:index#rejoinMeeting --> meeting rejoined');
476
520
 
477
521
  if (wasSharing) {
478
- // Stop the share streams if user tried to rejoin
479
- this.meeting.setLocalShareTrack(null);
480
- this.meeting.isSharing = false;
481
- if (this.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE) {
482
- this.meeting.shareStatus = SHARE_STATUS.NO_SHARE;
483
- }
484
- this.meeting.mediaProperties.mediaDirection.sendShare = false;
485
- Trigger.trigger(
486
- this.meeting,
487
- {
488
- file: 'reconnection-manager/index',
489
- function: 'rejoinMeeting',
490
- },
491
- EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
492
- {
493
- reason: SHARE_STOPPED_REASON.MEETING_REJOIN,
494
- }
495
- );
522
+ await this.stopLocalShareStream(SHARE_STOPPED_REASON.MEETING_REJOIN);
496
523
  }
497
524
  } catch (joinError) {
498
525
  this.rejoinAttempts += 1;
@@ -534,16 +561,14 @@ export default class ReconnectionManager {
534
561
  * @memberof ReconnectionManager
535
562
  */
536
563
  async reconnectMedia() {
537
- LoggerProxy.logger.log(
538
- 'ReconnectionManager:index#reconnectMedia --> Begin reestablishment of media'
539
- );
564
+ LoggerProxy.logger.log('ReconnectionManager:index#reconnectMedia --> do turn discovery');
540
565
 
541
- // do the TURN server discovery again since the TURN server might change
542
- const turnServerResult = await this.meeting.roap.doTurnDiscovery(this.meeting, true);
566
+ // do the TURN server discovery again and ignore reachability results since the TURN server might change
567
+ const turnServerResult = await this.meeting.roap.doTurnDiscovery(this.meeting, true, true);
543
568
 
544
569
  const iceServers = [];
545
570
 
546
- if (turnServerResult.turnServerInfo) {
571
+ if (turnServerResult.turnServerInfo?.url) {
547
572
  iceServers.push({
548
573
  urls: turnServerResult.turnServerInfo.url,
549
574
  username: turnServerResult.turnServerInfo.username || '',
@@ -551,13 +576,19 @@ export default class ReconnectionManager {
551
576
  });
552
577
  }
553
578
 
579
+ LoggerProxy.logger.log(
580
+ 'ReconnectionManager:index#reconnectMedia --> renew webRTC media connection and send local sdp offer'
581
+ );
582
+
554
583
  await this.meeting.mediaProperties.webrtcMediaConnection.reconnect(iceServers);
555
584
 
556
585
  // resend media requests
557
586
  if (this.meeting.isMultistream) {
558
- Object.values(this.meeting.mediaRequestManagers).forEach((mediaRequestManager) =>
559
- // @ts-ignore - Fix type
560
- mediaRequestManager.commit()
587
+ Object.values(this.meeting.mediaRequestManagers).forEach(
588
+ (mediaRequestManager: MediaRequestManager) => {
589
+ mediaRequestManager.clearPreviousRequests();
590
+ mediaRequestManager.commit();
591
+ }
561
592
  );
562
593
  }
563
594
  }
@@ -1,5 +1,5 @@
1
1
  import PermissionError from '../common/errors/permission';
2
- import {CONTROLS, HTTP_VERBS} from '../constants';
2
+ import {CONTROLS, HTTP_VERBS, SELF_POLICY} from '../constants';
3
3
  import MeetingRequest from '../meeting/request';
4
4
  import RecordingAction from './enums';
5
5
  import Util from './util';
@@ -28,6 +28,14 @@ export default class RecordingController {
28
28
  */
29
29
  private displayHints: Array<string> = [];
30
30
 
31
+ /**
32
+ * @instance
33
+ * @type {Object}
34
+ * @private
35
+ * @memberof RecordingInfo
36
+ */
37
+ private selfUserPolicies: Record<SELF_POLICY, boolean>;
38
+
31
39
  /**
32
40
  * @instance
33
41
  * @type {string}
@@ -81,7 +89,6 @@ export default class RecordingController {
81
89
 
82
90
  /**
83
91
  * @param {MeetingRequest} request
84
- * @param {LocusInfo} info
85
92
  * @returns {void}
86
93
  * @private
87
94
  * @memberof RecordingController
@@ -126,6 +133,16 @@ export default class RecordingController {
126
133
  this.displayHints = hints;
127
134
  }
128
135
 
136
+ /**
137
+ * @param {Object} selfUserPolicies
138
+ * @returns {void}
139
+ * @public
140
+ * @memberof RecordingController
141
+ */
142
+ public setUserPolicy(selfUserPolicies: Record<SELF_POLICY, boolean>) {
143
+ this.selfUserPolicies = selfUserPolicies;
144
+ }
145
+
129
146
  /**
130
147
  * @param {string} id
131
148
  * @returns {void}
@@ -264,7 +281,7 @@ export default class RecordingController {
264
281
  );
265
282
 
266
283
  // assumes action is proper cased (i.e., Example)
267
- if (Util?.[`canUser${action}`](this.displayHints)) {
284
+ if (Util?.[`canUser${action}`](this.displayHints, this.selfUserPolicies)) {
268
285
  if (this.serviceUrl) {
269
286
  return this.recordingService(action);
270
287
  }
@@ -1,17 +1,34 @@
1
- import {DISPLAY_HINTS} from '../constants';
1
+ import {DISPLAY_HINTS, SELF_POLICY} from '../constants';
2
2
  import RecordingAction from './enums';
3
+ import MeetingUtil from '../meeting/util';
3
4
 
4
- const canUserStart = (displayHints: Array<string>): boolean =>
5
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START);
5
+ const canUserStart = (
6
+ displayHints: Array<string>,
7
+ userPolicies: Record<SELF_POLICY, boolean>
8
+ ): boolean =>
9
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START) &&
10
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);
6
11
 
7
- const canUserPause = (displayHints: Array<string>): boolean =>
8
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE);
12
+ const canUserPause = (
13
+ displayHints: Array<string>,
14
+ userPolicies: Record<SELF_POLICY, boolean>
15
+ ): boolean =>
16
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE) &&
17
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);
9
18
 
10
- const canUserResume = (displayHints: Array<string>): boolean =>
11
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME);
19
+ const canUserResume = (
20
+ displayHints: Array<string>,
21
+ userPolicies: Record<SELF_POLICY, boolean>
22
+ ): boolean =>
23
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME) &&
24
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);
12
25
 
13
- const canUserStop = (displayHints: Array<string>): boolean =>
14
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP);
26
+ const canUserStop = (
27
+ displayHints: Array<string>,
28
+ userPolicies: Record<SELF_POLICY, boolean>
29
+ ): boolean =>
30
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP) &&
31
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_NETWORK_BASED_RECORD, userPolicies);
15
32
 
16
33
  const extractLocusId = (url: string) => {
17
34
  return url?.split('/').pop();
package/src/roap/index.ts CHANGED
@@ -7,6 +7,9 @@ import LoggerProxy from '../common/logs/logger-proxy';
7
7
  import RoapRequest from './request';
8
8
  import TurnDiscovery from './turnDiscovery';
9
9
  import Meeting from '../meeting';
10
+ import MeetingUtil from '../meeting/util';
11
+ import Metrics from '../metrics';
12
+ import BEHAVIORAL_METRICS from '../metrics/constants';
10
13
 
11
14
  /**
12
15
  * Roap options
@@ -98,11 +101,8 @@ export default class Roap extends StatelessWebexPlugin {
98
101
  roapMessage,
99
102
  locusSelfUrl: meeting.selfUrl,
100
103
  mediaId: options.mediaId,
101
- correlationId: options.correlationId,
102
- audioMuted: meeting.audio?.isLocallyMuted(),
103
- videoMuted: meeting.video?.isLocallyMuted(),
104
104
  meetingId: meeting.id,
105
- preferTranscoding: !meeting.isMultistream,
105
+ locusMediaRequest: meeting.locusMediaRequest,
106
106
  })
107
107
  .then(() => {
108
108
  LoggerProxy.logger.log(`Roap:index#sendRoapOK --> ROAP OK sent with seq ${options.seq}`);
@@ -135,11 +135,8 @@ export default class Roap extends StatelessWebexPlugin {
135
135
  roapMessage,
136
136
  locusSelfUrl: meeting.selfUrl,
137
137
  mediaId: options.mediaId,
138
- correlationId: options.correlationId,
139
- audioMuted: meeting.isAudioMuted(),
140
- videoMuted: meeting.isVideoMuted(),
141
138
  meetingId: meeting.id,
142
- preferTranscoding: !meeting.isMultistream,
139
+ locusMediaRequest: meeting.locusMediaRequest,
143
140
  });
144
141
  }
145
142
 
@@ -167,11 +164,8 @@ export default class Roap extends StatelessWebexPlugin {
167
164
  roapMessage,
168
165
  locusSelfUrl: meeting.selfUrl,
169
166
  mediaId: options.mediaId,
170
- correlationId: options.correlationId,
171
- audioMuted: meeting.audio?.isLocallyMuted(),
172
- videoMuted: meeting.video?.isLocallyMuted(),
173
167
  meetingId: meeting.id,
174
- preferTranscoding: !meeting.isMultistream,
168
+ locusMediaRequest: meeting.locusMediaRequest,
175
169
  })
176
170
  .then(() => {
177
171
  LoggerProxy.logger.log(
@@ -187,37 +181,71 @@ export default class Roap extends StatelessWebexPlugin {
187
181
  * @memberof Roap
188
182
  */
189
183
  sendRoapMediaRequest(options: any) {
190
- const {meeting, seq, sdp, reconnect, tieBreaker} = options;
184
+ const {meeting, seq, sdp, tieBreaker} = options;
191
185
  const roapMessage = {
192
186
  messageType: ROAP.ROAP_TYPES.OFFER,
193
187
  sdps: [sdp],
194
188
  version: ROAP.ROAP_VERSION,
195
189
  seq,
196
190
  tieBreaker,
191
+ headers: ['includeAnswerInHttpResponse', 'noOkInTransaction'],
197
192
  };
198
193
 
199
- // When reconnecting, it's important that the first roap message being sent out has empty media id.
200
- // Normally this is the roap offer, but when TURN discovery is enabled,
201
- // then this is the TURN discovery request message
202
- const sendEmptyMediaId = reconnect && !meeting.config.experimental.enableTurnDiscovery;
194
+ // The only time we want to send an empty media id is when we are reconnecting, because this way we tell Locus
195
+ // that it needs to create a new confluence, but when reconnecting we always send TURN_DISCOVERY_REQUEST first,
196
+ // so we don't need to ever send an empty media id here
197
+ const sendEmptyMediaId = false;
203
198
 
204
199
  return this.roapRequest
205
200
  .sendRoap({
206
201
  roapMessage,
207
- correlationId: meeting.correlationId,
208
202
  locusSelfUrl: meeting.selfUrl,
209
203
  mediaId: sendEmptyMediaId ? '' : meeting.mediaId,
210
- audioMuted: meeting.audio?.isLocallyMuted(),
211
- videoMuted: meeting.video?.isLocallyMuted(),
212
204
  meetingId: meeting.id,
213
205
  preferTranscoding: !meeting.isMultistream,
206
+ locusMediaRequest: meeting.locusMediaRequest,
207
+ ipVersion: MeetingUtil.getIpVersion(meeting.webex),
214
208
  })
215
209
  .then(({locus, mediaConnections}) => {
216
210
  if (mediaConnections) {
217
211
  meeting.updateMediaConnections(mediaConnections);
218
212
  }
219
213
 
220
- return locus;
214
+ let roapAnswer;
215
+
216
+ if (mediaConnections?.[0]?.remoteSdp) {
217
+ const remoteSdp = JSON.parse(mediaConnections[0].remoteSdp);
218
+
219
+ if (remoteSdp.roapMessage) {
220
+ const {
221
+ seq: answerSeq,
222
+ messageType,
223
+ sdps,
224
+ errorType,
225
+ errorCause,
226
+ headers,
227
+ } = remoteSdp.roapMessage;
228
+
229
+ roapAnswer = {
230
+ seq: answerSeq,
231
+ messageType,
232
+ sdp: sdps[0],
233
+ errorType,
234
+ errorCause,
235
+ headers,
236
+ };
237
+ }
238
+ }
239
+
240
+ if (!roapAnswer) {
241
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_HTTP_RESPONSE_MISSING, {
242
+ correlationId: meeting.correlationId,
243
+ messageType: 'ANSWER',
244
+ isMultistream: meeting.isMultistream,
245
+ });
246
+ }
247
+
248
+ return {locus, roapAnswer};
221
249
  });
222
250
  }
223
251
 
@@ -229,9 +257,10 @@ export default class Roap extends StatelessWebexPlugin {
229
257
  * @param {Meeting} meeting
230
258
  * @param {Boolean} isReconnecting should be set to true if this is a new
231
259
  * media connection just after a reconnection
260
+ * @param {Boolean} [isForced]
232
261
  * @returns {Promise}
233
262
  */
234
- doTurnDiscovery(meeting: Meeting, isReconnecting: boolean) {
235
- return this.turnDiscovery.doTurnDiscovery(meeting, isReconnecting);
263
+ doTurnDiscovery(meeting: Meeting, isReconnecting: boolean, isForced?: boolean) {
264
+ return this.turnDiscovery.doTurnDiscovery(meeting, isReconnecting, isForced);
236
265
  }
237
266
  }