@webex/calling 3.0.0-next.4 → 3.0.0-next.41

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 (316) hide show
  1. package/CHANGELOG.md +1403 -1403
  2. package/README.md +74 -74
  3. package/dist/CallHistory/CallHistory.js +201 -0
  4. package/dist/CallHistory/CallHistory.js.map +1 -0
  5. package/dist/CallHistory/CallHistory.test.js +142 -0
  6. package/dist/CallHistory/CallHistory.test.js.map +1 -0
  7. package/dist/CallHistory/callHistoryFixtures.js +366 -0
  8. package/dist/CallHistory/callHistoryFixtures.js.map +1 -0
  9. package/dist/CallHistory/constants.js +17 -0
  10. package/dist/CallHistory/constants.js.map +1 -0
  11. package/dist/CallHistory/types.js +7 -0
  12. package/dist/CallHistory/types.js.map +1 -0
  13. package/dist/CallSettings/CallSettings.js +279 -0
  14. package/dist/CallSettings/CallSettings.js.map +1 -0
  15. package/dist/CallSettings/CallSettings.test.js +122 -0
  16. package/dist/CallSettings/CallSettings.test.js.map +1 -0
  17. package/dist/CallSettings/UcmBackendConnector.js +216 -0
  18. package/dist/CallSettings/UcmBackendConnector.js.map +1 -0
  19. package/dist/CallSettings/UcmBackendConnector.test.js +259 -0
  20. package/dist/CallSettings/UcmBackendConnector.test.js.map +1 -0
  21. package/dist/CallSettings/WxCallBackendConnector.js +547 -0
  22. package/dist/CallSettings/WxCallBackendConnector.js.map +1 -0
  23. package/dist/CallSettings/WxCallBackendConnector.test.js +802 -0
  24. package/dist/CallSettings/WxCallBackendConnector.test.js.map +1 -0
  25. package/dist/CallSettings/constants.js +19 -0
  26. package/dist/CallSettings/constants.js.map +1 -0
  27. package/dist/CallSettings/testFixtures.js +68 -0
  28. package/dist/CallSettings/testFixtures.js.map +1 -0
  29. package/dist/CallSettings/types.js +7 -0
  30. package/dist/CallSettings/types.js.map +1 -0
  31. package/dist/CallingClient/CallingClient.js +631 -0
  32. package/dist/CallingClient/CallingClient.js.map +1 -0
  33. package/dist/CallingClient/CallingClient.test.js +992 -0
  34. package/dist/CallingClient/CallingClient.test.js.map +1 -0
  35. package/dist/CallingClient/callRecordFixtures.js +101 -0
  36. package/dist/CallingClient/callRecordFixtures.js.map +1 -0
  37. package/dist/CallingClient/calling/CallerId/index.js +267 -0
  38. package/dist/CallingClient/calling/CallerId/index.js.map +1 -0
  39. package/dist/CallingClient/calling/CallerId/index.test.js +274 -0
  40. package/dist/CallingClient/calling/CallerId/index.test.js.map +1 -0
  41. package/dist/CallingClient/calling/CallerId/types.js +7 -0
  42. package/dist/CallingClient/calling/CallerId/types.js.map +1 -0
  43. package/dist/CallingClient/calling/call.js +3055 -0
  44. package/dist/CallingClient/calling/call.js.map +1 -0
  45. package/dist/CallingClient/calling/call.test.js +2858 -0
  46. package/dist/CallingClient/calling/call.test.js.map +1 -0
  47. package/dist/CallingClient/calling/callManager.js +432 -0
  48. package/dist/CallingClient/calling/callManager.js.map +1 -0
  49. package/dist/CallingClient/calling/callManager.test.js +683 -0
  50. package/dist/CallingClient/calling/callManager.test.js.map +1 -0
  51. package/dist/CallingClient/calling/index.js +30 -0
  52. package/dist/CallingClient/calling/index.js.map +1 -0
  53. package/dist/CallingClient/calling/types.js +69 -0
  54. package/dist/CallingClient/calling/types.js.map +1 -0
  55. package/dist/CallingClient/callingClientFixtures.js +143 -0
  56. package/dist/CallingClient/callingClientFixtures.js.map +1 -0
  57. package/dist/CallingClient/constants.js +134 -0
  58. package/dist/CallingClient/constants.js.map +1 -0
  59. package/dist/CallingClient/line/index.js +314 -0
  60. package/dist/CallingClient/line/index.js.map +1 -0
  61. package/dist/CallingClient/line/line.test.js +270 -0
  62. package/dist/CallingClient/line/line.test.js.map +1 -0
  63. package/dist/CallingClient/line/types.js +21 -0
  64. package/dist/CallingClient/line/types.js.map +1 -0
  65. package/dist/CallingClient/registration/index.js +19 -0
  66. package/dist/CallingClient/registration/index.js.map +1 -0
  67. package/dist/CallingClient/registration/register.js +1286 -0
  68. package/dist/CallingClient/registration/register.js.map +1 -0
  69. package/dist/CallingClient/registration/register.test.js +839 -0
  70. package/dist/CallingClient/registration/register.test.js.map +1 -0
  71. package/dist/CallingClient/registration/registerFixtures.js +36 -0
  72. package/dist/CallingClient/registration/registerFixtures.js.map +1 -0
  73. package/dist/CallingClient/registration/types.js +7 -0
  74. package/dist/CallingClient/registration/types.js.map +1 -0
  75. package/dist/CallingClient/types.js +7 -0
  76. package/dist/CallingClient/types.js.map +1 -0
  77. package/dist/Contacts/ContactsClient.js +1156 -0
  78. package/dist/Contacts/ContactsClient.js.map +1 -0
  79. package/dist/Contacts/ContactsClient.test.js +725 -0
  80. package/dist/Contacts/ContactsClient.test.js.map +1 -0
  81. package/dist/Contacts/constants.js +28 -0
  82. package/dist/Contacts/constants.js.map +1 -0
  83. package/dist/Contacts/contactFixtures.js +314 -0
  84. package/dist/Contacts/contactFixtures.js.map +1 -0
  85. package/dist/Contacts/types.js +43 -0
  86. package/dist/Contacts/types.js.map +1 -0
  87. package/dist/Errors/catalog/CallError.js +92 -0
  88. package/dist/Errors/catalog/CallError.js.map +1 -0
  89. package/dist/Errors/catalog/CallingDeviceError.js +86 -0
  90. package/dist/Errors/catalog/CallingDeviceError.js.map +1 -0
  91. package/dist/Errors/catalog/ExtendedError.js +44 -0
  92. package/dist/Errors/catalog/ExtendedError.js.map +1 -0
  93. package/dist/Errors/catalog/LineError.js +88 -0
  94. package/dist/Errors/catalog/LineError.js.map +1 -0
  95. package/dist/Errors/index.js +28 -0
  96. package/dist/Errors/index.js.map +1 -0
  97. package/dist/Errors/types.js +57 -0
  98. package/dist/Errors/types.js.map +1 -0
  99. package/dist/Events/impl/index.js +81 -0
  100. package/dist/Events/impl/index.js.map +1 -0
  101. package/dist/Events/types.js +103 -0
  102. package/dist/Events/types.js.map +1 -0
  103. package/dist/Logger/index.js +220 -0
  104. package/dist/Logger/index.js.map +1 -0
  105. package/dist/Logger/index.test.js +62 -0
  106. package/dist/Logger/index.test.js.map +1 -0
  107. package/dist/Logger/types.js +34 -0
  108. package/dist/Logger/types.js.map +1 -0
  109. package/dist/Metrics/index.js +327 -0
  110. package/dist/Metrics/index.js.map +1 -0
  111. package/dist/Metrics/index.test.js +291 -0
  112. package/dist/Metrics/index.test.js.map +1 -0
  113. package/dist/Metrics/types.js +45 -0
  114. package/dist/Metrics/types.js.map +1 -0
  115. package/dist/SDKConnector/index.js +104 -0
  116. package/dist/SDKConnector/index.js.map +1 -0
  117. package/dist/SDKConnector/index.test.js +9 -0
  118. package/dist/SDKConnector/index.test.js.map +1 -0
  119. package/dist/SDKConnector/types.js +7 -0
  120. package/dist/SDKConnector/types.js.map +1 -0
  121. package/dist/SDKConnector/utils.js +39 -0
  122. package/dist/SDKConnector/utils.js.map +1 -0
  123. package/dist/SDKConnector/utils.test.js +9 -0
  124. package/dist/SDKConnector/utils.test.js.map +1 -0
  125. package/dist/Voicemail/BroadworksBackendConnector.js +641 -0
  126. package/dist/Voicemail/BroadworksBackendConnector.js.map +1 -0
  127. package/dist/Voicemail/BroadworksBackendConnector.test.js +733 -0
  128. package/dist/Voicemail/BroadworksBackendConnector.test.js.map +1 -0
  129. package/dist/Voicemail/UcmBackendConnector.js +574 -0
  130. package/dist/Voicemail/UcmBackendConnector.js.map +1 -0
  131. package/dist/Voicemail/UcmBackendConnector.test.js +629 -0
  132. package/dist/Voicemail/UcmBackendConnector.test.js.map +1 -0
  133. package/dist/Voicemail/Voicemail.js +380 -0
  134. package/dist/Voicemail/Voicemail.js.map +1 -0
  135. package/dist/Voicemail/Voicemail.test.js +226 -0
  136. package/dist/Voicemail/Voicemail.test.js.map +1 -0
  137. package/dist/Voicemail/WxCallBackendConnector.js +547 -0
  138. package/dist/Voicemail/WxCallBackendConnector.js.map +1 -0
  139. package/dist/Voicemail/WxCallBackendConnector.test.js +942 -0
  140. package/dist/Voicemail/WxCallBackendConnector.test.js.map +1 -0
  141. package/dist/Voicemail/constants.js +37 -0
  142. package/dist/Voicemail/constants.js.map +1 -0
  143. package/dist/Voicemail/types.js +7 -0
  144. package/dist/Voicemail/types.js.map +1 -0
  145. package/dist/Voicemail/voicemailFixture.js +524 -0
  146. package/dist/Voicemail/voicemailFixture.js.map +1 -0
  147. package/dist/api.js +157 -0
  148. package/dist/api.js.map +1 -0
  149. package/dist/common/Utils.js +1257 -0
  150. package/dist/common/Utils.js.map +1 -0
  151. package/dist/common/Utils.test.js +1227 -0
  152. package/dist/common/Utils.test.js.map +1 -0
  153. package/dist/common/constants.js +49 -0
  154. package/dist/common/constants.js.map +1 -0
  155. package/dist/common/index.js +19 -0
  156. package/dist/common/index.js.map +1 -0
  157. package/dist/common/testUtil.js +959 -0
  158. package/dist/common/testUtil.js.map +1 -0
  159. package/dist/common/types.js +66 -0
  160. package/dist/common/types.js.map +1 -0
  161. package/dist/index.js +309 -0
  162. package/dist/index.js.map +1 -0
  163. package/dist/module/CallHistory/CallHistory.js +83 -81
  164. package/dist/module/CallHistory/callHistoryFixtures.js +366 -307
  165. package/dist/module/CallHistory/constants.js +9 -9
  166. package/dist/module/CallHistory/types.js +1 -1
  167. package/dist/module/CallSettings/CallSettings.js +65 -65
  168. package/dist/module/CallSettings/UcmBackendConnector.js +100 -100
  169. package/dist/module/CallSettings/WxCallBackendConnector.js +287 -287
  170. package/dist/module/CallSettings/constants.js +11 -11
  171. package/dist/module/CallSettings/testFixtures.js +62 -62
  172. package/dist/module/CallSettings/types.js +1 -1
  173. package/dist/module/CallingClient/CallingClient.js +265 -248
  174. package/dist/module/CallingClient/callRecordFixtures.js +93 -93
  175. package/dist/module/CallingClient/calling/CallerId/index.js +149 -169
  176. package/dist/module/CallingClient/calling/CallerId/types.js +1 -1
  177. package/dist/module/CallingClient/calling/call.js +1701 -1658
  178. package/dist/module/CallingClient/calling/callManager.js +278 -284
  179. package/dist/module/CallingClient/calling/index.js +2 -2
  180. package/dist/module/CallingClient/calling/types.js +53 -53
  181. package/dist/module/CallingClient/callingClientFixtures.js +156 -38
  182. package/dist/module/CallingClient/constants.js +126 -122
  183. package/dist/module/CallingClient/line/index.js +155 -158
  184. package/dist/module/CallingClient/line/types.js +10 -15
  185. package/dist/module/CallingClient/registration/index.js +1 -1
  186. package/dist/module/CallingClient/registration/register.js +515 -507
  187. package/dist/module/CallingClient/registration/registerFixtures.js +28 -28
  188. package/dist/module/CallingClient/registration/types.js +1 -1
  189. package/dist/module/CallingClient/types.js +1 -1
  190. package/dist/module/Contacts/ContactsClient.js +487 -484
  191. package/dist/module/Contacts/constants.js +20 -20
  192. package/dist/module/Contacts/contactFixtures.js +284 -284
  193. package/dist/module/Contacts/types.js +10 -10
  194. package/dist/module/Errors/catalog/CallError.js +26 -26
  195. package/dist/module/Errors/catalog/CallingDeviceError.js +18 -18
  196. package/dist/module/Errors/catalog/ExtendedError.js +10 -10
  197. package/dist/module/Errors/catalog/LineError.js +24 -24
  198. package/dist/module/Errors/index.js +3 -2
  199. package/dist/module/Errors/types.js +48 -48
  200. package/dist/module/Events/impl/index.js +19 -19
  201. package/dist/module/Events/types.js +85 -83
  202. package/dist/module/Logger/index.js +114 -114
  203. package/dist/module/Logger/types.js +25 -25
  204. package/dist/module/Metrics/index.js +232 -232
  205. package/dist/module/Metrics/types.js +37 -37
  206. package/dist/module/SDKConnector/index.js +39 -39
  207. package/dist/module/SDKConnector/types.js +1 -1
  208. package/dist/module/SDKConnector/utils.js +12 -12
  209. package/dist/module/Voicemail/BroadworksBackendConnector.js +291 -291
  210. package/dist/module/Voicemail/UcmBackendConnector.js +279 -279
  211. package/dist/module/Voicemail/Voicemail.js +110 -110
  212. package/dist/module/Voicemail/WxCallBackendConnector.js +279 -279
  213. package/dist/module/Voicemail/constants.js +29 -29
  214. package/dist/module/Voicemail/types.js +1 -1
  215. package/dist/module/Voicemail/voicemailFixture.js +510 -510
  216. package/dist/module/api.js +7 -6
  217. package/dist/module/common/Utils.js +797 -802
  218. package/dist/module/common/constants.js +41 -41
  219. package/dist/module/common/index.js +1 -1
  220. package/dist/module/common/testUtil.js +939 -938
  221. package/dist/module/common/types.js +58 -57
  222. package/dist/module/index.js +17 -8
  223. package/dist/types/CallHistory/CallHistory.d.ts +18 -17
  224. package/dist/types/CallHistory/CallHistory.d.ts.map +1 -1
  225. package/dist/types/CallHistory/callHistoryFixtures.d.ts +95 -94
  226. package/dist/types/CallHistory/callHistoryFixtures.d.ts.map +1 -1
  227. package/dist/types/CallHistory/constants.d.ts +9 -9
  228. package/dist/types/CallHistory/types.d.ts +18 -18
  229. package/dist/types/CallSettings/CallSettings.d.ts +19 -19
  230. package/dist/types/CallSettings/CallSettings.d.ts.map +1 -1
  231. package/dist/types/CallSettings/UcmBackendConnector.d.ts +19 -19
  232. package/dist/types/CallSettings/UcmBackendConnector.d.ts.map +1 -1
  233. package/dist/types/CallSettings/WxCallBackendConnector.d.ts +21 -21
  234. package/dist/types/CallSettings/constants.d.ts +11 -11
  235. package/dist/types/CallSettings/testFixtures.d.ts +15 -15
  236. package/dist/types/CallSettings/types.d.ts +108 -107
  237. package/dist/types/CallSettings/types.d.ts.map +1 -1
  238. package/dist/types/CallingClient/CallingClient.d.ts +37 -35
  239. package/dist/types/CallingClient/CallingClient.d.ts.map +1 -1
  240. package/dist/types/CallingClient/callRecordFixtures.d.ts +3 -3
  241. package/dist/types/CallingClient/calling/CallerId/index.d.ts +17 -17
  242. package/dist/types/CallingClient/calling/CallerId/index.d.ts.map +1 -1
  243. package/dist/types/CallingClient/calling/CallerId/types.d.ts +41 -41
  244. package/dist/types/CallingClient/calling/CallerId/types.d.ts.map +1 -1
  245. package/dist/types/CallingClient/calling/call.d.ts +98 -96
  246. package/dist/types/CallingClient/calling/call.d.ts.map +1 -1
  247. package/dist/types/CallingClient/calling/callManager.d.ts +24 -25
  248. package/dist/types/CallingClient/calling/callManager.d.ts.map +1 -1
  249. package/dist/types/CallingClient/calling/index.d.ts +2 -2
  250. package/dist/types/CallingClient/calling/types.d.ts +206 -206
  251. package/dist/types/CallingClient/calling/types.d.ts.map +1 -1
  252. package/dist/types/CallingClient/callingClientFixtures.d.ts +86 -18
  253. package/dist/types/CallingClient/callingClientFixtures.d.ts.map +1 -1
  254. package/dist/types/CallingClient/constants.d.ts +126 -122
  255. package/dist/types/CallingClient/constants.d.ts.map +1 -1
  256. package/dist/types/CallingClient/line/index.d.ts +43 -43
  257. package/dist/types/CallingClient/line/index.d.ts.map +1 -1
  258. package/dist/types/CallingClient/line/types.d.ts +43 -55
  259. package/dist/types/CallingClient/line/types.d.ts.map +1 -1
  260. package/dist/types/CallingClient/registration/index.d.ts +1 -1
  261. package/dist/types/CallingClient/registration/register.d.ts +64 -64
  262. package/dist/types/CallingClient/registration/register.d.ts.map +1 -1
  263. package/dist/types/CallingClient/registration/registerFixtures.d.ts +28 -28
  264. package/dist/types/CallingClient/registration/types.d.ts +20 -20
  265. package/dist/types/CallingClient/registration/types.d.ts.map +1 -1
  266. package/dist/types/CallingClient/types.d.ts +31 -29
  267. package/dist/types/CallingClient/types.d.ts.map +1 -1
  268. package/dist/types/Contacts/ContactsClient.d.ts +27 -26
  269. package/dist/types/Contacts/ContactsClient.d.ts.map +1 -1
  270. package/dist/types/Contacts/constants.d.ts +19 -19
  271. package/dist/types/Contacts/contactFixtures.d.ts +280 -280
  272. package/dist/types/Contacts/types.d.ts +74 -72
  273. package/dist/types/Contacts/types.d.ts.map +1 -1
  274. package/dist/types/Errors/catalog/CallError.d.ts +11 -11
  275. package/dist/types/Errors/catalog/CallingDeviceError.d.ts +10 -10
  276. package/dist/types/Errors/catalog/CallingDeviceError.d.ts.map +1 -1
  277. package/dist/types/Errors/catalog/ExtendedError.d.ts +6 -6
  278. package/dist/types/Errors/catalog/LineError.d.ts +10 -10
  279. package/dist/types/Errors/catalog/LineError.d.ts.map +1 -1
  280. package/dist/types/Errors/index.d.ts +3 -2
  281. package/dist/types/Errors/index.d.ts.map +1 -1
  282. package/dist/types/Errors/types.d.ts +59 -60
  283. package/dist/types/Errors/types.d.ts.map +1 -1
  284. package/dist/types/Events/impl/index.d.ts +8 -8
  285. package/dist/types/Events/types.d.ts +311 -288
  286. package/dist/types/Events/types.d.ts.map +1 -1
  287. package/dist/types/Logger/index.d.ts +12 -12
  288. package/dist/types/Logger/types.d.ts +25 -25
  289. package/dist/types/Metrics/index.d.ts +5 -5
  290. package/dist/types/Metrics/types.d.ts +42 -42
  291. package/dist/types/SDKConnector/index.d.ts +12 -12
  292. package/dist/types/SDKConnector/types.d.ts +129 -128
  293. package/dist/types/SDKConnector/types.d.ts.map +1 -1
  294. package/dist/types/SDKConnector/utils.d.ts +5 -5
  295. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts +27 -27
  296. package/dist/types/Voicemail/UcmBackendConnector.d.ts +34 -34
  297. package/dist/types/Voicemail/Voicemail.d.ts +27 -27
  298. package/dist/types/Voicemail/Voicemail.d.ts.map +1 -1
  299. package/dist/types/Voicemail/WxCallBackendConnector.d.ts +23 -23
  300. package/dist/types/Voicemail/constants.d.ts +29 -29
  301. package/dist/types/Voicemail/types.d.ts +133 -133
  302. package/dist/types/Voicemail/types.d.ts.map +1 -1
  303. package/dist/types/Voicemail/voicemailFixture.d.ts +417 -417
  304. package/dist/types/api.d.ts +16 -16
  305. package/dist/types/api.d.ts.map +1 -1
  306. package/dist/types/common/Utils.d.ts +34 -34
  307. package/dist/types/common/Utils.d.ts.map +1 -1
  308. package/dist/types/common/constants.d.ts +41 -41
  309. package/dist/types/common/index.d.ts +1 -1
  310. package/dist/types/common/testUtil.d.ts +3612 -3611
  311. package/dist/types/common/testUtil.d.ts.map +1 -1
  312. package/dist/types/common/types.d.ts +192 -191
  313. package/dist/types/common/types.d.ts.map +1 -1
  314. package/dist/types/index.d.ts +21 -8
  315. package/dist/types/index.d.ts.map +1 -1
  316. package/package.json +5 -3
