@webex/plugin-meetings 3.8.0-next.3 → 3.8.0-next.31

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 (98) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/config.js +1 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/constants.js +1 -0
  6. package/dist/constants.js.map +1 -1
  7. package/dist/interpretation/index.js +4 -4
  8. package/dist/interpretation/index.js.map +1 -1
  9. package/dist/interpretation/siLanguage.js +1 -1
  10. package/dist/locus-info/controlsUtils.js +1 -1
  11. package/dist/locus-info/controlsUtils.js.map +1 -1
  12. package/dist/media/index.js +3 -15
  13. package/dist/media/index.js.map +1 -1
  14. package/dist/meeting/index.js +89 -5
  15. package/dist/meeting/index.js.map +1 -1
  16. package/dist/meeting/locusMediaRequest.js +21 -5
  17. package/dist/meeting/locusMediaRequest.js.map +1 -1
  18. package/dist/meeting/util.js +4 -1
  19. package/dist/meeting/util.js.map +1 -1
  20. package/dist/meeting-info/meeting-info-v2.js +359 -60
  21. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  22. package/dist/meetings/index.js +60 -1
  23. package/dist/meetings/index.js.map +1 -1
  24. package/dist/member/index.js +10 -0
  25. package/dist/member/index.js.map +1 -1
  26. package/dist/member/util.js +3 -0
  27. package/dist/member/util.js.map +1 -1
  28. package/dist/metrics/constants.js +9 -0
  29. package/dist/metrics/constants.js.map +1 -1
  30. package/dist/reachability/clusterReachability.js +52 -8
  31. package/dist/reachability/clusterReachability.js.map +1 -1
  32. package/dist/reachability/index.js +70 -45
  33. package/dist/reachability/index.js.map +1 -1
  34. package/dist/reachability/reachability.types.js +14 -0
  35. package/dist/reachability/reachability.types.js.map +1 -1
  36. package/dist/reachability/request.js +19 -3
  37. package/dist/reachability/request.js.map +1 -1
  38. package/dist/reconnection-manager/index.js +2 -2
  39. package/dist/reconnection-manager/index.js.map +1 -1
  40. package/dist/recording-controller/util.js +5 -5
  41. package/dist/recording-controller/util.js.map +1 -1
  42. package/dist/roap/index.js.map +1 -1
  43. package/dist/roap/turnDiscovery.js +31 -23
  44. package/dist/roap/turnDiscovery.js.map +1 -1
  45. package/dist/roap/types.js +17 -0
  46. package/dist/roap/types.js.map +1 -0
  47. package/dist/types/config.d.ts +1 -0
  48. package/dist/types/constants.d.ts +1 -0
  49. package/dist/types/meeting/index.d.ts +32 -1
  50. package/dist/types/meeting-info/meeting-info-v2.d.ts +80 -0
  51. package/dist/types/meetings/index.d.ts +29 -0
  52. package/dist/types/member/index.d.ts +1 -0
  53. package/dist/types/metrics/constants.d.ts +9 -0
  54. package/dist/types/reachability/clusterReachability.d.ts +13 -1
  55. package/dist/types/reachability/index.d.ts +2 -1
  56. package/dist/types/reachability/reachability.types.d.ts +5 -0
  57. package/dist/types/roap/index.d.ts +3 -2
  58. package/dist/types/roap/turnDiscovery.d.ts +1 -17
  59. package/dist/types/roap/types.d.ts +16 -0
  60. package/dist/webinar/index.js +1 -1
  61. package/package.json +22 -22
  62. package/src/config.ts +1 -0
  63. package/src/constants.ts +1 -0
  64. package/src/interpretation/index.ts +3 -3
  65. package/src/locus-info/controlsUtils.ts +2 -2
  66. package/src/media/index.ts +5 -21
  67. package/src/meeting/index.ts +91 -13
  68. package/src/meeting/locusMediaRequest.ts +27 -4
  69. package/src/meeting/util.ts +2 -1
  70. package/src/meeting-info/meeting-info-v2.ts +247 -6
  71. package/src/meetings/index.ts +72 -1
  72. package/src/member/index.ts +11 -0
  73. package/src/member/util.ts +3 -0
  74. package/src/metrics/constants.ts +9 -0
  75. package/src/reachability/clusterReachability.ts +47 -1
  76. package/src/reachability/index.ts +15 -0
  77. package/src/reachability/reachability.types.ts +6 -0
  78. package/src/reachability/request.ts +7 -0
  79. package/src/reconnection-manager/index.ts +2 -2
  80. package/src/recording-controller/util.ts +17 -13
  81. package/src/roap/index.ts +3 -7
  82. package/src/roap/turnDiscovery.ts +21 -35
  83. package/src/roap/types.ts +23 -0
  84. package/test/unit/spec/interpretation/index.ts +39 -1
  85. package/test/unit/spec/locus-info/controlsUtils.js +8 -0
  86. package/test/unit/spec/media/index.ts +6 -16
  87. package/test/unit/spec/meeting/index.js +212 -125
  88. package/test/unit/spec/meeting/locusMediaRequest.ts +96 -58
  89. package/test/unit/spec/meeting/utils.js +55 -0
  90. package/test/unit/spec/meeting-info/meetinginfov2.js +443 -114
  91. package/test/unit/spec/meetings/index.js +78 -1
  92. package/test/unit/spec/member/index.js +7 -0
  93. package/test/unit/spec/member/util.js +24 -0
  94. package/test/unit/spec/reachability/clusterReachability.ts +47 -1
  95. package/test/unit/spec/reachability/index.ts +12 -0
  96. package/test/unit/spec/reachability/request.js +47 -2
  97. package/test/unit/spec/reconnection-manager/index.js +4 -4
  98. package/test/unit/spec/roap/turnDiscovery.ts +72 -28
