@webex/calling 3.8.1 → 3.9.0-multi-llms.2

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 (193) hide show
  1. package/dist/CallHistory/CallHistory.js +51 -46
  2. package/dist/CallHistory/CallHistory.js.map +1 -1
  3. package/dist/CallHistory/CallHistory.test.js +146 -147
  4. package/dist/CallHistory/CallHistory.test.js.map +1 -1
  5. package/dist/CallHistory/callHistoryFixtures.js.map +1 -1
  6. package/dist/CallHistory/constants.js.map +1 -1
  7. package/dist/CallHistory/types.js.map +1 -1
  8. package/dist/CallSettings/CallSettings.js +8 -8
  9. package/dist/CallSettings/CallSettings.js.map +1 -1
  10. package/dist/CallSettings/CallSettings.test.js +1 -1
  11. package/dist/CallSettings/CallSettings.test.js.map +1 -1
  12. package/dist/CallSettings/UcmBackendConnector.js +12 -11
  13. package/dist/CallSettings/UcmBackendConnector.js.map +1 -1
  14. package/dist/CallSettings/UcmBackendConnector.test.js +9 -10
  15. package/dist/CallSettings/UcmBackendConnector.test.js.map +1 -1
  16. package/dist/CallSettings/WxCallBackendConnector.js +68 -61
  17. package/dist/CallSettings/WxCallBackendConnector.js.map +1 -1
  18. package/dist/CallSettings/WxCallBackendConnector.test.js +168 -102
  19. package/dist/CallSettings/WxCallBackendConnector.test.js.map +1 -1
  20. package/dist/CallSettings/constants.js.map +1 -1
  21. package/dist/CallSettings/testFixtures.js.map +1 -1
  22. package/dist/CallSettings/types.js.map +1 -1
  23. package/dist/CallingClient/CallingClient.js +530 -219
  24. package/dist/CallingClient/CallingClient.js.map +1 -1
  25. package/dist/CallingClient/CallingClient.test.js +500 -291
  26. package/dist/CallingClient/CallingClient.test.js.map +1 -1
  27. package/dist/CallingClient/callRecordFixtures.js.map +1 -1
  28. package/dist/CallingClient/calling/CallerId/index.js +2 -2
  29. package/dist/CallingClient/calling/CallerId/index.js.map +1 -1
  30. package/dist/CallingClient/calling/CallerId/index.test.js +8 -7
  31. package/dist/CallingClient/calling/CallerId/index.test.js.map +1 -1
  32. package/dist/CallingClient/calling/CallerId/types.js.map +1 -1
  33. package/dist/CallingClient/calling/call.js +369 -333
  34. package/dist/CallingClient/calling/call.js.map +1 -1
  35. package/dist/CallingClient/calling/call.test.js +411 -410
  36. package/dist/CallingClient/calling/call.test.js.map +1 -1
  37. package/dist/CallingClient/calling/callManager.js +3 -4
  38. package/dist/CallingClient/calling/callManager.js.map +1 -1
  39. package/dist/CallingClient/calling/callManager.test.js +67 -68
  40. package/dist/CallingClient/calling/callManager.test.js.map +1 -1
  41. package/dist/CallingClient/calling/index.js.map +1 -1
  42. package/dist/CallingClient/calling/types.js.map +1 -1
  43. package/dist/CallingClient/callingClientFixtures.js.map +1 -1
  44. package/dist/CallingClient/constants.js +11 -8
  45. package/dist/CallingClient/constants.js.map +1 -1
  46. package/dist/CallingClient/line/index.js +10 -11
  47. package/dist/CallingClient/line/index.js.map +1 -1
  48. package/dist/CallingClient/line/line.test.js +12 -17
  49. package/dist/CallingClient/line/line.test.js.map +1 -1
  50. package/dist/CallingClient/line/types.js.map +1 -1
  51. package/dist/CallingClient/registration/index.js.map +1 -1
  52. package/dist/CallingClient/registration/register.js +557 -442
  53. package/dist/CallingClient/registration/register.js.map +1 -1
  54. package/dist/CallingClient/registration/register.test.js +526 -395
  55. package/dist/CallingClient/registration/register.test.js.map +1 -1
  56. package/dist/CallingClient/registration/registerFixtures.js.map +1 -1
  57. package/dist/CallingClient/registration/types.js.map +1 -1
  58. package/dist/CallingClient/registration/webWorker.js +116 -0
  59. package/dist/CallingClient/registration/webWorker.js.map +1 -0
  60. package/dist/CallingClient/registration/webWorker.test.js +256 -0
  61. package/dist/CallingClient/registration/webWorker.test.js.map +1 -0
  62. package/dist/CallingClient/registration/webWorkerStr.js +15 -0
  63. package/dist/CallingClient/registration/webWorkerStr.js.map +1 -0
  64. package/dist/CallingClient/types.js.map +1 -1
  65. package/dist/CallingClient/windowsChromiumIceWarmupUtils.js +142 -0
  66. package/dist/CallingClient/windowsChromiumIceWarmupUtils.js.map +1 -0
  67. package/dist/Contacts/ContactsClient.js +244 -238
  68. package/dist/Contacts/ContactsClient.js.map +1 -1
  69. package/dist/Contacts/ContactsClient.test.js +89 -90
  70. package/dist/Contacts/ContactsClient.test.js.map +1 -1
  71. package/dist/Contacts/constants.js +2 -2
  72. package/dist/Contacts/constants.js.map +1 -1
  73. package/dist/Contacts/contactFixtures.js.map +1 -1
  74. package/dist/Contacts/types.js.map +1 -1
  75. package/dist/Errors/catalog/CallError.js +2 -2
  76. package/dist/Errors/catalog/CallError.js.map +1 -1
  77. package/dist/Errors/catalog/CallingDeviceError.js +2 -2
  78. package/dist/Errors/catalog/CallingDeviceError.js.map +1 -1
  79. package/dist/Errors/catalog/ExtendedError.js +3 -3
  80. package/dist/Errors/catalog/ExtendedError.js.map +1 -1
  81. package/dist/Errors/catalog/LineError.js +2 -2
  82. package/dist/Errors/catalog/LineError.js.map +1 -1
  83. package/dist/Errors/index.js.map +1 -1
  84. package/dist/Errors/types.js +2 -0
  85. package/dist/Errors/types.js.map +1 -1
  86. package/dist/Events/impl/index.js +2 -2
  87. package/dist/Events/impl/index.js.map +1 -1
  88. package/dist/Events/types.js.map +1 -1
  89. package/dist/Logger/index.js.map +1 -1
  90. package/dist/Logger/index.test.js.map +1 -1
  91. package/dist/Logger/types.js.map +1 -1
  92. package/dist/Metrics/index.js +175 -86
  93. package/dist/Metrics/index.js.map +1 -1
  94. package/dist/Metrics/index.test.js +70 -4
  95. package/dist/Metrics/index.test.js.map +1 -1
  96. package/dist/Metrics/types.js +15 -1
  97. package/dist/Metrics/types.js.map +1 -1
  98. package/dist/SDKConnector/index.js +0 -1
  99. package/dist/SDKConnector/index.js.map +1 -1
  100. package/dist/SDKConnector/index.test.js.map +1 -1
  101. package/dist/SDKConnector/types.js.map +1 -1
  102. package/dist/SDKConnector/utils.js.map +1 -1
  103. package/dist/SDKConnector/utils.test.js.map +1 -1
  104. package/dist/Voicemail/BroadworksBackendConnector.js +42 -39
  105. package/dist/Voicemail/BroadworksBackendConnector.js.map +1 -1
  106. package/dist/Voicemail/BroadworksBackendConnector.test.js +119 -120
  107. package/dist/Voicemail/BroadworksBackendConnector.test.js.map +1 -1
  108. package/dist/Voicemail/UcmBackendConnector.js +54 -47
  109. package/dist/Voicemail/UcmBackendConnector.js.map +1 -1
  110. package/dist/Voicemail/UcmBackendConnector.test.js +73 -74
  111. package/dist/Voicemail/UcmBackendConnector.test.js.map +1 -1
  112. package/dist/Voicemail/Voicemail.js +12 -11
  113. package/dist/Voicemail/Voicemail.js.map +1 -1
  114. package/dist/Voicemail/Voicemail.test.js +2 -2
  115. package/dist/Voicemail/Voicemail.test.js.map +1 -1
  116. package/dist/Voicemail/WxCallBackendConnector.js +78 -70
  117. package/dist/Voicemail/WxCallBackendConnector.js.map +1 -1
  118. package/dist/Voicemail/WxCallBackendConnector.test.js +184 -185
  119. package/dist/Voicemail/WxCallBackendConnector.test.js.map +1 -1
  120. package/dist/Voicemail/constants.js.map +1 -1
  121. package/dist/Voicemail/types.js.map +1 -1
  122. package/dist/Voicemail/voicemailFixture.js.map +1 -1
  123. package/dist/api.js.map +1 -1
  124. package/dist/common/Utils.js +125 -99
  125. package/dist/common/Utils.js.map +1 -1
  126. package/dist/common/Utils.test.js +283 -143
  127. package/dist/common/Utils.test.js.map +1 -1
  128. package/dist/common/constants.js.map +1 -1
  129. package/dist/common/index.js.map +1 -1
  130. package/dist/common/testUtil.js +1 -1
  131. package/dist/common/testUtil.js.map +1 -1
  132. package/dist/common/types.js +8 -1
  133. package/dist/common/types.js.map +1 -1
  134. package/dist/index.js +5 -5
  135. package/dist/index.js.map +1 -1
  136. package/dist/module/CallHistory/CallHistory.js +4 -0
  137. package/dist/module/CallSettings/UcmBackendConnector.js +1 -0
  138. package/dist/module/CallSettings/WxCallBackendConnector.js +8 -1
  139. package/dist/module/CallingClient/CallingClient.js +199 -42
  140. package/dist/module/CallingClient/calling/call.js +79 -43
  141. package/dist/module/CallingClient/constants.js +10 -6
  142. package/dist/module/CallingClient/line/index.js +3 -3
  143. package/dist/module/CallingClient/registration/register.js +111 -72
  144. package/dist/module/CallingClient/registration/webWorker.js +60 -0
  145. package/dist/module/CallingClient/registration/webWorkerStr.js +93 -0
  146. package/dist/module/CallingClient/windowsChromiumIceWarmupUtils.js +59 -0
  147. package/dist/module/Contacts/ContactsClient.js +23 -17
  148. package/dist/module/Contacts/constants.js +1 -1
  149. package/dist/module/Errors/types.js +2 -0
  150. package/dist/module/Metrics/index.js +94 -33
  151. package/dist/module/Metrics/types.js +14 -0
  152. package/dist/module/Voicemail/BroadworksBackendConnector.js +3 -0
  153. package/dist/module/Voicemail/UcmBackendConnector.js +6 -0
  154. package/dist/module/Voicemail/WxCallBackendConnector.js +8 -0
  155. package/dist/module/common/Utils.js +37 -12
  156. package/dist/module/common/types.js +7 -0
  157. package/dist/types/CallHistory/CallHistory.d.ts.map +1 -1
  158. package/dist/types/CallSettings/UcmBackendConnector.d.ts.map +1 -1
  159. package/dist/types/CallSettings/WxCallBackendConnector.d.ts.map +1 -1
  160. package/dist/types/CallSettings/types.d.ts +1 -1
  161. package/dist/types/CallSettings/types.d.ts.map +1 -1
  162. package/dist/types/CallingClient/CallingClient.d.ts +12 -1
  163. package/dist/types/CallingClient/CallingClient.d.ts.map +1 -1
  164. package/dist/types/CallingClient/calling/call.d.ts.map +1 -1
  165. package/dist/types/CallingClient/calling/types.d.ts +2 -1
  166. package/dist/types/CallingClient/calling/types.d.ts.map +1 -1
  167. package/dist/types/CallingClient/constants.d.ts +10 -6
  168. package/dist/types/CallingClient/constants.d.ts.map +1 -1
  169. package/dist/types/CallingClient/line/index.d.ts.map +1 -1
  170. package/dist/types/CallingClient/registration/register.d.ts +2 -2
  171. package/dist/types/CallingClient/registration/register.d.ts.map +1 -1
  172. package/dist/types/CallingClient/registration/types.d.ts.map +1 -1
  173. package/dist/types/CallingClient/registration/webWorker.d.ts +3 -0
  174. package/dist/types/CallingClient/registration/webWorker.d.ts.map +1 -0
  175. package/dist/types/CallingClient/registration/webWorkerStr.d.ts +3 -0
  176. package/dist/types/CallingClient/registration/webWorkerStr.d.ts.map +1 -0
  177. package/dist/types/CallingClient/windowsChromiumIceWarmupUtils.d.ts +5 -0
  178. package/dist/types/CallingClient/windowsChromiumIceWarmupUtils.d.ts.map +1 -0
  179. package/dist/types/Contacts/ContactsClient.d.ts.map +1 -1
  180. package/dist/types/Contacts/constants.d.ts +1 -1
  181. package/dist/types/Contacts/constants.d.ts.map +1 -1
  182. package/dist/types/Errors/types.d.ts +2 -0
  183. package/dist/types/Errors/types.d.ts.map +1 -1
  184. package/dist/types/Metrics/index.d.ts.map +1 -1
  185. package/dist/types/Metrics/types.d.ts +20 -4
  186. package/dist/types/Metrics/types.d.ts.map +1 -1
  187. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts.map +1 -1
  188. package/dist/types/Voicemail/UcmBackendConnector.d.ts.map +1 -1
  189. package/dist/types/Voicemail/WxCallBackendConnector.d.ts.map +1 -1
  190. package/dist/types/common/Utils.d.ts.map +1 -1
  191. package/dist/types/common/types.d.ts +13 -0
  192. package/dist/types/common/types.d.ts.map +1 -1
  193. package/package.json +10 -8