@@ -1,507 +1,515 @@
1
- import { v4 as uuid } from 'uuid';
2
- import { ERROR_CODE } from '../../Errors/types';
3
- import { emitFinalFailure, handleRegistrationErrors } from '../../common';
4
- import { METRIC_EVENT, METRIC_TYPE, REG_ACTION } from '../../Metrics/types';
5
- import { getMetricManager } from '../../Metrics';
6
- import { getCallManager } from '../calling';
7
- import log from '../../Logger';
8
- import SDKConnector from '../../SDKConnector';
9
- import { ALLOWED_SERVICES, HTTP_METHODS, MobiusStatus, } 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, FAILBACK_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, } from '../constants';
11
- import { LINE_EVENTS } from '../line/types';
12
- export class Registration {
13
- sdkConnector;
14
- webex;
15
- userId = '';
16
- serviceData;
17
- failback429RetryAttempts;
18
- registrationStatus;
19
- failbackTimer;
20
- activeMobiusUrl;
21
- keepaliveTimer;
22
- rehomingIntervalMin;
23
- rehomingIntervalMax;
24
- mutex;
25
- metricManager;
26
- lineEmitter;
27
- callManager;
28
- deviceInfo = {};
29
- primaryMobiusUris;
30
- backupMobiusUris;
31
- registerRetry = false;
32
- reconnectPending = false;
33
- constructor(webex, serviceData, mutex, lineEmitter, logLevel) {
34
- this.sdkConnector = SDKConnector;
35
- this.serviceData = serviceData;
36
- if (!this.sdkConnector.getWebex()) {
37
- SDKConnector.setWebex(webex);
38
- }
39
- this.webex = this.sdkConnector.getWebex();
40
- this.userId = this.webex.internal.device.userId;
41
- this.registrationStatus = MobiusStatus.DEFAULT;
42
- this.failback429RetryAttempts = 0;
43
- log.setLogger(logLevel, REGISTRATION_FILE);
44
- this.rehomingIntervalMin = DEFAULT_REHOMING_INTERVAL_MIN;
45
- this.rehomingIntervalMax = DEFAULT_REHOMING_INTERVAL_MAX;
46
- this.mutex = mutex;
47
- this.callManager = getCallManager(this.webex, serviceData.indicator);
48
- this.metricManager = getMetricManager(this.webex, serviceData.indicator);
49
- this.lineEmitter = lineEmitter;
50
- this.primaryMobiusUris = [];
51
- this.backupMobiusUris = [];
52
- }
53
- getActiveMobiusUrl() {
54
- return this.activeMobiusUrl;
55
- }
56
- setActiveMobiusUrl(url) {
57
- log.info(`ActiveMobiusUrl: ${url}`, { method: 'setActiveMobiusUrl', file: REGISTRATION_FILE });
58
- this.activeMobiusUrl = url;
59
- this.callManager.updateActiveMobius(url);
60
- }
61
- setMobiusServers(primaryMobiusUris, backupMobiusUris) {
62
- this.primaryMobiusUris = primaryMobiusUris;
63
- this.backupMobiusUris = backupMobiusUris;
64
- }
65
- async postKeepAlive(url) {
66
- return this.webex.request({
67
- uri: `${url}/status`,
68
- method: HTTP_METHODS.POST,
69
- headers: {
70
- [CISCO_DEVICE_URL]: this.webex.internal.device.url,
71
- [SPARK_USER_AGENT]: CALLING_USER_AGENT,
72
- },
73
- service: ALLOWED_SERVICES.MOBIUS,
74
- });
75
- }
76
- async deleteRegistration(url, deviceId, deviceUrl) {
77
- const response = await fetch(`${url}${DEVICES_ENDPOINT_RESOURCE}/${deviceId}`, {
78
- method: HTTP_METHODS.DELETE,
79
- headers: {
80
- [CISCO_DEVICE_URL]: deviceUrl,
81
- Authorization: await this.webex.credentials.getUserToken(),
82
- trackingId: `${WEBEX_WEB_CLIENT}_${uuid()}`,
83
- [SPARK_USER_AGENT]: CALLING_USER_AGENT,
84
- },
85
- });
86
- this.lineEmitter(LINE_EVENTS.UNREGISTERED);
87
- return response.json();
88
- }
89
- async postRegistration(url) {
90
- const deviceInfo = {
91
- userId: this.userId,
92
- clientDeviceUri: this.webex.internal.device.url,
93
- serviceData: this.serviceData,
94
- };
95
- return this.webex.request({
96
- uri: `${url}device`,
97
- method: HTTP_METHODS.POST,
98
- headers: {
99
- [CISCO_DEVICE_URL]: deviceInfo.clientDeviceUri,
100
- [SPARK_USER_AGENT]: CALLING_USER_AGENT,
101
- },
102
- body: deviceInfo,
103
- service: ALLOWED_SERVICES.MOBIUS,
104
- });
105
- }
106
- async restorePreviousRegistration(caller) {
107
- let abort = false;
108
- if (this.activeMobiusUrl) {
109
- abort = await this.attemptRegistrationWithServers(caller, [this.activeMobiusUrl]);
110
- }
111
- return abort;
112
- }
113
- async scheduleFailback429Retry() {
114
- if (this.failback429RetryAttempts >= REG_FAILBACK_429_MAX_RETRIES) {
115
- return;
116
- }
117
- this.clearFailbackTimer();
118
- this.failback429RetryAttempts += 1;
119
- log.log(`Received 429 while rehoming, 429 retry count : ${this.failback429RetryAttempts}`, {
120
- file: REGISTRATION_FILE,
121
- method: FAILBACK_429_RETRY_UTIL,
122
- });
123
- const interval = this.getRegRetryInterval(this.failback429RetryAttempts);
124
- this.startFailbackTimer(interval);
125
- const abort = await this.restorePreviousRegistration(FAILBACK_429_RETRY_UTIL);
126
- if (!abort && !this.isDeviceRegistered()) {
127
- await this.restartRegistration(FAILBACK_429_RETRY_UTIL);
128
- }
129
- }
130
- getRegRetryInterval(attempt = 1) {
131
- return (BASE_REG_RETRY_TIMER_VAL_IN_SEC +
132
- BASE_REG_TIMER_MFACTOR ** attempt +
133
- Math.floor((Math.random() * (REG_RANDOM_T_FACTOR_UPPER_LIMIT - SEC_TO_MSEC_MFACTOR + 1) +
134
- SEC_TO_MSEC_MFACTOR) /
135
- SEC_TO_MSEC_MFACTOR));
136
- }
137
- async startFailoverTimer(attempt = 1, timeElapsed = 0) {
138
- const loggerContext = {
139
- file: REGISTRATION_FILE,
140
- method: this.startFailoverTimer.name,
141
- };
142
- let interval = this.getRegRetryInterval(attempt);
143
- if (timeElapsed + interval > REG_TRY_BACKUP_TIMER_VAL_IN_SEC) {
144
- const excessVal = timeElapsed + interval - REG_TRY_BACKUP_TIMER_VAL_IN_SEC;
145
- interval -= excessVal;
146
- }
147
- let abort;
148
- if (interval > BASE_REG_RETRY_TIMER_VAL_IN_SEC) {
149
- const scheduledTime = Math.floor(Date.now() / 1000);
150
- setTimeout(async () => {
151
- await this.mutex.runExclusive(async () => {
152
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name);
153
- const currentTime = Math.floor(Date.now() / 1000);
154
- if (!abort && !this.isDeviceRegistered()) {
155
- await this.startFailoverTimer(attempt + 1, timeElapsed + (currentTime - scheduledTime));
156
- }
157
- });
158
- }, interval * SEC_TO_MSEC_MFACTOR);
159
- log.log(`Scheduled retry with primary in ${interval} seconds, number of attempts : ${attempt}`, loggerContext);
160
- }
161
- else if (this.backupMobiusUris.length) {
162
- log.log('Failing over to backup servers.', loggerContext);
163
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
164
- if (!abort && !this.isDeviceRegistered()) {
165
- interval = this.getRegRetryInterval();
166
- setTimeout(async () => {
167
- await this.mutex.runExclusive(async () => {
168
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
169
- if (!abort && !this.isDeviceRegistered()) {
170
- emitFinalFailure((clientError) => {
171
- this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
172
- }, loggerContext);
173
- }
174
- });
175
- }, interval * SEC_TO_MSEC_MFACTOR);
176
- log.log(`Scheduled retry with backup servers in ${interval} seconds.`, loggerContext);
177
- }
178
- }
179
- else {
180
- emitFinalFailure((clientError) => {
181
- this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
182
- }, loggerContext);
183
- }
184
- }
185
- clearFailbackTimer() {
186
- if (this.failbackTimer) {
187
- clearTimeout(this.failbackTimer);
188
- this.failbackTimer = undefined;
189
- }
190
- }
191
- isFailbackRequired() {
192
- return this.isDeviceRegistered() && this.primaryMobiusUris.indexOf(this.activeMobiusUrl) === -1;
193
- }
194
- getFailbackInterval() {
195
- return Math.floor(Math.random() * (this.rehomingIntervalMax - this.rehomingIntervalMin + 1) +
196
- this.rehomingIntervalMin);
197
- }
198
- initiateFailback() {
199
- if (this.isFailbackRequired()) {
200
- if (!this.failbackTimer) {
201
- this.failback429RetryAttempts = 0;
202
- const intervalInMinutes = this.getFailbackInterval();
203
- this.startFailbackTimer(intervalInMinutes * MINUTES_TO_SEC_MFACTOR);
204
- }
205
- }
206
- else {
207
- this.failback429RetryAttempts = 0;
208
- this.clearFailbackTimer();
209
- }
210
- }
211
- startFailbackTimer(intervalInSeconds) {
212
- this.failbackTimer = setTimeout(async () => this.executeFailback(), intervalInSeconds * SEC_TO_MSEC_MFACTOR);
213
- log.log(`Failback scheduled after ${intervalInSeconds} seconds.`, {
214
- file: REGISTRATION_FILE,
215
- method: this.startFailbackTimer.name,
216
- });
217
- }
218
- async executeFailback() {
219
- await this.mutex.runExclusive(async () => {
220
- if (this.isFailbackRequired()) {
221
- if (Object.keys(this.callManager.getActiveCalls()).length === 0) {
222
- log.info(`Attempting failback to primary.`, {
223
- file: REGISTRATION_FILE,
224
- method: this.executeFailback.name,
225
- });
226
- await this.deregister();
227
- const abort = await this.attemptRegistrationWithServers(FAILBACK_UTIL);
228
- if (!abort && !this.isDeviceRegistered()) {
229
- const abortNew = await this.restorePreviousRegistration(FAILBACK_UTIL);
230
- if (abortNew) {
231
- this.clearFailbackTimer();
232
- return;
233
- }
234
- if (!this.isDeviceRegistered()) {
235
- await this.restartRegistration(this.executeFailback.name);
236
- }
237
- else {
238
- this.failbackTimer = undefined;
239
- this.initiateFailback();
240
- }
241
- }
242
- }
243
- else {
244
- log.info('Active calls present, deferring failback to next cycle.', {
245
- file: REGISTRATION_FILE,
246
- method: this.executeFailback.name,
247
- });
248
- this.failbackTimer = undefined;
249
- this.initiateFailback();
250
- }
251
- }
252
- });
253
- }
254
- setIntervalValues(deviceInfo) {
255
- if (this.primaryMobiusUris.indexOf(this.activeMobiusUrl) !== -1) {
256
- this.rehomingIntervalMin = deviceInfo?.rehomingIntervalMin
257
- ? deviceInfo.rehomingIntervalMin
258
- : DEFAULT_REHOMING_INTERVAL_MIN;
259
- this.rehomingIntervalMax = deviceInfo?.rehomingIntervalMax
260
- ? deviceInfo.rehomingIntervalMax
261
- : DEFAULT_REHOMING_INTERVAL_MAX;
262
- }
263
- }
264
- getDeviceInfo() {
265
- return this.deviceInfo;
266
- }
267
- isDeviceRegistered() {
268
- return this.registrationStatus === MobiusStatus.ACTIVE;
269
- }
270
- getStatus() {
271
- return this.registrationStatus;
272
- }
273
- setStatus(value) {
274
- this.registrationStatus = value;
275
- }
276
- async restartRegistration(caller) {
277
- this.clearFailbackTimer();
278
- this.failback429RetryAttempts = 0;
279
- const abort = await this.attemptRegistrationWithServers(caller, this.primaryMobiusUris);
280
- if (!abort && !this.isDeviceRegistered()) {
281
- await this.startFailoverTimer();
282
- }
283
- }
284
- async handleConnectionRestoration(retry) {
285
- await this.mutex.runExclusive(async () => {
286
- if (retry) {
287
- log.info('Mercury connection is up again, Re-registering with Mobius', {
288
- file: REGISTRATION_FILE,
289
- method: this.handleConnectionRestoration.name,
290
- });
291
- this.clearKeepaliveTimer();
292
- if (this.isDeviceRegistered()) {
293
- await this.deregister();
294
- }
295
- if (this.activeMobiusUrl) {
296
- const abort = await this.restorePreviousRegistration(this.handleConnectionRestoration.name);
297
- if (!abort && !this.isDeviceRegistered()) {
298
- await this.restartRegistration(this.handleConnectionRestoration.name);
299
- }
300
- }
301
- retry = false;
302
- }
303
- });
304
- return retry;
305
- }
306
- restoreRegistrationCallBack() {
307
- return async (restoreData, caller) => {
308
- const logContext = { file: REGISTRATION_FILE, method: caller };
309
- if (!this.isRegRetry()) {
310
- log.info('Registration restoration in progress.', logContext);
311
- const restore = this.getExistingDevice(restoreData);
312
- if (restore) {
313
- this.setRegRetry(true);
314
- await this.deregister();
315
- const finalError = await this.restorePreviousRegistration(caller);
316
- this.setRegRetry(false);
317
- if (this.isDeviceRegistered()) {
318
- log.info('Registration restored successfully.', logContext);
319
- }
320
- return finalError;
321
- }
322
- this.lineEmitter(LINE_EVENTS.UNREGISTERED);
323
- }
324
- else {
325
- this.lineEmitter(LINE_EVENTS.UNREGISTERED);
326
- }
327
- return false;
328
- };
329
- }
330
- async triggerRegistration() {
331
- if (this.primaryMobiusUris.length > 0) {
332
- const abort = await this.attemptRegistrationWithServers(this.triggerRegistration.name, this.primaryMobiusUris);
333
- if (!this.isDeviceRegistered() && !abort) {
334
- await this.startFailoverTimer();
335
- }
336
- }
337
- }
338
- async attemptRegistrationWithServers(caller, servers = this.primaryMobiusUris) {
339
- let abort = false;
340
- if (this.isDeviceRegistered()) {
341
- log.log(`[${caller}] : Device already registered with : ${this.activeMobiusUrl}`, {
342
- file: REGISTRATION_FILE,
343
- method: this.attemptRegistrationWithServers.name,
344
- });
345
- return abort;
346
- }
347
- for (const url of servers) {
348
- try {
349
- abort = false;
350
- this.registrationStatus = MobiusStatus.DEFAULT;
351
- this.lineEmitter(LINE_EVENTS.CONNECTING);
352
- log.log(`[${caller}] : Mobius url to contact: ${url}`, {
353
- file: REGISTRATION_FILE,
354
- method: this.attemptRegistrationWithServers.name,
355
- });
356
- const resp = await this.postRegistration(url);
357
- this.deviceInfo = resp.body;
358
- this.lineEmitter(LINE_EVENTS.REGISTERED, resp.body);
359
- this.registrationStatus = MobiusStatus.ACTIVE;
360
- this.setActiveMobiusUrl(url);
361
- this.setIntervalValues(this.deviceInfo);
362
- this.metricManager.setDeviceInfo(this.deviceInfo);
363
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, undefined);
364
- this.startKeepaliveTimer(this.deviceInfo.device?.uri, this.deviceInfo.keepaliveInterval);
365
- this.initiateFailback();
366
- break;
367
- }
368
- catch (err) {
369
- const body = err;
370
- abort = await handleRegistrationErrors(body, (clientError, finalError) => {
371
- if (finalError) {
372
- this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
373
- }
374
- else {
375
- this.lineEmitter(LINE_EVENTS.UNREGISTERED);
376
- }
377
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION_ERROR, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, clientError);
378
- }, { method: this.attemptRegistrationWithServers.name, file: REGISTRATION_FILE }, this.restoreRegistrationCallBack());
379
- if (this.registrationStatus === MobiusStatus.ACTIVE) {
380
- log.info(`[${caller}] : Device is already restored, active mobius url: ${this.activeMobiusUrl}`, {
381
- file: REGISTRATION_FILE,
382
- method: this.attemptRegistrationWithServers.name,
383
- });
384
- break;
385
- }
386
- if (abort) {
387
- break;
388
- }
389
- else if (caller === this.executeFailback.name) {
390
- const error = body.statusCode;
391
- if (error === ERROR_CODE.TOO_MANY_REQUESTS) {
392
- await this.scheduleFailback429Retry();
393
- abort = true;
394
- break;
395
- }
396
- }
397
- }
398
- }
399
- return abort;
400
- }
401
- startKeepaliveTimer(url, interval) {
402
- let keepAliveRetryCount = 0;
403
- this.clearKeepaliveTimer();
404
- this.keepaliveTimer = setInterval(async () => {
405
- const logContext = {
406
- file: REGISTRATION_FILE,
407
- method: this.startKeepaliveTimer.name,
408
- };
409
- await this.mutex.runExclusive(async () => {
410
- if (this.isDeviceRegistered() && keepAliveRetryCount < 5) {
411
- try {
412
- const res = await this.postKeepAlive(url);
413
- log.info(`Sent Keepalive, status: ${res.statusCode}`, logContext);
414
- if (keepAliveRetryCount > 0) {
415
- this.lineEmitter(LINE_EVENTS.RECONNECTED);
416
- }
417
- keepAliveRetryCount = 0;
418
- }
419
- catch (err) {
420
- keepAliveRetryCount += 1;
421
- const error = err;
422
- log.warn(`Keep-alive missed ${keepAliveRetryCount} times. Status -> ${error.statusCode} `, logContext);
423
- const abort = await handleRegistrationErrors(error, (clientError, finalError) => {
424
- if (finalError) {
425
- this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
426
- }
427
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, clientError);
428
- }, { method: this.startKeepaliveTimer.name, file: REGISTRATION_FILE });
429
- if (abort || keepAliveRetryCount >= 5) {
430
- this.setStatus(MobiusStatus.DEFAULT);
431
- this.clearKeepaliveTimer();
432
- this.clearFailbackTimer();
433
- this.lineEmitter(LINE_EVENTS.UNREGISTERED);
434
- if (!abort) {
435
- await this.reconnectOnFailure(this.startKeepaliveTimer.name);
436
- }
437
- }
438
- else {
439
- this.lineEmitter(LINE_EVENTS.RECONNECTING);
440
- }
441
- }
442
- }
443
- });
444
- }, interval * 1000);
445
- }
446
- clearKeepaliveTimer() {
447
- if (this.keepaliveTimer) {
448
- clearInterval(this.keepaliveTimer);
449
- this.keepaliveTimer = undefined;
450
- }
451
- }
452
- isReconnectPending() {
453
- return this.reconnectPending;
454
- }
455
- async deregister() {
456
- try {
457
- await this.deleteRegistration(this.activeMobiusUrl, this.deviceInfo.device?.deviceId, this.deviceInfo.device?.clientDeviceUri);
458
- }
459
- catch (err) {
460
- log.warn(`Delete failed with Mobius`, {});
461
- }
462
- this.clearKeepaliveTimer();
463
- this.setStatus(MobiusStatus.DEFAULT);
464
- }
465
- isRegRetry() {
466
- return this.registerRetry;
467
- }
468
- setRegRetry(value) {
469
- this.registerRetry = value;
470
- }
471
- getExistingDevice(restoreData) {
472
- if (restoreData.devices && restoreData.devices.length > 0) {
473
- this.deviceInfo = {
474
- userId: restoreData.userId,
475
- device: restoreData.devices[0],
476
- keepaliveInterval: DEFAULT_KEEPALIVE_INTERVAL,
477
- rehomingIntervalMax: DEFAULT_REHOMING_INTERVAL_MAX,
478
- rehomingIntervalMin: DEFAULT_REHOMING_INTERVAL_MIN,
479
- };
480
- const stringToReplace = `${DEVICES_ENDPOINT_RESOURCE}/${restoreData.devices[0].deviceId}`;
481
- const uri = restoreData.devices[0].uri.replace(stringToReplace, '');
482
- this.setActiveMobiusUrl(uri);
483
- this.registrationStatus = MobiusStatus.ACTIVE;
484
- return true;
485
- }
486
- return false;
487
- }
488
- async reconnectOnFailure(caller) {
489
- this.reconnectPending = false;
490
- if (!this.isDeviceRegistered()) {
491
- if (Object.keys(this.callManager.getActiveCalls()).length === 0) {
492
- const abort = await this.restorePreviousRegistration(caller);
493
- if (!abort && !this.isDeviceRegistered()) {
494
- await this.restartRegistration(caller);
495
- }
496
- }
497
- else {
498
- this.reconnectPending = true;
499
- log.info('Active call(s) present, deferred reconnect till call cleanup.', {
500
- file: REGISTRATION_FILE,
501
- method: this.reconnectOnFailure.name,
502
- });
503
- }
504
- }
505
- }
506
- }
507
- export const createRegistration = (webex, serviceData, mutex, lineEmitter, logLevel) => new Registration(webex, serviceData, mutex, lineEmitter, logLevel);
1
+ import { v4 as uuid } from 'uuid';
2
+ import { ERROR_CODE } from '../../Errors/types';
3
+ import { emitFinalFailure, handleRegistrationErrors } from '../../common';
4
+ import { METRIC_EVENT, METRIC_TYPE, REG_ACTION } from '../../Metrics/types';
5
+ import { getMetricManager } from '../../Metrics';
6
+ import { getCallManager } from '../calling';
7
+ import log from '../../Logger';
8
+ import SDKConnector from '../../SDKConnector';
9
+ import { ALLOWED_SERVICES, HTTP_METHODS, RegistrationStatus, } 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, FAILBACK_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, } from '../constants';
11
+ import { LINE_EVENTS } from '../line/types';
12
+ export class Registration {
13
+ sdkConnector;
14
+ webex;
15
+ userId = '';
16
+ serviceData;
17
+ failback429RetryAttempts;
18
+ registrationStatus;
19
+ failbackTimer;
20
+ activeMobiusUrl;
21
+ keepaliveTimer;
22
+ rehomingIntervalMin;
23
+ rehomingIntervalMax;
24
+ mutex;
25
+ metricManager;
26
+ lineEmitter;
27
+ callManager;
28
+ deviceInfo = {};
29
+ primaryMobiusUris;
30
+ backupMobiusUris;
31
+ registerRetry = false;
32
+ reconnectPending = false;
33
+ constructor(webex, serviceData, mutex, lineEmitter, logLevel) {
34
+ this.sdkConnector = SDKConnector;
35
+ this.serviceData = serviceData;
36
+ if (!this.sdkConnector.getWebex()) {
37
+ SDKConnector.setWebex(webex);
38
+ }
39
+ this.webex = this.sdkConnector.getWebex();
40
+ this.userId = this.webex.internal.device.userId;
41
+ this.registrationStatus = RegistrationStatus.IDLE;
42
+ this.failback429RetryAttempts = 0;
43
+ log.setLogger(logLevel, REGISTRATION_FILE);
44
+ this.rehomingIntervalMin = DEFAULT_REHOMING_INTERVAL_MIN;
45
+ this.rehomingIntervalMax = DEFAULT_REHOMING_INTERVAL_MAX;
46
+ this.mutex = mutex;
47
+ this.callManager = getCallManager(this.webex, serviceData.indicator);
48
+ this.metricManager = getMetricManager(this.webex, serviceData.indicator);
49
+ this.lineEmitter = lineEmitter;
50
+ this.primaryMobiusUris = [];
51
+ this.backupMobiusUris = [];
52
+ }
53
+ getActiveMobiusUrl() {
54
+ return this.activeMobiusUrl;
55
+ }
56
+ setActiveMobiusUrl(url) {
57
+ log.info(`ActiveMobiusUrl: ${url}`, { method: 'setActiveMobiusUrl', file: REGISTRATION_FILE });
58
+ this.activeMobiusUrl = url;
59
+ this.callManager.updateActiveMobius(url);
60
+ }
61
+ setMobiusServers(primaryMobiusUris, backupMobiusUris) {
62
+ this.primaryMobiusUris = primaryMobiusUris;
63
+ this.backupMobiusUris = backupMobiusUris;
64
+ }
65
+ async postKeepAlive(url) {
66
+ return this.webex.request({
67
+ uri: `${url}/status`,
68
+ method: HTTP_METHODS.POST,
69
+ headers: {
70
+ [CISCO_DEVICE_URL]: this.webex.internal.device.url,
71
+ [SPARK_USER_AGENT]: CALLING_USER_AGENT,
72
+ },
73
+ service: ALLOWED_SERVICES.MOBIUS,
74
+ });
75
+ }
76
+ async deleteRegistration(url, deviceId, deviceUrl) {
77
+ let response;
78
+ try {
79
+ response = await fetch(`${url}${DEVICES_ENDPOINT_RESOURCE}/${deviceId}`, {
80
+ method: HTTP_METHODS.DELETE,
81
+ headers: {
82
+ [CISCO_DEVICE_URL]: deviceUrl,
83
+ Authorization: await this.webex.credentials.getUserToken(),
84
+ trackingId: `${WEBEX_WEB_CLIENT}_${uuid()}`,
85
+ [SPARK_USER_AGENT]: CALLING_USER_AGENT,
86
+ },
87
+ });
88
+ }
89
+ catch (error) {
90
+ log.warn(`Delete failed with Mobius`, {});
91
+ }
92
+ this.setStatus(RegistrationStatus.INACTIVE);
93
+ this.lineEmitter(LINE_EVENTS.UNREGISTERED);
94
+ return response?.json();
95
+ }
96
+ async postRegistration(url) {
97
+ const deviceInfo = {
98
+ userId: this.userId,
99
+ clientDeviceUri: this.webex.internal.device.url,
100
+ serviceData: this.serviceData,
101
+ };
102
+ return this.webex.request({
103
+ uri: `${url}device`,
104
+ method: HTTP_METHODS.POST,
105
+ headers: {
106
+ [CISCO_DEVICE_URL]: deviceInfo.clientDeviceUri,
107
+ [SPARK_USER_AGENT]: CALLING_USER_AGENT,
108
+ },
109
+ body: deviceInfo,
110
+ service: ALLOWED_SERVICES.MOBIUS,
111
+ });
112
+ }
113
+ async restorePreviousRegistration(caller) {
114
+ let abort = false;
115
+ if (this.activeMobiusUrl) {
116
+ abort = await this.attemptRegistrationWithServers(caller, [this.activeMobiusUrl]);
117
+ }
118
+ return abort;
119
+ }
120
+ async scheduleFailback429Retry() {
121
+ if (this.failback429RetryAttempts >= REG_FAILBACK_429_MAX_RETRIES) {
122
+ return;
123
+ }
124
+ this.clearFailbackTimer();
125
+ this.failback429RetryAttempts += 1;
126
+ log.log(`Received 429 while rehoming, 429 retry count : ${this.failback429RetryAttempts}`, {
127
+ file: REGISTRATION_FILE,
128
+ method: FAILBACK_429_RETRY_UTIL,
129
+ });
130
+ const interval = this.getRegRetryInterval(this.failback429RetryAttempts);
131
+ this.startFailbackTimer(interval);
132
+ const abort = await this.restorePreviousRegistration(FAILBACK_429_RETRY_UTIL);
133
+ if (!abort && !this.isDeviceRegistered()) {
134
+ await this.restartRegistration(FAILBACK_429_RETRY_UTIL);
135
+ }
136
+ }
137
+ getRegRetryInterval(attempt = 1) {
138
+ return (BASE_REG_RETRY_TIMER_VAL_IN_SEC +
139
+ BASE_REG_TIMER_MFACTOR ** attempt +
140
+ Math.floor((Math.random() * (REG_RANDOM_T_FACTOR_UPPER_LIMIT - SEC_TO_MSEC_MFACTOR + 1) +
141
+ SEC_TO_MSEC_MFACTOR) /
142
+ SEC_TO_MSEC_MFACTOR));
143
+ }
144
+ async startFailoverTimer(attempt = 1, timeElapsed = 0) {
145
+ const loggerContext = {
146
+ file: REGISTRATION_FILE,
147
+ method: this.startFailoverTimer.name,
148
+ };
149
+ let interval = this.getRegRetryInterval(attempt);
150
+ if (timeElapsed + interval > REG_TRY_BACKUP_TIMER_VAL_IN_SEC) {
151
+ const excessVal = timeElapsed + interval - REG_TRY_BACKUP_TIMER_VAL_IN_SEC;
152
+ interval -= excessVal;
153
+ }
154
+ let abort;
155
+ if (interval > BASE_REG_RETRY_TIMER_VAL_IN_SEC) {
156
+ const scheduledTime = Math.floor(Date.now() / 1000);
157
+ setTimeout(async () => {
158
+ await this.mutex.runExclusive(async () => {
159
+ abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name);
160
+ const currentTime = Math.floor(Date.now() / 1000);
161
+ if (!abort && !this.isDeviceRegistered()) {
162
+ await this.startFailoverTimer(attempt + 1, timeElapsed + (currentTime - scheduledTime));
163
+ }
164
+ });
165
+ }, interval * SEC_TO_MSEC_MFACTOR);
166
+ log.log(`Scheduled retry with primary in ${interval} seconds, number of attempts : ${attempt}`, loggerContext);
167
+ }
168
+ else if (this.backupMobiusUris.length) {
169
+ log.log('Failing over to backup servers.', loggerContext);
170
+ abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
171
+ if (!abort && !this.isDeviceRegistered()) {
172
+ interval = this.getRegRetryInterval();
173
+ setTimeout(async () => {
174
+ await this.mutex.runExclusive(async () => {
175
+ abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
176
+ if (!abort && !this.isDeviceRegistered()) {
177
+ emitFinalFailure((clientError) => {
178
+ this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
179
+ }, loggerContext);
180
+ }
181
+ });
182
+ }, interval * SEC_TO_MSEC_MFACTOR);
183
+ log.log(`Scheduled retry with backup servers in ${interval} seconds.`, loggerContext);
184
+ }
185
+ }
186
+ else {
187
+ emitFinalFailure((clientError) => {
188
+ this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
189
+ }, loggerContext);
190
+ }
191
+ }
192
+ clearFailbackTimer() {
193
+ if (this.failbackTimer) {
194
+ clearTimeout(this.failbackTimer);
195
+ this.failbackTimer = undefined;
196
+ }
197
+ }
198
+ isFailbackRequired() {
199
+ return this.isDeviceRegistered() && this.primaryMobiusUris.indexOf(this.activeMobiusUrl) === -1;
200
+ }
201
+ getFailbackInterval() {
202
+ return Math.floor(Math.random() * (this.rehomingIntervalMax - this.rehomingIntervalMin + 1) +
203
+ this.rehomingIntervalMin);
204
+ }
205
+ initiateFailback() {
206
+ if (this.isFailbackRequired()) {
207
+ if (!this.failbackTimer) {
208
+ this.failback429RetryAttempts = 0;
209
+ const intervalInMinutes = this.getFailbackInterval();
210
+ this.startFailbackTimer(intervalInMinutes * MINUTES_TO_SEC_MFACTOR);
211
+ }
212
+ }
213
+ else {
214
+ this.failback429RetryAttempts = 0;
215
+ this.clearFailbackTimer();
216
+ }
217
+ }
218
+ startFailbackTimer(intervalInSeconds) {
219
+ this.failbackTimer = setTimeout(async () => this.executeFailback(), intervalInSeconds * SEC_TO_MSEC_MFACTOR);
220
+ log.log(`Failback scheduled after ${intervalInSeconds} seconds.`, {
221
+ file: REGISTRATION_FILE,
222
+ method: this.startFailbackTimer.name,
223
+ });
224
+ }
225
+ async executeFailback() {
226
+ await this.mutex.runExclusive(async () => {
227
+ if (this.isFailbackRequired()) {
228
+ if (Object.keys(this.callManager.getActiveCalls()).length === 0) {
229
+ log.info(`Attempting failback to primary.`, {
230
+ file: REGISTRATION_FILE,
231
+ method: this.executeFailback.name,
232
+ });
233
+ await this.deregister();
234
+ const abort = await this.attemptRegistrationWithServers(FAILBACK_UTIL);
235
+ if (!abort && !this.isDeviceRegistered()) {
236
+ const abortNew = await this.restorePreviousRegistration(FAILBACK_UTIL);
237
+ if (abortNew) {
238
+ this.clearFailbackTimer();
239
+ return;
240
+ }
241
+ if (!this.isDeviceRegistered()) {
242
+ await this.restartRegistration(this.executeFailback.name);
243
+ }
244
+ else {
245
+ this.failbackTimer = undefined;
246
+ this.initiateFailback();
247
+ }
248
+ }
249
+ }
250
+ else {
251
+ log.info('Active calls present, deferring failback to next cycle.', {
252
+ file: REGISTRATION_FILE,
253
+ method: this.executeFailback.name,
254
+ });
255
+ this.failbackTimer = undefined;
256
+ this.initiateFailback();
257
+ }
258
+ }
259
+ });
260
+ }
261
+ setIntervalValues(deviceInfo) {
262
+ if (this.primaryMobiusUris.indexOf(this.activeMobiusUrl) !== -1) {
263
+ this.rehomingIntervalMin = deviceInfo?.rehomingIntervalMin
264
+ ? deviceInfo.rehomingIntervalMin
265
+ : DEFAULT_REHOMING_INTERVAL_MIN;
266
+ this.rehomingIntervalMax = deviceInfo?.rehomingIntervalMax
267
+ ? deviceInfo.rehomingIntervalMax
268
+ : DEFAULT_REHOMING_INTERVAL_MAX;
269
+ }
270
+ }
271
+ getDeviceInfo() {
272
+ return this.deviceInfo;
273
+ }
274
+ isDeviceRegistered() {
275
+ return this.registrationStatus === RegistrationStatus.ACTIVE;
276
+ }
277
+ getStatus() {
278
+ return this.registrationStatus;
279
+ }
280
+ setStatus(value) {
281
+ this.registrationStatus = value;
282
+ }
283
+ async restartRegistration(caller) {
284
+ this.clearFailbackTimer();
285
+ this.failback429RetryAttempts = 0;
286
+ const abort = await this.attemptRegistrationWithServers(caller, this.primaryMobiusUris);
287
+ if (!abort && !this.isDeviceRegistered()) {
288
+ await this.startFailoverTimer();
289
+ }
290
+ }
291
+ async handleConnectionRestoration(retry) {
292
+ await this.mutex.runExclusive(async () => {
293
+ if (retry) {
294
+ log.info('Mercury connection is up again, re-registering with Webex Calling if needed', {
295
+ file: REGISTRATION_FILE,
296
+ method: this.handleConnectionRestoration.name,
297
+ });
298
+ this.clearKeepaliveTimer();
299
+ if (this.isDeviceRegistered()) {
300
+ await this.deregister();
301
+ }
302
+ if (this.activeMobiusUrl) {
303
+ const abort = await this.restorePreviousRegistration(this.handleConnectionRestoration.name);
304
+ if (!abort && !this.isDeviceRegistered()) {
305
+ await this.restartRegistration(this.handleConnectionRestoration.name);
306
+ }
307
+ }
308
+ retry = false;
309
+ }
310
+ });
311
+ return retry;
312
+ }
313
+ restoreRegistrationCallBack() {
314
+ return async (restoreData, caller) => {
315
+ const logContext = { file: REGISTRATION_FILE, method: caller };
316
+ if (!this.isRegRetry()) {
317
+ log.info('Registration restoration in progress.', logContext);
318
+ const restore = this.getExistingDevice(restoreData);
319
+ if (restore) {
320
+ this.setRegRetry(true);
321
+ await this.deregister();
322
+ const finalError = await this.restorePreviousRegistration(caller);
323
+ this.setRegRetry(false);
324
+ if (this.isDeviceRegistered()) {
325
+ log.info('Registration restored successfully.', logContext);
326
+ }
327
+ return finalError;
328
+ }
329
+ this.lineEmitter(LINE_EVENTS.UNREGISTERED);
330
+ }
331
+ else {
332
+ this.lineEmitter(LINE_EVENTS.UNREGISTERED);
333
+ }
334
+ return false;
335
+ };
336
+ }
337
+ async triggerRegistration() {
338
+ if (this.primaryMobiusUris.length > 0) {
339
+ const abort = await this.attemptRegistrationWithServers(this.triggerRegistration.name, this.primaryMobiusUris);
340
+ if (!this.isDeviceRegistered() && !abort) {
341
+ await this.startFailoverTimer();
342
+ }
343
+ }
344
+ }
345
+ async attemptRegistrationWithServers(caller, servers = this.primaryMobiusUris) {
346
+ let abort = false;
347
+ if (this.isDeviceRegistered()) {
348
+ log.log(`[${caller}] : Device already registered with : ${this.activeMobiusUrl}`, {
349
+ file: REGISTRATION_FILE,
350
+ method: this.attemptRegistrationWithServers.name,
351
+ });
352
+ return abort;
353
+ }
354
+ for (const url of servers) {
355
+ try {
356
+ abort = false;
357
+ this.registrationStatus = RegistrationStatus.INACTIVE;
358
+ this.lineEmitter(LINE_EVENTS.CONNECTING);
359
+ log.log(`[${caller}] : Mobius url to contact: ${url}`, {
360
+ file: REGISTRATION_FILE,
361
+ method: this.attemptRegistrationWithServers.name,
362
+ });
363
+ const resp = await this.postRegistration(url);
364
+ this.deviceInfo = resp.body;
365
+ this.registrationStatus = RegistrationStatus.ACTIVE;
366
+ this.lineEmitter(LINE_EVENTS.REGISTERED, resp.body);
367
+ this.setActiveMobiusUrl(url);
368
+ this.setIntervalValues(this.deviceInfo);
369
+ this.metricManager.setDeviceInfo(this.deviceInfo);
370
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, undefined);
371
+ this.startKeepaliveTimer(this.deviceInfo.device?.uri, this.deviceInfo.keepaliveInterval);
372
+ this.initiateFailback();
373
+ break;
374
+ }
375
+ catch (err) {
376
+ const body = err;
377
+ abort = await handleRegistrationErrors(body, (clientError, finalError) => {
378
+ if (finalError) {
379
+ this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
380
+ }
381
+ else {
382
+ this.lineEmitter(LINE_EVENTS.UNREGISTERED);
383
+ }
384
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION_ERROR, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, clientError);
385
+ }, { method: this.attemptRegistrationWithServers.name, file: REGISTRATION_FILE }, this.restoreRegistrationCallBack());
386
+ if (this.registrationStatus === RegistrationStatus.ACTIVE) {
387
+ log.info(`[${caller}] : Device is already restored, active mobius url: ${this.activeMobiusUrl}`, {
388
+ file: REGISTRATION_FILE,
389
+ method: this.attemptRegistrationWithServers.name,
390
+ });
391
+ break;
392
+ }
393
+ if (abort) {
394
+ this.setStatus(RegistrationStatus.INACTIVE);
395
+ break;
396
+ }
397
+ else if (caller === this.executeFailback.name) {
398
+ const error = body.statusCode;
399
+ if (error === ERROR_CODE.TOO_MANY_REQUESTS) {
400
+ await this.scheduleFailback429Retry();
401
+ abort = true;
402
+ break;
403
+ }
404
+ }
405
+ }
406
+ }
407
+ return abort;
408
+ }
409
+ startKeepaliveTimer(url, interval) {
410
+ let keepAliveRetryCount = 0;
411
+ this.clearKeepaliveTimer();
412
+ this.keepaliveTimer = setInterval(async () => {
413
+ const logContext = {
414
+ file: REGISTRATION_FILE,
415
+ method: this.startKeepaliveTimer.name,
416
+ };
417
+ await this.mutex.runExclusive(async () => {
418
+ if (this.isDeviceRegistered() && keepAliveRetryCount < 5) {
419
+ try {
420
+ const res = await this.postKeepAlive(url);
421
+ log.info(`Sent Keepalive, status: ${res.statusCode}`, logContext);
422
+ if (keepAliveRetryCount > 0) {
423
+ this.lineEmitter(LINE_EVENTS.RECONNECTED);
424
+ }
425
+ keepAliveRetryCount = 0;
426
+ }
427
+ catch (err) {
428
+ keepAliveRetryCount += 1;
429
+ const error = err;
430
+ log.warn(`Keep-alive missed ${keepAliveRetryCount} times. Status -> ${error.statusCode} `, logContext);
431
+ const abort = await handleRegistrationErrors(error, (clientError, finalError) => {
432
+ if (finalError) {
433
+ this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
434
+ }
435
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, clientError);
436
+ }, { method: this.startKeepaliveTimer.name, file: REGISTRATION_FILE });
437
+ if (abort || keepAliveRetryCount >= 5) {
438
+ this.setStatus(RegistrationStatus.INACTIVE);
439
+ this.clearKeepaliveTimer();
440
+ this.clearFailbackTimer();
441
+ this.lineEmitter(LINE_EVENTS.UNREGISTERED);
442
+ if (!abort) {
443
+ await this.reconnectOnFailure(this.startKeepaliveTimer.name);
444
+ }
445
+ }
446
+ else {
447
+ this.lineEmitter(LINE_EVENTS.RECONNECTING);
448
+ }
449
+ }
450
+ }
451
+ });
452
+ }, interval * 1000);
453
+ }
454
+ clearKeepaliveTimer() {
455
+ if (this.keepaliveTimer) {
456
+ clearInterval(this.keepaliveTimer);
457
+ this.keepaliveTimer = undefined;
458
+ }
459
+ }
460
+ isReconnectPending() {
461
+ return this.reconnectPending;
462
+ }
463
+ async deregister() {
464
+ try {
465
+ await this.deleteRegistration(this.activeMobiusUrl, this.deviceInfo.device?.deviceId, this.deviceInfo.device?.clientDeviceUri);
466
+ }
467
+ catch (err) {
468
+ log.warn(`Delete failed with Mobius`, {});
469
+ }
470
+ this.clearKeepaliveTimer();
471
+ this.setStatus(RegistrationStatus.INACTIVE);
472
+ }
473
+ isRegRetry() {
474
+ return this.registerRetry;
475
+ }
476
+ setRegRetry(value) {
477
+ this.registerRetry = value;
478
+ }
479
+ getExistingDevice(restoreData) {
480
+ if (restoreData.devices && restoreData.devices.length > 0) {
481
+ this.deviceInfo = {
482
+ userId: restoreData.userId,
483
+ device: restoreData.devices[0],
484
+ keepaliveInterval: DEFAULT_KEEPALIVE_INTERVAL,
485
+ rehomingIntervalMax: DEFAULT_REHOMING_INTERVAL_MAX,
486
+ rehomingIntervalMin: DEFAULT_REHOMING_INTERVAL_MIN,
487
+ };
488
+ const stringToReplace = `${DEVICES_ENDPOINT_RESOURCE}/${restoreData.devices[0].deviceId}`;
489
+ const uri = restoreData.devices[0].uri.replace(stringToReplace, '');
490
+ this.setActiveMobiusUrl(uri);
491
+ this.registrationStatus = RegistrationStatus.ACTIVE;
492
+ return true;
493
+ }
494
+ return false;
495
+ }
496
+ async reconnectOnFailure(caller) {
497
+ this.reconnectPending = false;
498
+ if (!this.isDeviceRegistered()) {
499
+ if (Object.keys(this.callManager.getActiveCalls()).length === 0) {
500
+ const abort = await this.restorePreviousRegistration(caller);
501
+ if (!abort && !this.isDeviceRegistered()) {
502
+ await this.restartRegistration(caller);
503
+ }
504
+ }
505
+ else {
506
+ this.reconnectPending = true;
507
+ log.info('Active call(s) present, deferred reconnect till call cleanup.', {
508
+ file: REGISTRATION_FILE,
509
+ method: this.reconnectOnFailure.name,
510
+ });
511
+ }
512
+ }
513
+ }
514
+ }
515
+ export const createRegistration = (webex, serviceData, mutex, lineEmitter, logLevel) => new Registration(webex, serviceData, mutex, lineEmitter, logLevel);