@@ -4,7 +4,7 @@
4
4
  import { Defer } from '@webex/common';
5
5
  import { IP_VERSION } from '../constants';
6
6
  import ReachabilityRequest, { ClusterList } from './request';
7
- import { ClusterReachabilityResult, ClientMediaPreferences, ReachabilityMetrics, ReachabilityReportV0, ReachabilityReportV1, ReachabilityResults, ReachabilityResultsForBackend, GetClustersTrigger } from './reachability.types';
7
+ import { ClusterReachabilityResult, ClientMediaPreferences, ReachabilityMetrics, ReachabilityReportV0, ReachabilityReportV1, ReachabilityResults, ReachabilityResultsForBackend, GetClustersTrigger, NatType } from './reachability.types';
8
8
  import { ClusterReachability } from './clusterReachability';
9
9
  import EventsScope from '../common/events/events-scope';
10
10
  /**
@@ -46,6 +46,7 @@ export default class Reachability extends EventsScope {
46
46
  };
47
47
  startTime: any;
48
48
  totalDuration: any;
49
+ natType: NatType;
49
50
  protected lastTrigger?: string;
50
51
  /**
51
52
  * Creates an instance of Reachability.
@@ -4,6 +4,10 @@ export type TransportResult = {
4
4
  latencyInMilliseconds?: number;
5
5
  clientMediaIPs?: string[];
6
6
  };
7
+ export declare enum NatType {
8
+ Unknown = "unknown",
9
+ SymmetricNat = "symmetric-nat"
10
+ }
7
11
  export type ClusterReachabilityResult = {
8
12
  udp: TransportResult;
9
13
  tcp: TransportResult;
@@ -22,6 +26,7 @@ export type ReachabilityMetrics = {
22
26
  reachability_vmn_tcp_failed: number;
23
27
  reachability_vmn_xtls_success: number;
24
28
  reachability_vmn_xtls_failed: number;
29
+ natType: NatType;
25
30
  };
26
31
  /**
27
32
  * This is the type that matches what backend expects us to send to them. It is a bit weird, because
@@ -1,7 +1,8 @@
1
1
  import { StatelessWebexPlugin } from '@webex/webex-core';
2
- import TurnDiscovery, { TurnDiscoveryResult } from './turnDiscovery';
2
+ import TurnDiscovery from './turnDiscovery';
3
+ import { TurnDiscoveryResult } from './types';
3
4
  import Meeting from '../meeting';
4
- export { type TurnDiscoveryResult, type TurnServerInfo, type TurnDiscoverySkipReason, } from './turnDiscovery';
5
+ export { type TurnDiscoveryResult, type TurnServerInfo, type TurnDiscoverySkipReason } from './types';
5
6
  /**
6
7
  * Roap options
7
8
  * @typedef {Object} RoapOptions
@@ -1,21 +1,6 @@
1
- import { Enum } from '../constants';
2
1
  import RoapRequest from './request';
3
2
  import Meeting from '../meeting';
4
- declare const TurnDiscoverySkipReason: {
5
- readonly missingHttpResponse: "missing http response";
6
- readonly reachability: "reachability";
7
- readonly alreadyInProgress: "already in progress";
8
- };
9
- export type TurnDiscoverySkipReason = Enum<typeof TurnDiscoverySkipReason> | string | undefined;
10
- export type TurnServerInfo = {
11
- url: string;
12
- username: string;
13
- password: string;
14
- };
15
- export type TurnDiscoveryResult = {
16
- turnServerInfo?: TurnServerInfo;
17
- turnDiscoverySkippedReason: TurnDiscoverySkipReason;
18
- };
3
+ import { TurnDiscoverySkipReason, TurnDiscoveryResult } from './types';
19
4
  /**
20
5
  * Handles the process of finding out TURN server information from Linus.
21
6
  * This is achieved by sending a TURN_DISCOVERY_REQUEST.
@@ -152,4 +137,3 @@ export default class TurnDiscovery {
152
137
  */