@@ -1,13 +1,14 @@
1
1
  import { v4 as uuid } from 'uuid';
2
2
  import { METHOD_START_MESSAGE } from '../../common/constants';
3
3
  import { emitFinalFailure, handleRegistrationErrors, uploadLogs } from '../../common';
4
- import { METRIC_EVENT, METRIC_TYPE, REG_ACTION } from '../../Metrics/types';
4
+ import webWorkerStr from './webWorkerStr';
5
+ import { METRIC_EVENT, METRIC_TYPE, REG_ACTION, } from '../../Metrics/types';
5
6
  import { getMetricManager } from '../../Metrics';
6
7
  import { getCallManager } from '../calling';
7
8
  import log from '../../Logger';
8
9
  import SDKConnector from '../../SDKConnector';
9
- import { ALLOWED_SERVICES, HTTP_METHODS, RegistrationStatus, ServiceIndicator, } from '../../common/types';
10
- import { CALLING_USER_AGENT, CISCO_DEVICE_URL, DEVICES_ENDPOINT_RESOURCE, SPARK_USER_AGENT, WEBEX_WEB_CLIENT, BASE_REG_RETRY_TIMER_VAL_IN_SEC, BASE_REG_TIMER_MFACTOR, SEC_TO_MSEC_MFACTOR, REG_RANDOM_T_FACTOR_UPPER_LIMIT, REG_TRY_BACKUP_TIMER_VAL_IN_SEC, MINUTES_TO_SEC_MFACTOR, REG_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC, FAILOVER_UTIL, REGISTER_UTIL, RETRY_TIMER_UPPER_LIMIT, METHODS, } from '../constants';
10
+ import { ALLOWED_SERVICES, HTTP_METHODS, RegistrationStatus, ServiceIndicator, WorkerMessageType, } from '../../common/types';
11
+ import { CALLING_USER_AGENT, CISCO_DEVICE_URL, DEVICES_ENDPOINT_RESOURCE, SPARK_USER_AGENT, WEBEX_WEB_CLIENT, BASE_REG_RETRY_TIMER_VAL_IN_SEC, BASE_REG_TIMER_MFACTOR, SEC_TO_MSEC_MFACTOR, REG_RANDOM_T_FACTOR_UPPER_LIMIT, REG_TRY_BACKUP_TIMER_VAL_IN_SEC, MINUTES_TO_SEC_MFACTOR, REG_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, FAILOVER_UTIL, REGISTER_UTIL, RETRY_TIMER_UPPER_LIMIT, KEEPALIVE_UTIL, REGISTRATION_UTIL, METHODS, URL_ENDPOINT, } from '../constants';
11
12
  import { LINE_EVENTS } from '../line/types';
