@webex/plugin-meetings 3.0.0-beta.13 → 3.0.0-beta.15

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 (252) hide show
  1. package/UPGRADING.md +9 -9
  2. package/browsers.js +19 -24
  3. package/dist/common/browser-detection.js +1 -0
  4. package/dist/common/browser-detection.js.map +1 -1
  5. package/dist/common/collection.js.map +1 -1
  6. package/dist/common/errors/captcha-error.js +5 -5
  7. package/dist/common/errors/captcha-error.js.map +1 -1
  8. package/dist/common/errors/intent-to-join.js +5 -5
  9. package/dist/common/errors/intent-to-join.js.map +1 -1
  10. package/dist/common/errors/join-meeting.js +6 -6
  11. package/dist/common/errors/join-meeting.js.map +1 -1
  12. package/dist/common/errors/media.js +5 -5
  13. package/dist/common/errors/media.js.map +1 -1
  14. package/dist/common/errors/parameter.js +5 -5
  15. package/dist/common/errors/parameter.js.map +1 -1
  16. package/dist/common/errors/password-error.js +5 -5
  17. package/dist/common/errors/password-error.js.map +1 -1
  18. package/dist/common/errors/permission.js +4 -4
  19. package/dist/common/errors/permission.js.map +1 -1
  20. package/dist/common/errors/reconnection.js +5 -5
  21. package/dist/common/errors/reconnection.js.map +1 -1
  22. package/dist/common/errors/stats.js +5 -5
  23. package/dist/common/errors/stats.js.map +1 -1
  24. package/dist/common/errors/webex-errors.js.map +1 -1
  25. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  26. package/dist/common/events/events-scope.js.map +1 -1
  27. package/dist/common/events/events.js.map +1 -1
  28. package/dist/common/events/trigger-proxy.js.map +1 -1
  29. package/dist/common/events/util.js.map +1 -1
  30. package/dist/common/logs/logger-proxy.js.map +1 -1
  31. package/dist/common/logs/request.js.map +1 -1
  32. package/dist/config.js.map +1 -1
  33. package/dist/constants.js.map +1 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/locus-info/controlsUtils.js.map +1 -1
  36. package/dist/locus-info/fullState.js.map +1 -1
  37. package/dist/locus-info/hostUtils.js.map +1 -1
  38. package/dist/locus-info/index.js +11 -8
  39. package/dist/locus-info/index.js.map +1 -1
  40. package/dist/locus-info/infoUtils.js.map +1 -1
  41. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  42. package/dist/locus-info/parser.js +2 -1
  43. package/dist/locus-info/parser.js.map +1 -1
  44. package/dist/locus-info/selfUtils.js +2 -1
  45. package/dist/locus-info/selfUtils.js.map +1 -1
  46. package/dist/media/index.js.map +1 -1
  47. package/dist/media/internal-media-core-wrapper.js.map +1 -1
  48. package/dist/media/properties.js.map +1 -1
  49. package/dist/media/util.js +1 -1
  50. package/dist/media/util.js.map +1 -1
  51. package/dist/mediaQualityMetrics/config.js.map +1 -1
  52. package/dist/meeting/effectsState.js +1 -1
  53. package/dist/meeting/effectsState.js.map +1 -1
  54. package/dist/meeting/in-meeting-actions.js.map +1 -1
  55. package/dist/meeting/index.js +118 -89
  56. package/dist/meeting/index.js.map +1 -1
  57. package/dist/meeting/muteState.js +1 -1
  58. package/dist/meeting/muteState.js.map +1 -1
  59. package/dist/meeting/request.js +25 -0
  60. package/dist/meeting/request.js.map +1 -1
  61. package/dist/meeting/request.type.js +8 -0
  62. package/dist/meeting/request.type.js.map +1 -0
  63. package/dist/meeting/state.js +5 -5
  64. package/dist/meeting/state.js.map +1 -1
  65. package/dist/meeting/util.js.map +1 -1
  66. package/dist/meeting-info/collection.js.map +1 -1
  67. package/dist/meeting-info/index.js +2 -2
  68. package/dist/meeting-info/index.js.map +1 -1
  69. package/dist/meeting-info/meeting-info-v2.js +48 -48
  70. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  71. package/dist/meeting-info/request.js.map +1 -1
  72. package/dist/meeting-info/util.js.map +1 -1
  73. package/dist/meeting-info/utilv2.js +1 -1
  74. package/dist/meeting-info/utilv2.js.map +1 -1
  75. package/dist/meetings/collection.js.map +1 -1
  76. package/dist/meetings/index.js +251 -250
  77. package/dist/meetings/index.js.map +1 -1
  78. package/dist/meetings/request.js +2 -2
  79. package/dist/meetings/request.js.map +1 -1
  80. package/dist/meetings/util.js +14 -14
  81. package/dist/meetings/util.js.map +1 -1
  82. package/dist/member/index.js +31 -31
  83. package/dist/member/index.js.map +1 -1
  84. package/dist/member/util.js.map +1 -1
  85. package/dist/members/collection.js.map +1 -1
  86. package/dist/members/index.js +43 -43
  87. package/dist/members/index.js.map +1 -1
  88. package/dist/members/request.js.map +1 -1
  89. package/dist/members/util.js.map +1 -1
  90. package/dist/metrics/config.js.map +1 -1
  91. package/dist/metrics/constants.js.map +1 -1
  92. package/dist/metrics/index.js +23 -20
  93. package/dist/metrics/index.js.map +1 -1
  94. package/dist/multistream/multistreamMedia.js +2 -1
  95. package/dist/multistream/multistreamMedia.js.map +1 -1
  96. package/dist/multistream/receiveSlot.js.map +1 -1
  97. package/dist/multistream/receiveSlotManager.js +2 -0
  98. package/dist/multistream/receiveSlotManager.js.map +1 -1
  99. package/dist/multistream/remoteMedia.js.map +1 -1
  100. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  101. package/dist/multistream/remoteMediaManager.js.map +1 -1
  102. package/dist/networkQualityMonitor/index.js +8 -8
  103. package/dist/networkQualityMonitor/index.js.map +1 -1
  104. package/dist/personal-meeting-room/index.js +7 -7
  105. package/dist/personal-meeting-room/index.js.map +1 -1
  106. package/dist/personal-meeting-room/request.js.map +1 -1
  107. package/dist/personal-meeting-room/util.js.map +1 -1
  108. package/dist/reachability/index.js.map +1 -1
  109. package/dist/reachability/request.js.map +1 -1
  110. package/dist/reactions/reactions.js.map +1 -1
  111. package/dist/reactions/reactions.type.js +3 -1
  112. package/dist/reactions/reactions.type.js.map +1 -1
  113. package/dist/reconnection-manager/index.js +4 -4
  114. package/dist/reconnection-manager/index.js.map +1 -1
  115. package/dist/roap/index.js +5 -5
  116. package/dist/roap/index.js.map +1 -1
  117. package/dist/roap/request.js.map +1 -1
  118. package/dist/roap/turnDiscovery.js.map +1 -1
  119. package/dist/statsAnalyzer/global.js.map +1 -1
  120. package/dist/statsAnalyzer/index.js.map +1 -1
  121. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  122. package/dist/transcription/index.js +4 -1
  123. package/dist/transcription/index.js.map +1 -1
  124. package/internal-README.md +7 -6
  125. package/package.json +18 -18
  126. package/src/common/browser-detection.ts +9 -6
  127. package/src/common/collection.ts +3 -1
  128. package/src/common/errors/captcha-error.ts +6 -6
  129. package/src/common/errors/intent-to-join.ts +6 -6
  130. package/src/common/errors/join-meeting.ts +12 -8
  131. package/src/common/errors/media.ts +6 -6
  132. package/src/common/errors/parameter.ts +9 -6
  133. package/src/common/errors/password-error.ts +6 -6
  134. package/src/common/errors/permission.ts +5 -5
  135. package/src/common/errors/reconnection.ts +6 -6
  136. package/src/common/errors/stats.ts +6 -6
  137. package/src/common/errors/webex-errors.ts +7 -5
  138. package/src/common/errors/webex-meetings-error.ts +1 -1
  139. package/src/common/events/events-scope.ts +5 -1
  140. package/src/common/events/events.ts +5 -1
  141. package/src/common/events/trigger-proxy.ts +8 -3
  142. package/src/common/events/util.ts +1 -2
  143. package/src/common/logs/logger-proxy.ts +21 -10
  144. package/src/common/logs/request.ts +11 -8
  145. package/src/config.ts +11 -11
  146. package/src/constants.ts +1 -1
  147. package/src/index.js +1 -1
  148. package/src/locus-info/controlsUtils.ts +34 -24
  149. package/src/locus-info/fullState.ts +15 -11
  150. package/src/locus-info/hostUtils.ts +4 -3
  151. package/src/locus-info/index.ts +25 -34
  152. package/src/locus-info/infoUtils.ts +12 -4
  153. package/src/locus-info/mediaSharesUtils.ts +4 -4
  154. package/src/locus-info/parser.ts +45 -68
  155. package/src/locus-info/selfUtils.ts +106 -57
  156. package/src/media/index.ts +123 -135
  157. package/src/media/internal-media-core-wrapper.ts +2 -2
  158. package/src/media/properties.ts +30 -20
  159. package/src/media/util.ts +1 -1
  160. package/src/mediaQualityMetrics/config.ts +46 -46
  161. package/src/meeting/effectsState.ts +35 -35
  162. package/src/meeting/in-meeting-actions.ts +7 -3
  163. package/src/meeting/index.ts +1576 -1291
  164. package/src/meeting/muteState.ts +62 -31
  165. package/src/meeting/request.ts +174 -113
  166. package/src/meeting/request.type.ts +11 -0
  167. package/src/meeting/state.ts +45 -30
  168. package/src/meeting/util.ts +101 -70
  169. package/src/meeting-info/collection.ts +2 -1
  170. package/src/meeting-info/index.ts +32 -30
  171. package/src/meeting-info/meeting-info-v2.ts +106 -108
  172. package/src/meeting-info/request.ts +9 -3
  173. package/src/meeting-info/util.ts +54 -46
  174. package/src/meeting-info/utilv2.ts +59 -53
  175. package/src/meetings/collection.ts +1 -1
  176. package/src/meetings/index.ts +512 -440
  177. package/src/meetings/request.ts +26 -24
  178. package/src/meetings/util.ts +29 -29
  179. package/src/member/index.ts +55 -49
  180. package/src/member/util.ts +26 -13
  181. package/src/members/collection.ts +0 -1
  182. package/src/members/index.ts +182 -126
  183. package/src/members/request.ts +46 -14
  184. package/src/members/util.ts +44 -42
  185. package/src/metrics/config.ts +254 -81
  186. package/src/metrics/constants.ts +0 -2
  187. package/src/metrics/index.ts +84 -71
  188. package/src/multistream/multistreamMedia.ts +1 -0
  189. package/src/multistream/receiveSlot.ts +1 -0
  190. package/src/multistream/receiveSlotManager.ts +1 -0
  191. package/src/multistream/remoteMedia.ts +1 -1
  192. package/src/multistream/remoteMediaGroup.ts +2 -1
  193. package/src/multistream/remoteMediaManager.ts +3 -0
  194. package/src/networkQualityMonitor/index.ts +20 -23
  195. package/src/personal-meeting-room/index.ts +12 -16
  196. package/src/personal-meeting-room/request.ts +10 -3
  197. package/src/personal-meeting-room/util.ts +3 -3
  198. package/src/reachability/index.ts +61 -59
  199. package/src/reachability/request.ts +36 -32
  200. package/src/reactions/reactions.ts +4 -4
  201. package/src/reactions/reactions.type.ts +4 -3
  202. package/src/reconnection-manager/index.ts +139 -84
  203. package/src/roap/index.ts +46 -38
  204. package/src/roap/request.ts +44 -31
  205. package/src/roap/turnDiscovery.ts +59 -30
  206. package/src/statsAnalyzer/global.ts +30 -33
  207. package/src/statsAnalyzer/index.ts +432 -175
  208. package/src/statsAnalyzer/mqaUtil.ts +178 -72
  209. package/src/transcription/index.ts +34 -32
  210. package/test/integration/spec/journey.js +663 -462
  211. package/test/integration/spec/space-meeting.js +318 -203
  212. package/test/integration/spec/transcription.js +6 -7
  213. package/test/unit/spec/common/browser-detection.js +9 -28
  214. package/test/unit/spec/fixture/locus.js +92 -90
  215. package/test/unit/spec/locus-info/controlsUtils.js +5 -5
  216. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  217. package/test/unit/spec/locus-info/index.js +1 -2
  218. package/test/unit/spec/locus-info/infoUtils.js +26 -33
  219. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  220. package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
  221. package/test/unit/spec/locus-info/parser.js +3 -9
  222. package/test/unit/spec/locus-info/selfConstant.js +72 -103
  223. package/test/unit/spec/locus-info/selfUtils.js +21 -12
  224. package/test/unit/spec/meeting/effectsState.js +36 -46
  225. package/test/unit/spec/meeting/in-meeting-actions.ts +2 -3
  226. package/test/unit/spec/meeting/index.js +1342 -684
  227. package/test/unit/spec/meeting/muteState.js +42 -33
  228. package/test/unit/spec/meeting/request.js +75 -45
  229. package/test/unit/spec/meeting/utils.js +78 -53
  230. package/test/unit/spec/meeting-info/meetinginfov2.js +100 -73
  231. package/test/unit/spec/meeting-info/request.js +7 -9
  232. package/test/unit/spec/meeting-info/util.js +11 -12
  233. package/test/unit/spec/meeting-info/utilv2.js +110 -74
  234. package/test/unit/spec/meetings/collection.js +1 -1
  235. package/test/unit/spec/meetings/index.js +438 -257
  236. package/test/unit/spec/meetings/utils.js +14 -12
  237. package/test/unit/spec/member/index.js +0 -1
  238. package/test/unit/spec/member/util.js +5 -6
  239. package/test/unit/spec/members/index.js +104 -54
  240. package/test/unit/spec/members/request.js +29 -20
  241. package/test/unit/spec/members/utils.js +8 -5
  242. package/test/unit/spec/metrics/index.js +16 -21
  243. package/test/unit/spec/networkQualityMonitor/index.js +21 -15
  244. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  245. package/test/unit/spec/reachability/index.ts +9 -11
  246. package/test/unit/spec/reconnection-manager/index.js +16 -18
  247. package/test/unit/spec/roap/turnDiscovery.ts +22 -19
  248. package/test/unit/spec/stats-analyzer/index.js +25 -20
  249. package/test/utils/cmr.js +44 -42
  250. package/test/utils/testUtils.js +83 -74
  251. package/test/utils/webex-config.js +18 -18
  252. package/test/utils/webex-test-users.js +53 -50