153
138
  doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean, isForced?: boolean): Promise<TurnDiscoveryResult>;
154
139
  }
155
- export {};
@@ -0,0 +1,16 @@
1
+ import { Enum } from '../constants';
2
+ export declare const TurnDiscoverySkipReason: {
3
+ readonly missingHttpResponse: "missing http response";
4
+ readonly reachability: "reachability";
5
+ readonly alreadyInProgress: "already in progress";
6
+ };
7
+ export type TurnDiscoverySkipReason = Enum<typeof TurnDiscoverySkipReason> | string | undefined;
8
+ export type TurnServerInfo = {
9
+ urls: string[];
10
+ username: string;
11
+ password: string;
12
+ };
13
+ export type TurnDiscoveryResult = {
14
+ turnServerInfo?: TurnServerInfo;
15
+ turnDiscoverySkippedReason: TurnDiscoverySkipReason;
16
+ };
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.8.0-next.3"
461
+ version: "3.8.0-next.31"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,13 +43,13 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.8.0-next.3",
47
- "@webex/plugin-rooms": "3.7.0-next.25",
48
- "@webex/test-helper-chai": "3.7.0-next.18",
49
- "@webex/test-helper-mocha": "3.7.0-next.18",
50
- "@webex/test-helper-mock-webex": "3.7.0-next.18",
51
- "@webex/test-helper-retry": "3.7.0-next.18",
52
- "@webex/test-helper-test-users": "3.7.0-next.18",
46
+ "@webex/plugin-meetings": "3.8.0-next.31",
47
+ "@webex/plugin-rooms": "3.8.0-next.13",
48
+ "@webex/test-helper-chai": "3.8.0-next.11",
49
+ "@webex/test-helper-mocha": "3.8.0-next.11",
50
+ "@webex/test-helper-mock-webex": "3.8.0-next.11",
51
+ "@webex/test-helper-retry": "3.8.0-next.11",
52
+ "@webex/test-helper-test-users": "3.8.0-next.11",
53
53
  "chai": "^4.3.4",
54
54
  "chai-as-promised": "^7.1.1",
55
55
  "eslint": "^8.24.0",
@@ -61,22 +61,22 @@
61
61
  "typescript": "^4.7.4"
62
62
  },