12
13
  export class Registration {
13
14
  sdkConnector;
@@ -18,7 +19,6 @@ export class Registration {
18
19
  registrationStatus;
19
20
  failbackTimer;
20
21
  activeMobiusUrl;
21
- keepaliveTimer;
22
22
  rehomingIntervalMin;
23
23
  rehomingIntervalMax;
24
24
  mutex;
@@ -35,6 +35,7 @@ export class Registration {
35
35
  failoverImmediately = false;
36
36
  retryAfter;
37
37
  scheduled429Retry = false;
38
+ webWorker;
38
39
  constructor(webex, serviceData, mutex, lineEmitter, logLevel, jwe) {
39
40
  this.jwe = jwe;
40
41
  this.sdkConnector = SDKConnector;
@@ -73,17 +74,6 @@ export class Registration {
73
74
  this.primaryMobiusUris = primaryMobiusUris;
74
75
  this.backupMobiusUris = backupMobiusUris;
75
76
  }
76
- async postKeepAlive(url) {
77
- return this.webex.request({
78
- uri: `${url}/status`,
79
- method: HTTP_METHODS.POST,
80
- headers: {
81
- [CISCO_DEVICE_URL]: this.webex.internal.device.url,
82
- [SPARK_USER_AGENT]: CALLING_USER_AGENT,
83
- },
84
- service: ALLOWED_SERVICES.MOBIUS,
85
- });
86
- }
87
77
  async deleteRegistration(url, deviceId, deviceUrl) {
88
78
  let response;
89
79
  try {
@@ -100,8 +90,9 @@ export class Registration {
100
90
  catch (error) {
101
91
  log.warn(`Delete failed with Mobius ${error}`, {
102
92
  file: REGISTRATION_FILE,
103
- method: METHODS.DEREGISTER,
93
+ method: METHODS.DELETE_REGISTRATION,
104
94
  });
95
+ await uploadLogs();
105
96
  }
106
97
  this.setStatus(RegistrationStatus.INACTIVE);
107
98
  this.lineEmitter(LINE_EVENTS.UNREGISTERED);
@@ -167,9 +158,7 @@ export class Registration {
167
158
  method: FAILOVER_UTIL,
168
159
  };
169
160
  let interval = this.getRegRetryInterval(attempt);
170
- const TIMER_THRESHOLD = this.isCCFlow
171
- ? REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC
172
- : REG_TRY_BACKUP_TIMER_VAL_IN_SEC;
161
+ const TIMER_THRESHOLD = REG_TRY_BACKUP_TIMER_VAL_IN_SEC;
173
162
  if (timeElapsed + interval > TIMER_THRESHOLD) {
174
163
  const excessVal = timeElapsed + interval - TIMER_THRESHOLD;
175
164
  interval -= excessVal;
@@ -230,6 +219,40 @@ export class Registration {
230
219
  this.failbackTimer = undefined;
231
220
  }
232
221
  }
222
+ async isPrimaryActive() {
223
+ let status;
224
+ for (const mobiusUrl of this.primaryMobiusUris) {
225
+ try {
226
+ const baseUri = mobiusUrl.replace(URL_ENDPOINT, '/');
227
+ const response = await this.webex.request({
228
+ uri: `${baseUri}ping`,
229
+ method: HTTP_METHODS.GET,
230
+ headers: {
231
+ [CISCO_DEVICE_URL]: this.webex.internal.device.url,
232
+ [SPARK_USER_AGENT]: CALLING_USER_AGENT,
233
+ },
234
+ service: ALLOWED_SERVICES.MOBIUS,
235
+ });
236
+ const { statusCode } = response;
237
+ if (statusCode === 200) {
238
+ log.info(`Ping successful for primary Mobius: ${mobiusUrl}`, {
239
+ file: REGISTRATION_FILE,
240
+ method: FAILBACK_UTIL,
241
+ });
242
+ status = 'up';
243
+ break;
244
+ }
245
+ }
246
+ catch (error) {
247
+ log.warn(`Ping failed for primary Mobius: ${mobiusUrl} with error: ${error}`, {
248
+ file: REGISTRATION_FILE,
249
+ method: FAILBACK_UTIL,
250
+ });
251
+ status = 'down';
252
+ }
253
+ }
254
+ return status === 'up';
255
+ }
233
256
  isFailbackRequired() {
234
257
  return this.isDeviceRegistered() && this.primaryMobiusUris.indexOf(this.activeMobiusUrl) === -1;
235
258
  }
@@ -260,7 +283,8 @@ export class Registration {
260
283
  async executeFailback() {
261
284
  await this.mutex.runExclusive(async () => {
262
285
  if (this.isFailbackRequired()) {
263
- if (Object.keys(this.callManager.getActiveCalls()).length === 0) {
286
+ const primaryServerStatus = await this.isPrimaryActive();
287
+ if (Object.keys(this.callManager.getActiveCalls()).length === 0 && primaryServerStatus) {
264
288
  log.info(`Attempting failback to primary.`, {
265
289
  file: REGISTRATION_FILE,
266
290
  method: this.executeFailback.name,
@@ -284,7 +308,7 @@ export class Registration {
284
308
  }
285
309
  }
286
310
  else {
287
- log.info('Active calls present, deferring failback to next cycle.', {
311
+ log.info('Active calls present or primary Mobius is down, deferring failback to next cycle.', {
288
312
  file: REGISTRATION_FILE,
289
313
  method: this.executeFailback.name,
290
314
  });
@@ -331,18 +355,18 @@ export class Registration {
331
355
  });
332
356
  await this.mutex.runExclusive(async () => {
333
357
  if (retry) {
334
- log.log('Mercury connection is up again, re-registering with Webex Calling if needed', {
358
+ log.log('Network is up again, re-registering with Webex Calling if needed', {
335
359
  file: REGISTRATION_FILE,
336
- method: this.handleConnectionRestoration.name,
360
+ method: METHODS.HANDLE_CONNECTION_RESTORATION,
337
361
  });
338
362
  this.clearKeepaliveTimer();
339
363
  if (this.isDeviceRegistered()) {
340
364
  await this.deregister();
341
365
  }
342
366
  if (this.activeMobiusUrl) {
343
- const abort = await this.restorePreviousRegistration(this.handleConnectionRestoration.name);
367
+ const abort = await this.restorePreviousRegistration(METHODS.HANDLE_CONNECTION_RESTORATION);
344
368
  if (!abort && !this.isDeviceRegistered()) {
345
- await this.restartRegistration(this.handleConnectionRestoration.name);
369
+ await this.restartRegistration(METHODS.HANDLE_CONNECTION_RESTORATION);
346
370
  }
347
371
  }
348
372
  retry = false;
@@ -376,7 +400,7 @@ export class Registration {
376
400
  }
377
401
  async triggerRegistration() {
378
402
  if (this.primaryMobiusUris.length > 0) {
379
- const abort = await this.attemptRegistrationWithServers(this.triggerRegistration.name, this.primaryMobiusUris);
403
+ const abort = await this.attemptRegistrationWithServers(REGISTRATION_UTIL, this.primaryMobiusUris);
380
404
  if (!this.isDeviceRegistered() && !abort) {
381
405
  await this.startFailoverTimer();
382
406
  }
@@ -396,6 +420,9 @@ export class Registration {
396
420
  return abort;
397
421
  }
398
422
  for (const url of servers) {
423
+ const serverType = (this.primaryMobiusUris.includes(url) && 'PRIMARY') ||
424
+ (this.backupMobiusUris?.includes(url) && 'BACKUP') ||
425
+ 'UNKNOWN';
399
426
  try {
400
427
  abort = false;
401
428
  this.registrationStatus = RegistrationStatus.INACTIVE;
@@ -407,16 +434,16 @@ export class Registration {
407
434
  const resp = await this.postRegistration(url);
408
435
  this.deviceInfo = resp.body;
409
436
  this.registrationStatus = RegistrationStatus.ACTIVE;
437
+ this.setActiveMobiusUrl(url);
410
438
  this.lineEmitter(LINE_EVENTS.REGISTERED, resp.body);
411
- log.log(`Registration successful for deviceId: ${this.deviceInfo.device?.deviceId} userId: ${this.userId}`, {
439
+ log.log(`Registration successful for deviceId: ${this.deviceInfo.device?.deviceId} userId: ${this.userId} responseTrackingId: ${resp.headers?.trackingid}`, {
412
440
  file: REGISTRATION_FILE,
413
441
  method: METHODS.REGISTER,
414
442
  });
415
- this.setActiveMobiusUrl(url);
416
443
  this.setIntervalValues(this.deviceInfo);
417
444
  this.metricManager.setDeviceInfo(this.deviceInfo);
418
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, undefined);
419
- this.startKeepaliveTimer(this.deviceInfo.device?.uri, this.deviceInfo.keepaliveInterval);
445
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, caller, serverType, resp.headers?.trackingid ?? '', undefined, undefined);
446
+ this.startKeepaliveTimer(this.deviceInfo.device?.uri, this.deviceInfo.keepaliveInterval, serverType);
420
447
  this.initiateFailback();
421
448
  break;
422
449
  }
@@ -429,7 +456,7 @@ export class Registration {
429
456
  else {
430
457
  this.lineEmitter(LINE_EVENTS.UNREGISTERED);
431
458
  }
432
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION_ERROR, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, clientError);
459
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION_ERROR, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, caller, serverType, body.headers?.trackingid ?? '', undefined, clientError);
433
460
  }, { method: caller, file: REGISTRATION_FILE }, (retryAfter, retryCaller) => this.handle429Retry(retryAfter, retryCaller), this.restoreRegistrationCallBack());
434
461
  if (this.registrationStatus === RegistrationStatus.ACTIVE) {
435
462
  log.info(`[${caller}] : Device is already restored, active mobius url: ${this.activeMobiusUrl}`, {
@@ -440,63 +467,75 @@ export class Registration {
440
467
  }
441
468
  if (abort) {
442
469
  this.setStatus(RegistrationStatus.INACTIVE);
470
+ await uploadLogs();
443
471
  break;
444
472
  }
445
473
  }
446
474
  }
447
475
  return abort;
448
476
  }
449
- startKeepaliveTimer(url, interval) {
450
- let keepAliveRetryCount = 0;
477
+ async startKeepaliveTimer(url, interval, serverType) {
451
478
  this.clearKeepaliveTimer();
452
479
  const RETRY_COUNT_THRESHOLD = this.isCCFlow ? 4 : 5;
453
- this.keepaliveTimer = setInterval(async () => {
454
- const logContext = {
455
- file: REGISTRATION_FILE,
456
- method: this.startKeepaliveTimer.name,
457
- };
458
- await this.mutex.runExclusive(async () => {
459
- if (this.isDeviceRegistered() && keepAliveRetryCount < RETRY_COUNT_THRESHOLD) {
460
- try {
461
- const res = await this.postKeepAlive(url);
462
- log.log(`Sent Keepalive, status: ${res.statusCode}`, logContext);
463
- if (keepAliveRetryCount > 0) {
480
+ await this.mutex.runExclusive(async () => {
481
+ if (this.isDeviceRegistered()) {
482
+ const accessToken = await this.webex.credentials.getUserToken();
483
+ if (!this.webWorker) {
484
+ const blob = new Blob([webWorkerStr], { type: 'application/javascript' });
485
+ const blobUrl = URL.createObjectURL(blob);
486
+ this.webWorker = new Worker(blobUrl);
487
+ URL.revokeObjectURL(blobUrl);
488
+ this.webWorker.postMessage({
489
+ type: WorkerMessageType.START_KEEPALIVE,
490
+ accessToken: String(accessToken),
491
+ deviceUrl: String(this.webex.internal.device.url),
492
+ interval,
493
+ retryCountThreshold: RETRY_COUNT_THRESHOLD,
494
+ url,
495
+ });
496
+ this.webWorker.onmessage = async (event) => {
497
+ const logContext = {
498
+ file: REGISTRATION_FILE,
499
+ method: this.startKeepaliveTimer.name,
500
+ };
501
+ if (event.data.type === WorkerMessageType.KEEPALIVE_SUCCESS) {
502
+ log.info(`Sent Keepalive, status: ${event.data.statusCode}`, logContext);
464
503
  this.lineEmitter(LINE_EVENTS.RECONNECTED);
465
504
  }
466
- keepAliveRetryCount = 0;
467
- }
468
- catch (err) {
469
- keepAliveRetryCount += 1;
470
- const error = err;
471
- log.warn(`Keep-alive missed ${keepAliveRetryCount} times. Status -> ${error.statusCode} `, logContext);
472
- const abort = await handleRegistrationErrors(error, (clientError, finalError) => {
473
- if (finalError) {
474
- this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
505
+ if (event.data.type === WorkerMessageType.KEEPALIVE_FAILURE) {
506
+ const error = event.data.err;
507
+ log.warn(`Keep-alive missed ${event.data.keepAliveRetryCount} times. Status -> ${error.statusCode} `, logContext);
508
+ const abort = await handleRegistrationErrors(error, (clientError, finalError) => {
509
+ if (finalError) {
510
+ this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
511
+ }
512
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.KEEPALIVE_ERROR, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, KEEPALIVE_UTIL, serverType, error.headers?.trackingid ?? '', event.data.keepAliveRetryCount, clientError);
513
+ }, { method: KEEPALIVE_UTIL, file: REGISTRATION_FILE });
514
+ if (abort || event.data.keepAliveRetryCount >= RETRY_COUNT_THRESHOLD) {
515
+ this.failoverImmediately = this.isCCFlow;
516
+ this.setStatus(RegistrationStatus.INACTIVE);
517
+ this.clearKeepaliveTimer();
518
+ this.clearFailbackTimer();
519
+ this.lineEmitter(LINE_EVENTS.UNREGISTERED);
520
+ await uploadLogs();
521
+ if (!abort) {
522
+ await this.reconnectOnFailure(KEEPALIVE_UTIL);
523
+ }
475
524
  }
476
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, clientError);
477
- }, { method: this.startKeepaliveTimer.name, file: REGISTRATION_FILE });
478
- if (abort || keepAliveRetryCount >= RETRY_COUNT_THRESHOLD) {
479
- this.failoverImmediately = this.isCCFlow;
480
- this.setStatus(RegistrationStatus.INACTIVE);
481
- this.clearKeepaliveTimer();
482
- this.clearFailbackTimer();
483
- this.lineEmitter(LINE_EVENTS.UNREGISTERED);
484
- if (!abort) {
485
- await this.reconnectOnFailure(this.startKeepaliveTimer.name);
525
+ else {
526
+ this.lineEmitter(LINE_EVENTS.RECONNECTING);
486
527
  }
487
528
  }
488
- else {
489
- this.lineEmitter(LINE_EVENTS.RECONNECTING);
490
- }
491
- }
529
+ };
492
530
  }
493
- });
494
- }, interval * 1000);
531
+ }
532
+ });
495
533
  }
496
534
  clearKeepaliveTimer() {
497
- if (this.keepaliveTimer) {
498
- clearInterval(this.keepaliveTimer);
499
- this.keepaliveTimer = undefined;
535
+ if (this.webWorker) {
536
+ this.webWorker.postMessage({ type: WorkerMessageType.CLEAR_KEEPALIVE });
537
+ this.webWorker.terminate();
538
+ this.webWorker = undefined;
500
539
  }
501
540
  }
502
541
  isReconnectPending() {
@@ -0,0 +1,60 @@
1
+ import { v4 as uuid } from 'uuid';
2
+ import { HTTP_METHODS, WorkerMessageType } from '../../common/types';
3
+ let keepaliveTimer;
4
+ const messageHandler = (event) => {
5
+ const { type } = event.data;
6
+ const postKeepAlive = async (accessToken, deviceUrl, url) => {
7
+ const response = await fetch(`${url}/status`, {
8
+ method: HTTP_METHODS.POST,
9
+ headers: {
10
+ 'cisco-device-url': deviceUrl,
11
+ 'spark-user-agent': 'webex-calling/beta',
12
+ Authorization: `${accessToken}`,
13
+ trackingId: `web_worker_${uuid()}`,
14
+ },
15
+ });
16
+ if (!response.ok) {
17
+ throw new Error(`Keepalive failed with status: ${response.status}`);
18
+ }
19
+ return response;
20
+ };
21
+ if (type === WorkerMessageType.START_KEEPALIVE) {
22
+ let keepAliveRetryCount = 0;
23
+ const { accessToken, deviceUrl, interval, retryCountThreshold, url } = event.data;
24
+ if (keepaliveTimer) {
25
+ clearInterval(keepaliveTimer);
26
+ keepaliveTimer = undefined;
27
+ }
28
+ keepaliveTimer = setInterval(async () => {
29
+ if (keepAliveRetryCount < retryCountThreshold) {
30
+ try {
31
+ const res = await postKeepAlive(accessToken, deviceUrl, url);
32
+ const statusCode = res.status;
33
+ if (keepAliveRetryCount > 0) {
34
+ postMessage({
35
+ type: WorkerMessageType.KEEPALIVE_SUCCESS,
36
+ statusCode,
37
+ });
38
+ }
39
+ keepAliveRetryCount = 0;
40
+ }
41
+ catch (err) {
42
+ keepAliveRetryCount += 1;
43
+ postMessage({
44
+ type: WorkerMessageType.KEEPALIVE_FAILURE,
45
+ err,
46
+ keepAliveRetryCount,
47
+ });
48
+ }
49
+ }
50
+ }, interval * 1000);
51
+ }
52
+ if (type === WorkerMessageType.CLEAR_KEEPALIVE) {
53
+ if (keepaliveTimer) {
54
+ clearInterval(keepaliveTimer);
55
+ keepaliveTimer = undefined;
56
+ }
57
+ }
58
+ };
59
+ self.addEventListener('message', messageHandler);
60
+ export default messageHandler;
@@ -0,0 +1,93 @@
1
+ const webWorkerStr = `/* eslint-env worker */
2
+
3
+ const uuid = () => {
4
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
5
+ const r = (Math.random() * 16) | 0;
6
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
7
+ return v.toString(16);
8
+ });
9
+ };
10
+
11
+ // Enum values from the original imports
12
+ const HTTP_METHODS = {
13
+ GET: 'GET',
14
+ POST: 'POST',
15
+ PUT: 'PUT',
16
+ DELETE: 'DELETE',
17
+ PATCH: 'PATCH',
18
+ };
19
+
20
+ const WorkerMessageType = {
21
+ START_KEEPALIVE: 'START_KEEPALIVE',
22
+ CLEAR_KEEPALIVE: 'CLEAR_KEEPALIVE',
23
+ KEEPALIVE_SUCCESS: 'KEEPALIVE_SUCCESS',
24
+ KEEPALIVE_FAILURE: 'KEEPALIVE_FAILURE',
25
+ };
26
+
27
+ let keepaliveTimer;
28
+
29
+ const messageHandler = (event) => {
30
+ const {type} = event.data;
31
+
32
+ const postKeepAlive = async (accessToken, deviceUrl, url) => {
33
+ const response = await fetch(\`\${url}/status\`, {
34
+ method: HTTP_METHODS.POST,
35
+ headers: {
36
+ 'cisco-device-url': deviceUrl,
37
+ 'spark-user-agent': 'webex-calling/beta',
38
+ Authorization: \`\${accessToken}\`,
39
+ trackingId: \`web_worker_\${uuid()}\`,
40
+ },
41
+ });
42
+
43
+ if (!response.ok) {
44
+ throw new Error(\`Keepalive failed with status: \${response.status}\`);
45
+ }
46
+
47
+ return response;
48
+ };
49
+
50
+ if (type === WorkerMessageType.START_KEEPALIVE) {
51
+ let keepAliveRetryCount = 0;
52
+ const {accessToken, deviceUrl, interval, retryCountThreshold, url} = event.data;
53
+
54
+ if (keepaliveTimer) {
55
+ clearInterval(keepaliveTimer);
56
+ keepaliveTimer = undefined;
57
+ }
58
+
59
+ keepaliveTimer = setInterval(async () => {
60
+ if (keepAliveRetryCount < retryCountThreshold) {
61
+ try {
62
+ const res = await postKeepAlive(accessToken, deviceUrl, url);
63
+ const statusCode = res.status;
64
+ if (keepAliveRetryCount > 0) {
65
+ self.postMessage({
66
+ type: WorkerMessageType.KEEPALIVE_SUCCESS,
67
+ statusCode,
68
+ });
69
+ }
70
+ keepAliveRetryCount = 0;
71
+ } catch (err) {
72
+ keepAliveRetryCount += 1;
73
+ self.postMessage({
74
+ type: WorkerMessageType.KEEPALIVE_FAILURE,
75
+ err,
76
+ keepAliveRetryCount,
77
+ });
78
+ }
79
+ }
80
+ }, interval * 1000);
81
+ }
82
+
83
+ if (type === WorkerMessageType.CLEAR_KEEPALIVE) {
84
+ if (keepaliveTimer) {
85
+ clearInterval(keepaliveTimer);
86
+ keepaliveTimer = undefined;
87
+ }
88
+ }
89
+ };
90
+
91
+ self.addEventListener('message', messageHandler);
92
+ `;
93
+ export default webWorkerStr;
@@ -0,0 +1,59 @@
1
+ function waitForIceComplete(pc, timeoutMs) {
2
+ return new Promise((resolve) => {
3
+ if (!pc) {
4
+ resolve({ ok: false, reason: 'no-pc' });
5
+ return;
6
+ }
7
+ if (pc.iceGatheringState === 'complete') {
8
+ resolve({ ok: true, reached: 'already' });
9
+ return;
10
+ }
11
+ let done = false;
12
+ const onChange = () => {
13
+ if (pc.iceGatheringState === 'complete' && !done) {
14
+ done = true;
15
+ pc.removeEventListener('icegatheringstatechange', onChange);
16
+ resolve({ ok: true, reached: 'event' });
17
+ }
18
+ };
19
+ pc.addEventListener('icegatheringstatechange', onChange);
20
+ setTimeout(() => {
21
+ if (done)
22
+ return;
23
+ done = true;
24
+ pc.removeEventListener('icegatheringstatechange', onChange);
25
+ resolve({ ok: pc.iceGatheringState === 'complete', reached: 'timeout' });
26
+ }, timeoutMs);
27
+ });
28
+ }
29
+ export default async function windowsChromiumIceWarmup({ iceServers = [], timeoutMs = 1000 }) {
30
+ const pc1 = new RTCPeerConnection({ iceServers, iceCandidatePoolSize: 1 });
31
+ const pc2 = new RTCPeerConnection({ iceServers, iceCandidatePoolSize: 1 });
32
+ const candidates = { pc1: [], pc2: [] };
33
+ pc1.onicecandidate = (e) => {
34
+ if (e.candidate && e.candidate.type !== 'host') {
35
+ candidates.pc1.push(e.candidate);
36
+ }
37
+ };
38
+ await pc1.createDataChannel('warmup');
39
+ await pc1.addTransceiver('audio');
40
+ const offer = await pc1.createOffer();
41
+ await pc1.setLocalDescription(offer);
42
+ await waitForIceComplete(pc1, timeoutMs);
43
+ await pc2.setRemoteDescription(offer);
44
+ pc2.onicecandidate = (e) => {
45
+ if (e.candidate && e.candidate.type !== 'host') {
46
+ candidates.pc2.push(e.candidate);
47
+ }
48
+ };
49
+ const answer = await pc2.createAnswer();
50
+ await pc2.setLocalDescription(answer);
51
+ await pc1.setRemoteDescription(answer);
52
+ await waitForIceComplete(pc2, timeoutMs);
53
+ await Promise.all([
54
+ ...candidates.pc1.map((candidate) => pc2.addIceCandidate(candidate).catch(console.error)),
55
+ ...candidates.pc2.map((candidate) => pc1.addIceCandidate(candidate).catch(console.error)),
56
+ ]);
57
+ pc1.close();
58
+ pc2.close();
59
+ }