@@ -1 +1 @@
1
- {"version":3,"names":["AllEqualLayout","screenShareVideo","size","activeSpeakerVideoPaneGroups","id","numPanes","priority","SingleLayout","OnePlusFiveLayout","TwoMainPlusSixSmallLayout","RemoteScreenShareWithSmallThumbnailsLayout","Stage2x2With6ThumbnailsLayout","memberVideoPanes","csi","undefined","DefaultConfiguration","audio","numOfActiveSpeakerStreams","video","preferLiveVideo","initialLayoutId","layouts","AllEqual","OnePlusFive","Single","Stage","ScreenShareView","screenShare","Event","RemoteMediaManager","receiveSlotManager","mediaRequestManagers","config","started","media","activeSpeakerGroups","memberPanes","checkConfigValidity","slots","screenShareAudio","unused","activeSpeaker","receiverSelected","receiveSlotAllocations","LoggerProxy","logger","log","Error","forEach","layout","groupIds","paneIds","groupPriorites","group","pane","createAudioMedia","preallocateVideoReceiveSlots","setLayout","invalidateCurrentRemoteMedia","commit","slot","releaseSlot","length","push","releaseUnusedVideoSlots","currentLayout","currentLayoutId","activeSpeakerCount","reduce","sum","paneGroup","receiverSelectedCount","maxNumVideoPanesRequired","maxValue","Math","max","getRequiredNumVideoSlotsForLayout","allocateSlot","MC","MediaType","VideoMain","layoutId","updateVideoReceiveSlots","updateVideoRemoteMediaObjects","emitVideoLayoutChangedEvent","i","AudioMain","RemoteMediaGroup","emit","file","function","AudioCreated","requiredCsis","memberVideoPane","isCsiNeededByCurrentLayout","notNeededReceiverSelectedSlots","paneIndex","freeSlot","pop","memberPane","existingSlot","find","isExistingSlotAlreadyAllocated","includes","requiredNumSlots","totalNumSlots","numSlotsToCreate","trimReceiverSelectedSlots","allocateSlotsToVideoPaneGroups","groupId","paneGroupInCurrentLayout","groupInLayout","mediaGroup","resolution","warn","paneId","paneInCurrentLayout","paneInLayout","remoteMedia","RemoteMedia","sendMediaRequest","options","stop","remoteMediaGroup","VideoLayoutChanged","activeSpeakerVideoPanes","cancelMediaRequest","newPane","receiveSlot","reject","resolve","getUnderlyingReceiveSlot","index","indexOf","splice","pin","unpin","isPinned","EventsScope"],"sources":["remoteMediaManager.ts"],"sourcesContent":["import {cloneDeep, remove} from 'lodash';\nimport {EventMap} from 'typed-emitter';\nimport {MediaConnection as MC} from '@webex/internal-media-core';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport EventsScope from '../common/events/events-scope';\n\nimport {RemoteMedia, RemoteVideoResolution} from './remoteMedia';\nimport {ReceiveSlot, CSI} from './receiveSlot';\nimport {ReceiveSlotManager} from './receiveSlotManager';\nimport {RemoteMediaGroup} from './remoteMediaGroup';\nimport {MediaRequestManager} from './mediaRequestManager';\n\nexport type PaneSize = RemoteVideoResolution;\nexport type LayoutId = string;\nexport type PaneId = string;\nexport type PaneGroupId = string;\n\nexport interface ActiveSpeakerVideoPaneGroup {\n id: PaneGroupId;\n numPanes: number; // maximum number of panes in the group (actual number may be lower, if there are not enough participants in the meeting)\n size: PaneSize; // preferred size for all panes in the group\n priority: number; // 0-255 (255 = highest priority), each group must have a different priority from all other groups\n}\n\nexport interface MemberVideoPane {\n id: PaneId;\n size: PaneSize;\n csi?: CSI;\n}\n\nexport interface VideoLayout {\n screenShareVideo: {\n size: PaneSize | null; // null if you don't want to receive any screen share video\n };\n activeSpeakerVideoPaneGroups?: ActiveSpeakerVideoPaneGroup[]; // list of active speaker video pane groups\n memberVideoPanes?: MemberVideoPane[]; // list of video panes for specific members, CSI values can be changed later via setVideoPaneCsi()\n}\n\nexport interface Configuration {\n audio: {\n numOfActiveSpeakerStreams: number; // number of audio streams we want to receive\n };\n video: {\n preferLiveVideo: boolean; // applies to all pane groups with active speaker policy\n initialLayoutId: LayoutId;\n\n layouts: {[key: LayoutId]: VideoLayout}; // a map of all available layouts, a layout can be set via setLayout() method\n };\n screenShare: {\n audio: boolean; // whether we ever want to receive screen share audio at all\n video: boolean; // whether we ever want to receive screen share video at all\n };\n}\n\n/* Predefined layouts: */\n\n// An \"all equal\" grid, with size up to 3 x 3 = 9:\nconst AllEqualLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 9,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with just a single remote active speaker video pane:\nconst SingleLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 1,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with 1 big pane for the highest priority active speaker and 5 small panes for other active speakers:\nconst OnePlusFiveLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainBigOne',\n numPanes: 1,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondarySetOfSmallPanes',\n numPanes: 5,\n size: 'very small',\n priority: 254,\n },\n ],\n};\n\n// A layout with 2 big panes for 2 main active speakers and a strip of 6 small panes for other active speakers:\nconst TwoMainPlusSixSmallLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainGroupWith2BigPanes',\n numPanes: 2,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondaryGroupOfSmallPanes',\n numPanes: 6,\n size: 'small',\n priority: 254,\n },\n ],\n};\n\n// A strip of 8 small video panes (thumbnails) displayed at the top of a remote screenshare:\nconst RemoteScreenShareWithSmallThumbnailsLayout: VideoLayout = {\n screenShareVideo: {size: 'best'},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 8,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n};\n\n// A staged layout with 4 pre-selected meeting participants in the main 2x2 grid and 6 small panes for other active speakers at the top:\nconst Stage2x2With6ThumbnailsLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 6,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n memberVideoPanes: [\n {id: 'stage-1', size: 'medium', csi: undefined},\n {id: 'stage-2', size: 'medium', csi: undefined},\n {id: 'stage-3', size: 'medium', csi: undefined},\n {id: 'stage-4', size: 'medium', csi: undefined},\n ],\n};\n\n/**\n * Default configuration:\n * - uses 3 audio streams\n * - prefers active speakers with live video (e.g. are not audio only or video muted) over active speakers without live video\n * - has a few layouts defined, including 1 that contains remote screen share (ScreenShareView)\n */\nexport const DefaultConfiguration: Configuration = {\n audio: {\n numOfActiveSpeakerStreams: 3,\n },\n video: {\n preferLiveVideo: true,\n initialLayoutId: 'AllEqual',\n\n layouts: {\n AllEqual: AllEqualLayout,\n OnePlusFive: OnePlusFiveLayout,\n Single: SingleLayout,\n Stage: Stage2x2With6ThumbnailsLayout,\n ScreenShareView: RemoteScreenShareWithSmallThumbnailsLayout,\n },\n },\n screenShare: {\n audio: true,\n video: true,\n },\n};\n\nexport enum Event {\n // events for audio streams\n AudioCreated = 'AudioCreated',\n ScreenShareAudioCreated = 'ScreenShareCreated',\n\n // events for video streams\n VideoLayoutChanged = 'VideoLayoutChanged',\n}\n\nexport interface VideoLayoutChangedEventData {\n layoutId: LayoutId;\n activeSpeakerVideoPanes: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberVideoPanes: {[key: PaneId]: RemoteMedia};\n screenShareVideo?: RemoteMedia;\n}\nexport interface Events extends EventMap {\n // audio\n [Event.AudioCreated]: (audio: RemoteMediaGroup) => void;\n [Event.ScreenShareAudioCreated]: (screenShareAudio: RemoteMedia) => void;\n\n // video\n [Event.VideoLayoutChanged]: (data: VideoLayoutChangedEventData) => void;\n}\n\n/**\n * A helper class that manages all remote audio/video streams in order to achieve a predefined set of layouts.\n * It also creates a fixed number of audio streams and these don't change during the meeting.\n *\n * Things that RemoteMediaManager does:\n * - owns the receive slots (creates them when needed, and re-uses them when switching layouts)\n * - constructs appropriate RemoteMedia and RemoteMediaGroup objects and sends appropriate mediaRequests\n */\nexport class RemoteMediaManager extends EventsScope {\n private config: Configuration;\n\n private started: boolean;\n\n private receiveSlotManager: ReceiveSlotManager;\n\n private mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n };\n\n private currentLayout?: VideoLayout;\n\n private slots: {\n audio: ReceiveSlot[];\n screenShareAudio?: ReceiveSlot;\n screenShareVideo?: ReceiveSlot;\n video: {\n unused: ReceiveSlot[];\n activeSpeaker: ReceiveSlot[];\n receiverSelected: ReceiveSlot[];\n };\n };\n\n private media: {\n audio?: RemoteMediaGroup;\n video: {\n activeSpeakerGroups: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberPanes: {[key: PaneId]: RemoteMedia};\n };\n };\n\n private receiveSlotAllocations: {\n activeSpeaker: {[key: PaneGroupId]: {slots: ReceiveSlot[]}};\n receiverSelected: {[key: PaneId]: ReceiveSlot};\n };\n\n private currentLayoutId?: LayoutId;\n\n /**\n * Constructor\n *\n * @param {ReceiveSlotManager} receiveSlotManager\n * @param {{audio: MediaRequestManager, video: mediaRequestManagers}} mediaRequestManagers\n * @param {Configuration} config Configuration describing what video layouts to use during the meeting\n */\n constructor(\n receiveSlotManager: ReceiveSlotManager,\n mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n },\n config: Configuration = DefaultConfiguration\n ) {\n super();\n this.started = false;\n this.config = config;\n this.receiveSlotManager = receiveSlotManager;\n this.mediaRequestManagers = mediaRequestManagers;\n this.media = {\n audio: undefined,\n video: {\n activeSpeakerGroups: {},\n memberPanes: {},\n },\n };\n\n this.checkConfigValidity();\n\n this.slots = {\n audio: [],\n screenShareAudio: undefined,\n screenShareVideo: undefined,\n video: {\n unused: [],\n activeSpeaker: [],\n receiverSelected: [],\n },\n };\n\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#constructor --> RemoteMediaManager created with config: ${JSON.stringify(\n this.config\n )}`\n );\n }\n\n /**\n * Checks if configuration is valid, throws an error if it's not\n */\n private checkConfigValidity() {\n if (!(this.config.video.initialLayoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid config: initialLayoutId \"${this.config.video.initialLayoutId}\" doesn't match any of the layouts`\n );\n }\n\n // check if each layout is valid\n Object.values(this.config.video.layouts).forEach((layout) => {\n const groupIds = {};\n const paneIds = {};\n const groupPriorites = {};\n\n layout.activeSpeakerVideoPaneGroups?.forEach((group) => {\n if (groupIds[group.id]) {\n throw new Error(\n `invalid config: duplicate active speaker video pane group id: ${group.id}`\n );\n }\n groupIds[group.id] = true;\n\n if (groupPriorites[group.priority]) {\n throw new Error(\n `invalid config: multiple active speaker video pane groups have same priority: ${group.priority}`\n );\n }\n groupPriorites[group.priority] = true;\n });\n\n layout.memberVideoPanes?.forEach((pane) => {\n if (paneIds[pane.id]) {\n throw new Error(`invalid config: duplicate member video pane id: ${pane.id}`);\n }\n paneIds[pane.id] = true;\n });\n });\n }\n\n /**\n * Starts the RemoteMediaManager.\n *\n * @returns {Promise}\n */\n public async start() {\n if (this.started) {\n throw new Error('start() failure: already started');\n }\n this.started = true;\n\n await this.createAudioMedia();\n\n // todo: create screen share audio remote media (SPARK-377812)\n // todo: create screen share video receive slot (SPARK-377812)\n\n await this.preallocateVideoReceiveSlots();\n\n await this.setLayout(this.config.video.initialLayoutId);\n }\n\n /**\n * Releases all the used resources (like allocated receive slots). This function needs\n * to be called when we leave the meeting, etc.\n */\n public stop() {\n // invalidate all remoteMedia objects\n this.invalidateCurrentRemoteMedia({audio: true, video: true, commit: true});\n\n // release all audio receive slots\n this.slots.audio.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.audio.length = 0;\n\n // todo: screenshare slots... (SPARK-377812)\n\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n\n this.slots.video.unused.push(...this.slots.video.receiverSelected);\n this.slots.video.receiverSelected.length = 0;\n\n this.releaseUnusedVideoSlots();\n\n this.currentLayout = undefined;\n this.currentLayoutId = undefined;\n this.started = false;\n }\n\n /**\n * Returns the total number of main video panes required for a given layout\n *\n * @param {VideoLayout} layout\n * @returns {number}\n */\n private getRequiredNumVideoSlotsForLayout(layout?: VideoLayout) {\n if (!layout) {\n return 0;\n }\n\n const activeSpeakerCount =\n layout.activeSpeakerVideoPaneGroups?.reduce(\n (sum, paneGroup) => sum + paneGroup.numPanes,\n 0\n ) || 0;\n\n const receiverSelectedCount = layout.memberVideoPanes?.length || 0;\n\n return activeSpeakerCount + receiverSelectedCount;\n }\n\n /**\n * Allocates the maximum number of panes that any of the configured layouts will require.\n * We do this at the beginning, because it's more efficient (much faster) then allocating receive slots\n * later, after the SDP exchange was done.\n */\n private async preallocateVideoReceiveSlots() {\n const maxNumVideoPanesRequired = Object.values(this.config.video.layouts).reduce(\n (maxValue, layout) => Math.max(maxValue, this.getRequiredNumVideoSlotsForLayout(layout)),\n 0\n );\n\n while (this.slots.video.unused.length < maxNumVideoPanesRequired) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n await this.receiveSlotManager.allocateSlot(MC.MediaType.VideoMain)\n );\n }\n }\n\n /**\n * Changes the layout (triggers Event.VideoLayoutChanged)\n *\n * @param {LayoutId} layoutId new layout id\n * @returns {Promise}\n */\n public async setLayout(layoutId: LayoutId) {\n if (!(layoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid layoutId: \"${layoutId}\" doesn't match any of the configured layouts`\n );\n }\n if (!this.started) {\n throw new Error('setLayout() called before start()');\n }\n this.currentLayoutId = layoutId;\n this.currentLayout = cloneDeep(this.config.video.layouts[this.currentLayoutId]);\n\n await this.updateVideoReceiveSlots();\n this.updateVideoRemoteMediaObjects();\n this.emitVideoLayoutChangedEvent();\n }\n\n /**\n * Returns the currently selected layout id\n *\n * @returns {LayoutId}\n */\n public getLayoutId(): LayoutId | undefined {\n return this.currentLayoutId;\n }\n\n /**\n * Creates the audio slots\n */\n private async createAudioMedia() {\n // create the audio receive slots\n for (let i = 0; i < this.config.audio.numOfActiveSpeakerStreams; i += 1) {\n // eslint-disable-next-line no-await-in-loop\n const slot = await this.receiveSlotManager.allocateSlot(MC.MediaType.AudioMain);\n\n this.slots.audio.push(slot);\n }\n\n // create a remote media group\n this.media.audio = new RemoteMediaGroup(\n this.mediaRequestManagers.audio,\n this.slots.audio,\n 255,\n true\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createAudioMedia'},\n Event.AudioCreated,\n this.media.audio\n );\n }\n\n /**\n * Goes over all receiver-selected slots and keeps only the ones that are required by a given layout,\n * the rest are all moved to the \"unused\" list\n */\n private trimReceiverSelectedSlots() {\n const requiredCsis = {};\n\n // fill requiredCsis with all the CSIs that the given layout requires\n this.currentLayout?.memberVideoPanes?.forEach((memberVideoPane) => {\n if (memberVideoPane.csi !== undefined) {\n requiredCsis[memberVideoPane.csi] = true;\n }\n });\n\n const isCsiNeededByCurrentLayout = (csi?: CSI): boolean => {\n if (csi === undefined) {\n return false;\n }\n\n return !!requiredCsis[csi];\n };\n\n // keep receiverSelected slots that match our new requiredCsis, move the rest of receiverSelected slots to unused\n const notNeededReceiverSelectedSlots = remove(\n this.slots.video.receiverSelected,\n (slot) => isCsiNeededByCurrentLayout(slot.csi) === false\n );\n\n this.slots.video.unused.push(...notNeededReceiverSelectedSlots);\n }\n\n /**\n * Releases all the \"unused\" video slots.\n */\n private releaseUnusedVideoSlots() {\n this.slots.video.unused.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.video.unused.length = 0;\n }\n\n /**\n * Allocates receive slots to all video panes in the current selected layout\n */\n private allocateSlotsToVideoPaneGroups() {\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n this.currentLayout?.activeSpeakerVideoPaneGroups?.forEach((group) => {\n this.receiveSlotAllocations.activeSpeaker[group.id] = {slots: []};\n\n for (let paneIndex = 0; paneIndex < group.numPanes; paneIndex += 1) {\n // allocate a slot from the \"unused\" list\n const freeSlot = this.slots.video.unused.pop();\n\n if (freeSlot) {\n this.slots.video.activeSpeaker.push(freeSlot);\n this.receiveSlotAllocations.activeSpeaker[group.id].slots.push(freeSlot);\n }\n }\n });\n\n this.currentLayout?.memberVideoPanes?.forEach((memberPane) => {\n // check if there is existing slot for this csi\n const existingSlot = this.slots.video.receiverSelected.find(\n (slot) => slot.csi === memberPane.csi\n );\n\n const isExistingSlotAlreadyAllocated = Object.values(\n this.receiveSlotAllocations.receiverSelected\n ).includes(existingSlot);\n\n if (memberPane.csi !== undefined && existingSlot && !isExistingSlotAlreadyAllocated) {\n // found it, so use it\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = existingSlot;\n } else {\n // allocate a slot from the \"unused\" list\n const freeSlot = this.slots.video.unused.pop();\n\n if (freeSlot) {\n this.slots.video.receiverSelected.push(freeSlot);\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = freeSlot;\n }\n }\n });\n }\n\n /**\n * Makes sure we have the right number of receive slots created for the current layout\n * and allocates them to the right video panes / pane groups\n *\n * @returns {Promise}\n */\n private async updateVideoReceiveSlots() {\n const requiredNumSlots = this.getRequiredNumVideoSlotsForLayout(this.currentLayout);\n const totalNumSlots =\n this.slots.video.unused.length +\n this.slots.video.activeSpeaker.length +\n this.slots.video.receiverSelected.length;\n\n // ensure we have enough total slots for current layout\n if (totalNumSlots < requiredNumSlots) {\n let numSlotsToCreate = requiredNumSlots - totalNumSlots;\n\n while (numSlotsToCreate > 0) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n await this.receiveSlotManager.allocateSlot(MC.MediaType.VideoMain)\n );\n numSlotsToCreate -= 1;\n }\n }\n\n // move all no longer needed receiver-selected slots to \"unused\"\n this.trimReceiverSelectedSlots();\n\n // move all active speaker slots to \"unused\"\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n\n // allocate the slots to the right panes / pane groups\n this.allocateSlotsToVideoPaneGroups();\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#updateVideoReceiveSlots --> receive slots updated: unused=${this.slots.video.unused.length}, activeSpeaker=${this.slots.video.activeSpeaker.length}, receiverSelected=${this.slots.video.receiverSelected.length}`\n );\n\n // If this is the initial layout, there may be some \"unused\" slots left because of the preallocation\n // done in this.preallocateVideoReceiveSlots(), so release them now\n this.releaseUnusedVideoSlots();\n }\n\n /**\n * Creates new RemoteMedia and RemoteMediaGroup objects for the current layout\n * and sends the media requests for all of them.\n */\n private updateVideoRemoteMediaObjects() {\n // invalidate all the previous remote media objects and cancel their media requests\n this.invalidateCurrentRemoteMedia({audio: false, video: true, commit: false});\n\n // create new remoteMediaGroup objects\n this.media.video.activeSpeakerGroups = {};\n this.media.video.memberPanes = {};\n\n for (const [groupId, group] of Object.entries(this.receiveSlotAllocations.activeSpeaker)) {\n const paneGroupInCurrentLayout = this.currentLayout?.activeSpeakerVideoPaneGroups?.find(\n (groupInLayout) => groupInLayout.id === groupId\n );\n\n if (paneGroupInCurrentLayout) {\n const mediaGroup = new RemoteMediaGroup(\n this.mediaRequestManagers.video,\n group.slots,\n paneGroupInCurrentLayout.priority,\n false,\n {\n preferLiveVideo: this.config.video.preferLiveVideo,\n resolution: paneGroupInCurrentLayout.size,\n }\n );\n\n this.media.video.activeSpeakerGroups[groupId] = mediaGroup;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a group id ${groupId} from this.receiveSlotAllocations.activeSpeaker cannot be found in the current layout configuration`\n );\n }\n }\n\n // create new remoteMedia objects\n for (const [paneId, slot] of Object.entries(this.receiveSlotAllocations.receiverSelected)) {\n const paneInCurrentLayout = this.currentLayout?.memberVideoPanes?.find(\n (paneInLayout) => paneInLayout.id === paneId\n );\n\n if (paneInCurrentLayout) {\n const remoteMedia = new RemoteMedia(slot, this.mediaRequestManagers.video, {\n resolution: paneInCurrentLayout.size,\n });\n\n if (paneInCurrentLayout.csi) {\n remoteMedia.sendMediaRequest(paneInCurrentLayout.csi, false);\n }\n\n this.media.video.memberPanes[paneId] = remoteMedia;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a pane id ${paneId} from this.receiveSlotAllocations.receiverSelected cannot be found in the current layout configuration`\n );\n }\n }\n // todo: screenshare (SPARK-377812)\n\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Invalidates all remote media objects belonging to currently selected layout\n */\n private invalidateCurrentRemoteMedia(options: {audio: boolean; video: boolean; commit: boolean}) {\n const {audio, video, commit} = options;\n\n if (audio && this.media.audio) {\n this.media.audio.stop(commit);\n }\n if (video) {\n Object.values(this.media.video.activeSpeakerGroups).forEach((remoteMediaGroup) => {\n remoteMediaGroup.stop(false);\n });\n Object.values(this.media.video.memberPanes).forEach((remoteMedia) => {\n remoteMedia.stop(false);\n });\n if (commit) {\n this.mediaRequestManagers.video.commit();\n }\n }\n }\n\n /** emits Event.VideoLayoutChanged */\n private emitVideoLayoutChangedEvent() {\n // todo: at this point the receive slots might still be showing a participant from previous layout, we should\n // wait for our media requests to be fullfilled, but there is no API for that right now (we could wait for source updates\n // but in some cases they might never come, or would need to always make sure to use a new set of receiver slots)\n // for now it's fine to have it like this, we will re-evaluate if it needs improving after more testing\n\n this.emit(\n {\n file: 'multistream/remoteMediaManager',\n function: 'emitVideoLayoutChangedEvent',\n },\n Event.VideoLayoutChanged,\n {\n layoutId: this.currentLayoutId,\n activeSpeakerVideoPanes: this.media.video.activeSpeakerGroups,\n memberVideoPanes: this.media.video.memberPanes,\n screenShareVideo: undefined, // todo: screen share (SPARK-377812)\n }\n );\n }\n\n /**\n * Sets a new CSI on a given remote media object\n *\n * @param {RemoteMedia} remoteMedia remote Media object to modify\n * @param {CSI} csi new CSI value, can be null if we want to stop receiving media\n */\n public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi: CSI | null) {\n if (!Object.values(this.media.video.memberPanes).includes(remoteMedia)) {\n throw new Error('remoteMedia not found');\n }\n\n if (csi) {\n remoteMedia.sendMediaRequest(csi, true);\n } else {\n remoteMedia.cancelMediaRequest(true);\n }\n }\n\n /**\n * Adds a new member video pane to the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {MemberVideoPane} newPane\n * @returns {Promise<RemoteMedia>}\n */\n public async addMemberVideoPane(newPane: MemberVideoPane): Promise<RemoteMedia> {\n if (!this.currentLayout) {\n throw new Error('There is no current layout selected, call start() first');\n }\n\n if (!this.currentLayout?.memberVideoPanes) {\n this.currentLayout.memberVideoPanes = [];\n }\n\n if (newPane.id in this.currentLayout.memberVideoPanes) {\n throw new Error(\n `duplicate pane id ${newPane.id} - this pane already exists in current layout's memberVideoPanes`\n );\n }\n\n this.currentLayout.memberVideoPanes.push(newPane);\n\n const receiveSlot = await this.receiveSlotManager.allocateSlot(MC.MediaType.VideoMain);\n\n this.slots.video.receiverSelected.push(receiveSlot);\n\n const remoteMedia = new RemoteMedia(receiveSlot, this.mediaRequestManagers.video, {\n resolution: newPane.size,\n });\n\n if (newPane.csi) {\n remoteMedia.sendMediaRequest(newPane.csi, true);\n }\n\n this.media.video.memberPanes[newPane.id] = remoteMedia;\n\n return remoteMedia;\n }\n\n /**\n * Removes a member video pane from the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {PaneId} paneId pane id of the pane to remove\n * @returns {Promise<void>}\n */\n public removeMemberVideoPane(paneId: PaneId): Promise<void> {\n if (!this.currentLayout) {\n return Promise.reject(new Error('There is no current layout selected, call start() first'));\n }\n\n if (!this.currentLayout.memberVideoPanes?.find((pane) => pane.id === paneId)) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in currentLayout.memberVideoPanes)`\n );\n\n return Promise.resolve();\n }\n\n if (!this.media.video.memberPanes[paneId]) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in this.media.video.memberPanes)`\n );\n\n return Promise.resolve();\n }\n\n const remoteMedia = this.media.video.memberPanes[paneId];\n\n const receiveSlot = remoteMedia.getUnderlyingReceiveSlot();\n\n if (receiveSlot) {\n this.receiveSlotManager.releaseSlot(receiveSlot);\n\n const index = this.slots.video.receiverSelected.indexOf(receiveSlot);\n\n if (index >= 0) {\n this.slots.video.receiverSelected.splice(index, 1);\n }\n }\n remoteMedia.stop();\n\n delete this.media.video.memberPanes[paneId];\n delete this.currentLayout.memberVideoPanes?.[paneId];\n\n return Promise.resolve();\n }\n\n /**\n * Pins an active speaker remote media object to the given CSI value. From that moment\n * onwards the remote media will only play audio/video from that specific CSI until\n * unpinActiveSpeakerVideoPane() is called or current layout is changed.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n * @param {CSI} csi CSI value to pin to, if undefined, then current CSI value is used\n */\n public pinActiveSpeakerVideoPane(remoteMedia: RemoteMedia, csi?: CSI): void {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'unpinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the unpinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.pin(remoteMedia, csi);\n }\n\n /**\n * Unpins a remote media object from the fixed CSI value it was pinned to.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n */\n public unpinActiveSpeakerVideoPane(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'pinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the pinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.unpin(remoteMedia);\n }\n\n /**\n * Returns true if a given remote media object belongs to an active speaker group and has been pinned.\n * Throws an error if the remote media object doesn't belong to any active speaker remote media group.\n *\n * @param {RemoteMedia} remoteMedia remote media object\n * @returns {boolean}\n */\n public isPinned(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia)\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among any remote media (pinned or unpinned) from any active speaker group'\n );\n }\n\n return remoteMediaGroup.isPinned(remoteMedia);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["AllEqualLayout","screenShareVideo","size","activeSpeakerVideoPaneGroups","id","numPanes","priority","SingleLayout","OnePlusFiveLayout","TwoMainPlusSixSmallLayout","RemoteScreenShareWithSmallThumbnailsLayout","Stage2x2With6ThumbnailsLayout","memberVideoPanes","csi","undefined","DefaultConfiguration","audio","numOfActiveSpeakerStreams","video","preferLiveVideo","initialLayoutId","layouts","AllEqual","OnePlusFive","Single","Stage","ScreenShareView","screenShare","Event","RemoteMediaManager","receiveSlotManager","mediaRequestManagers","config","started","media","activeSpeakerGroups","memberPanes","checkConfigValidity","slots","screenShareAudio","unused","activeSpeaker","receiverSelected","receiveSlotAllocations","LoggerProxy","logger","log","Error","forEach","layout","groupIds","paneIds","groupPriorites","group","pane","createAudioMedia","preallocateVideoReceiveSlots","setLayout","invalidateCurrentRemoteMedia","commit","slot","releaseSlot","length","push","releaseUnusedVideoSlots","currentLayout","currentLayoutId","activeSpeakerCount","reduce","sum","paneGroup","receiverSelectedCount","maxNumVideoPanesRequired","maxValue","Math","max","getRequiredNumVideoSlotsForLayout","allocateSlot","MC","MediaType","VideoMain","layoutId","updateVideoReceiveSlots","updateVideoRemoteMediaObjects","emitVideoLayoutChangedEvent","i","AudioMain","RemoteMediaGroup","emit","file","function","AudioCreated","requiredCsis","memberVideoPane","isCsiNeededByCurrentLayout","notNeededReceiverSelectedSlots","paneIndex","freeSlot","pop","memberPane","existingSlot","find","isExistingSlotAlreadyAllocated","includes","requiredNumSlots","totalNumSlots","numSlotsToCreate","trimReceiverSelectedSlots","allocateSlotsToVideoPaneGroups","groupId","paneGroupInCurrentLayout","groupInLayout","mediaGroup","resolution","warn","paneId","paneInCurrentLayout","paneInLayout","remoteMedia","RemoteMedia","sendMediaRequest","options","stop","remoteMediaGroup","VideoLayoutChanged","activeSpeakerVideoPanes","cancelMediaRequest","newPane","receiveSlot","reject","resolve","getUnderlyingReceiveSlot","index","indexOf","splice","pin","unpin","isPinned","EventsScope"],"sources":["remoteMediaManager.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\nimport {cloneDeep, remove} from 'lodash';\nimport {EventMap} from 'typed-emitter';\nimport {MediaConnection as MC} from '@webex/internal-media-core';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport EventsScope from '../common/events/events-scope';\n\nimport {RemoteMedia, RemoteVideoResolution} from './remoteMedia';\nimport {ReceiveSlot, CSI} from './receiveSlot';\nimport {ReceiveSlotManager} from './receiveSlotManager';\nimport {RemoteMediaGroup} from './remoteMediaGroup';\nimport {MediaRequestManager} from './mediaRequestManager';\n\nexport type PaneSize = RemoteVideoResolution;\nexport type LayoutId = string;\nexport type PaneId = string;\nexport type PaneGroupId = string;\n\nexport interface ActiveSpeakerVideoPaneGroup {\n id: PaneGroupId;\n numPanes: number; // maximum number of panes in the group (actual number may be lower, if there are not enough participants in the meeting)\n size: PaneSize; // preferred size for all panes in the group\n priority: number; // 0-255 (255 = highest priority), each group must have a different priority from all other groups\n}\n\nexport interface MemberVideoPane {\n id: PaneId;\n size: PaneSize;\n csi?: CSI;\n}\n\nexport interface VideoLayout {\n screenShareVideo: {\n size: PaneSize | null; // null if you don't want to receive any screen share video\n };\n activeSpeakerVideoPaneGroups?: ActiveSpeakerVideoPaneGroup[]; // list of active speaker video pane groups\n memberVideoPanes?: MemberVideoPane[]; // list of video panes for specific members, CSI values can be changed later via setVideoPaneCsi()\n}\n\nexport interface Configuration {\n audio: {\n numOfActiveSpeakerStreams: number; // number of audio streams we want to receive\n };\n video: {\n preferLiveVideo: boolean; // applies to all pane groups with active speaker policy\n initialLayoutId: LayoutId;\n\n layouts: {[key: LayoutId]: VideoLayout}; // a map of all available layouts, a layout can be set via setLayout() method\n };\n screenShare: {\n audio: boolean; // whether we ever want to receive screen share audio at all\n video: boolean; // whether we ever want to receive screen share video at all\n };\n}\n\n/* Predefined layouts: */\n\n// An \"all equal\" grid, with size up to 3 x 3 = 9:\nconst AllEqualLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 9,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with just a single remote active speaker video pane:\nconst SingleLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 1,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with 1 big pane for the highest priority active speaker and 5 small panes for other active speakers:\nconst OnePlusFiveLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainBigOne',\n numPanes: 1,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondarySetOfSmallPanes',\n numPanes: 5,\n size: 'very small',\n priority: 254,\n },\n ],\n};\n\n// A layout with 2 big panes for 2 main active speakers and a strip of 6 small panes for other active speakers:\nconst TwoMainPlusSixSmallLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainGroupWith2BigPanes',\n numPanes: 2,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondaryGroupOfSmallPanes',\n numPanes: 6,\n size: 'small',\n priority: 254,\n },\n ],\n};\n\n// A strip of 8 small video panes (thumbnails) displayed at the top of a remote screenshare:\nconst RemoteScreenShareWithSmallThumbnailsLayout: VideoLayout = {\n screenShareVideo: {size: 'best'},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 8,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n};\n\n// A staged layout with 4 pre-selected meeting participants in the main 2x2 grid and 6 small panes for other active speakers at the top:\nconst Stage2x2With6ThumbnailsLayout: VideoLayout = {\n screenShareVideo: {size: null},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 6,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n memberVideoPanes: [\n {id: 'stage-1', size: 'medium', csi: undefined},\n {id: 'stage-2', size: 'medium', csi: undefined},\n {id: 'stage-3', size: 'medium', csi: undefined},\n {id: 'stage-4', size: 'medium', csi: undefined},\n ],\n};\n\n/**\n * Default configuration:\n * - uses 3 audio streams\n * - prefers active speakers with live video (e.g. are not audio only or video muted) over active speakers without live video\n * - has a few layouts defined, including 1 that contains remote screen share (ScreenShareView)\n */\nexport const DefaultConfiguration: Configuration = {\n audio: {\n numOfActiveSpeakerStreams: 3,\n },\n video: {\n preferLiveVideo: true,\n initialLayoutId: 'AllEqual',\n\n layouts: {\n AllEqual: AllEqualLayout,\n OnePlusFive: OnePlusFiveLayout,\n Single: SingleLayout,\n Stage: Stage2x2With6ThumbnailsLayout,\n ScreenShareView: RemoteScreenShareWithSmallThumbnailsLayout,\n },\n },\n screenShare: {\n audio: true,\n video: true,\n },\n};\n\nexport enum Event {\n // events for audio streams\n AudioCreated = 'AudioCreated',\n ScreenShareAudioCreated = 'ScreenShareCreated',\n\n // events for video streams\n VideoLayoutChanged = 'VideoLayoutChanged',\n}\n\nexport interface VideoLayoutChangedEventData {\n layoutId: LayoutId;\n activeSpeakerVideoPanes: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberVideoPanes: {[key: PaneId]: RemoteMedia};\n screenShareVideo?: RemoteMedia;\n}\nexport interface Events extends EventMap {\n // audio\n [Event.AudioCreated]: (audio: RemoteMediaGroup) => void;\n [Event.ScreenShareAudioCreated]: (screenShareAudio: RemoteMedia) => void;\n\n // video\n [Event.VideoLayoutChanged]: (data: VideoLayoutChangedEventData) => void;\n}\n\n/**\n * A helper class that manages all remote audio/video streams in order to achieve a predefined set of layouts.\n * It also creates a fixed number of audio streams and these don't change during the meeting.\n *\n * Things that RemoteMediaManager does:\n * - owns the receive slots (creates them when needed, and re-uses them when switching layouts)\n * - constructs appropriate RemoteMedia and RemoteMediaGroup objects and sends appropriate mediaRequests\n */\nexport class RemoteMediaManager extends EventsScope {\n private config: Configuration;\n\n private started: boolean;\n\n private receiveSlotManager: ReceiveSlotManager;\n\n private mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n };\n\n private currentLayout?: VideoLayout;\n\n private slots: {\n audio: ReceiveSlot[];\n screenShareAudio?: ReceiveSlot;\n screenShareVideo?: ReceiveSlot;\n video: {\n unused: ReceiveSlot[];\n activeSpeaker: ReceiveSlot[];\n receiverSelected: ReceiveSlot[];\n };\n };\n\n private media: {\n audio?: RemoteMediaGroup;\n video: {\n activeSpeakerGroups: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberPanes: {[key: PaneId]: RemoteMedia};\n };\n };\n\n private receiveSlotAllocations: {\n activeSpeaker: {[key: PaneGroupId]: {slots: ReceiveSlot[]}};\n receiverSelected: {[key: PaneId]: ReceiveSlot};\n };\n\n private currentLayoutId?: LayoutId;\n\n /**\n * Constructor\n *\n * @param {ReceiveSlotManager} receiveSlotManager\n * @param {{audio: MediaRequestManager, video: mediaRequestManagers}} mediaRequestManagers\n * @param {Configuration} config Configuration describing what video layouts to use during the meeting\n */\n constructor(\n receiveSlotManager: ReceiveSlotManager,\n mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n },\n config: Configuration = DefaultConfiguration\n ) {\n super();\n this.started = false;\n this.config = config;\n this.receiveSlotManager = receiveSlotManager;\n this.mediaRequestManagers = mediaRequestManagers;\n this.media = {\n audio: undefined,\n video: {\n activeSpeakerGroups: {},\n memberPanes: {},\n },\n };\n\n this.checkConfigValidity();\n\n this.slots = {\n audio: [],\n screenShareAudio: undefined,\n screenShareVideo: undefined,\n video: {\n unused: [],\n activeSpeaker: [],\n receiverSelected: [],\n },\n };\n\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#constructor --> RemoteMediaManager created with config: ${JSON.stringify(\n this.config\n )}`\n );\n }\n\n /**\n * Checks if configuration is valid, throws an error if it's not\n */\n private checkConfigValidity() {\n if (!(this.config.video.initialLayoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid config: initialLayoutId \"${this.config.video.initialLayoutId}\" doesn't match any of the layouts`\n );\n }\n\n // check if each layout is valid\n Object.values(this.config.video.layouts).forEach((layout) => {\n const groupIds = {};\n const paneIds = {};\n const groupPriorites = {};\n\n layout.activeSpeakerVideoPaneGroups?.forEach((group) => {\n if (groupIds[group.id]) {\n throw new Error(\n `invalid config: duplicate active speaker video pane group id: ${group.id}`\n );\n }\n groupIds[group.id] = true;\n\n if (groupPriorites[group.priority]) {\n throw new Error(\n `invalid config: multiple active speaker video pane groups have same priority: ${group.priority}`\n );\n }\n groupPriorites[group.priority] = true;\n });\n\n layout.memberVideoPanes?.forEach((pane) => {\n if (paneIds[pane.id]) {\n throw new Error(`invalid config: duplicate member video pane id: ${pane.id}`);\n }\n paneIds[pane.id] = true;\n });\n });\n }\n\n /**\n * Starts the RemoteMediaManager.\n *\n * @returns {Promise}\n */\n public async start() {\n if (this.started) {\n throw new Error('start() failure: already started');\n }\n this.started = true;\n\n await this.createAudioMedia();\n\n // todo: create screen share audio remote media (SPARK-377812)\n // todo: create screen share video receive slot (SPARK-377812)\n\n await this.preallocateVideoReceiveSlots();\n\n await this.setLayout(this.config.video.initialLayoutId);\n }\n\n /**\n * Releases all the used resources (like allocated receive slots). This function needs\n * to be called when we leave the meeting, etc.\n */\n public stop() {\n // invalidate all remoteMedia objects\n this.invalidateCurrentRemoteMedia({audio: true, video: true, commit: true});\n\n // release all audio receive slots\n this.slots.audio.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.audio.length = 0;\n\n // todo: screenshare slots... (SPARK-377812)\n\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n\n this.slots.video.unused.push(...this.slots.video.receiverSelected);\n this.slots.video.receiverSelected.length = 0;\n\n this.releaseUnusedVideoSlots();\n\n this.currentLayout = undefined;\n this.currentLayoutId = undefined;\n this.started = false;\n }\n\n /**\n * Returns the total number of main video panes required for a given layout\n *\n * @param {VideoLayout} layout\n * @returns {number}\n */\n private getRequiredNumVideoSlotsForLayout(layout?: VideoLayout) {\n if (!layout) {\n return 0;\n }\n\n const activeSpeakerCount =\n layout.activeSpeakerVideoPaneGroups?.reduce(\n (sum, paneGroup) => sum + paneGroup.numPanes,\n 0\n ) || 0;\n\n const receiverSelectedCount = layout.memberVideoPanes?.length || 0;\n\n return activeSpeakerCount + receiverSelectedCount;\n }\n\n /**\n * Allocates the maximum number of panes that any of the configured layouts will require.\n * We do this at the beginning, because it's more efficient (much faster) then allocating receive slots\n * later, after the SDP exchange was done.\n */\n private async preallocateVideoReceiveSlots() {\n const maxNumVideoPanesRequired = Object.values(this.config.video.layouts).reduce(\n (maxValue, layout) => Math.max(maxValue, this.getRequiredNumVideoSlotsForLayout(layout)),\n 0\n );\n\n while (this.slots.video.unused.length < maxNumVideoPanesRequired) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n // eslint-disable-next-line no-await-in-loop\n await this.receiveSlotManager.allocateSlot(MC.MediaType.VideoMain)\n );\n }\n }\n\n /**\n * Changes the layout (triggers Event.VideoLayoutChanged)\n *\n * @param {LayoutId} layoutId new layout id\n * @returns {Promise}\n */\n public async setLayout(layoutId: LayoutId) {\n if (!(layoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid layoutId: \"${layoutId}\" doesn't match any of the configured layouts`\n );\n }\n if (!this.started) {\n throw new Error('setLayout() called before start()');\n }\n this.currentLayoutId = layoutId;\n this.currentLayout = cloneDeep(this.config.video.layouts[this.currentLayoutId]);\n\n await this.updateVideoReceiveSlots();\n this.updateVideoRemoteMediaObjects();\n this.emitVideoLayoutChangedEvent();\n }\n\n /**\n * Returns the currently selected layout id\n *\n * @returns {LayoutId}\n */\n public getLayoutId(): LayoutId | undefined {\n return this.currentLayoutId;\n }\n\n /**\n * Creates the audio slots\n */\n private async createAudioMedia() {\n // create the audio receive slots\n for (let i = 0; i < this.config.audio.numOfActiveSpeakerStreams; i += 1) {\n // eslint-disable-next-line no-await-in-loop\n const slot = await this.receiveSlotManager.allocateSlot(MC.MediaType.AudioMain);\n\n this.slots.audio.push(slot);\n }\n\n // create a remote media group\n this.media.audio = new RemoteMediaGroup(\n this.mediaRequestManagers.audio,\n this.slots.audio,\n 255,\n true\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createAudioMedia'},\n Event.AudioCreated,\n this.media.audio\n );\n }\n\n /**\n * Goes over all receiver-selected slots and keeps only the ones that are required by a given layout,\n * the rest are all moved to the \"unused\" list\n */\n private trimReceiverSelectedSlots() {\n const requiredCsis = {};\n\n // fill requiredCsis with all the CSIs that the given layout requires\n this.currentLayout?.memberVideoPanes?.forEach((memberVideoPane) => {\n if (memberVideoPane.csi !== undefined) {\n requiredCsis[memberVideoPane.csi] = true;\n }\n });\n\n const isCsiNeededByCurrentLayout = (csi?: CSI): boolean => {\n if (csi === undefined) {\n return false;\n }\n\n return !!requiredCsis[csi];\n };\n\n // keep receiverSelected slots that match our new requiredCsis, move the rest of receiverSelected slots to unused\n const notNeededReceiverSelectedSlots = remove(\n this.slots.video.receiverSelected,\n (slot) => isCsiNeededByCurrentLayout(slot.csi) === false\n );\n\n this.slots.video.unused.push(...notNeededReceiverSelectedSlots);\n }\n\n /**\n * Releases all the \"unused\" video slots.\n */\n private releaseUnusedVideoSlots() {\n this.slots.video.unused.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.video.unused.length = 0;\n }\n\n /**\n * Allocates receive slots to all video panes in the current selected layout\n */\n private allocateSlotsToVideoPaneGroups() {\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n this.currentLayout?.activeSpeakerVideoPaneGroups?.forEach((group) => {\n this.receiveSlotAllocations.activeSpeaker[group.id] = {slots: []};\n\n for (let paneIndex = 0; paneIndex < group.numPanes; paneIndex += 1) {\n // allocate a slot from the \"unused\" list\n const freeSlot = this.slots.video.unused.pop();\n\n if (freeSlot) {\n this.slots.video.activeSpeaker.push(freeSlot);\n this.receiveSlotAllocations.activeSpeaker[group.id].slots.push(freeSlot);\n }\n }\n });\n\n this.currentLayout?.memberVideoPanes?.forEach((memberPane) => {\n // check if there is existing slot for this csi\n const existingSlot = this.slots.video.receiverSelected.find(\n (slot) => slot.csi === memberPane.csi\n );\n\n const isExistingSlotAlreadyAllocated = Object.values(\n this.receiveSlotAllocations.receiverSelected\n ).includes(existingSlot);\n\n if (memberPane.csi !== undefined && existingSlot && !isExistingSlotAlreadyAllocated) {\n // found it, so use it\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = existingSlot;\n } else {\n // allocate a slot from the \"unused\" list\n const freeSlot = this.slots.video.unused.pop();\n\n if (freeSlot) {\n this.slots.video.receiverSelected.push(freeSlot);\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = freeSlot;\n }\n }\n });\n }\n\n /**\n * Makes sure we have the right number of receive slots created for the current layout\n * and allocates them to the right video panes / pane groups\n *\n * @returns {Promise}\n */\n private async updateVideoReceiveSlots() {\n const requiredNumSlots = this.getRequiredNumVideoSlotsForLayout(this.currentLayout);\n const totalNumSlots =\n this.slots.video.unused.length +\n this.slots.video.activeSpeaker.length +\n this.slots.video.receiverSelected.length;\n\n // ensure we have enough total slots for current layout\n if (totalNumSlots < requiredNumSlots) {\n let numSlotsToCreate = requiredNumSlots - totalNumSlots;\n\n while (numSlotsToCreate > 0) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n // eslint-disable-next-line no-await-in-loop\n await this.receiveSlotManager.allocateSlot(MC.MediaType.VideoMain)\n );\n numSlotsToCreate -= 1;\n }\n }\n\n // move all no longer needed receiver-selected slots to \"unused\"\n this.trimReceiverSelectedSlots();\n\n // move all active speaker slots to \"unused\"\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n\n // allocate the slots to the right panes / pane groups\n this.allocateSlotsToVideoPaneGroups();\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#updateVideoReceiveSlots --> receive slots updated: unused=${this.slots.video.unused.length}, activeSpeaker=${this.slots.video.activeSpeaker.length}, receiverSelected=${this.slots.video.receiverSelected.length}`\n );\n\n // If this is the initial layout, there may be some \"unused\" slots left because of the preallocation\n // done in this.preallocateVideoReceiveSlots(), so release them now\n this.releaseUnusedVideoSlots();\n }\n\n /**\n * Creates new RemoteMedia and RemoteMediaGroup objects for the current layout\n * and sends the media requests for all of them.\n */\n private updateVideoRemoteMediaObjects() {\n // invalidate all the previous remote media objects and cancel their media requests\n this.invalidateCurrentRemoteMedia({audio: false, video: true, commit: false});\n\n // create new remoteMediaGroup objects\n this.media.video.activeSpeakerGroups = {};\n this.media.video.memberPanes = {};\n\n for (const [groupId, group] of Object.entries(this.receiveSlotAllocations.activeSpeaker)) {\n const paneGroupInCurrentLayout = this.currentLayout?.activeSpeakerVideoPaneGroups?.find(\n (groupInLayout) => groupInLayout.id === groupId\n );\n\n if (paneGroupInCurrentLayout) {\n const mediaGroup = new RemoteMediaGroup(\n this.mediaRequestManagers.video,\n group.slots,\n paneGroupInCurrentLayout.priority,\n false,\n {\n preferLiveVideo: this.config.video.preferLiveVideo,\n resolution: paneGroupInCurrentLayout.size,\n }\n );\n\n this.media.video.activeSpeakerGroups[groupId] = mediaGroup;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a group id ${groupId} from this.receiveSlotAllocations.activeSpeaker cannot be found in the current layout configuration`\n );\n }\n }\n\n // create new remoteMedia objects\n for (const [paneId, slot] of Object.entries(this.receiveSlotAllocations.receiverSelected)) {\n const paneInCurrentLayout = this.currentLayout?.memberVideoPanes?.find(\n (paneInLayout) => paneInLayout.id === paneId\n );\n\n if (paneInCurrentLayout) {\n const remoteMedia = new RemoteMedia(slot, this.mediaRequestManagers.video, {\n resolution: paneInCurrentLayout.size,\n });\n\n if (paneInCurrentLayout.csi) {\n remoteMedia.sendMediaRequest(paneInCurrentLayout.csi, false);\n }\n\n this.media.video.memberPanes[paneId] = remoteMedia;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a pane id ${paneId} from this.receiveSlotAllocations.receiverSelected cannot be found in the current layout configuration`\n );\n }\n }\n // todo: screenshare (SPARK-377812)\n\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Invalidates all remote media objects belonging to currently selected layout\n */\n private invalidateCurrentRemoteMedia(options: {audio: boolean; video: boolean; commit: boolean}) {\n const {audio, video, commit} = options;\n\n if (audio && this.media.audio) {\n this.media.audio.stop(commit);\n }\n if (video) {\n Object.values(this.media.video.activeSpeakerGroups).forEach((remoteMediaGroup) => {\n remoteMediaGroup.stop(false);\n });\n Object.values(this.media.video.memberPanes).forEach((remoteMedia) => {\n remoteMedia.stop(false);\n });\n if (commit) {\n this.mediaRequestManagers.video.commit();\n }\n }\n }\n\n /** emits Event.VideoLayoutChanged */\n private emitVideoLayoutChangedEvent() {\n // todo: at this point the receive slots might still be showing a participant from previous layout, we should\n // wait for our media requests to be fullfilled, but there is no API for that right now (we could wait for source updates\n // but in some cases they might never come, or would need to always make sure to use a new set of receiver slots)\n // for now it's fine to have it like this, we will re-evaluate if it needs improving after more testing\n\n this.emit(\n {\n file: 'multistream/remoteMediaManager',\n function: 'emitVideoLayoutChangedEvent',\n },\n Event.VideoLayoutChanged,\n {\n layoutId: this.currentLayoutId,\n activeSpeakerVideoPanes: this.media.video.activeSpeakerGroups,\n memberVideoPanes: this.media.video.memberPanes,\n screenShareVideo: undefined, // todo: screen share (SPARK-377812)\n }\n );\n }\n\n /**\n * Sets a new CSI on a given remote media object\n *\n * @param {RemoteMedia} remoteMedia remote Media object to modify\n * @param {CSI} csi new CSI value, can be null if we want to stop receiving media\n */\n public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi: CSI | null) {\n if (!Object.values(this.media.video.memberPanes).includes(remoteMedia)) {\n throw new Error('remoteMedia not found');\n }\n\n if (csi) {\n remoteMedia.sendMediaRequest(csi, true);\n } else {\n remoteMedia.cancelMediaRequest(true);\n }\n }\n\n /**\n * Adds a new member video pane to the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {MemberVideoPane} newPane\n * @returns {Promise<RemoteMedia>}\n */\n public async addMemberVideoPane(newPane: MemberVideoPane): Promise<RemoteMedia> {\n if (!this.currentLayout) {\n throw new Error('There is no current layout selected, call start() first');\n }\n\n if (!this.currentLayout?.memberVideoPanes) {\n this.currentLayout.memberVideoPanes = [];\n }\n\n if (newPane.id in this.currentLayout.memberVideoPanes) {\n throw new Error(\n `duplicate pane id ${newPane.id} - this pane already exists in current layout's memberVideoPanes`\n );\n }\n\n this.currentLayout.memberVideoPanes.push(newPane);\n\n const receiveSlot = await this.receiveSlotManager.allocateSlot(MC.MediaType.VideoMain);\n\n this.slots.video.receiverSelected.push(receiveSlot);\n\n const remoteMedia = new RemoteMedia(receiveSlot, this.mediaRequestManagers.video, {\n resolution: newPane.size,\n });\n\n if (newPane.csi) {\n remoteMedia.sendMediaRequest(newPane.csi, true);\n }\n\n this.media.video.memberPanes[newPane.id] = remoteMedia;\n\n return remoteMedia;\n }\n\n /**\n * Removes a member video pane from the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {PaneId} paneId pane id of the pane to remove\n * @returns {Promise<void>}\n */\n public removeMemberVideoPane(paneId: PaneId): Promise<void> {\n if (!this.currentLayout) {\n return Promise.reject(new Error('There is no current layout selected, call start() first'));\n }\n\n if (!this.currentLayout.memberVideoPanes?.find((pane) => pane.id === paneId)) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in currentLayout.memberVideoPanes)`\n );\n\n return Promise.resolve();\n }\n\n if (!this.media.video.memberPanes[paneId]) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in this.media.video.memberPanes)`\n );\n\n return Promise.resolve();\n }\n\n const remoteMedia = this.media.video.memberPanes[paneId];\n\n const receiveSlot = remoteMedia.getUnderlyingReceiveSlot();\n\n if (receiveSlot) {\n this.receiveSlotManager.releaseSlot(receiveSlot);\n\n const index = this.slots.video.receiverSelected.indexOf(receiveSlot);\n\n if (index >= 0) {\n this.slots.video.receiverSelected.splice(index, 1);\n }\n }\n remoteMedia.stop();\n\n delete this.media.video.memberPanes[paneId];\n delete this.currentLayout.memberVideoPanes?.[paneId];\n\n return Promise.resolve();\n }\n\n /**\n * Pins an active speaker remote media object to the given CSI value. From that moment\n * onwards the remote media will only play audio/video from that specific CSI until\n * unpinActiveSpeakerVideoPane() is called or current layout is changed.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n * @param {CSI} csi CSI value to pin to, if undefined, then current CSI value is used\n */\n public pinActiveSpeakerVideoPane(remoteMedia: RemoteMedia, csi?: CSI): void {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'unpinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the unpinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.pin(remoteMedia, csi);\n }\n\n /**\n * Unpins a remote media object from the fixed CSI value it was pinned to.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n */\n public unpinActiveSpeakerVideoPane(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'pinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the pinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.unpin(remoteMedia);\n }\n\n /**\n * Returns true if a given remote media object belongs to an active speaker group and has been pinned.\n * Throws an error if the remote media object doesn't belong to any active speaker remote media group.\n *\n * @param {RemoteMedia} remoteMedia remote media object\n * @returns {boolean}\n */\n public isPinned(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia)\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among any remote media (pinned or unpinned) from any active speaker group'\n );\n }\n\n return remoteMediaGroup.isPinned(remoteMedia);\n }\n}\n"],"mappings":"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"}
@@ -37,14 +37,14 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
37
37
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
38
38
 
39
39
  /**
40
- * Meeting - network quality event
41
- * Emitted on each interval of retrieving stats Analyzer data
42
- * @event network:quality
43
- * @type {Object}
44
- * @property {string} mediaType {video|audio}
45
- * @property {number} networkQualityScore - value determined in determineUplinkNetworkQuality
46
- * @memberof NetworkQualityMonitor
47
- */
40
+ * Meeting - network quality event
41
+ * Emitted on each interval of retrieving stats Analyzer data
42
+ * @event network:quality
43
+ * @type {Object}
44
+ * @property {string} mediaType {video|audio}
45
+ * @property {number} networkQualityScore - value determined in determineUplinkNetworkQuality
46
+ * @memberof NetworkQualityMonitor
47
+ */
48
48
 
49
49
  /**
50
50
  * NetworkQualityMonitor class that will emit events based on detected quality
@@ -1 +1 @@
1
- {"version":3,"names":["NetworkQualityMonitor","config","indicatorTypes","PACKETLOSS","LATENCY","JITTER","frequencyTypes","UPLINK","DOWNLINK","networkQualityScore","networkQualityStatus","STATS","VIDEO_CORRELATE","AUDIO_CORRELATE","SHARE_CORRELATE","mediaType","emit","file","function","EVENT_TRIGGERS","NETWORK_QUALITY","emitNetworkQuality","remoteRtpResults","statsAnalyzerCurrentStats","roundTripTimeInMilliseconds","roundTripTime","jitterInMilliseconds","jitter","currentPacketLossRatio","send","determinePacketLoss","videoPacketLossRatioThreshold","determineLatency","rttThreshold","deterMineJitter","jitterThreshold","determineIfUndefined","value","acceptable","updateNetworkQualityStatus","EventsScope"],"sources":["index.ts"],"sourcesContent":["import EventsScope from '../common/events/events-scope';\nimport {EVENT_TRIGGERS, STATS} from '../constants';\n\n\n/**\n * Meeting - network quality event\n * Emitted on each interval of retrieving stats Analyzer data\n * @event network:quality\n * @type {Object}\n * @property {string} mediaType {video|audio}\n * @property {number} networkQualityScore - value determined in determineUplinkNetworkQuality\n * @memberof NetworkQualityMonitor\n */\n/**\n * NetworkQualityMonitor class that will emit events based on detected quality\n *\n * @class NetworkQualityMonitor\n * @extends {EventsScope}\n */\nexport default class NetworkQualityMonitor extends EventsScope {\n config: any;\n frequencyTypes: any;\n indicatorTypes: any;\n mediaType: any;\n networkQualityScore: any;\n networkQualityStatus: any;\n\n /**\n * Creates a new instance of NetworkQualityMonitor\n * @constructor\n * @public\n * @param {Object} config\n * @property {Object} indicatorTypes - network properties used to evaluate network quality used as constants\n * @property {Object} frequencyTypes - frequency properties used as constants {uplink|send} {downlink|receive}\n * @property {number} networkQualityScore - 0|1 1 is acceptable 0 is bad/unknown\n * @property {Object} networkQualityStatus - hash object based on indicatorTypes and frequencyTypes\n * @property {string} mediaType - audio|video\n */\n constructor(config: any) {\n super();\n this.config = config;\n this.indicatorTypes = Object.freeze({\n PACKETLOSS: 'packetLoss',\n LATENCY: 'latency',\n JITTER: 'jitter'\n });\n this.frequencyTypes = Object.freeze({\n UPLINK: 'uplink',\n DOWNLINK: 'downlink'\n });\n this.networkQualityScore = 1;\n this.networkQualityStatus = {\n [this.frequencyTypes.UPLINK]: {\n [STATS.VIDEO_CORRELATE]: {},\n [STATS.AUDIO_CORRELATE]: {},\n [STATS.SHARE_CORRELATE]: {}\n }\n };\n this.mediaType = null;\n }\n\n /**\n * emits NETWORK_QUALITY event on meeting with payload of media type and uplinkNetworkQuality score\n *\n * @memberof NetworkQualityMonitor\n * @returns {void}\n */\n emitNetworkQuality() {\n this.emit(\n {\n file: 'networkQualityMonitor',\n function: 'emitNetworkQuality'\n },\n EVENT_TRIGGERS.NETWORK_QUALITY,\n {\n mediaType: this.mediaType,\n networkQualityScore: this.networkQualityScore\n }\n );\n }\n\n /**\n * invokes emitNetworkQuality method resets values back to default\n * @returns {void}\n * @memberof NetworkQualityMonitor\n */\n updateNetworkQualityStatus() {\n this.emitNetworkQuality();\n\n // reset values\n this.networkQualityScore = 1;\n this.mediaType = null;\n }\n\n\n /**\n * filter data to determine uplink network quality, invoked on same interval as stats analyzer remote-inbout-rtp\n * @param {Object} configObj\n * @param {string} configObj.mediaType {audio|video}\n * @param {RTCStats} configObj.remoteRtpResults RTC stats remote obj\n * @param {Object} configObj.statsAnalyzerCurrentStats statsResults\n * @returns {void}\n * @public\n * @memberof NetworkQualityMonitor\n */\n public determineUplinkNetworkQuality({\n mediaType,\n remoteRtpResults,\n statsAnalyzerCurrentStats,\n }: {\n mediaType: string;\n remoteRtpResults: any;\n statsAnalyzerCurrentStats: object;\n }) {\n const roundTripTimeInMilliseconds = remoteRtpResults.roundTripTime * 1000;\n const jitterInMilliseconds = remoteRtpResults.jitter * 1000;\n const {currentPacketLossRatio} = statsAnalyzerCurrentStats[mediaType].send;\n\n this.mediaType = mediaType;\n\n const {JITTER, PACKETLOSS, LATENCY} = this.indicatorTypes;\n const {UPLINK} = this.frequencyTypes;\n\n /**\n * determines if packetLoss ratio is over threshold set in config\n * sets networkQualityScore to 0 if over threshold\n * @returns {boolean}\n */\n const determinePacketLoss = () => {\n if (currentPacketLossRatio >\n this.config.videoPacketLossRatioThreshold) {\n this.networkQualityScore = 0;\n\n return false;\n }\n\n return true;\n };\n\n /**\n * determines if round trip time value is over threshold set in config\n * sets networkQualityScore to 0 if over threshold\n * @returns {boolean}\n */\n const determineLatency = () => {\n if (roundTripTimeInMilliseconds > this.config.rttThreshold) {\n this.networkQualityScore = 0;\n\n return false;\n }\n\n return true;\n };\n\n /**\n * determines if jitter value is over threshold in config\n * sets networkQualityScore to 0 if over threshold\n * @returns {boolean}\n */\n const deterMineJitter = () => {\n if (jitterInMilliseconds > this.config.jitterThreshold) {\n this.networkQualityScore = 0;\n\n return false;\n }\n\n return true;\n };\n\n /**\n * returns null if val is specifically undefined\n * @param {(number|undefined)} value\n * @returns {(number|null)}\n */\n const determineIfUndefined = (value: number | undefined) => (typeof value === 'undefined' ? null : value);\n\n /**\n * Values for some browsers specifically Safari will be undefined we explicitly set to null\n * https://bugs.webkit.org/show_bug.cgi?id=206645\n * https://bugs.webkit.org/show_bug.cgi?id=212668\n */\n // PACKET LOSS\n this.networkQualityStatus[UPLINK][mediaType][PACKETLOSS] = {\n acceptable: determinePacketLoss(),\n value: determineIfUndefined(currentPacketLossRatio)\n };\n\n\n // LATENCY measured in Round trip time\n this.networkQualityStatus[UPLINK][mediaType][LATENCY] = {\n acceptable: determineLatency(),\n value: determineIfUndefined(remoteRtpResults.roundTripTime)\n };\n\n // JITTER\n this.networkQualityStatus[UPLINK][mediaType][JITTER] = {\n acceptable: deterMineJitter(),\n value: determineIfUndefined(remoteRtpResults.jitter)\n };\n\n this.updateNetworkQualityStatus();\n }\n\n /**\n * Get the current status of network quaility object - networkQualityStatus\n * @returns {Object}\n * @public\n */\n get networkQualityStats() {\n const {UPLINK} = this.frequencyTypes;\n\n return this.networkQualityStatus[UPLINK];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;;;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA;AACA;AACA;AACA;AACA;AACA;IACqBA,qB;;;;;EAQnB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,+BAAYC,MAAZ,EAAyB;IAAA;;IAAA;;IAAA;IACvB;IADuB;IAAA;IAAA;IAAA;IAAA;IAAA;IAEvB,MAAKA,MAAL,GAAcA,MAAd;IACA,MAAKC,cAAL,GAAsB,qBAAc;MAClCC,UAAU,EAAE,YADsB;MAElCC,OAAO,EAAE,SAFyB;MAGlCC,MAAM,EAAE;IAH0B,CAAd,CAAtB;IAKA,MAAKC,cAAL,GAAsB,qBAAc;MAClCC,MAAM,EAAE,QAD0B;MAElCC,QAAQ,EAAE;IAFwB,CAAd,CAAtB;IAIA,MAAKC,mBAAL,GAA2B,CAA3B;IACA,MAAKC,oBAAL,qCACG,MAAKJ,cAAL,CAAoBC,MADvB,oFAEKI,gBAAA,CAAMC,eAFX,EAE6B,EAF7B,wDAGKD,gBAAA,CAAME,eAHX,EAG6B,EAH7B,wDAIKF,gBAAA,CAAMG,eAJX,EAI6B,EAJ7B;IAOA,MAAKC,SAAL,GAAiB,IAAjB;IApBuB;EAqBxB;EAED;AACF;AACA;AACA;AACA;AACA;;;;;WACE,8BAAqB;MACnB,KAAKC,IAAL,CACE;QACEC,IAAI,EAAE,uBADR;QAEEC,QAAQ,EAAE;MAFZ,CADF,EAKEC,yBAAA,CAAeC,eALjB,EAME;QACEL,SAAS,EAAE,KAAKA,SADlB;QAEEN,mBAAmB,EAAE,KAAKA;MAF5B,CANF;IAWD;IAED;AACF;AACA;AACA;AACA;;;;WACE,sCAA6B;MAC3B,KAAKY,kBAAL,GAD2B,CAG3B;;MACA,KAAKZ,mBAAL,GAA2B,CAA3B;MACA,KAAKM,SAAL,GAAiB,IAAjB;IACD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,6CAQG;MAAA;;MAAA,IAPDA,SAOC,QAPDA,SAOC;MAAA,IANDO,gBAMC,QANDA,gBAMC;MAAA,IALDC,yBAKC,QALDA,yBAKC;MACD,IAAMC,2BAA2B,GAAGF,gBAAgB,CAACG,aAAjB,GAAiC,IAArE;MACA,IAAMC,oBAAoB,GAAGJ,gBAAgB,CAACK,MAAjB,GAA0B,IAAvD;MACA,IAAOC,sBAAP,GAAiCL,yBAAyB,CAACR,SAAD,CAAzB,CAAqCc,IAAtE,CAAOD,sBAAP;MAEA,KAAKb,SAAL,GAAiBA,SAAjB;MAEA,2BAAsC,KAAKb,cAA3C;MAAA,IAAOG,MAAP,wBAAOA,MAAP;MAAA,IAAeF,UAAf,wBAAeA,UAAf;MAAA,IAA2BC,OAA3B,wBAA2BA,OAA3B;MACA,IAAOG,MAAP,GAAiB,KAAKD,cAAtB,CAAOC,MAAP;MAEA;AACJ;AACA;AACA;AACA;;MACI,IAAMuB,mBAAmB,GAAG,SAAtBA,mBAAsB,GAAM;QAChC,IAAIF,sBAAsB,GACxB,MAAI,CAAC3B,MAAL,CAAY8B,6BADd,EAC6C;UAC3C,MAAI,CAACtB,mBAAL,GAA2B,CAA3B;UAEA,OAAO,KAAP;QACD;;QAED,OAAO,IAAP;MACD,CATD;MAWA;AACJ;AACA;AACA;AACA;;;MACI,IAAMuB,gBAAgB,GAAG,SAAnBA,gBAAmB,GAAM;QAC7B,IAAIR,2BAA2B,GAAG,MAAI,CAACvB,MAAL,CAAYgC,YAA9C,EAA4D;UAC1D,MAAI,CAACxB,mBAAL,GAA2B,CAA3B;UAEA,OAAO,KAAP;QACD;;QAED,OAAO,IAAP;MACD,CARD;MAUA;AACJ;AACA;AACA;AACA;;;MACI,IAAMyB,eAAe,GAAG,SAAlBA,eAAkB,GAAM;QAC5B,IAAIR,oBAAoB,GAAG,MAAI,CAACzB,MAAL,CAAYkC,eAAvC,EAAwD;UACtD,MAAI,CAAC1B,mBAAL,GAA2B,CAA3B;UAEA,OAAO,KAAP;QACD;;QAED,OAAO,IAAP;MACD,CARD;MAUA;AACJ;AACA;AACA;AACA;;;MACI,IAAM2B,oBAAoB,GAAG,SAAvBA,oBAAuB,CAACC,KAAD;QAAA,OAAgC,OAAOA,KAAP,KAAiB,WAAjB,GAA+B,IAA/B,GAAsCA,KAAtE;MAAA,CAA7B;MAEA;AACJ;AACA;AACA;AACA;MACI;;;MACA,KAAK3B,oBAAL,CAA0BH,MAA1B,EAAkCQ,SAAlC,EAA6CZ,UAA7C,IAA2D;QACzDmC,UAAU,EAAER,mBAAmB,EAD0B;QAEzDO,KAAK,EAAED,oBAAoB,CAACR,sBAAD;MAF8B,CAA3D,CArEC,CA2ED;;MACA,KAAKlB,oBAAL,CAA0BH,MAA1B,EAAkCQ,SAAlC,EAA6CX,OAA7C,IAAwD;QACtDkC,UAAU,EAAEN,gBAAgB,EAD0B;QAEtDK,KAAK,EAAED,oBAAoB,CAACd,gBAAgB,CAACG,aAAlB;MAF2B,CAAxD,CA5EC,CAiFD;;MACA,KAAKf,oBAAL,CAA0BH,MAA1B,EAAkCQ,SAAlC,EAA6CV,MAA7C,IAAuD;QACrDiC,UAAU,EAAEJ,eAAe,EAD0B;QAErDG,KAAK,EAAED,oBAAoB,CAACd,gBAAgB,CAACK,MAAlB;MAF0B,CAAvD;MAKA,KAAKY,0BAAL;IACD;IAED;AACF;AACA;AACA;AACA;;;;SACE,eAA0B;MACxB,IAAOhC,MAAP,GAAiB,KAAKD,cAAtB,CAAOC,MAAP;MAEA,OAAO,KAAKG,oBAAL,CAA0BH,MAA1B,CAAP;IACD;;;EAjMgDiC,oB"}
1
+ {"version":3,"names":["NetworkQualityMonitor","config","indicatorTypes","PACKETLOSS","LATENCY","JITTER","frequencyTypes","UPLINK","DOWNLINK","networkQualityScore","networkQualityStatus","STATS","VIDEO_CORRELATE","AUDIO_CORRELATE","SHARE_CORRELATE","mediaType","emit","file","function","EVENT_TRIGGERS","NETWORK_QUALITY","emitNetworkQuality","remoteRtpResults","statsAnalyzerCurrentStats","roundTripTimeInMilliseconds","roundTripTime","jitterInMilliseconds","jitter","currentPacketLossRatio","send","determinePacketLoss","videoPacketLossRatioThreshold","determineLatency","rttThreshold","deterMineJitter","jitterThreshold","determineIfUndefined","value","acceptable","updateNetworkQualityStatus","EventsScope"],"sources":["index.ts"],"sourcesContent":["import EventsScope from '../common/events/events-scope';\nimport {EVENT_TRIGGERS, STATS} from '../constants';\n\n/**\n * Meeting - network quality event\n * Emitted on each interval of retrieving stats Analyzer data\n * @event network:quality\n * @type {Object}\n * @property {string} mediaType {video|audio}\n * @property {number} networkQualityScore - value determined in determineUplinkNetworkQuality\n * @memberof NetworkQualityMonitor\n */\n/**\n * NetworkQualityMonitor class that will emit events based on detected quality\n *\n * @class NetworkQualityMonitor\n * @extends {EventsScope}\n */\nexport default class NetworkQualityMonitor extends EventsScope {\n config: any;\n frequencyTypes: any;\n indicatorTypes: any;\n mediaType: any;\n networkQualityScore: any;\n networkQualityStatus: any;\n\n /**\n * Creates a new instance of NetworkQualityMonitor\n * @constructor\n * @public\n * @param {Object} config\n * @property {Object} indicatorTypes - network properties used to evaluate network quality used as constants\n * @property {Object} frequencyTypes - frequency properties used as constants {uplink|send} {downlink|receive}\n * @property {number} networkQualityScore - 0|1 1 is acceptable 0 is bad/unknown\n * @property {Object} networkQualityStatus - hash object based on indicatorTypes and frequencyTypes\n * @property {string} mediaType - audio|video\n */\n constructor(config: any) {\n super();\n this.config = config;\n this.indicatorTypes = Object.freeze({\n PACKETLOSS: 'packetLoss',\n LATENCY: 'latency',\n JITTER: 'jitter',\n });\n this.frequencyTypes = Object.freeze({\n UPLINK: 'uplink',\n DOWNLINK: 'downlink',\n });\n this.networkQualityScore = 1;\n this.networkQualityStatus = {\n [this.frequencyTypes.UPLINK]: {\n [STATS.VIDEO_CORRELATE]: {},\n [STATS.AUDIO_CORRELATE]: {},\n [STATS.SHARE_CORRELATE]: {},\n },\n };\n this.mediaType = null;\n }\n\n /**\n * emits NETWORK_QUALITY event on meeting with payload of media type and uplinkNetworkQuality score\n *\n * @memberof NetworkQualityMonitor\n * @returns {void}\n */\n emitNetworkQuality() {\n this.emit(\n {\n file: 'networkQualityMonitor',\n function: 'emitNetworkQuality',\n },\n EVENT_TRIGGERS.NETWORK_QUALITY,\n {\n mediaType: this.mediaType,\n networkQualityScore: this.networkQualityScore,\n }\n );\n }\n\n /**\n * invokes emitNetworkQuality method resets values back to default\n * @returns {void}\n * @memberof NetworkQualityMonitor\n */\n updateNetworkQualityStatus() {\n this.emitNetworkQuality();\n\n // reset values\n this.networkQualityScore = 1;\n this.mediaType = null;\n }\n\n /**\n * filter data to determine uplink network quality, invoked on same interval as stats analyzer remote-inbout-rtp\n * @param {Object} configObj\n * @param {string} configObj.mediaType {audio|video}\n * @param {RTCStats} configObj.remoteRtpResults RTC stats remote obj\n * @param {Object} configObj.statsAnalyzerCurrentStats statsResults\n * @returns {void}\n * @public\n * @memberof NetworkQualityMonitor\n */\n public determineUplinkNetworkQuality({\n mediaType,\n remoteRtpResults,\n statsAnalyzerCurrentStats,\n }: {\n mediaType: string;\n remoteRtpResults: any;\n statsAnalyzerCurrentStats: object;\n }) {\n const roundTripTimeInMilliseconds = remoteRtpResults.roundTripTime * 1000;\n const jitterInMilliseconds = remoteRtpResults.jitter * 1000;\n const {currentPacketLossRatio} = statsAnalyzerCurrentStats[mediaType].send;\n\n this.mediaType = mediaType;\n\n const {JITTER, PACKETLOSS, LATENCY} = this.indicatorTypes;\n const {UPLINK} = this.frequencyTypes;\n\n /**\n * determines if packetLoss ratio is over threshold set in config\n * sets networkQualityScore to 0 if over threshold\n * @returns {boolean}\n */\n const determinePacketLoss = () => {\n if (currentPacketLossRatio > this.config.videoPacketLossRatioThreshold) {\n this.networkQualityScore = 0;\n\n return false;\n }\n\n return true;\n };\n\n /**\n * determines if round trip time value is over threshold set in config\n * sets networkQualityScore to 0 if over threshold\n * @returns {boolean}\n */\n const determineLatency = () => {\n if (roundTripTimeInMilliseconds > this.config.rttThreshold) {\n this.networkQualityScore = 0;\n\n return false;\n }\n\n return true;\n };\n\n /**\n * determines if jitter value is over threshold in config\n * sets networkQualityScore to 0 if over threshold\n * @returns {boolean}\n */\n const deterMineJitter = () => {\n if (jitterInMilliseconds > this.config.jitterThreshold) {\n this.networkQualityScore = 0;\n\n return false;\n }\n\n return true;\n };\n\n /**\n * returns null if val is specifically undefined\n * @param {(number|undefined)} value\n * @returns {(number|null)}\n */\n const determineIfUndefined = (value: number | undefined) =>\n typeof value === 'undefined' ? null : value;\n\n /**\n * Values for some browsers specifically Safari will be undefined we explicitly set to null\n * https://bugs.webkit.org/show_bug.cgi?id=206645\n * https://bugs.webkit.org/show_bug.cgi?id=212668\n */\n // PACKET LOSS\n this.networkQualityStatus[UPLINK][mediaType][PACKETLOSS] = {\n acceptable: determinePacketLoss(),\n value: determineIfUndefined(currentPacketLossRatio),\n };\n\n // LATENCY measured in Round trip time\n this.networkQualityStatus[UPLINK][mediaType][LATENCY] = {\n acceptable: determineLatency(),\n value: determineIfUndefined(remoteRtpResults.roundTripTime),\n };\n\n // JITTER\n this.networkQualityStatus[UPLINK][mediaType][JITTER] = {\n acceptable: deterMineJitter(),\n value: determineIfUndefined(remoteRtpResults.jitter),\n };\n\n this.updateNetworkQualityStatus();\n }\n\n /**\n * Get the current status of network quaility object - networkQualityStatus\n * @returns {Object}\n * @public\n */\n get networkQualityStats() {\n const {UPLINK} = this.frequencyTypes;\n\n return this.networkQualityStatus[UPLINK];\n }\n}\n"],"mappings":"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"}
@@ -64,7 +64,7 @@ var PersonalMeetingRoom = /*#__PURE__*/function (_StatelessWebexPlugin) {
64
64
  * @type {Object}
65
65
  * @public
66
66
  * @memberof PersonalMeetingRoom
67
- */
67
+ */
68
68
 
69
69
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "link", void 0);
70
70
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "meetingInfo", void 0);
@@ -83,7 +83,7 @@ var PersonalMeetingRoom = /*#__PURE__*/function (_StatelessWebexPlugin) {
83
83
  * @type {String}
84
84
  * @public
85
85
  * @memberof PersonalMeetingRoom
86
- */
86
+ */
87
87
 
88
88
  _this.sipUri = null;
89
89
  /**
@@ -92,7 +92,7 @@ var PersonalMeetingRoom = /*#__PURE__*/function (_StatelessWebexPlugin) {
92
92
  * @type {String}
93
93
  * @public
94
94
  * @memberof PersonalMeetingRoom
95
- */
95
+ */
96
96
 
97
97
  _this.link = null;
98
98
  /**
@@ -101,7 +101,7 @@ var PersonalMeetingRoom = /*#__PURE__*/function (_StatelessWebexPlugin) {
101
101
  * @type {Object}
102
102
  * @public
103
103
  * @memberof PersonalMeetingRoom
104
- */
104
+ */
105
105
 
106
106
  _this.userId = null;
107
107
  /**
@@ -110,7 +110,7 @@ var PersonalMeetingRoom = /*#__PURE__*/function (_StatelessWebexPlugin) {
110
110
  * @type {String}
111
111
  * @public
112
112
  * @memberof PersonalMeetingRoom
113
- */
113
+ */
114
114
 
115
115
  _this.name = null;
116
116
  /**
@@ -119,7 +119,7 @@ var PersonalMeetingRoom = /*#__PURE__*/function (_StatelessWebexPlugin) {
119
119
  * @type {MeetingInfo}
120
120
  * @private
121
121
  * @memberof PersonalMeetingRoom
122
- */
122
+ */
123
123
 
124
124
  _this.meetingInfo = attrs.meetingInfo;
125
125
  /**
@@ -128,7 +128,7 @@ var PersonalMeetingRoom = /*#__PURE__*/function (_StatelessWebexPlugin) {
128
128
  * @type {Object}
129
129
  * @private
130
130
  * @memberof PersonalMeetingRoom
131
- */
131
+ */
132
132
  // @ts-ignore
133
133
 
134
134
  _this.personalMeetingRoomRequest = new _request.default({}, options);
@@ -1 +1 @@
1
- {"version":3,"names":["PersonalMeetingRoom","attrs","options","MEETINGS","pmr","sipUri","link","userId","name","meetingInfo","personalMeetingRoomRequest","PersonalMeetingRoomRequest","pin","preferred","webex","internal","device","passcode","meetingAddress","claimPmr","then","body","set","reject","ParameterError","sipMeetingUri","meetingLink","webExMeetingLink","owner","meetingName","number","meetingNumber","type","_PERSONAL_ROOM_","fetchMeetingInfo","isPmr","TypeError","StatelessWebexPlugin"],"sources":["index.ts"],"sourcesContent":["// @ts-ignore\nimport {StatelessWebexPlugin} from '@webex/webex-core';\n\nimport {MEETINGS, _PERSONAL_ROOM_} from '../constants';\nimport ParameterError from '../common/errors/parameter';\n\nimport PersonalMeetingRoomRequest from './request';\n\n\n/**\n * @class PersonalMeetingRoom\n */\nexport default class PersonalMeetingRoom extends StatelessWebexPlugin {\n link: any;\n meetingInfo: any;\n name: any;\n personalMeetingRoomRequest: any;\n pmr: any;\n sipUri: any;\n userId: any;\n meetingLink: any;\n number: any;\n\n namespace = MEETINGS;\n\n /**\n *\n * @param {Object} attrs\n * @param {Object} options\n */\n constructor(attrs: any, options: any) {\n super({}, options);\n /**\n * The pmr server object\n * @instance\n * @type {Object}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.pmr = null;\n /**\n * The pmr sip Uri\n * @instance\n * @type {String}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.sipUri = null;\n /**\n * The pmr link\n * @instance\n * @type {String}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.link = null;\n /**\n * The pmr server object\n * @instance\n * @type {Object}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.userId = null;\n /**\n * The pmr name\n * @instance\n * @type {String}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.name = null;\n /**\n * The meeting info request server interface\n * @instance\n * @type {MeetingInfo}\n * @private\n * @memberof PersonalMeetingRoom\n */\n this.meetingInfo = attrs.meetingInfo;\n /**\n * The pmr server request interface\n * @instance\n * @type {Object}\n * @private\n * @memberof PersonalMeetingRoom\n */\n // @ts-ignore\n this.personalMeetingRoomRequest = new PersonalMeetingRoomRequest({}, options);\n }\n\n /**\n * claims a pmr and updates the cached PMR values\n * @param {String} link\n * @param {String} pin\n * @param {Boolean} [preferred] defaults to true to set this claimed PMR as the preferred\n * @returns {Promise}\n * @public\n * @memberof PersonalMeetingRoom\n */\n public claim(link: string, pin: string, preferred: boolean = true) {\n const options = {\n // @ts-ignore\n userId: this.webex.internal.device.userId,\n passcode: pin,\n meetingAddress: link,\n preferred\n };\n\n return this.personalMeetingRoomRequest.claimPmr(options).then((pmr) => {\n if (pmr && pmr.body) {\n this.set(pmr.body);\n }\n else {\n return Promise.reject(new ParameterError('No PMR body provided. PMR values not updated.'));\n }\n\n return pmr.body;\n });\n }\n\n /**\n * @param {Object} body the response body from meeting info request\n * @returns {undefined}\n * @private\n * @memberof PersonalMeetingRoom\n */\n private set(body: any) {\n this.pmr = body;\n this.sipUri = body.sipMeetingUri;\n this.meetingLink = body.webExMeetingLink || body.meetingLink;\n this.userId = body.owner;\n this.name = body.meetingName;\n this.number = body.meetingNumber;\n }\n\n /**\n * TODO: implement TTL for syncing and caching so to not request again and again\n * @param {Object} options\n * @returns {Promise}\n * @public\n * @memberof PersonalMeetingRoom\n */\n public get() {\n const options = {\n type: _PERSONAL_ROOM_\n\n };\n\n return this.meetingInfo.fetchMeetingInfo(options).then((pmr) => {\n if (pmr && pmr.body && pmr.body.isPmr) {\n this.set(pmr.body);\n }\n else {\n return Promise.reject(new TypeError('The PMR requested is NOT a PMR. PMR values not set.'));\n }\n\n return pmr.body;\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["PersonalMeetingRoom","attrs","options","MEETINGS","pmr","sipUri","link","userId","name","meetingInfo","personalMeetingRoomRequest","PersonalMeetingRoomRequest","pin","preferred","webex","internal","device","passcode","meetingAddress","claimPmr","then","body","set","reject","ParameterError","sipMeetingUri","meetingLink","webExMeetingLink","owner","meetingName","number","meetingNumber","type","_PERSONAL_ROOM_","fetchMeetingInfo","isPmr","TypeError","StatelessWebexPlugin"],"sources":["index.ts"],"sourcesContent":["// @ts-ignore\nimport {StatelessWebexPlugin} from '@webex/webex-core';\n\nimport {MEETINGS, _PERSONAL_ROOM_} from '../constants';\nimport ParameterError from '../common/errors/parameter';\n\nimport PersonalMeetingRoomRequest from './request';\n\n/**\n * @class PersonalMeetingRoom\n */\nexport default class PersonalMeetingRoom extends StatelessWebexPlugin {\n link: any;\n meetingInfo: any;\n name: any;\n personalMeetingRoomRequest: any;\n pmr: any;\n sipUri: any;\n userId: any;\n meetingLink: any;\n number: any;\n\n namespace = MEETINGS;\n\n /**\n *\n * @param {Object} attrs\n * @param {Object} options\n */\n constructor(attrs: any, options: any) {\n super({}, options);\n /**\n * The pmr server object\n * @instance\n * @type {Object}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.pmr = null;\n /**\n * The pmr sip Uri\n * @instance\n * @type {String}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.sipUri = null;\n /**\n * The pmr link\n * @instance\n * @type {String}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.link = null;\n /**\n * The pmr server object\n * @instance\n * @type {Object}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.userId = null;\n /**\n * The pmr name\n * @instance\n * @type {String}\n * @public\n * @memberof PersonalMeetingRoom\n */\n this.name = null;\n /**\n * The meeting info request server interface\n * @instance\n * @type {MeetingInfo}\n * @private\n * @memberof PersonalMeetingRoom\n */\n this.meetingInfo = attrs.meetingInfo;\n /**\n * The pmr server request interface\n * @instance\n * @type {Object}\n * @private\n * @memberof PersonalMeetingRoom\n */\n // @ts-ignore\n this.personalMeetingRoomRequest = new PersonalMeetingRoomRequest({}, options);\n }\n\n /**\n * claims a pmr and updates the cached PMR values\n * @param {String} link\n * @param {String} pin\n * @param {Boolean} [preferred] defaults to true to set this claimed PMR as the preferred\n * @returns {Promise}\n * @public\n * @memberof PersonalMeetingRoom\n */\n public claim(link: string, pin: string, preferred = true) {\n const options = {\n // @ts-ignore\n userId: this.webex.internal.device.userId,\n passcode: pin,\n meetingAddress: link,\n preferred,\n };\n\n return this.personalMeetingRoomRequest.claimPmr(options).then((pmr) => {\n if (pmr && pmr.body) {\n this.set(pmr.body);\n } else {\n return Promise.reject(new ParameterError('No PMR body provided. PMR values not updated.'));\n }\n\n return pmr.body;\n });\n }\n\n /**\n * @param {Object} body the response body from meeting info request\n * @returns {undefined}\n * @private\n * @memberof PersonalMeetingRoom\n */\n private set(body: any) {\n this.pmr = body;\n this.sipUri = body.sipMeetingUri;\n this.meetingLink = body.webExMeetingLink || body.meetingLink;\n this.userId = body.owner;\n this.name = body.meetingName;\n this.number = body.meetingNumber;\n }\n\n /**\n * TODO: implement TTL for syncing and caching so to not request again and again\n * @param {Object} options\n * @returns {Promise}\n * @public\n * @memberof PersonalMeetingRoom\n */\n public get() {\n const options = {\n type: _PERSONAL_ROOM_,\n };\n\n return this.meetingInfo.fetchMeetingInfo(options).then((pmr) => {\n if (pmr && pmr.body && pmr.body.isPmr) {\n this.set(pmr.body);\n } else {\n return Promise.reject(new TypeError('The PMR requested is NOT a PMR. PMR values not set.'));\n }\n\n return pmr.body;\n });\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"names":["PersonalMeetingRoomRequest","MEETINGS","options","userId","passcode","meetingAddress","preferred","ParameterError","validPin","PersonalMeetingRoomUtil","getClaimPmrPin","reject","validLink","getClaimPmrLink","request","getClaimedRequestParams","StatelessWebexPlugin"],"sources":["request.ts"],"sourcesContent":["// @ts-ignore\nimport {StatelessWebexPlugin} from '@webex/webex-core';\n\nimport {MEETINGS} from '../constants';\nimport ParameterError from '../common/errors/parameter';\n\nimport PersonalMeetingRoomUtil from './util';\n\n\n/**\n * @class MeetingInfoRequest\n */\nexport default class PersonalMeetingRoomRequest extends StatelessWebexPlugin {\n namespace = MEETINGS;\n\n /**\n *\n * @param {Object} options with format of {userId, passcode, meetingAddress, preferred}\n * @returns {Promise} returns a promise that resolves/rejects the result of the request\n * @memberof PersonalMeetingRoomRequest\n */\n claimPmr(options: any) {\n if (!options || !options.userId || !options.passcode || !options.meetingAddress || !options.preferred) {\n throw new ParameterError('Claiming a PMR should be done with userId, passcode, preferred, and meetingAddress in options.');\n }\n const validPin = PersonalMeetingRoomUtil.getClaimPmrPin(options.passcode);\n\n if (!validPin) {\n return Promise.reject(new ParameterError('The host pin provided was of an invalid format'));\n }\n const validLink = PersonalMeetingRoomUtil.getClaimPmrLink(options.meetingAddress);\n\n if (!validLink) {\n return Promise.reject(new ParameterError('The PMR link provided was of an invalid format'));\n }\n const request = PersonalMeetingRoomUtil.getClaimedRequestParams(validLink, validPin, options);\n\n // @ts-ignore\n return this.request(request);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;;AAEA;;AACA;;AAEA;;;;;;AAGA;AACA;AACA;IACqBA,0B;;;;;;;;;;;;;;;4FACPC,mB;;;;;;;IAEZ;AACF;AACA;AACA;AACA;AACA;IACE,kBAASC,OAAT,EAAuB;MACrB,IAAI,CAACA,OAAD,IAAY,CAACA,OAAO,CAACC,MAArB,IAA+B,CAACD,OAAO,CAACE,QAAxC,IAAoD,CAACF,OAAO,CAACG,cAA7D,IAA+E,CAACH,OAAO,CAACI,SAA5F,EAAuG;QACrG,MAAM,IAAIC,kBAAJ,CAAmB,gGAAnB,CAAN;MACD;;MACD,IAAMC,QAAQ,GAAGC,aAAA,CAAwBC,cAAxB,CAAuCR,OAAO,CAACE,QAA/C,CAAjB;;MAEA,IAAI,CAACI,QAAL,EAAe;QACb,OAAO,iBAAQG,MAAR,CAAe,IAAIJ,kBAAJ,CAAmB,gDAAnB,CAAf,CAAP;MACD;;MACD,IAAMK,SAAS,GAAGH,aAAA,CAAwBI,eAAxB,CAAwCX,OAAO,CAACG,cAAhD,CAAlB;;MAEA,IAAI,CAACO,SAAL,EAAgB;QACd,OAAO,iBAAQD,MAAR,CAAe,IAAIJ,kBAAJ,CAAmB,gDAAnB,CAAf,CAAP;MACD;;MACD,IAAMO,OAAO,GAAGL,aAAA,CAAwBM,uBAAxB,CAAgDH,SAAhD,EAA2DJ,QAA3D,EAAqEN,OAArE,CAAhB,CAdqB,CAgBrB;;;MACA,OAAO,KAAKY,OAAL,CAAaA,OAAb,CAAP;IACD;;;EA3BqDE,+B"}
1
+ {"version":3,"names":["PersonalMeetingRoomRequest","MEETINGS","options","userId","passcode","meetingAddress","preferred","ParameterError","validPin","PersonalMeetingRoomUtil","getClaimPmrPin","reject","validLink","getClaimPmrLink","request","getClaimedRequestParams","StatelessWebexPlugin"],"sources":["request.ts"],"sourcesContent":["// @ts-ignore\nimport {StatelessWebexPlugin} from '@webex/webex-core';\n\nimport {MEETINGS} from '../constants';\nimport ParameterError from '../common/errors/parameter';\n\nimport PersonalMeetingRoomUtil from './util';\n\n/**\n * @class MeetingInfoRequest\n */\nexport default class PersonalMeetingRoomRequest extends StatelessWebexPlugin {\n namespace = MEETINGS;\n\n /**\n *\n * @param {Object} options with format of {userId, passcode, meetingAddress, preferred}\n * @returns {Promise} returns a promise that resolves/rejects the result of the request\n * @memberof PersonalMeetingRoomRequest\n */\n claimPmr(options: any) {\n if (\n !options ||\n !options.userId ||\n !options.passcode ||\n !options.meetingAddress ||\n !options.preferred\n ) {\n throw new ParameterError(\n 'Claiming a PMR should be done with userId, passcode, preferred, and meetingAddress in options.'\n );\n }\n const validPin = PersonalMeetingRoomUtil.getClaimPmrPin(options.passcode);\n\n if (!validPin) {\n return Promise.reject(new ParameterError('The host pin provided was of an invalid format'));\n }\n const validLink = PersonalMeetingRoomUtil.getClaimPmrLink(options.meetingAddress);\n\n if (!validLink) {\n return Promise.reject(new ParameterError('The PMR link provided was of an invalid format'));\n }\n const request = PersonalMeetingRoomUtil.getClaimedRequestParams(validLink, validPin, options);\n\n // @ts-ignore\n return this.request(request);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;;AAEA;;AACA;;AAEA;;;;;;AAEA;AACA;AACA;IACqBA,0B;;;;;;;;;;;;;;;4FACPC,mB;;;;;;;IAEZ;AACF;AACA;AACA;AACA;AACA;IACE,kBAASC,OAAT,EAAuB;MACrB,IACE,CAACA,OAAD,IACA,CAACA,OAAO,CAACC,MADT,IAEA,CAACD,OAAO,CAACE,QAFT,IAGA,CAACF,OAAO,CAACG,cAHT,IAIA,CAACH,OAAO,CAACI,SALX,EAME;QACA,MAAM,IAAIC,kBAAJ,CACJ,gGADI,CAAN;MAGD;;MACD,IAAMC,QAAQ,GAAGC,aAAA,CAAwBC,cAAxB,CAAuCR,OAAO,CAACE,QAA/C,CAAjB;;MAEA,IAAI,CAACI,QAAL,EAAe;QACb,OAAO,iBAAQG,MAAR,CAAe,IAAIJ,kBAAJ,CAAmB,gDAAnB,CAAf,CAAP;MACD;;MACD,IAAMK,SAAS,GAAGH,aAAA,CAAwBI,eAAxB,CAAwCX,OAAO,CAACG,cAAhD,CAAlB;;MAEA,IAAI,CAACO,SAAL,EAAgB;QACd,OAAO,iBAAQD,MAAR,CAAe,IAAIJ,kBAAJ,CAAmB,gDAAnB,CAAf,CAAP;MACD;;MACD,IAAMO,OAAO,GAAGL,aAAA,CAAwBM,uBAAxB,CAAgDH,SAAhD,EAA2DJ,QAA3D,EAAqEN,OAArE,CAAhB,CAtBqB,CAwBrB;;;MACA,OAAO,KAAKY,OAAL,CAAaA,OAAb,CAAP;IACD;;;EAnCqDE,+B"}
@@ -1 +1 @@
1
- {"version":3,"names":["PersonalMeetingRoomUtil","getClaimPmrLink","pmrLink","validator","VALID_PMR_ADDRESS","test","match","VALID_PMR_LINK","WEBEX_DOT_COM","getClaimPmrPin","hostPin","VALID_PIN","getClaimedRequestParams","link","pin","options","method","HTTP_VERBS","POST","api","HECATE","resource","CMR_MEETINGS","CLAIM","body","userId","passcode","preferred","meetingAddress"],"sources":["util.ts"],"sourcesContent":["import {\n HTTP_VERBS,\n VALID_PIN,\n VALID_PMR_ADDRESS,\n VALID_PMR_LINK,\n CMR_MEETINGS,\n CLAIM,\n HECATE,\n WEBEX_DOT_COM\n} from '../constants';\n\nconst PersonalMeetingRoomUtil: any = {};\n\nPersonalMeetingRoomUtil.getClaimPmrLink = (pmrLink) => {\n let validator = VALID_PMR_ADDRESS.test(pmrLink);\n\n if (validator) {\n return pmrLink;\n }\n validator = pmrLink.match(VALID_PMR_LINK);\n if (validator) {\n // userId + '@' + site + '.webex.com'\n return `${validator[4]}@${validator[2]}.${WEBEX_DOT_COM}`;\n }\n\n return null;\n};\n\nPersonalMeetingRoomUtil.getClaimPmrPin = (hostPin) => {\n if (VALID_PIN.test(hostPin)) {\n return hostPin;\n }\n\n return null;\n};\n\nPersonalMeetingRoomUtil.getClaimedRequestParams = (link, pin, options) => ({\n method: HTTP_VERBS.POST,\n api: HECATE,\n resource: `/${CMR_MEETINGS}/${CLAIM}`,\n body: {\n userId: options.userId,\n passcode: pin,\n preferred: options.preferred,\n meetingAddress: link\n }\n});\n\nexport default PersonalMeetingRoomUtil;\n"],"mappings":";;;;;;;;;;AAAA;;AAWA,IAAMA,uBAA4B,GAAG,EAArC;;AAEAA,uBAAuB,CAACC,eAAxB,GAA0C,UAACC,OAAD,EAAa;EACrD,IAAIC,SAAS,GAAGC,4BAAA,CAAkBC,IAAlB,CAAuBH,OAAvB,CAAhB;;EAEA,IAAIC,SAAJ,EAAe;IACb,OAAOD,OAAP;EACD;;EACDC,SAAS,GAAGD,OAAO,CAACI,KAAR,CAAcC,yBAAd,CAAZ;;EACA,IAAIJ,SAAJ,EAAe;IACb;IACA,iBAAUA,SAAS,CAAC,CAAD,CAAnB,cAA0BA,SAAS,CAAC,CAAD,CAAnC,cAA0CK,wBAA1C;EACD;;EAED,OAAO,IAAP;AACD,CAbD;;AAeAR,uBAAuB,CAACS,cAAxB,GAAyC,UAACC,OAAD,EAAa;EACpD,IAAIC,oBAAA,CAAUN,IAAV,CAAeK,OAAf,CAAJ,EAA6B;IAC3B,OAAOA,OAAP;EACD;;EAED,OAAO,IAAP;AACD,CAND;;AAQAV,uBAAuB,CAACY,uBAAxB,GAAkD,UAACC,IAAD,EAAOC,GAAP,EAAYC,OAAZ;EAAA,OAAyB;IACzEC,MAAM,EAAEC,qBAAA,CAAWC,IADsD;IAEzEC,GAAG,EAAEC,iBAFoE;IAGzEC,QAAQ,aAAMC,uBAAN,cAAsBC,gBAAtB,CAHiE;IAIzEC,IAAI,EAAE;MACJC,MAAM,EAAEV,OAAO,CAACU,MADZ;MAEJC,QAAQ,EAAEZ,GAFN;MAGJa,SAAS,EAAEZ,OAAO,CAACY,SAHf;MAIJC,cAAc,EAAEf;IAJZ;EAJmE,CAAzB;AAAA,CAAlD;;eAYeb,uB"}
1
+ {"version":3,"names":["PersonalMeetingRoomUtil","getClaimPmrLink","pmrLink","validator","VALID_PMR_ADDRESS","test","match","VALID_PMR_LINK","WEBEX_DOT_COM","getClaimPmrPin","hostPin","VALID_PIN","getClaimedRequestParams","link","pin","options","method","HTTP_VERBS","POST","api","HECATE","resource","CMR_MEETINGS","CLAIM","body","userId","passcode","preferred","meetingAddress"],"sources":["util.ts"],"sourcesContent":["import {\n HTTP_VERBS,\n VALID_PIN,\n VALID_PMR_ADDRESS,\n VALID_PMR_LINK,\n CMR_MEETINGS,\n CLAIM,\n HECATE,\n WEBEX_DOT_COM,\n} from '../constants';\n\nconst PersonalMeetingRoomUtil: any = {};\n\nPersonalMeetingRoomUtil.getClaimPmrLink = (pmrLink) => {\n let validator = VALID_PMR_ADDRESS.test(pmrLink);\n\n if (validator) {\n return pmrLink;\n }\n validator = pmrLink.match(VALID_PMR_LINK);\n if (validator) {\n // userId + '@' + site + '.webex.com'\n return `${validator[4]}@${validator[2]}.${WEBEX_DOT_COM}`;\n }\n\n return null;\n};\n\nPersonalMeetingRoomUtil.getClaimPmrPin = (hostPin) => {\n if (VALID_PIN.test(hostPin)) {\n return hostPin;\n }\n\n return null;\n};\n\nPersonalMeetingRoomUtil.getClaimedRequestParams = (link, pin, options) => ({\n method: HTTP_VERBS.POST,\n api: HECATE,\n resource: `/${CMR_MEETINGS}/${CLAIM}`,\n body: {\n userId: options.userId,\n passcode: pin,\n preferred: options.preferred,\n meetingAddress: link,\n },\n});\n\nexport default PersonalMeetingRoomUtil;\n"],"mappings":";;;;;;;;;;AAAA;;AAWA,IAAMA,uBAA4B,GAAG,EAArC;;AAEAA,uBAAuB,CAACC,eAAxB,GAA0C,UAACC,OAAD,EAAa;EACrD,IAAIC,SAAS,GAAGC,4BAAA,CAAkBC,IAAlB,CAAuBH,OAAvB,CAAhB;;EAEA,IAAIC,SAAJ,EAAe;IACb,OAAOD,OAAP;EACD;;EACDC,SAAS,GAAGD,OAAO,CAACI,KAAR,CAAcC,yBAAd,CAAZ;;EACA,IAAIJ,SAAJ,EAAe;IACb;IACA,iBAAUA,SAAS,CAAC,CAAD,CAAnB,cAA0BA,SAAS,CAAC,CAAD,CAAnC,cAA0CK,wBAA1C;EACD;;EAED,OAAO,IAAP;AACD,CAbD;;AAeAR,uBAAuB,CAACS,cAAxB,GAAyC,UAACC,OAAD,EAAa;EACpD,IAAIC,oBAAA,CAAUN,IAAV,CAAeK,OAAf,CAAJ,EAA6B;IAC3B,OAAOA,OAAP;EACD;;EAED,OAAO,IAAP;AACD,CAND;;AAQAV,uBAAuB,CAACY,uBAAxB,GAAkD,UAACC,IAAD,EAAOC,GAAP,EAAYC,OAAZ;EAAA,OAAyB;IACzEC,MAAM,EAAEC,qBAAA,CAAWC,IADsD;IAEzEC,GAAG,EAAEC,iBAFoE;IAGzEC,QAAQ,aAAMC,uBAAN,cAAsBC,gBAAtB,CAHiE;IAIzEC,IAAI,EAAE;MACJC,MAAM,EAAEV,OAAO,CAACU,MADZ;MAEJC,QAAQ,EAAEZ,GAFN;MAGJa,SAAS,EAAEZ,OAAO,CAACY,SAHf;MAIJC,cAAc,EAAEf;IAJZ;EAJmE,CAAzB;AAAA,CAAlD;;eAYeb,uB"}
@@ -1 +1 @@
1
- {"version":3,"names":["DEFAULT_TIMEOUT","VIDEO_MESH_TIMEOUT","Reachability","webex","reachabilityRequest","ReachabilityRequest","clusterLatencyResults","setup","window","localStorage","removeItem","REACHABILITY","LoggerProxy","logger","error","getClusters","clusters","performReachabilityCheck","results","setItem","log","reachable","reachabilityData","getItem","reachabilityResults","JSON","parse","some","result","udp","tcp","e","cluster","iceServers","map","url","username","credential","urls","iceCandidatePoolSize","iceTransportPolicy","key","config","peerConnection","RTCPeerConnection","peerConnectionError","startTime","begin","clusterList","buildPeerConnectionConfig","createPeerConnection","createOffer","offerToReceiveAudio","description","setLocalDescription","iceGatheringState","isVideoMesh","catch","iceGatheringStateError","all","then","parseIceResultsToReachabilityResults","reachabilityLatencyResults","logUnreachableClusters","unreachableList","forEach","unreachable","push","onicegatheringstatechange","COMPLETE","ICE_GATHERING_STATE","iceConnectionState","elapsed","getElapsedTime","setLatencyAndClose","onicecandidate","SERVER_REFLEXIVE","candidate","String","type","toLowerCase","timeout","ELAPSED","resolve","peerConnectionProxy","Proxy","get","target","property","targetMember","bind","set","value","clusterId","Reflect","handleIceGatheringStateChange","handleOnIceCandidate","setTimeout","CLOSED","CONNECTION_STATE","connectionState","list","getUnreachablClusters","iceResults","reachabilityMap","latencyResult","latencyInMilliseconds","toString","length","getLocalSDPForClusters","localSDPData","REACHABLE","UNREACHABLE","resultKey","intialState","close"],"sources":["index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-disable class-methods-use-this */\n/* globals window */\nimport _ from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport {\n ICE_GATHERING_STATE,\n CONNECTION_STATE,\n REACHABILITY\n} from '../constants';\n\nimport ReachabilityRequest from './request';\n\nconst DEFAULT_TIMEOUT = 3000;\nconst VIDEO_MESH_TIMEOUT = 1000;\n\n/**\n * @class Reachability\n * @export\n */\nexport default class Reachability {\n webex: object;\n reachabilityRequest: any;\n clusterLatencyResults: any;\n\n /**\n * Creates an instance of Reachability.\n * @param {object} webex\n * @memberof Reachability\n */\n constructor(webex: object) {\n this.webex = webex;\n\n /**\n * internal request object for the server\n * @instance\n * @type {Array}\n * @private\n * @memberof Reachability\n */\n this.reachabilityRequest = new ReachabilityRequest(this.webex);\n\n /**\n * internal object of clusters latency results\n * @instance\n * @type {object}\n * @private\n * @memberof Reachability\n */\n this.clusterLatencyResults = {};\n }\n\n\n /**\n * fetches reachability data\n * @returns {Object} reachability data\n * @public\n * @async\n * @memberof Reachability\n */\n public async gatherReachability() {\n this.setup();\n\n // Remove stored reachability results to ensure no stale data\n if (window?.localStorage?.removeItem) {\n window.localStorage.removeItem(REACHABILITY.localStorage);\n }\n else {\n LoggerProxy.logger.error('Reachability:index#gatherReachability --> Error in accessing LocalStorage.');\n\n return {};\n }\n\n // Fetch clusters and measure latency\n try {\n const clusters = await this.reachabilityRequest.getClusters();\n\n // Perform Reachability Check\n const results = await this.performReachabilityCheck(clusters);\n\n window.localStorage.setItem(REACHABILITY.localStorage, JSON.stringify(results));\n\n LoggerProxy.logger.log('Reachability:index#gatherReachability --> Reachability checks completed');\n\n return results;\n }\n catch (getClusterError) {\n LoggerProxy.logger.error(`Reachability:index#gatherReachability --> Error in calling getClusters(): ${getClusterError}`);\n\n return {};\n }\n }\n\n /**\n * fetches reachability data and checks for cluster reachability\n * @returns {boolean}\n * @public\n * @memberof Reachability\n */\n isAnyClusterReachable() {\n let reachable = false;\n const reachabilityData = window.localStorage.getItem(REACHABILITY.localStorage);\n\n if (reachabilityData) {\n try {\n const reachabilityResults = JSON.parse(reachabilityData);\n\n reachable = Object.values(reachabilityResults).some((result: any) => result.udp?.reachable === 'true' || result.tcp?.reachable === 'true');\n }\n catch (e) {\n LoggerProxy.logger.error(`Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`);\n }\n }\n\n return reachable;\n }\n\n\n /**\n * Generate peerConnection config settings\n * @param {object} cluster\n * @returns {object} peerConnectionConfig\n * @private\n * @memberof Reachability\n */\n private buildPeerConnectionConfig(cluster: any) {\n const iceServers = _.uniq([\n ...cluster.udp,\n ...cluster.tcp\n ]).map((url) => ({\n username: '',\n credential: '',\n urls: [url]\n }));\n\n return {\n iceServers: [\n ...iceServers\n ],\n iceCandidatePoolSize: '0',\n iceTransportPolicy: 'all'\n };\n }\n\n\n /**\n * Creates an RTCPeerConnection\n * @param {object} cluster\n * @returns {RTCPeerConnection} peerConnection\n * @private\n * @memberof Reachability\n */\n private createPeerConnection(cluster: any) {\n const {key, config} = cluster;\n\n try {\n const peerConnection = new window.RTCPeerConnection(config);\n\n // @ts-ignore\n peerConnection.key = key;\n\n return peerConnection;\n }\n catch (peerConnectionError) {\n LoggerProxy.logger.log(`Reachability:index#createPeerConnection --> Error creating peerConnection: ${peerConnectionError}`);\n\n return null;\n }\n }\n\n\n /**\n * Gets total elapsed time\n * @param {RTCPeerConnection} peerConnection\n * @returns {Number} Milliseconds\n * @private\n * @memberof Reachability\n */\n private getElapsedTime(peerConnection: any) {\n const startTime = peerConnection.begin;\n\n delete peerConnection.begin;\n\n return Date.now() - startTime;\n }\n\n\n /**\n * creates offer and generates localSDP\n * @param {object} clusterList cluster List\n * @returns {Promise} Reachability latency results\n * @private\n * @memberof Reachability\n */\n private getLocalSDPForClusters(clusterList: object) {\n let clusters: any[] = [...Object.keys(clusterList)];\n\n clusters = clusters.map(async (key) => {\n const cluster = clusterList[key];\n const config = this.buildPeerConnectionConfig(cluster);\n const peerConnection = this.createPeerConnection({key, config});\n const description = await peerConnection.createOffer({offerToReceiveAudio: true});\n\n // @ts-ignore\n peerConnection.begin = Date.now();\n peerConnection.setLocalDescription(description);\n\n return this.iceGatheringState(peerConnection, cluster.isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT)\n .catch((iceGatheringStateError) => {\n LoggerProxy.logger.log(`Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`);\n });\n });\n\n return Promise.all(clusters)\n .then(this.parseIceResultsToReachabilityResults)\n .then((reachabilityLatencyResults) => {\n this.logUnreachableClusters();\n\n // return results\n return reachabilityLatencyResults;\n });\n }\n\n\n /**\n * Get list of all unreachable clusters\n * @returns {array} Unreachable clusters\n * @private\n * @memberof Reachability\n */\n private getUnreachablClusters() {\n const unreachableList = [];\n const clusters = this.clusterLatencyResults;\n\n Object.keys(clusters).forEach((key) => {\n const cluster = clusters[key];\n\n if (cluster.unreachable && !cluster.reachable) {\n unreachableList.push(key);\n }\n });\n\n return unreachableList;\n }\n\n\n /**\n * Attach an event handler for the icegatheringstatechange\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleIceGatheringStateChange(peerConnection: RTCPeerConnection) {\n peerConnection.onicegatheringstatechange = () => {\n const {COMPLETE} = ICE_GATHERING_STATE;\n\n if (peerConnection.iceConnectionState === COMPLETE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n // @ts-ignore\n LoggerProxy.logger.log(`Reachability:index#onIceGatheringStateChange --> Successfully pinged ${peerConnection.key}:`, elapsed);\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n\n /**\n * Attach an event handler for the icecandidate\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleOnIceCandidate(peerConnection: RTCPeerConnection) {\n peerConnection.onicecandidate = (e) => {\n const SERVER_REFLEXIVE = 'srflx';\n\n if (e.candidate && String(e.candidate.type).toLowerCase() === SERVER_REFLEXIVE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n // @ts-ignore\n LoggerProxy.logger.log(`Reachability:index#onIceCandidate --> Successfully pinged ${peerConnection.key}:`, elapsed);\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n /**\n * An event handler on an RTCPeerConnection when the state of the ICE\n * candidate gathering process changes. Used to measure connection\n * speed.\n * @private\n * @param {RTCPeerConnection} peerConnection\n * @param {number} timeout\n * @returns {Promise}\n */\n private iceGatheringState(peerConnection: RTCPeerConnection, timeout: number) {\n const ELAPSED = 'elapsed';\n\n return new Promise((resolve) => {\n const peerConnectionProxy = new window.Proxy(peerConnection, {\n get(target, property) {\n const targetMember = target[property];\n\n if (typeof (targetMember) === 'function') {\n return targetMember.bind(target);\n }\n\n return targetMember;\n },\n set: (target, property, value) => {\n // only intercept elapsed property\n if (property === ELAPSED) {\n // @ts-ignore\n resolve({clusterId: peerConnection.key, elapsed: value});\n\n return true;\n }\n\n // pass thru\n return window.Reflect.set(target, property, value);\n }\n });\n\n // Using peerConnection proxy so handle functions below\n // won't be coupled to our promise implementation\n this.handleIceGatheringStateChange(peerConnectionProxy);\n this.handleOnIceCandidate(peerConnectionProxy);\n\n // Set maximum timeout\n window.setTimeout(() => {\n const {CLOSED} = CONNECTION_STATE;\n\n // Close any open peerConnections\n if (peerConnectionProxy.connectionState !== CLOSED) {\n this.setLatencyAndClose(peerConnectionProxy, null);\n }\n }, timeout);\n });\n }\n\n\n /**\n * Make a log of unreachable clusters.\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private logUnreachableClusters() {\n const list = this.getUnreachablClusters();\n\n list.forEach((cluster) => {\n LoggerProxy.logger.log(`Reachability:index#logUnreachableClusters --> No ice candidate for ${cluster}.`);\n });\n }\n\n\n /**\n * Calculates time to establish connection\n * @param {array} iceResults iceResults\n * @returns {object} reachabilityMap\n * @private\n * @memberof Reachability\n */\n private parseIceResultsToReachabilityResults(iceResults: Array<any>) {\n const reachabilityMap = {};\n\n iceResults.forEach(({clusterId, elapsed}) => {\n let latencyResult;\n\n if (elapsed === null) {\n latencyResult = {reachable: 'false'};\n }\n else {\n latencyResult = {\n reachable: 'true',\n latencyInMilliseconds: (elapsed).toString()\n };\n }\n\n reachabilityMap[clusterId] = {\n udp: latencyResult,\n tcp: latencyResult\n };\n });\n\n return reachabilityMap;\n }\n\n\n /**\n * fetches reachability data\n * @param {object} clusterList\n * @returns {Promise<localSDPData>} reachability check results\n * @private\n * @memberof Reachability\n */\n private performReachabilityCheck(clusterList: object) {\n if (!clusterList || !Object.keys(clusterList).length) {\n return Promise.resolve({});\n }\n\n return new Promise((resolve) => {\n this.getLocalSDPForClusters(clusterList)\n .then((localSDPData) => {\n if (!localSDPData || !Object.keys(localSDPData).length) {\n // TODO: handle the error condition properly and try retry\n LoggerProxy.logger.log('Reachability:index#performReachabilityCheck --> Local SDP is empty or has missing elements..returning');\n resolve({});\n }\n else {\n resolve(localSDPData);\n }\n })\n .catch((error) => {\n LoggerProxy.logger.error(`Reachability:index#performReachabilityCheck --> Error in getLocalSDPForClusters: ${error}`);\n resolve({});\n });\n });\n }\n\n\n /**\n * Records latency and closes the peerConnection\n * @param {RTCPeerConnection} peerConnection\n * @param {number} elapsed Latency in milliseconds\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setLatencyAndClose(peerConnection: RTCPeerConnection, elapsed: number) {\n const REACHABLE = 'reachable';\n const UNREACHABLE = 'unreachable';\n const {CLOSED} = CONNECTION_STATE;\n // @ts-ignore\n const {key} = peerConnection;\n const resultKey = elapsed === null ? UNREACHABLE : REACHABLE;\n const intialState = {[REACHABLE]: 0, [UNREACHABLE]: 0};\n\n if (peerConnection.connectionState === CLOSED) {\n LoggerProxy.logger.log(`Reachability:index#setLatencyAndClose --> Attempting to set latency of ${elapsed} on closed peerConnection.`);\n\n return;\n }\n\n this.clusterLatencyResults[key] = this.clusterLatencyResults[key] || intialState;\n this.clusterLatencyResults[key][resultKey] += 1;\n\n // Set to null in case this fired from\n // an event other than onIceCandidate\n peerConnection.onicecandidate = null;\n peerConnection.close();\n // @ts-ignore\n peerConnection.elapsed = elapsed;\n }\n\n\n /**\n * utility function\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setup() {\n this.clusterLatencyResults = {};\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA;;AACA;;AAMA;;AAEA,IAAMA,eAAe,GAAG,IAAxB;AACA,IAAMC,kBAAkB,GAAG,IAA3B;AAEA;AACA;AACA;AACA;;IACqBC,Y;EAKnB;AACF;AACA;AACA;AACA;EACE,sBAAYC,KAAZ,EAA2B;IAAA;IAAA;IAAA;IAAA;IACzB,KAAKA,KAAL,GAAaA,KAAb;IAEA;AACJ;AACA;AACA;AACA;AACA;AACA;;IACI,KAAKC,mBAAL,GAA2B,IAAIC,gBAAJ,CAAwB,KAAKF,KAA7B,CAA3B;IAEA;AACJ;AACA;AACA;AACA;AACA;AACA;;IACI,KAAKG,qBAAL,GAA6B,EAA7B;EACD;EAGD;AACF;AACA;AACA;AACA;AACA;AACA;;;;;;wGACE;QAAA;;QAAA;QAAA;UAAA;YAAA;cAAA;gBACE,KAAKC,KAAL,GADF,CAGE;;gBAHF,iBAIMC,MAJN,4DAIM,QAAQC,YAJd,iDAIM,qBAAsBC,UAJ5B;kBAAA;kBAAA;gBAAA;;gBAKIF,MAAM,CAACC,YAAP,CAAoBC,UAApB,CAA+BC,uBAAA,CAAaF,YAA5C;gBALJ;gBAAA;;cAAA;gBAQIG,oBAAA,CAAYC,MAAZ,CAAmBC,KAAnB,CAAyB,4EAAzB;;gBARJ,iCAUW,EAVX;;cAAA;gBAAA;gBAAA;gBAAA,OAe2B,KAAKV,mBAAL,CAAyBW,WAAzB,EAf3B;;cAAA;gBAeUC,QAfV;gBAAA;gBAAA,OAkB0B,KAAKC,wBAAL,CAA8BD,QAA9B,CAlB1B;;cAAA;gBAkBUE,OAlBV;gBAoBIV,MAAM,CAACC,YAAP,CAAoBU,OAApB,CAA4BR,uBAAA,CAAaF,YAAzC,EAAuD,wBAAeS,OAAf,CAAvD;;gBAEAN,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,CAAuB,yEAAvB;;gBAtBJ,iCAwBWF,OAxBX;;cAAA;gBAAA;gBAAA;;gBA2BIN,oBAAA,CAAYC,MAAZ,CAAmBC,KAAnB;;gBA3BJ,iCA6BW,EA7BX;;cAAA;cAAA;gBAAA;YAAA;UAAA;QAAA;MAAA,C;;;;;;;;IAiCA;AACF;AACA;AACA;AACA;AACA;;;;WACE,iCAAwB;MACtB,IAAIO,SAAS,GAAG,KAAhB;MACA,IAAMC,gBAAgB,GAAGd,MAAM,CAACC,YAAP,CAAoBc,OAApB,CAA4BZ,uBAAA,CAAaF,YAAzC,CAAzB;;MAEA,IAAIa,gBAAJ,EAAsB;QACpB,IAAI;UACF,IAAME,mBAAmB,GAAGC,IAAI,CAACC,KAAL,CAAWJ,gBAAX,CAA5B;UAEAD,SAAS,GAAG,qBAAcG,mBAAd,EAAmCG,IAAnC,CAAwC,UAACC,MAAD;YAAA;;YAAA,OAAiB,gBAAAA,MAAM,CAACC,GAAP,4DAAYR,SAAZ,MAA0B,MAA1B,IAAoC,gBAAAO,MAAM,CAACE,GAAP,4DAAYT,SAAZ,MAA0B,MAA/E;UAAA,CAAxC,CAAZ;QACD,CAJD,CAKA,OAAOU,CAAP,EAAU;UACRnB,oBAAA,CAAYC,MAAZ,CAAmBC,KAAnB,uFAAwGiB,CAAxG;QACD;MACF;;MAED,OAAOV,SAAP;IACD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;;;;WACE,mCAAkCW,OAAlC,EAAgD;MAC9C,IAAMC,UAAU,GAAG,+DACdD,OAAO,CAACH,GADM,oCAEdG,OAAO,CAACF,GAFM,IAGhBI,GAHgB,CAGZ,UAACC,GAAD;QAAA,OAAU;UACfC,QAAQ,EAAE,EADK;UAEfC,UAAU,EAAE,EAFG;UAGfC,IAAI,EAAE,CAACH,GAAD;QAHS,CAAV;MAAA,CAHY,CAAnB;MASA,OAAO;QACLF,UAAU,mCACLA,UADK,CADL;QAILM,oBAAoB,EAAE,GAJjB;QAKLC,kBAAkB,EAAE;MALf,CAAP;IAOD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;;;;WACE,8BAA6BR,OAA7B,EAA2C;MACzC,IAAOS,GAAP,GAAsBT,OAAtB,CAAOS,GAAP;MAAA,IAAYC,MAAZ,GAAsBV,OAAtB,CAAYU,MAAZ;;MAEA,IAAI;QACF,IAAMC,cAAc,GAAG,IAAInC,MAAM,CAACoC,iBAAX,CAA6BF,MAA7B,CAAvB,CADE,CAGF;;QACAC,cAAc,CAACF,GAAf,GAAqBA,GAArB;QAEA,OAAOE,cAAP;MACD,CAPD,CAQA,OAAOE,mBAAP,EAA4B;QAC1BjC,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,sFAAqGyB,mBAArG;;QAEA,OAAO,IAAP;MACD;IACF;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;;;;WACE,wBAAuBF,cAAvB,EAA4C;MAC1C,IAAMG,SAAS,GAAGH,cAAc,CAACI,KAAjC;MAEA,OAAOJ,cAAc,CAACI,KAAtB;MAEA,OAAO,sBAAaD,SAApB;IACD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;;;;WACE,gCAA+BE,WAA/B,EAAoD;MAAA;;MAClD,IAAIhC,QAAe,oCAAO,mBAAYgC,WAAZ,CAAP,CAAnB;MAEAhC,QAAQ,GAAGA,QAAQ,CAACkB,GAAT;QAAA,mFAAa,kBAAOO,GAAP;UAAA;UAAA;YAAA;cAAA;gBAAA;kBAChBT,OADgB,GACNgB,WAAW,CAACP,GAAD,CADL;kBAEhBC,MAFgB,GAEP,KAAI,CAACO,yBAAL,CAA+BjB,OAA/B,CAFO;kBAGhBW,cAHgB,GAGC,KAAI,CAACO,oBAAL,CAA0B;oBAACT,GAAG,EAAHA,GAAD;oBAAMC,MAAM,EAANA;kBAAN,CAA1B,CAHD;kBAAA;kBAAA,OAIIC,cAAc,CAACQ,WAAf,CAA2B;oBAACC,mBAAmB,EAAE;kBAAtB,CAA3B,CAJJ;;gBAAA;kBAIhBC,WAJgB;kBAMtB;kBACAV,cAAc,CAACI,KAAf,GAAuB,mBAAvB;kBACAJ,cAAc,CAACW,mBAAf,CAAmCD,WAAnC;kBARsB,kCAUf,KAAI,CAACE,iBAAL,CAAuBZ,cAAvB,EAAuCX,OAAO,CAACwB,WAAR,GAAsBvD,kBAAtB,GAA2CD,eAAlF,EACJyD,KADI,CACE,UAACC,sBAAD,EAA4B;oBACjC9C,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,gFAA+FsC,sBAA/F;kBACD,CAHI,CAVe;;gBAAA;gBAAA;kBAAA;cAAA;YAAA;UAAA;QAAA,CAAb;;QAAA;UAAA;QAAA;MAAA,IAAX;MAgBA,OAAO,iBAAQC,GAAR,CAAY3C,QAAZ,EACJ4C,IADI,CACC,KAAKC,oCADN,EAEJD,IAFI,CAEC,UAACE,0BAAD,EAAgC;QACpC,KAAI,CAACC,sBAAL,GADoC,CAGpC;;;QACA,OAAOD,0BAAP;MACD,CAPI,CAAP;IAQD;IAGD;AACF;AACA;AACA;AACA;AACA;;;;WACE,iCAAgC;MAC9B,IAAME,eAAe,GAAG,EAAxB;MACA,IAAMhD,QAAQ,GAAG,KAAKV,qBAAtB;MAEA,mBAAYU,QAAZ,EAAsBiD,OAAtB,CAA8B,UAACxB,GAAD,EAAS;QACrC,IAAMT,OAAO,GAAGhB,QAAQ,CAACyB,GAAD,CAAxB;;QAEA,IAAIT,OAAO,CAACkC,WAAR,IAAuB,CAAClC,OAAO,CAACX,SAApC,EAA+C;UAC7C2C,eAAe,CAACG,IAAhB,CAAqB1B,GAArB;QACD;MACF,CAND;MAQA,OAAOuB,eAAP;IACD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,uCAAsCrB,cAAtC,EAAyE;MAAA;;MACvEA,cAAc,CAACyB,yBAAf,GAA2C,YAAM;QAC/C,IAAOC,QAAP,GAAmBC,8BAAnB,CAAOD,QAAP;;QAEA,IAAI1B,cAAc,CAAC4B,kBAAf,KAAsCF,QAA1C,EAAoD;UAClD,IAAMG,OAAO,GAAG,MAAI,CAACC,cAAL,CAAoB9B,cAApB,CAAhB,CADkD,CAGlD;;;UACA/B,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,gFAA+FuB,cAAc,CAACF,GAA9G,QAAsH+B,OAAtH;;UACA,MAAI,CAACE,kBAAL,CAAwB/B,cAAxB,EAAwC6B,OAAxC;QACD;MACF,CAVD;IAWD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,8BAA6B7B,cAA7B,EAAgE;MAAA;;MAC9DA,cAAc,CAACgC,cAAf,GAAgC,UAAC5C,CAAD,EAAO;QACrC,IAAM6C,gBAAgB,GAAG,OAAzB;;QAEA,IAAI7C,CAAC,CAAC8C,SAAF,IAAeC,MAAM,CAAC/C,CAAC,CAAC8C,SAAF,CAAYE,IAAb,CAAN,CAAyBC,WAAzB,OAA2CJ,gBAA9D,EAAgF;UAC9E,IAAMJ,OAAO,GAAG,MAAI,CAACC,cAAL,CAAoB9B,cAApB,CAAhB,CAD8E,CAG9E;;;UACA/B,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,qEAAoFuB,cAAc,CAACF,GAAnG,QAA2G+B,OAA3G;;UACA,MAAI,CAACE,kBAAL,CAAwB/B,cAAxB,EAAwC6B,OAAxC;QACD;MACF,CAVD;IAWD;IAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,2BAA0B7B,cAA1B,EAA6DsC,OAA7D,EAA8E;MAAA;;MAC5E,IAAMC,OAAO,GAAG,SAAhB;MAEA,OAAO,qBAAY,UAACC,OAAD,EAAa;QAC9B,IAAMC,mBAAmB,GAAG,IAAI5E,MAAM,CAAC6E,KAAX,CAAiB1C,cAAjB,EAAiC;UAC3D2C,GAD2D,eACvDC,MADuD,EAC/CC,QAD+C,EACrC;YACpB,IAAMC,YAAY,GAAGF,MAAM,CAACC,QAAD,CAA3B;;YAEA,IAAI,OAAQC,YAAR,KAA0B,UAA9B,EAA0C;cACxC,OAAOA,YAAY,CAACC,IAAb,CAAkBH,MAAlB,CAAP;YACD;;YAED,OAAOE,YAAP;UACD,CAT0D;UAU3DE,GAAG,EAAE,aAACJ,MAAD,EAASC,QAAT,EAAmBI,KAAnB,EAA6B;YAChC;YACA,IAAIJ,QAAQ,KAAKN,OAAjB,EAA0B;cACxB;cACAC,OAAO,CAAC;gBAACU,SAAS,EAAElD,cAAc,CAACF,GAA3B;gBAAgC+B,OAAO,EAAEoB;cAAzC,CAAD,CAAP;cAEA,OAAO,IAAP;YACD,CAP+B,CAShC;;;YACA,OAAOpF,MAAM,CAACsF,OAAP,CAAeH,GAAf,CAAmBJ,MAAnB,EAA2BC,QAA3B,EAAqCI,KAArC,CAAP;UACD;QArB0D,CAAjC,CAA5B,CAD8B,CAyB9B;QACA;;QACA,MAAI,CAACG,6BAAL,CAAmCX,mBAAnC;;QACA,MAAI,CAACY,oBAAL,CAA0BZ,mBAA1B,EA5B8B,CA8B9B;;;QACA5E,MAAM,CAACyF,UAAP,CAAkB,YAAM;UACtB,IAAOC,MAAP,GAAiBC,2BAAjB,CAAOD,MAAP,CADsB,CAGtB;;UACA,IAAId,mBAAmB,CAACgB,eAApB,KAAwCF,MAA5C,EAAoD;YAClD,MAAI,CAACxB,kBAAL,CAAwBU,mBAAxB,EAA6C,IAA7C;UACD;QACF,CAPD,EAOGH,OAPH;MAQD,CAvCM,CAAP;IAwCD;IAGD;AACF;AACA;AACA;AACA;AACA;;;;WACE,kCAAiC;MAC/B,IAAMoB,IAAI,GAAG,KAAKC,qBAAL,EAAb;MAEAD,IAAI,CAACpC,OAAL,CAAa,UAACjC,OAAD,EAAa;QACxBpB,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,8EAA6FY,OAA7F;MACD,CAFD;IAGD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;;;;WACE,8CAA6CuE,UAA7C,EAAqE;MACnE,IAAMC,eAAe,GAAG,EAAxB;MAEAD,UAAU,CAACtC,OAAX,CAAmB,iBAA0B;QAAA,IAAxB4B,SAAwB,SAAxBA,SAAwB;QAAA,IAAbrB,OAAa,SAAbA,OAAa;QAC3C,IAAIiC,aAAJ;;QAEA,IAAIjC,OAAO,KAAK,IAAhB,EAAsB;UACpBiC,aAAa,GAAG;YAACpF,SAAS,EAAE;UAAZ,CAAhB;QACD,CAFD,MAGK;UACHoF,aAAa,GAAG;YACdpF,SAAS,EAAE,MADG;YAEdqF,qBAAqB,EAAGlC,OAAD,CAAUmC,QAAV;UAFT,CAAhB;QAID;;QAEDH,eAAe,CAACX,SAAD,CAAf,GAA6B;UAC3BhE,GAAG,EAAE4E,aADsB;UAE3B3E,GAAG,EAAE2E;QAFsB,CAA7B;MAID,CAjBD;MAmBA,OAAOD,eAAP;IACD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;;;;WACE,kCAAiCxD,WAAjC,EAAsD;MAAA;;MACpD,IAAI,CAACA,WAAD,IAAgB,CAAC,mBAAYA,WAAZ,EAAyB4D,MAA9C,EAAsD;QACpD,OAAO,iBAAQzB,OAAR,CAAgB,EAAhB,CAAP;MACD;;MAED,OAAO,qBAAY,UAACA,OAAD,EAAa;QAC9B,MAAI,CAAC0B,sBAAL,CAA4B7D,WAA5B,EACGY,IADH,CACQ,UAACkD,YAAD,EAAkB;UACtB,IAAI,CAACA,YAAD,IAAiB,CAAC,mBAAYA,YAAZ,EAA0BF,MAAhD,EAAwD;YACtD;YACAhG,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,CAAuB,uGAAvB;;YACA+D,OAAO,CAAC,EAAD,CAAP;UACD,CAJD,MAKK;YACHA,OAAO,CAAC2B,YAAD,CAAP;UACD;QACF,CAVH,EAWGrD,KAXH,CAWS,UAAC3C,KAAD,EAAW;UAChBF,oBAAA,CAAYC,MAAZ,CAAmBC,KAAnB,4FAA6GA,KAA7G;;UACAqE,OAAO,CAAC,EAAD,CAAP;QACD,CAdH;MAeD,CAhBM,CAAP;IAiBD;IAGD;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,4BAA2BxC,cAA3B,EAA8D6B,OAA9D,EAA+E;MAAA;;MAC7E,IAAMuC,SAAS,GAAG,WAAlB;MACA,IAAMC,WAAW,GAAG,aAApB;MACA,IAAOd,MAAP,GAAiBC,2BAAjB,CAAOD,MAAP,CAH6E,CAI7E;;MACA,IAAOzD,GAAP,GAAcE,cAAd,CAAOF,GAAP;MACA,IAAMwE,SAAS,GAAGzC,OAAO,KAAK,IAAZ,GAAmBwC,WAAnB,GAAiCD,SAAnD;MACA,IAAMG,WAAW,mEAAKH,SAAL,EAAiB,CAAjB,+CAAqBC,WAArB,EAAmC,CAAnC,gBAAjB;;MAEA,IAAIrE,cAAc,CAACyD,eAAf,KAAmCF,MAAvC,EAA+C;QAC7CtF,oBAAA,CAAYC,MAAZ,CAAmBO,GAAnB,kFAAiGoD,OAAjG;;QAEA;MACD;;MAED,KAAKlE,qBAAL,CAA2BmC,GAA3B,IAAkC,KAAKnC,qBAAL,CAA2BmC,GAA3B,KAAmCyE,WAArE;MACA,KAAK5G,qBAAL,CAA2BmC,GAA3B,EAAgCwE,SAAhC,KAA8C,CAA9C,CAhB6E,CAkB7E;MACA;;MACAtE,cAAc,CAACgC,cAAf,GAAgC,IAAhC;MACAhC,cAAc,CAACwE,KAAf,GArB6E,CAsB7E;;MACAxE,cAAc,CAAC6B,OAAf,GAAyBA,OAAzB;IACD;IAGD;AACF;AACA;AACA;AACA;AACA;;;;WACE,iBAAgB;MACd,KAAKlE,qBAAL,GAA6B,EAA7B;IACD"}
1
+ {"version":3,"names":["DEFAULT_TIMEOUT","VIDEO_MESH_TIMEOUT","Reachability","webex","reachabilityRequest","ReachabilityRequest","clusterLatencyResults","setup","window","localStorage","removeItem","REACHABILITY","LoggerProxy","logger","error","getClusters","clusters","performReachabilityCheck","results","setItem","log","reachable","reachabilityData","getItem","reachabilityResults","JSON","parse","some","result","udp","tcp","e","cluster","iceServers","map","url","username","credential","urls","iceCandidatePoolSize","iceTransportPolicy","key","config","peerConnection","RTCPeerConnection","peerConnectionError","startTime","begin","clusterList","buildPeerConnectionConfig","createPeerConnection","createOffer","offerToReceiveAudio","description","setLocalDescription","iceGatheringState","isVideoMesh","catch","iceGatheringStateError","all","then","parseIceResultsToReachabilityResults","reachabilityLatencyResults","logUnreachableClusters","unreachableList","forEach","unreachable","push","onicegatheringstatechange","COMPLETE","ICE_GATHERING_STATE","iceConnectionState","elapsed","getElapsedTime","setLatencyAndClose","onicecandidate","SERVER_REFLEXIVE","candidate","String","type","toLowerCase","timeout","ELAPSED","resolve","peerConnectionProxy","Proxy","get","target","property","targetMember","bind","set","value","clusterId","Reflect","handleIceGatheringStateChange","handleOnIceCandidate","setTimeout","CLOSED","CONNECTION_STATE","connectionState","list","getUnreachablClusters","iceResults","reachabilityMap","latencyResult","latencyInMilliseconds","toString","length","getLocalSDPForClusters","localSDPData","REACHABLE","UNREACHABLE","resultKey","intialState","close"],"sources":["index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-disable class-methods-use-this */\n/* globals window */\nimport _ from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport {ICE_GATHERING_STATE, CONNECTION_STATE, REACHABILITY} from '../constants';\n\nimport ReachabilityRequest from './request';\n\nconst DEFAULT_TIMEOUT = 3000;\nconst VIDEO_MESH_TIMEOUT = 1000;\n\n/**\n * @class Reachability\n * @export\n */\nexport default class Reachability {\n webex: object;\n reachabilityRequest: any;\n clusterLatencyResults: any;\n\n /**\n * Creates an instance of Reachability.\n * @param {object} webex\n * @memberof Reachability\n */\n constructor(webex: object) {\n this.webex = webex;\n\n /**\n * internal request object for the server\n * @instance\n * @type {Array}\n * @private\n * @memberof Reachability\n */\n this.reachabilityRequest = new ReachabilityRequest(this.webex);\n\n /**\n * internal object of clusters latency results\n * @instance\n * @type {object}\n * @private\n * @memberof Reachability\n */\n this.clusterLatencyResults = {};\n }\n\n /**\n * fetches reachability data\n * @returns {Object} reachability data\n * @public\n * @async\n * @memberof Reachability\n */\n public async gatherReachability() {\n this.setup();\n\n // Remove stored reachability results to ensure no stale data\n if (window?.localStorage?.removeItem) {\n window.localStorage.removeItem(REACHABILITY.localStorage);\n } else {\n LoggerProxy.logger.error(\n 'Reachability:index#gatherReachability --> Error in accessing LocalStorage.'\n );\n\n return {};\n }\n\n // Fetch clusters and measure latency\n try {\n const clusters = await this.reachabilityRequest.getClusters();\n\n // Perform Reachability Check\n const results = await this.performReachabilityCheck(clusters);\n\n window.localStorage.setItem(REACHABILITY.localStorage, JSON.stringify(results));\n\n LoggerProxy.logger.log(\n 'Reachability:index#gatherReachability --> Reachability checks completed'\n );\n\n return results;\n } catch (getClusterError) {\n LoggerProxy.logger.error(\n `Reachability:index#gatherReachability --> Error in calling getClusters(): ${getClusterError}`\n );\n\n return {};\n }\n }\n\n /**\n * fetches reachability data and checks for cluster reachability\n * @returns {boolean}\n * @public\n * @memberof Reachability\n */\n isAnyClusterReachable() {\n let reachable = false;\n const reachabilityData = window.localStorage.getItem(REACHABILITY.localStorage);\n\n if (reachabilityData) {\n try {\n const reachabilityResults = JSON.parse(reachabilityData);\n\n reachable = Object.values(reachabilityResults).some(\n (result: any) => result.udp?.reachable === 'true' || result.tcp?.reachable === 'true'\n );\n } catch (e) {\n LoggerProxy.logger.error(\n `Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`\n );\n }\n }\n\n return reachable;\n }\n\n /**\n * Generate peerConnection config settings\n * @param {object} cluster\n * @returns {object} peerConnectionConfig\n * @private\n * @memberof Reachability\n */\n private buildPeerConnectionConfig(cluster: any) {\n const iceServers = _.uniq([...cluster.udp, ...cluster.tcp]).map((url) => ({\n username: '',\n credential: '',\n urls: [url],\n }));\n\n return {\n iceServers: [...iceServers],\n iceCandidatePoolSize: '0',\n iceTransportPolicy: 'all',\n };\n }\n\n /**\n * Creates an RTCPeerConnection\n * @param {object} cluster\n * @returns {RTCPeerConnection} peerConnection\n * @private\n * @memberof Reachability\n */\n private createPeerConnection(cluster: any) {\n const {key, config} = cluster;\n\n try {\n const peerConnection = new window.RTCPeerConnection(config);\n\n // @ts-ignore\n peerConnection.key = key;\n\n return peerConnection;\n } catch (peerConnectionError) {\n LoggerProxy.logger.log(\n `Reachability:index#createPeerConnection --> Error creating peerConnection: ${peerConnectionError}`\n );\n\n return null;\n }\n }\n\n /**\n * Gets total elapsed time\n * @param {RTCPeerConnection} peerConnection\n * @returns {Number} Milliseconds\n * @private\n * @memberof Reachability\n */\n private getElapsedTime(peerConnection: any) {\n const startTime = peerConnection.begin;\n\n delete peerConnection.begin;\n\n return Date.now() - startTime;\n }\n\n /**\n * creates offer and generates localSDP\n * @param {object} clusterList cluster List\n * @returns {Promise} Reachability latency results\n * @private\n * @memberof Reachability\n */\n private getLocalSDPForClusters(clusterList: object) {\n let clusters: any[] = [...Object.keys(clusterList)];\n\n clusters = clusters.map(async (key) => {\n const cluster = clusterList[key];\n const config = this.buildPeerConnectionConfig(cluster);\n const peerConnection = this.createPeerConnection({key, config});\n const description = await peerConnection.createOffer({offerToReceiveAudio: true});\n\n // @ts-ignore\n peerConnection.begin = Date.now();\n peerConnection.setLocalDescription(description);\n\n return this.iceGatheringState(\n peerConnection,\n cluster.isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT\n ).catch((iceGatheringStateError) => {\n LoggerProxy.logger.log(\n `Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`\n );\n });\n });\n\n return Promise.all(clusters)\n .then(this.parseIceResultsToReachabilityResults)\n .then((reachabilityLatencyResults) => {\n this.logUnreachableClusters();\n\n // return results\n return reachabilityLatencyResults;\n });\n }\n\n /**\n * Get list of all unreachable clusters\n * @returns {array} Unreachable clusters\n * @private\n * @memberof Reachability\n */\n private getUnreachablClusters() {\n const unreachableList = [];\n const clusters = this.clusterLatencyResults;\n\n Object.keys(clusters).forEach((key) => {\n const cluster = clusters[key];\n\n if (cluster.unreachable && !cluster.reachable) {\n unreachableList.push(key);\n }\n });\n\n return unreachableList;\n }\n\n /**\n * Attach an event handler for the icegatheringstatechange\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleIceGatheringStateChange(peerConnection: RTCPeerConnection) {\n peerConnection.onicegatheringstatechange = () => {\n const {COMPLETE} = ICE_GATHERING_STATE;\n\n if (peerConnection.iceConnectionState === COMPLETE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n // @ts-ignore\n LoggerProxy.logger.log(\n `Reachability:index#onIceGatheringStateChange --> Successfully pinged ${peerConnection.key}:`,\n elapsed\n );\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n /**\n * Attach an event handler for the icecandidate\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleOnIceCandidate(peerConnection: RTCPeerConnection) {\n peerConnection.onicecandidate = (e) => {\n const SERVER_REFLEXIVE = 'srflx';\n\n if (e.candidate && String(e.candidate.type).toLowerCase() === SERVER_REFLEXIVE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n // @ts-ignore\n LoggerProxy.logger.log(\n `Reachability:index#onIceCandidate --> Successfully pinged ${peerConnection.key}:`,\n elapsed\n );\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n /**\n * An event handler on an RTCPeerConnection when the state of the ICE\n * candidate gathering process changes. Used to measure connection\n * speed.\n * @private\n * @param {RTCPeerConnection} peerConnection\n * @param {number} timeout\n * @returns {Promise}\n */\n private iceGatheringState(peerConnection: RTCPeerConnection, timeout: number) {\n const ELAPSED = 'elapsed';\n\n return new Promise((resolve) => {\n const peerConnectionProxy = new window.Proxy(peerConnection, {\n get(target, property) {\n const targetMember = target[property];\n\n if (typeof targetMember === 'function') {\n return targetMember.bind(target);\n }\n\n return targetMember;\n },\n set: (target, property, value) => {\n // only intercept elapsed property\n if (property === ELAPSED) {\n // @ts-ignore\n resolve({clusterId: peerConnection.key, elapsed: value});\n\n return true;\n }\n\n // pass thru\n return window.Reflect.set(target, property, value);\n },\n });\n\n // Using peerConnection proxy so handle functions below\n // won't be coupled to our promise implementation\n this.handleIceGatheringStateChange(peerConnectionProxy);\n this.handleOnIceCandidate(peerConnectionProxy);\n\n // Set maximum timeout\n window.setTimeout(() => {\n const {CLOSED} = CONNECTION_STATE;\n\n // Close any open peerConnections\n if (peerConnectionProxy.connectionState !== CLOSED) {\n this.setLatencyAndClose(peerConnectionProxy, null);\n }\n }, timeout);\n });\n }\n\n /**\n * Make a log of unreachable clusters.\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private logUnreachableClusters() {\n const list = this.getUnreachablClusters();\n\n list.forEach((cluster) => {\n LoggerProxy.logger.log(\n `Reachability:index#logUnreachableClusters --> No ice candidate for ${cluster}.`\n );\n });\n }\n\n /**\n * Calculates time to establish connection\n * @param {array} iceResults iceResults\n * @returns {object} reachabilityMap\n * @private\n * @memberof Reachability\n */\n private parseIceResultsToReachabilityResults(iceResults: Array<any>) {\n const reachabilityMap = {};\n\n iceResults.forEach(({clusterId, elapsed}) => {\n let latencyResult;\n\n if (elapsed === null) {\n latencyResult = {reachable: 'false'};\n } else {\n latencyResult = {\n reachable: 'true',\n latencyInMilliseconds: elapsed.toString(),\n };\n }\n\n reachabilityMap[clusterId] = {\n udp: latencyResult,\n tcp: latencyResult,\n };\n });\n\n return reachabilityMap;\n }\n\n /**\n * fetches reachability data\n * @param {object} clusterList\n * @returns {Promise<localSDPData>} reachability check results\n * @private\n * @memberof Reachability\n */\n private performReachabilityCheck(clusterList: object) {\n if (!clusterList || !Object.keys(clusterList).length) {\n return Promise.resolve({});\n }\n\n return new Promise((resolve) => {\n this.getLocalSDPForClusters(clusterList)\n .then((localSDPData) => {\n if (!localSDPData || !Object.keys(localSDPData).length) {\n // TODO: handle the error condition properly and try retry\n LoggerProxy.logger.log(\n 'Reachability:index#performReachabilityCheck --> Local SDP is empty or has missing elements..returning'\n );\n resolve({});\n } else {\n resolve(localSDPData);\n }\n })\n .catch((error) => {\n LoggerProxy.logger.error(\n `Reachability:index#performReachabilityCheck --> Error in getLocalSDPForClusters: ${error}`\n );\n resolve({});\n });\n });\n }\n\n /**\n * Records latency and closes the peerConnection\n * @param {RTCPeerConnection} peerConnection\n * @param {number} elapsed Latency in milliseconds\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setLatencyAndClose(peerConnection: RTCPeerConnection, elapsed: number) {\n const REACHABLE = 'reachable';\n const UNREACHABLE = 'unreachable';\n const {CLOSED} = CONNECTION_STATE;\n // @ts-ignore\n const {key} = peerConnection;\n const resultKey = elapsed === null ? UNREACHABLE : REACHABLE;\n const intialState = {[REACHABLE]: 0, [UNREACHABLE]: 0};\n\n if (peerConnection.connectionState === CLOSED) {\n LoggerProxy.logger.log(\n `Reachability:index#setLatencyAndClose --> Attempting to set latency of ${elapsed} on closed peerConnection.`\n );\n\n return;\n }\n\n this.clusterLatencyResults[key] = this.clusterLatencyResults[key] || intialState;\n this.clusterLatencyResults[key][resultKey] += 1;\n\n // Set to null in case this fired from\n // an event other than onIceCandidate\n peerConnection.onicecandidate = null;\n peerConnection.close();\n // @ts-ignore\n peerConnection.elapsed = elapsed;\n }\n\n /**\n * utility function\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setup() {\n this.clusterLatencyResults = {};\n }\n}\n"],"mappings":"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"}