63
63
  "dependencies": {
64
- "@webex/common": "3.7.0-next.18",
64
+ "@webex/common": "3.8.0-next.11",
65
65
  "@webex/event-dictionary-ts": "^1.0.1688",
66
- "@webex/internal-media-core": "2.14.4",
67
- "@webex/internal-plugin-conversation": "3.7.0-next.25",
68
- "@webex/internal-plugin-device": "3.7.0-next.18",
69
- "@webex/internal-plugin-llm": "3.8.0-next.1",
70
- "@webex/internal-plugin-mercury": "3.7.0-next.23",
71
- "@webex/internal-plugin-metrics": "3.7.0-next.18",
72
- "@webex/internal-plugin-support": "3.7.0-next.26",
73
- "@webex/internal-plugin-user": "3.7.0-next.18",
74
- "@webex/internal-plugin-voicea": "3.8.0-next.3",
75
- "@webex/media-helpers": "3.7.0-next.25",
76
- "@webex/plugin-people": "3.7.0-next.23",
77
- "@webex/plugin-rooms": "3.7.0-next.25",
66
+ "@webex/internal-media-core": "2.14.7",
67
+ "@webex/internal-plugin-conversation": "3.8.0-next.13",
68
+ "@webex/internal-plugin-device": "3.8.0-next.11",
69
+ "@webex/internal-plugin-llm": "3.8.0-next.14",
70
+ "@webex/internal-plugin-mercury": "3.8.0-next.13",
71
+ "@webex/internal-plugin-metrics": "3.8.0-next.11",
72
+ "@webex/internal-plugin-support": "3.8.0-next.13",
73
+ "@webex/internal-plugin-user": "3.8.0-next.11",
74
+ "@webex/internal-plugin-voicea": "3.8.0-next.31",
75
+ "@webex/media-helpers": "3.8.0-next.12",
76
+ "@webex/plugin-people": "3.8.0-next.13",
77
+ "@webex/plugin-rooms": "3.8.0-next.13",
78
78
  "@webex/web-capabilities": "^1.4.0",
79
- "@webex/webex-core": "3.7.0-next.18",
79
+ "@webex/webex-core": "3.8.0-next.11",
80
80
  "ampersand-collection": "^2.0.2",
81
81
  "bowser": "^2.11.0",
82
82
  "btoa": "^1.2.1",
@@ -92,5 +92,5 @@
92
92
  "//": [
93
93
  "TODO: upgrade jwt-decode when moving to node 18"
94
94
  ],
95
- "version": "3.8.0-next.3"
95
+ "version": "3.8.0-next.31"
96
96
  }
package/src/config.ts CHANGED
@@ -95,6 +95,7 @@ export default {
95
95
  // This only applies to non-multistream meetings
96
96
  iceCandidatesGatheringTimeout: undefined,
97
97
  backendIpv6NativeSupport: false,
98
+ enableReachabilityChecks: true,
98
99
  reachabilityGetClusterTimeout: 5000,
99
100
  logUploadIntervalMultiplicationFactor: 0, // if set to 0 or undefined, logs won't be uploaded periodically, if you want periodic logs, recommended value is 1
100
101
  },
package/src/constants.ts CHANGED
@@ -904,6 +904,7 @@ export enum SELF_POLICY {
904
904
  ENFORCE_VIRTUAL_BACKGROUND = 'enforceVirtualBackground',
905
905
  SUPPORT_LOCAL_RECORD = 'supportLocalRecord',
906
906
  SUPPORT_NETWORK_BASED_RECORD = 'supportNetworkBasedRecord',
907
+ SUPPORT_PREMISE_RECORD = 'supportPremiseRecord',
907
908
  SUPPORT_REALTIME_CLOSE_CAPTION = 'supportRealtimeCloseCaption',
908
909
  SUPPORT_CHAT = 'supportChat',
909
910
  SUPPORT_DESKTOP_SHARE_REMOTE = 'supportDesktopShareRemote',
@@ -35,13 +35,13 @@ const SimultaneousInterpretation = WebexPlugin.extend({
35
35
  derived: {
36
36
  shouldQuerySupportLanguages: {
37
37
  cache: false,
38
- deps: ['canManageInterpreters', 'hostSIEnabled'],
38
+ deps: ['canManageInterpreters', 'hostSIEnabled', 'locusUrl'],
39
39
  /**
40
40
  * Returns should query support languages or not
41
41
  * @returns {boolean}
42
42
  */
43
43
  fn() {
44
- return !!(this.canManageInterpreters && this.hostSIEnabled);
44
+ return !!(this.canManageInterpreters && this.hostSIEnabled && this.locusUrl);
45
45
  },
46
46
  },
47
47
  },
@@ -51,7 +51,7 @@ const SimultaneousInterpretation = WebexPlugin.extend({
51
51
  */
52
52
  initialize() {
53
53
  this.listenTo(this, 'change:shouldQuerySupportLanguages', () => {
54
- if (this.canManageInterpreters && !this.supportLanguages) {
54
+ if (this.shouldQuerySupportLanguages && !this.supportLanguages) {
55
55
  this.querySupportLanguages();
56
56
  }
57
57
  });
@@ -206,8 +206,8 @@ ControlsUtils.getControls = (oldControls: any, newControls: any) => {
206
206
  ),
207
207
 
208
208
  hasPracticeSessionEnabledChanged: !isEqual(
209
- previous?.practiceSession?.enabled,
210
- current?.practiceSession?.enabled
209
+ !!previous?.practiceSession?.enabled,
210
+ !!current?.practiceSession?.enabled
211
211
  ),
212
212
 
213
213
  hasStageViewChanged: !isEqual(previous?.videoLayout, current?.videoLayout),
@@ -21,6 +21,7 @@ import {MEDIA_TRACK_CONSTRAINT} from '../constants';
21
21
  import Config from '../config';
22
22
  import StaticConfig from '../common/config';
23
23
  import BrowserDetection from '../common/browser-detection';
24
+ import {TurnServerInfo} from '../roap/types';
24
25
 
25
26
  const {isBrowser} = BrowserDetection();
26
27
 
@@ -138,11 +139,7 @@ Media.createMediaConnection = (
138
139
  remoteQualityLevel?: 'LOW' | 'MEDIUM' | 'HIGH';
139
140
  enableRtx?: boolean;
140
141
  enableExtmap?: boolean;
141
- turnServerInfo?: {
142
- url: string;
143
- username: string;
144
- password: string;
145
- };
142
+ turnServerInfo?: TurnServerInfo;
146
143
  bundlePolicy?: BundlePolicy;
147
144
  iceCandidatesTimeout?: number;
148
145
  }
@@ -160,24 +157,11 @@ Media.createMediaConnection = (
160
157
 
161
158
  const iceServers = [];
162
159
 
163
- // we might not have any TURN server if TURN discovery failed or wasn't done or
164
- // we might get an empty TURN url if we land on a video mesh node
165
- if (turnServerInfo?.url) {
166
- if (!isBrowser('firefox')) {
167
- let bareTurnServer = turnServerInfo.url;
168
- bareTurnServer = bareTurnServer.replace('turns:', 'turn:');
169
- bareTurnServer = bareTurnServer.replace('443', '5004');
170
-
171
- iceServers.push({
172
- urls: bareTurnServer,
173
- username: turnServerInfo.username || '',
174
- credential: turnServerInfo.password || '',
175
- });
176
- }
177
-
160
+ // we might not have any TURN server if TURN discovery failed or wasn't done or we land on a video mesh node
161
+ if (turnServerInfo?.urls.length > 0) {
178
162
  // TURN-TLS server
179
163
  iceServers.push({
180
- urls: turnServerInfo.url,
164
+ urls: turnServerInfo.urls,
181
165
  username: turnServerInfo.username || '',
182
166
  credential: turnServerInfo.password || '',
183
167
  });
@@ -60,11 +60,8 @@ import {
60
60
  import LoggerProxy from '../common/logs/logger-proxy';
61
61
  import EventsUtil from '../common/events/util';
62
62
  import Trigger from '../common/events/trigger-proxy';
63
- import Roap, {
64
- type TurnDiscoveryResult,
65
- type TurnServerInfo,
66
- type TurnDiscoverySkipReason,
67
- } from '../roap/index';
63
+ import Roap, {type TurnDiscoveryResult, type TurnDiscoverySkipReason} from '../roap/index';
64
+ import {type TurnServerInfo} from '../roap/types';
68
65
  import Media, {type BundlePolicy} from '../media';
69
66
  import MediaProperties from '../media/properties';
70
67
  import MeetingStateMachine from './state';
@@ -241,6 +238,8 @@ export type CallStateForMetrics = {
241
238
  sessionCorrelationId?: string;
242
239
  joinTrigger?: string;
243
240
  loginType?: string;
241
+ userNameInput?: string;
242
+ emailInput?: string;
244
243
  };
245
244
 
246
245
  export const MEDIA_UPDATE_TYPE = {
@@ -1627,6 +1626,38 @@ export default class Meeting extends StatelessWebexPlugin {
1627
1626
  this.callStateForMetrics.correlationId = correlationId;
1628
1627
  }
1629
1628
 
1629
+ /**
1630
+ * Getter - Returns callStateForMetrics.userNameInput
1631
+ * @returns {string}
1632
+ */
1633
+ get userNameInput() {
1634
+ return this.callStateForMetrics?.userNameInput;
1635
+ }
1636
+
1637
+ /**
1638
+ * Setter - sets callStateForMetrics.userNameInput
1639
+ * @param {string} userNameInput
1640
+ */
1641
+ set userNameInput(userNameInput: string) {
1642
+ this.callStateForMetrics.userNameInput = userNameInput;
1643
+ }
1644
+
1645
+ /**
1646
+ * Getter - Returns callStateForMetrics.emailInput
1647
+ * @returns {string}
1648
+ */
1649
+ get emailInput() {
1650
+ return this.callStateForMetrics?.emailInput;
1651
+ }
1652
+
1653
+ /**
1654
+ * Setter - sets callStateForMetrics.emailInput
1655
+ * @param {string} emailInput
1656
+ */
1657
+ set emailInput(emailInput: string) {
1658
+ this.callStateForMetrics.emailInput = emailInput;
1659
+ }
1660
+
1630
1661
  /**
1631
1662
  * Getter - Returns callStateForMetrics.sessionCorrelationId
1632
1663
  * @returns {string}
@@ -1652,6 +1683,33 @@ export default class Meeting extends StatelessWebexPlugin {
1652
1683
  return this.#isoLocalClientMeetingJoinTime;
1653
1684
  }
1654
1685
 
1686
+ /**
1687
+ * Setter - sets isoLocalClientMeetingJoinTime
1688
+ * This will be set once on meeting join, and not updated again
1689
+ * this will always produce an ISO string
1690
+ * If the iso string is invalid, it will fallback to the current system time
1691
+ * @param {string | undefined} time
1692
+ */
1693
+ set isoLocalClientMeetingJoinTime(time: string | undefined) {
1694
+ const fallback = new Date().toISOString();
1695
+ if (!time) {
1696
+ this.#isoLocalClientMeetingJoinTime = fallback;
1697
+ } else {
1698
+ const date = new Date(time);
1699
+
1700
+ // Check if the date is valid
1701
+ if (Number.isNaN(date.getTime())) {
1702
+ LoggerProxy.logger.info(
1703
+ // @ts-ignore
1704
+ `Meeting:index#isoLocalClientMeetingJoinTime --> Invalid date provided: ${time}. Falling back to system clock.`
1705
+ );
1706
+ this.#isoLocalClientMeetingJoinTime = fallback;
1707
+ } else {
1708
+ this.#isoLocalClientMeetingJoinTime = date.toISOString();
1709
+ }
1710
+ }
1711
+ }
1712
+
1655
1713
  /**
1656
1714
  * Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
1657
1715
  * @param {any} info
@@ -5684,8 +5742,6 @@ export default class Meeting extends StatelessWebexPlugin {
5684
5742
  // @ts-ignore
5685
5743
  this.webex.internal.device.meetingStarted();
5686
5744
 
5687
- this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
5688
-
5689
5745
  LoggerProxy.logger.log('Meeting:index#join --> Success');
5690
5746
 
5691
5747
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
@@ -6146,10 +6202,7 @@ export default class Meeting extends StatelessWebexPlugin {
6146
6202
  },
6147
6203
  options: {meetingId: this.id, rawError: error},
6148
6204
  });
6149
- } else if (
6150
- error instanceof Errors.SdpOfferHandlingError ||
6151
- error instanceof Errors.SdpAnswerHandlingError
6152
- ) {
6205
+ } else if (error instanceof Errors.SdpOfferHandlingError) {
6153
6206
  sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
6154
6207
 
6155
6208
  // @ts-ignore
@@ -6160,6 +6213,24 @@ export default class Meeting extends StatelessWebexPlugin {
6160
6213
  },
6161
6214
  options: {meetingId: this.id, rawError: error},
6162
6215
  });
6216
+ } else if (error instanceof Errors.SdpAnswerHandlingError) {
6217
+ sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
6218
+
6219
+ // @ts-ignore
6220
+ this.webex.internal.newMetrics.submitClientEvent({
6221
+ name: 'client.media-engine.remote-sdp-received',
6222
+ payload: {
6223
+ canProceed: false,
6224
+ },
6225
+ options: {meetingId: this.id, rawError: error},
6226
+ });
6227
+
6228
+ if (this.deferSDPAnswer) {
6229
+ clearTimeout(this.sdpResponseTimer);
6230
+ this.sdpResponseTimer = undefined;
6231
+
6232
+ this.deferSDPAnswer.reject();
6233
+ }
6163
6234
  } else if (error instanceof Errors.SdpError) {
6164
6235
  // this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
6165
6236
  sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.correlationId);
@@ -6796,7 +6867,10 @@ export default class Meeting extends StatelessWebexPlugin {
6796
6867
  * @param {AddMediaOptions} [options] Options for enabling/disabling audio/video
6797
6868
  * @returns {RoapMediaConnection | MultistreamRoapMediaConnection}
6798
6869
  */
6799
- private async createMediaConnection(turnServerInfo, bundlePolicy?: BundlePolicy) {
6870
+ private async createMediaConnection(
6871
+ turnServerInfo?: TurnServerInfo,
6872
+ bundlePolicy?: BundlePolicy
6873
+ ) {
6800
6874
  this.rtcMetrics = this.isMultistream
6801
6875
  ? // @ts-ignore
6802
6876
  new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
@@ -8681,6 +8755,9 @@ export default class Meeting extends StatelessWebexPlugin {
8681
8755
  LoggerProxy.logger.log(
8682
8756
  `Meeting:index#handleShareVideoStreamMuteStateChange --> Share video stream mute state changed to muted ${muted}`
8683
8757
  );
8758
+
8759
+ const shareVideoStreamSettings = this.mediaProperties?.shareVideoStream?.getSettings();
8760
+
8684
8761
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
8685
8762
  correlationId: this.correlationId,
8686
8763
  muted,
@@ -8689,8 +8766,9 @@ export default class Meeting extends StatelessWebexPlugin {
8689
8766
  // SDK to TypeScript 5, which may affect other packages, use bracket notation for now, since
8690
8767
  // all we're doing here is adding metrics.
8691
8768
  // eslint-disable-next-line dot-notation
8692
- displaySurface: this.mediaProperties?.shareVideoStream?.getSettings()['displaySurface'],
8769
+ displaySurface: shareVideoStreamSettings?.['displaySurface'],
8693
8770
  isMultistream: this.isMultistream,
8771
+ frameRate: shareVideoStreamSettings?.frameRate,
8694
8772
  });
8695
8773
  };
8696
8774
 
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable valid-jsdoc */
2
2
  import {defer} from 'lodash';
3
- import {Defer} from '@webex/common';
3
+ import {Defer, transferEvents} from '@webex/common';
4
+ import {EventEmitter} from 'events';
4
5
  import {WebexPlugin} from '@webex/webex-core';
5
6
  import {MEDIA, HTTP_VERBS, ROAP} from '../constants';
6
7
  import LoggerProxy from '../common/logs/logger-proxy';
@@ -250,12 +251,19 @@ export class LocusMediaRequest extends WebexPlugin {
250
251
  this.confluenceState = 'creation in progress';
251
252
  }
252
253
 
253
- // @ts-ignore
254
- return this.request({
254
+ const upload = new EventEmitter();
255
+ const download = new EventEmitter();
256
+
257
+ const options = {
255
258
  method: HTTP_VERBS.PUT,
256
259
  uri,
257
260
  body,
258
- })
261
+ upload,
262
+ download,
263
+ };
264
+
265
+ // @ts-ignore
266
+ const promise = this.request(options)
259
267
  .then((result) => {
260
268
  if (isRequestAffectingConfluenceState(request)) {
261
269
  this.confluenceState = 'created';
@@ -294,6 +302,21 @@ export class LocusMediaRequest extends WebexPlugin {
294
302
 
295
303
  throw e;
296
304
  });
305
+
306
+ if (request.type === 'RoapMessage') {
307
+ const setupProgressListener = (direction: string, eventEmitter: EventEmitter) => {
308
+ eventEmitter.on('progress', (progressEvent: ProgressEvent) => {
309
+ LoggerProxy.logger.info(
310
+ `${request.type}: ${direction} Progress, Timestamp: ${progressEvent.timeStamp}, Progress: ${progressEvent.loaded}/${progressEvent.total}`
311
+ );
312
+ });
313
+ };
314
+
315
+ setupProgressListener('Upload', options.upload);
316
+ setupProgressListener('Download', options.download);
317
+ }
318
+
319
+ return promise;
297
320
  }
298
321
 
299
322
  /**
@@ -176,11 +176,12 @@ const MeetingUtil = {
176
176
  deviceCapabilities: options.deviceCapabilities,
177
177
  liveAnnotationSupported: options.liveAnnotationSupported,
178
178
  clientMediaPreferences,
179
+ alias: options.alias,
179
180
  })
180
181
  .then((res) => {
181
182
  const parsed = MeetingUtil.parseLocusJoin(res);
182
183
  meeting.setLocus(parsed);
183
-
184
+ meeting.isoLocalClientMeetingJoinTime = res?.headers?.date; // read from header if exist, else fall back to system clock : https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-555657
184
185
  webex.internal.newMetrics.submitClientEvent({
185
186
  name: 'client.locus.join.response',
186
187
  payload: {