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

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 (283) hide show
  1. package/CHANGELOG.md +1403 -0
  2. package/README.md +74 -74
  3. package/dist/module/CallHistory/CallHistory.js +81 -81
  4. package/dist/module/CallHistory/callHistoryFixtures.js +307 -307
  5. package/dist/module/CallHistory/constants.js +9 -9
  6. package/dist/module/CallHistory/types.js +1 -1
  7. package/dist/module/CallSettings/CallSettings.js +65 -65
  8. package/dist/module/CallSettings/UcmBackendConnector.js +100 -100
  9. package/dist/module/CallSettings/WxCallBackendConnector.js +287 -287
  10. package/dist/module/CallSettings/constants.js +11 -11
  11. package/dist/module/CallSettings/testFixtures.js +62 -62
  12. package/dist/module/CallSettings/types.js +1 -1
  13. package/dist/module/CallingClient/CallingClient.js +248 -248
  14. package/dist/module/CallingClient/callRecordFixtures.js +93 -93
  15. package/dist/module/CallingClient/calling/CallerId/index.js +169 -169
  16. package/dist/module/CallingClient/calling/CallerId/types.js +1 -1
  17. package/dist/module/CallingClient/calling/call.js +1658 -1658
  18. package/dist/module/CallingClient/calling/callManager.js +284 -284
  19. package/dist/module/CallingClient/calling/index.js +2 -2
  20. package/dist/module/CallingClient/calling/types.js +53 -53
  21. package/dist/module/CallingClient/callingClientFixtures.js +38 -38
  22. package/dist/module/CallingClient/constants.js +122 -122
  23. package/dist/module/CallingClient/line/index.js +158 -158
  24. package/dist/module/CallingClient/line/types.js +15 -15
  25. package/dist/module/CallingClient/registration/index.js +1 -1
  26. package/dist/module/CallingClient/registration/register.js +507 -507
  27. package/dist/module/CallingClient/registration/registerFixtures.js +28 -28
  28. package/dist/module/CallingClient/registration/types.js +1 -1
  29. package/dist/module/CallingClient/types.js +1 -1
  30. package/dist/module/Contacts/ContactsClient.js +484 -484
  31. package/dist/module/Contacts/constants.js +20 -20
  32. package/dist/module/Contacts/contactFixtures.js +284 -284
  33. package/dist/module/Contacts/types.js +10 -10
  34. package/dist/module/Errors/catalog/CallError.js +26 -26
  35. package/dist/module/Errors/catalog/CallingDeviceError.js +18 -18
  36. package/dist/module/Errors/catalog/ExtendedError.js +10 -10
  37. package/dist/module/Errors/catalog/LineError.js +24 -24
  38. package/dist/module/Errors/index.js +2 -2
  39. package/dist/module/Errors/types.js +48 -48
  40. package/dist/module/Events/impl/index.js +19 -19
  41. package/dist/module/Events/types.js +83 -83
  42. package/dist/module/Logger/index.js +114 -114
  43. package/dist/module/Logger/types.js +25 -25
  44. package/dist/module/Metrics/index.js +232 -232
  45. package/dist/module/Metrics/types.js +37 -37
  46. package/dist/module/SDKConnector/index.js +39 -39
  47. package/dist/module/SDKConnector/types.js +1 -1
  48. package/dist/module/SDKConnector/utils.js +12 -12
  49. package/dist/module/Voicemail/BroadworksBackendConnector.js +291 -291
  50. package/dist/module/Voicemail/UcmBackendConnector.js +279 -279
  51. package/dist/module/Voicemail/Voicemail.js +110 -110
  52. package/dist/module/Voicemail/WxCallBackendConnector.js +279 -279
  53. package/dist/module/Voicemail/constants.js +29 -29
  54. package/dist/module/Voicemail/types.js +1 -1
  55. package/dist/module/Voicemail/voicemailFixture.js +510 -510
  56. package/dist/module/api.js +6 -6
  57. package/dist/module/common/Utils.js +802 -802
  58. package/dist/module/common/constants.js +41 -41
  59. package/dist/module/common/index.js +1 -1
  60. package/dist/module/common/testUtil.js +938 -938
  61. package/dist/module/common/types.js +57 -57
  62. package/dist/module/index.js +8 -8
  63. package/dist/types/CallHistory/CallHistory.d.ts +17 -17
  64. package/dist/types/CallHistory/callHistoryFixtures.d.ts +94 -94
  65. package/dist/types/CallHistory/constants.d.ts +9 -9
  66. package/dist/types/CallHistory/types.d.ts +18 -18
  67. package/dist/types/CallSettings/CallSettings.d.ts +19 -19
  68. package/dist/types/CallSettings/UcmBackendConnector.d.ts +19 -19
  69. package/dist/types/CallSettings/WxCallBackendConnector.d.ts +21 -21
  70. package/dist/types/CallSettings/constants.d.ts +11 -11
  71. package/dist/types/CallSettings/testFixtures.d.ts +15 -15
  72. package/dist/types/CallSettings/types.d.ts +107 -107
  73. package/dist/types/CallingClient/CallingClient.d.ts +35 -35
  74. package/dist/types/CallingClient/callRecordFixtures.d.ts +3 -3
  75. package/dist/types/CallingClient/calling/CallerId/index.d.ts +17 -17
  76. package/dist/types/CallingClient/calling/CallerId/types.d.ts +41 -41
  77. package/dist/types/CallingClient/calling/call.d.ts +96 -96
  78. package/dist/types/CallingClient/calling/callManager.d.ts +25 -25
  79. package/dist/types/CallingClient/calling/index.d.ts +2 -2
  80. package/dist/types/CallingClient/calling/types.d.ts +206 -206
  81. package/dist/types/CallingClient/callingClientFixtures.d.ts +18 -18
  82. package/dist/types/CallingClient/constants.d.ts +122 -122
  83. package/dist/types/CallingClient/line/index.d.ts +43 -43
  84. package/dist/types/CallingClient/line/types.d.ts +55 -55
  85. package/dist/types/CallingClient/registration/index.d.ts +1 -1
  86. package/dist/types/CallingClient/registration/register.d.ts +64 -64
  87. package/dist/types/CallingClient/registration/registerFixtures.d.ts +28 -28
  88. package/dist/types/CallingClient/registration/types.d.ts +20 -20
  89. package/dist/types/CallingClient/types.d.ts +29 -29
  90. package/dist/types/Contacts/ContactsClient.d.ts +26 -26
  91. package/dist/types/Contacts/constants.d.ts +19 -19
  92. package/dist/types/Contacts/contactFixtures.d.ts +280 -280
  93. package/dist/types/Contacts/types.d.ts +72 -72
  94. package/dist/types/Errors/catalog/CallError.d.ts +11 -11
  95. package/dist/types/Errors/catalog/CallingDeviceError.d.ts +10 -10
  96. package/dist/types/Errors/catalog/ExtendedError.d.ts +6 -6
  97. package/dist/types/Errors/catalog/LineError.d.ts +10 -10
  98. package/dist/types/Errors/index.d.ts +2 -2
  99. package/dist/types/Errors/types.d.ts +60 -60
  100. package/dist/types/Events/impl/index.d.ts +8 -8
  101. package/dist/types/Events/types.d.ts +288 -288
  102. package/dist/types/Logger/index.d.ts +12 -12
  103. package/dist/types/Logger/types.d.ts +25 -25
  104. package/dist/types/Metrics/index.d.ts +5 -5
  105. package/dist/types/Metrics/types.d.ts +42 -42
  106. package/dist/types/SDKConnector/index.d.ts +12 -12
  107. package/dist/types/SDKConnector/types.d.ts +128 -128
  108. package/dist/types/SDKConnector/utils.d.ts +5 -5
  109. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts +27 -27
  110. package/dist/types/Voicemail/UcmBackendConnector.d.ts +34 -34
  111. package/dist/types/Voicemail/Voicemail.d.ts +27 -27
  112. package/dist/types/Voicemail/WxCallBackendConnector.d.ts +23 -23
  113. package/dist/types/Voicemail/constants.d.ts +29 -29
  114. package/dist/types/Voicemail/types.d.ts +133 -133
  115. package/dist/types/Voicemail/voicemailFixture.d.ts +417 -417
  116. package/dist/types/api.d.ts +16 -16
  117. package/dist/types/common/Utils.d.ts +34 -34
  118. package/dist/types/common/constants.d.ts +41 -41
  119. package/dist/types/common/index.d.ts +1 -1
  120. package/dist/types/common/testUtil.d.ts +3611 -3611
  121. package/dist/types/common/types.d.ts +191 -191
  122. package/dist/types/index.d.ts +8 -8
  123. package/package.json +4 -4
  124. package/dist/CallHistory/CallHistory.js +0 -203
  125. package/dist/CallHistory/CallHistory.js.map +0 -1
  126. package/dist/CallHistory/CallHistory.test.js +0 -133
  127. package/dist/CallHistory/CallHistory.test.js.map +0 -1
  128. package/dist/CallHistory/callHistoryFixtures.js +0 -310
  129. package/dist/CallHistory/callHistoryFixtures.js.map +0 -1
  130. package/dist/CallHistory/constants.js +0 -26
  131. package/dist/CallHistory/constants.js.map +0 -1
  132. package/dist/CallHistory/types.js +0 -7
  133. package/dist/CallHistory/types.js.map +0 -1
  134. package/dist/CallSettings/CallSettings.js +0 -276
  135. package/dist/CallSettings/CallSettings.js.map +0 -1
  136. package/dist/CallSettings/CallSettings.test.js +0 -122
  137. package/dist/CallSettings/CallSettings.test.js.map +0 -1
  138. package/dist/CallSettings/UcmBackendConnector.js +0 -217
  139. package/dist/CallSettings/UcmBackendConnector.js.map +0 -1
  140. package/dist/CallSettings/UcmBackendConnector.test.js +0 -227
  141. package/dist/CallSettings/UcmBackendConnector.test.js.map +0 -1
  142. package/dist/CallSettings/WxCallBackendConnector.js +0 -541
  143. package/dist/CallSettings/WxCallBackendConnector.js.map +0 -1
  144. package/dist/CallSettings/WxCallBackendConnector.test.js +0 -802
  145. package/dist/CallSettings/WxCallBackendConnector.test.js.map +0 -1
  146. package/dist/CallSettings/constants.js +0 -30
  147. package/dist/CallSettings/constants.js.map +0 -1
  148. package/dist/CallSettings/testFixtures.js +0 -72
  149. package/dist/CallSettings/testFixtures.js.map +0 -1
  150. package/dist/CallSettings/types.js +0 -7
  151. package/dist/CallSettings/types.js.map +0 -1
  152. package/dist/CallingClient/CallingClient.js +0 -572
  153. package/dist/CallingClient/CallingClient.js.map +0 -1
  154. package/dist/CallingClient/CallingClient.test.js +0 -931
  155. package/dist/CallingClient/CallingClient.test.js.map +0 -1
  156. package/dist/CallingClient/callRecordFixtures.js +0 -103
  157. package/dist/CallingClient/callRecordFixtures.js.map +0 -1
  158. package/dist/CallingClient/calling/CallerId/index.js +0 -287
  159. package/dist/CallingClient/calling/CallerId/index.js.map +0 -1
  160. package/dist/CallingClient/calling/CallerId/index.test.js +0 -274
  161. package/dist/CallingClient/calling/CallerId/index.test.js.map +0 -1
  162. package/dist/CallingClient/calling/CallerId/types.js +0 -7
  163. package/dist/CallingClient/calling/CallerId/types.js.map +0 -1
  164. package/dist/CallingClient/calling/call.js +0 -2995
  165. package/dist/CallingClient/calling/call.js.map +0 -1
  166. package/dist/CallingClient/calling/call.test.js +0 -2614
  167. package/dist/CallingClient/calling/call.test.js.map +0 -1
  168. package/dist/CallingClient/calling/callManager.js +0 -443
  169. package/dist/CallingClient/calling/callManager.js.map +0 -1
  170. package/dist/CallingClient/calling/callManager.test.js +0 -683
  171. package/dist/CallingClient/calling/callManager.test.js.map +0 -1
  172. package/dist/CallingClient/calling/index.js +0 -30
  173. package/dist/CallingClient/calling/index.js.map +0 -1
  174. package/dist/CallingClient/calling/types.js +0 -71
  175. package/dist/CallingClient/calling/types.js.map +0 -1
  176. package/dist/CallingClient/callingClientFixtures.js +0 -53
  177. package/dist/CallingClient/callingClientFixtures.js.map +0 -1
  178. package/dist/CallingClient/constants.js +0 -226
  179. package/dist/CallingClient/constants.js.map +0 -1
  180. package/dist/CallingClient/line/index.js +0 -312
  181. package/dist/CallingClient/line/index.js.map +0 -1
  182. package/dist/CallingClient/line/line.test.js +0 -270
  183. package/dist/CallingClient/line/line.test.js.map +0 -1
  184. package/dist/CallingClient/line/types.js +0 -25
  185. package/dist/CallingClient/line/types.js.map +0 -1
  186. package/dist/CallingClient/registration/index.js +0 -19
  187. package/dist/CallingClient/registration/index.js.map +0 -1
  188. package/dist/CallingClient/registration/register.js +0 -1295
  189. package/dist/CallingClient/registration/register.js.map +0 -1
  190. package/dist/CallingClient/registration/register.test.js +0 -838
  191. package/dist/CallingClient/registration/register.test.js.map +0 -1
  192. package/dist/CallingClient/registration/registerFixtures.js +0 -41
  193. package/dist/CallingClient/registration/registerFixtures.js.map +0 -1
  194. package/dist/CallingClient/registration/types.js +0 -7
  195. package/dist/CallingClient/registration/types.js.map +0 -1
  196. package/dist/CallingClient/types.js +0 -7
  197. package/dist/CallingClient/types.js.map +0 -1
  198. package/dist/Contacts/ContactsClient.js +0 -1139
  199. package/dist/Contacts/ContactsClient.js.map +0 -1
  200. package/dist/Contacts/ContactsClient.test.js +0 -725
  201. package/dist/Contacts/ContactsClient.test.js.map +0 -1
  202. package/dist/Contacts/constants.js +0 -36
  203. package/dist/Contacts/constants.js.map +0 -1
  204. package/dist/Contacts/contactFixtures.js +0 -340
  205. package/dist/Contacts/contactFixtures.js.map +0 -1
  206. package/dist/Contacts/types.js +0 -20
  207. package/dist/Contacts/types.js.map +0 -1
  208. package/dist/Errors/catalog/CallError.js +0 -94
  209. package/dist/Errors/catalog/CallError.js.map +0 -1
  210. package/dist/Errors/catalog/CallingDeviceError.js +0 -88
  211. package/dist/Errors/catalog/CallingDeviceError.js.map +0 -1
  212. package/dist/Errors/catalog/ExtendedError.js +0 -45
  213. package/dist/Errors/catalog/ExtendedError.js.map +0 -1
  214. package/dist/Errors/catalog/LineError.js +0 -90
  215. package/dist/Errors/catalog/LineError.js.map +0 -1
  216. package/dist/Errors/index.js +0 -21
  217. package/dist/Errors/index.js.map +0 -1
  218. package/dist/Errors/types.js +0 -62
  219. package/dist/Errors/types.js.map +0 -1
  220. package/dist/Events/impl/index.js +0 -82
  221. package/dist/Events/impl/index.js.map +0 -1
  222. package/dist/Events/types.js +0 -111
  223. package/dist/Events/types.js.map +0 -1
  224. package/dist/Logger/index.js +0 -221
  225. package/dist/Logger/index.js.map +0 -1
  226. package/dist/Logger/index.test.js +0 -62
  227. package/dist/Logger/index.test.js.map +0 -1
  228. package/dist/Logger/types.js +0 -37
  229. package/dist/Logger/types.js.map +0 -1
  230. package/dist/Metrics/index.js +0 -329
  231. package/dist/Metrics/index.js.map +0 -1
  232. package/dist/Metrics/index.test.js +0 -291
  233. package/dist/Metrics/index.test.js.map +0 -1
  234. package/dist/Metrics/types.js +0 -50
  235. package/dist/Metrics/types.js.map +0 -1
  236. package/dist/SDKConnector/index.js +0 -105
  237. package/dist/SDKConnector/index.js.map +0 -1
  238. package/dist/SDKConnector/index.test.js +0 -9
  239. package/dist/SDKConnector/index.test.js.map +0 -1
  240. package/dist/SDKConnector/types.js +0 -7
  241. package/dist/SDKConnector/types.js.map +0 -1
  242. package/dist/SDKConnector/utils.js +0 -40
  243. package/dist/SDKConnector/utils.js.map +0 -1
  244. package/dist/SDKConnector/utils.test.js +0 -9
  245. package/dist/SDKConnector/utils.test.js.map +0 -1
  246. package/dist/Voicemail/BroadworksBackendConnector.js +0 -632
  247. package/dist/Voicemail/BroadworksBackendConnector.js.map +0 -1
  248. package/dist/Voicemail/BroadworksBackendConnector.test.js +0 -733
  249. package/dist/Voicemail/BroadworksBackendConnector.test.js.map +0 -1
  250. package/dist/Voicemail/UcmBackendConnector.js +0 -566
  251. package/dist/Voicemail/UcmBackendConnector.js.map +0 -1
  252. package/dist/Voicemail/UcmBackendConnector.test.js +0 -628
  253. package/dist/Voicemail/UcmBackendConnector.test.js.map +0 -1
  254. package/dist/Voicemail/Voicemail.js +0 -378
  255. package/dist/Voicemail/Voicemail.js.map +0 -1
  256. package/dist/Voicemail/Voicemail.test.js +0 -226
  257. package/dist/Voicemail/Voicemail.test.js.map +0 -1
  258. package/dist/Voicemail/WxCallBackendConnector.js +0 -540
  259. package/dist/Voicemail/WxCallBackendConnector.js.map +0 -1
  260. package/dist/Voicemail/WxCallBackendConnector.test.js +0 -942
  261. package/dist/Voicemail/WxCallBackendConnector.test.js.map +0 -1
  262. package/dist/Voicemail/constants.js +0 -66
  263. package/dist/Voicemail/constants.js.map +0 -1
  264. package/dist/Voicemail/types.js +0 -7
  265. package/dist/Voicemail/types.js.map +0 -1
  266. package/dist/Voicemail/voicemailFixture.js +0 -559
  267. package/dist/Voicemail/voicemailFixture.js.map +0 -1
  268. package/dist/api.js +0 -134
  269. package/dist/api.js.map +0 -1
  270. package/dist/common/Utils.js +0 -1264
  271. package/dist/common/Utils.js.map +0 -1
  272. package/dist/common/Utils.test.js +0 -1227
  273. package/dist/common/Utils.test.js.map +0 -1
  274. package/dist/common/constants.js +0 -90
  275. package/dist/common/constants.js.map +0 -1
  276. package/dist/common/index.js +0 -19
  277. package/dist/common/index.js.map +0 -1
  278. package/dist/common/testUtil.js +0 -968
  279. package/dist/common/testUtil.js.map +0 -1
  280. package/dist/common/types.js +0 -75
  281. package/dist/common/types.js.map +0 -1
  282. package/dist/index.js +0 -63
  283. package/dist/index.js.map +0 -1
@@ -1,802 +1,802 @@
1
- import * as platform from 'platform';
2
- import { createCallError } from '../Errors/catalog/CallError';
3
- import { DEVICE_ERROR_CODE, ERROR_CODE, ERROR_TYPE, CALL_ERROR_CODE, } from '../Errors/types';
4
- import { ALLOWED_SERVICES, CALLING_BACKEND, HTTP_METHODS, MobiusStatus, SORT, ServiceIndicator, } from './types';
5
- import log from '../Logger';
6
- import { createClientError } from '../Errors/catalog/CallingDeviceError';
7
- import { BYTES_RECEIVED, BYTES_SENT, CALLING_USER_AGENT, CISCO_DEVICE_URL, CODEC_ID, DUMMY_METRICS, IDENTITY_ENDPOINT_RESOURCE, INBOUND_CODEC_MATCH, INBOUND_RTP, JITTER_BUFFER_DELAY, JITTER_BUFFER_EMITTED_COUNT, LOCAL_CANDIDATE_ID, MEDIA_ID, MEDIA_SOURCE, MIME_TYPE, NETWORK_TYPE, OUTBOUND_CODEC_MATCH, OUTBOUND_RTP, PACKETS_DISCARDED, PACKETS_LOST, PACKETS_RECEIVED, PACKETS_SENT, REMOTE_INBOUND_RTP, ROUND_TRIP_TIME_MEASUREMENTS, RTC_CODEC, RTC_ICE_CANDIDATE, RTC_ICE_CANDIDATE_PAIR, RTP_RX_STAT, RTP_TX_STAT, SCIM_ENDPOINT_RESOURCE, SCIM_USER_FILTER, SELECTED_CANDIDATE_PAIR_ID, SPARK_USER_AGENT, TARGET_BIT_RATE, TIMESTAMP, TOTAL_ROUND_TRIP_TIME, TOTAL_SAMPLES_DURATION, TRANSPORT, TYPE, URL_ENDPOINT, UTILS_FILE, } from '../CallingClient/constants';
8
- import { DEVICES, ITEMS, SETTINGS, VALUES, KEY, TIME, PLACEHOLDER_KEY, XSI_ACTION_ENDPOINT_ORG_URL_PARAM, XSI_ACTION_ENDPOINT, INFER_ID_CONSTANT, BW_XSI_URL, ENTITLEMENT_BASIC, ENTITLEMENT_BROADWORKS_CONN, ENTITLEMENT_STANDARD, NATIVE_WEBEX_TEAMS_CALLING, NATIVE_SIP_CALL_TO_UCM, BW_XSI_ENDPOINT_VERSION, } from './constants';
9
- import SDKConnector from '../SDKConnector';
10
- import { LineStatus } from '../CallingClient/line/types';
11
- import { createLineError } from '../Errors/catalog/LineError';
12
- export function filterMobiusUris(mobiusServers, defaultMobiusUrl) {
13
- const logContext = {
14
- file: UTILS_FILE,
15
- method: filterMobiusUris.name,
16
- };
17
- const urisArrayPrimary = [];
18
- const urisArrayBackup = [];
19
- if (mobiusServers?.primary?.uris) {
20
- log.info('Adding Primary uris', logContext);
21
- for (const uri of mobiusServers.primary.uris) {
22
- urisArrayPrimary.push(`${uri}${URL_ENDPOINT}`);
23
- }
24
- }
25
- if (mobiusServers?.backup?.uris) {
26
- log.info('Adding Backup uris', logContext);
27
- for (const uri of mobiusServers.backup.uris) {
28
- urisArrayBackup.push(`${uri}${URL_ENDPOINT}`);
29
- }
30
- }
31
- log.info('Adding Default uri', logContext);
32
- if (!urisArrayPrimary.length && !urisArrayBackup.length) {
33
- urisArrayPrimary.push(`${defaultMobiusUrl}${URL_ENDPOINT}`);
34
- }
35
- else {
36
- urisArrayBackup.push(`${defaultMobiusUrl}${URL_ENDPOINT}`);
37
- }
38
- const primaryUris = [];
39
- const backupUris = [];
40
- for (let i = 0; i < urisArrayPrimary.length; i += 1) {
41
- if (primaryUris.indexOf(urisArrayPrimary[i]) === -1) {
42
- primaryUris.push(urisArrayPrimary[i]);
43
- }
44
- }
45
- for (let i = 0; i < urisArrayBackup.length; i += 1) {
46
- if (backupUris.indexOf(urisArrayBackup[i]) === -1) {
47
- backupUris.push(urisArrayBackup[i]);
48
- }
49
- }
50
- return { primary: primaryUris, backup: backupUris };
51
- }
52
- function updateCallErrorContext(errContext, type, message, correlationId, callError) {
53
- const errObj = {};
54
- errObj.context = errContext;
55
- errObj.type = type;
56
- errObj.message = message;
57
- errObj.correlationId = correlationId;
58
- callError.setCallError(errObj);
59
- }
60
- function updateLineErrorContext(errContext, type, message, status, lineError) {
61
- const errObj = {};
62
- errObj.context = errContext;
63
- errObj.type = type;
64
- errObj.message = message;
65
- errObj.status = status;
66
- lineError.setError(errObj);
67
- }
68
- function updateErrorContext(errContext, type, message, clientError) {
69
- const errObj = {};
70
- errObj.context = errContext;
71
- errObj.type = type;
72
- errObj.message = message;
73
- clientError.setError(errObj);
74
- }
75
- export function emitFinalFailure(emitterCb, loggerContext) {
76
- const clientError = createLineError('', {}, ERROR_TYPE.DEFAULT, LineStatus.INACTIVE);
77
- updateLineErrorContext(loggerContext, ERROR_TYPE.SERVICE_UNAVAILABLE, 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.', LineStatus.INACTIVE, clientError);
78
- emitterCb(clientError);
79
- }
80
- export async function handleRegistrationErrors(err, emitterCb, loggerContext, restoreRegCb) {
81
- const lineError = createLineError('', {}, ERROR_TYPE.DEFAULT, LineStatus.INACTIVE);
82
- const errorCode = Number(err.statusCode);
83
- let finalError = false;
84
- log.warn(`Status code: -> ${errorCode}`, loggerContext);
85
- switch (errorCode) {
86
- case ERROR_CODE.UNAUTHORIZED: {
87
- finalError = true;
88
- log.warn(`401 Unauthorized`, loggerContext);
89
- updateLineErrorContext(loggerContext, ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', LineStatus.INACTIVE, lineError);
90
- emitterCb(lineError, finalError);
91
- break;
92
- }
93
- case ERROR_CODE.INTERNAL_SERVER_ERROR: {
94
- log.warn(`500 Internal Server Error`, loggerContext);
95
- updateLineErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', LineStatus.INACTIVE, lineError);
96
- emitterCb(lineError, finalError);
97
- break;
98
- }
99
- case ERROR_CODE.SERVICE_UNAVAILABLE: {
100
- log.warn(`503 Service Unavailable`, loggerContext);
101
- updateLineErrorContext(loggerContext, ERROR_TYPE.SERVICE_UNAVAILABLE, 'An error occurred on the server while processing the request. Wait a moment and try again.', LineStatus.INACTIVE, lineError);
102
- emitterCb(lineError, finalError);
103
- break;
104
- }
105
- case ERROR_CODE.FORBIDDEN: {
106
- log.warn(`403 Forbidden`, loggerContext);
107
- const errorBody = err.body;
108
- if (!errorBody) {
109
- log.warn('Error response has no body, throwing default error', loggerContext);
110
- updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.', LineStatus.INACTIVE, lineError);
111
- emitterCb(lineError, finalError);
112
- return finalError;
113
- }
114
- const code = Number(errorBody.errorCode);
115
- log.warn(`Error code found : ${code}`, loggerContext);
116
- switch (code) {
117
- case DEVICE_ERROR_CODE.DEVICE_LIMIT_EXCEEDED: {
118
- const errorMessage = 'User device limit exceeded';
119
- log.warn(errorMessage, loggerContext);
120
- if (restoreRegCb) {
121
- const caller = loggerContext.method || 'handleErrors';
122
- await restoreRegCb(errorBody, caller);
123
- }
124
- break;
125
- }
126
- case DEVICE_ERROR_CODE.DEVICE_CREATION_DISABLED: {
127
- const errorMessage = 'User is not configured for WebRTC calling. Please contact the administrator to resolve this issue.';
128
- finalError = true;
129
- updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
130
- log.warn(errorMessage, loggerContext);
131
- emitterCb(lineError, true);
132
- break;
133
- }
134
- case DEVICE_ERROR_CODE.DEVICE_CREATION_FAILED: {
135
- const errorMessage = 'An unknown error occurred while provisioning the device. Wait a moment and try again.';
136
- updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
137
- log.warn(errorMessage, loggerContext);
138
- emitterCb(lineError, finalError);
139
- break;
140
- }
141
- default: {
142
- const errorMessage = 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.';
143
- updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
144
- log.warn(errorMessage, loggerContext);
145
- emitterCb(lineError, finalError);
146
- }
147
- }
148
- break;
149
- }
150
- case ERROR_CODE.DEVICE_NOT_FOUND: {
151
- finalError = true;
152
- log.warn(`404 Device Not Found`, loggerContext);
153
- updateLineErrorContext(loggerContext, ERROR_TYPE.NOT_FOUND, 'The client has unregistered. Please wait for the client to register before attempting the call. If error persists, sign out, sign back in and attempt the call.', LineStatus.INACTIVE, lineError);
154
- emitterCb(lineError, finalError);
155
- break;
156
- }
157
- default: {
158
- updateLineErrorContext(loggerContext, ERROR_TYPE.DEFAULT, 'Unknown error', LineStatus.INACTIVE, lineError);
159
- log.warn(`Unknown Error`, loggerContext);
160
- emitterCb(lineError, finalError);
161
- }
162
- }
163
- return finalError;
164
- }
165
- export async function handleCallingClientErrors(err, emitterCb, loggerContext) {
166
- const clientError = createClientError('', {}, ERROR_TYPE.DEFAULT, MobiusStatus.DEFAULT);
167
- const errorCode = Number(err.statusCode);
168
- const finalError = false;
169
- log.warn(`Status code: -> ${errorCode}`, loggerContext);
170
- switch (errorCode) {
171
- case ERROR_CODE.INTERNAL_SERVER_ERROR: {
172
- log.warn(`500 Internal Server Error`, loggerContext);
173
- updateErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', clientError);
174
- emitterCb(clientError, finalError);
175
- break;
176
- }
177
- default: {
178
- updateErrorContext(loggerContext, ERROR_TYPE.DEFAULT, 'Unknown error', clientError);
179
- log.warn(`Unknown Error`, loggerContext);
180
- emitterCb(clientError, finalError);
181
- }
182
- }
183
- return finalError;
184
- }
185
- export async function handleCallErrors(emitterCb, errorLayer, retryCb, correlationId, err, caller, file) {
186
- const loggerContext = {
187
- file,
188
- method: caller,
189
- };
190
- const callError = createCallError('', loggerContext, ERROR_TYPE.DEFAULT, '', errorLayer);
191
- const errorCode = Number(err.statusCode);
192
- log.warn(`Status code: ->${errorCode}`, loggerContext);
193
- switch (errorCode) {
194
- case ERROR_CODE.UNAUTHORIZED: {
195
- log.warn(`401 Unauthorized`, loggerContext);
196
- updateCallErrorContext(loggerContext, ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', correlationId, callError);
197
- emitterCb(callError);
198
- break;
199
- }
200
- case ERROR_CODE.FORBIDDEN:
201
- case ERROR_CODE.SERVICE_UNAVAILABLE: {
202
- const errorBody = err.body;
203
- if (!errorBody) {
204
- log.warn('Error response has no body, throwing default error', loggerContext);
205
- updateCallErrorContext(loggerContext, err.statusCode === 403 ? ERROR_TYPE.FORBIDDEN_ERROR : ERROR_TYPE.SERVICE_UNAVAILABLE, err.statusCode === 403
206
- ? 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.'
207
- : 'An error occurred on the server while processing the request. Wait a moment and try again.', correlationId, callError);
208
- emitterCb(callError);
209
- return;
210
- }
211
- if (err.headers && 'retry-after' in err.headers && retryCb) {
212
- const retryInterval = Number(err.headers['retry-after']);
213
- log.warn(`Retry Interval received: ${retryInterval}`, loggerContext);
214
- retryCb(retryInterval);
215
- return;
216
- }
217
- const code = Number(errorBody.errorCode);
218
- let message;
219
- switch (code) {
220
- case CALL_ERROR_CODE.INVALID_STATUS_UPDATE: {
221
- message =
222
- 'An invalid status update has been received for the call. Wait a moment and try again.';
223
- break;
224
- }
225
- case CALL_ERROR_CODE.DEVICE_NOT_REGISTERED: {
226
- message =
227
- 'The client has unregistered. Please wait for the client to register before attempting the call. If error persists, sign out, sign back in and attempt the call.';
228
- break;
229
- }
230
- case CALL_ERROR_CODE.CALL_NOT_FOUND: {
231
- message = 'Call is not found on the server. Wait a moment and try again.';
232
- break;
233
- }
234
- case CALL_ERROR_CODE.ERROR_PROCESSING: {
235
- message =
236
- 'An error occurred while processing the call on the server. Wait a moment and try again.';
237
- break;
238
- }
239
- case CALL_ERROR_CODE.USER_BUSY: {
240
- message = 'Called user is busy.';
241
- break;
242
- }
243
- case CALL_ERROR_CODE.PARSING_ERROR: {
244
- message =
245
- 'An error occurred while parsing the provided information. Wait a moment and try again.';
246
- break;
247
- }
248
- case CALL_ERROR_CODE.NOT_ACCEPTABLE: {
249
- message =
250
- 'An error occurred on the server while accepting the call. Wait a moment and try again. Please contact the administrator if this persists.';
251
- break;
252
- }
253
- case CALL_ERROR_CODE.CALL_REJECTED: {
254
- message =
255
- 'Call rejected by the server. Wait a moment and try again. Please contact the administrator if this persists.';
256
- break;
257
- }
258
- case CALL_ERROR_CODE.NOT_AVAILABLE: {
259
- message =
260
- 'Calling services not available. Wait a moment and try again. Please contact the administrator if this persists.';
261
- break;
262
- }
263
- default: {
264
- message = 'An unknown error occurred. Wait a moment and try again.';
265
- }
266
- }
267
- updateCallErrorContext(loggerContext, err.statusCode === 403 ? ERROR_TYPE.FORBIDDEN_ERROR : ERROR_TYPE.SERVICE_UNAVAILABLE, message, correlationId, callError);
268
- emitterCb(callError);
269
- break;
270
- }
271
- case ERROR_CODE.DEVICE_NOT_FOUND: {
272
- log.warn(`404 Call Not Found`, loggerContext);
273
- updateCallErrorContext(loggerContext, ERROR_TYPE.NOT_FOUND, 'Call is no longer active. Wait a moment and try again.', correlationId, callError);
274
- emitterCb(callError);
275
- break;
276
- }
277
- case ERROR_CODE.INTERNAL_SERVER_ERROR: {
278
- log.warn(`500 Internal Server Error`, loggerContext);
279
- updateCallErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred in the call. Wait a moment and try again.', correlationId, callError);
280
- emitterCb(callError);
281
- break;
282
- }
283
- default: {
284
- log.warn(`Unknown Error`, loggerContext);
285
- }
286
- }
287
- }
288
- export async function serviceErrorCodeHandler(err, loggerContext) {
289
- const errorCode = Number(err.statusCode);
290
- const failureMessage = 'FAILURE';
291
- switch (errorCode) {
292
- case ERROR_CODE.BAD_REQUEST: {
293
- log.warn(`400 Bad request`, loggerContext);
294
- const errorDetails = {
295
- statusCode: 400,
296
- data: {
297
- error: '400 Bad request',
298
- },
299
- message: failureMessage,
300
- };
301
- return errorDetails;
302
- }
303
- case ERROR_CODE.UNAUTHORIZED: {
304
- log.warn(`401 User is unauthorised, possible token expiry`, loggerContext);
305
- const errorDetails = {
306
- statusCode: 401,
307
- data: {
308
- error: 'User is unauthorised, possible token expiry',
309
- },
310
- message: failureMessage,
311
- };
312
- return errorDetails;
313
- }
314
- case ERROR_CODE.FORBIDDEN: {
315
- log.warn(`403 User request is forbidden`, loggerContext);
316
- const errorDetails = {
317
- statusCode: 403,
318
- data: {
319
- error: 'User request is forbidden',
320
- },
321
- message: failureMessage,
322
- };
323
- return errorDetails;
324
- }
325
- case ERROR_CODE.DEVICE_NOT_FOUND: {
326
- log.warn(`404 User info not found`, loggerContext);
327
- const errorDetails = {
328
- statusCode: 404,
329
- data: {
330
- error: 'User info not found',
331
- },
332
- message: failureMessage,
333
- };
334
- return errorDetails;
335
- }
336
- case ERROR_CODE.REQUEST_TIMEOUT: {
337
- log.warn(`408 Request to the server timedout`, loggerContext);
338
- const errorDetails = {
339
- statusCode: 408,
340
- data: {
341
- error: 'Request to the server timedout',
342
- },
343
- message: failureMessage,
344
- };
345
- return errorDetails;
346
- }
347
- case ERROR_CODE.NOT_IMPLEMENTED: {
348
- log.warn(`501 Not Implemented error occurred`, loggerContext);
349
- const errorDetails = {
350
- statusCode: 501,
351
- data: {
352
- error: 'Method is not implemented at the backend',
353
- },
354
- message: failureMessage,
355
- };
356
- return errorDetails;
357
- }
358
- case ERROR_CODE.INTERNAL_SERVER_ERROR: {
359
- log.warn(`500 Internal server error occurred`, loggerContext);
360
- const errorDetails = {
361
- statusCode: 500,
362
- data: {
363
- error: 'Internal server error occurred',
364
- },
365
- message: failureMessage,
366
- };
367
- return errorDetails;
368
- }
369
- case ERROR_CODE.SERVICE_UNAVAILABLE: {
370
- log.warn(`503 Unable to establish a connection with the server`, loggerContext);
371
- const errorDetails = {
372
- statusCode: 503,
373
- data: {
374
- error: 'Unable to establish a connection with the server',
375
- },
376
- message: failureMessage,
377
- };
378
- return errorDetails;
379
- }
380
- default: {
381
- log.warn(`${errorCode || 422} Exception has occurred`, loggerContext);
382
- const errorDetails = {
383
- statusCode: errorCode || 422,
384
- data: {
385
- error: `${errorCode || 422} Exception has occurred`,
386
- },
387
- message: failureMessage,
388
- };
389
- return errorDetails;
390
- }
391
- }
392
- }
393
- export function parseMediaQualityStatistics(stats) {
394
- if (!stats || navigator.userAgent.indexOf('Firefox') !== -1) {
395
- log.info('RTCStatsReport is null, adding dummy stats', {
396
- file: UTILS_FILE,
397
- method: parseMediaQualityStatistics.name,
398
- });
399
- return DUMMY_METRICS;
400
- }
401
- try {
402
- let type;
403
- let id;
404
- let inboundCodec;
405
- let outboundCodec;
406
- const localCandidates = {};
407
- const candidatePairs = {};
408
- const codecList = {};
409
- const rxStat = {};
410
- const txStat = {};
411
- const vqPayload = {};
412
- let jitterBufferDelay = 0;
413
- let jitterBufferEmittedCount = 0;
414
- let totalRoundTripTime = 0;
415
- let roundTripTimeMeasurements = 0;
416
- let selectedPair = '';
417
- let bitRate = 0;
418
- vqPayload.maxJitter = 0;
419
- vqPayload.VoPktSizeMs = 20;
420
- stats.forEach((report) => {
421
- Object.keys(report).forEach((statName) => {
422
- if (statName !== TIMESTAMP) {
423
- if (!type || statName === TYPE) {
424
- type = report[statName];
425
- }
426
- else if (!id || statName === MEDIA_ID) {
427
- id = report[statName];
428
- }
429
- else if (id && id.indexOf(RTC_ICE_CANDIDATE_PAIR) !== -1) {
430
- if (statName === LOCAL_CANDIDATE_ID) {
431
- candidatePairs[id] = report[statName];
432
- }
433
- }
434
- else if (id && id.indexOf(RTC_ICE_CANDIDATE) !== -1) {
435
- if (statName === NETWORK_TYPE) {
436
- localCandidates[id] = report[statName];
437
- }
438
- }
439
- else if (id &&
440
- (id.indexOf(INBOUND_CODEC_MATCH) !== -1 ||
441
- id.indexOf(OUTBOUND_CODEC_MATCH) !== -1 ||
442
- id.indexOf(RTC_CODEC) !== -1)) {
443
- if (statName === MIME_TYPE) {
444
- codecList[id] = report[statName];
445
- }
446
- }
447
- else if (type && type === REMOTE_INBOUND_RTP) {
448
- switch (statName) {
449
- case TOTAL_ROUND_TRIP_TIME: {
450
- totalRoundTripTime = report[statName];
451
- break;
452
- }
453
- case ROUND_TRIP_TIME_MEASUREMENTS: {
454
- roundTripTimeMeasurements = report[statName];
455
- break;
456
- }
457
- default: {
458
- }
459
- }
460
- }
461
- else if (type && type === INBOUND_RTP) {
462
- switch (statName) {
463
- case CODEC_ID: {
464
- inboundCodec = report[statName];
465
- break;
466
- }
467
- case PACKETS_RECEIVED: {
468
- rxStat.Pkt = report[statName];
469
- break;
470
- }
471
- case BYTES_RECEIVED: {
472
- rxStat.Oct = report[statName];
473
- break;
474
- }
475
- case PACKETS_DISCARDED: {
476
- rxStat.LatePkt = report[statName];
477
- break;
478
- }
479
- case PACKETS_LOST: {
480
- rxStat.LostPkt = report[statName];
481
- break;
482
- }
483
- case JITTER_BUFFER_DELAY: {
484
- jitterBufferDelay = report[statName];
485
- break;
486
- }
487
- case JITTER_BUFFER_EMITTED_COUNT: {
488
- jitterBufferEmittedCount = report[statName];
489
- break;
490
- }
491
- default: {
492
- }
493
- }
494
- }
495
- else if (type && type === TRANSPORT) {
496
- switch (statName) {
497
- case SELECTED_CANDIDATE_PAIR_ID: {
498
- selectedPair = report[statName];
499
- break;
500
- }
501
- default: {
502
- }
503
- }
504
- }
505
- else if (type && type === OUTBOUND_RTP) {
506
- switch (statName) {
507
- case CODEC_ID: {
508
- outboundCodec = report[statName];
509
- break;
510
- }
511
- case PACKETS_SENT: {
512
- txStat.Pkt = report[statName];
513
- break;
514
- }
515
- case BYTES_SENT: {
516
- txStat.Oct = report[statName];
517
- break;
518
- }
519
- case TARGET_BIT_RATE: {
520
- bitRate = report[statName];
521
- break;
522
- }
523
- default: {
524
- }
525
- }
526
- }
527
- else if (type && type === MEDIA_SOURCE) {
528
- switch (statName) {
529
- case TOTAL_SAMPLES_DURATION: {
530
- rxStat.Dur = report[statName];
531
- txStat.Dur = report[statName];
532
- break;
533
- }
534
- default: {
535
- }
536
- }
537
- }
538
- }
539
- });
540
- });
541
- if (roundTripTimeMeasurements !== 0) {
542
- vqPayload.VoOneWayDelayMs = totalRoundTripTime / (2 * roundTripTimeMeasurements);
543
- }
544
- else {
545
- vqPayload.VoOneWayDelayMs = 0;
546
- }
547
- vqPayload.hwType = `${platform.os}/${platform.name}-${platform.version}`;
548
- vqPayload.networkType = localCandidates[candidatePairs[selectedPair]];
549
- rxStat.AvgJit = jitterBufferDelay / jitterBufferEmittedCount;
550
- vqPayload.VoRxCodec = codecList[inboundCodec].split('/')[1];
551
- const txVqPayload = {};
552
- txVqPayload.VoTxCodec = codecList[outboundCodec].split('/')[1];
553
- txVqPayload.rtpBitRate = bitRate;
554
- const byeStats = {};
555
- rxStat.VQMetrics = vqPayload;
556
- txStat.VQMetrics = txVqPayload;
557
- byeStats[RTP_RX_STAT] = rxStat;
558
- byeStats[RTP_TX_STAT] = txStat;
559
- log.log(JSON.stringify(byeStats), { file: UTILS_FILE, method: parseMediaQualityStatistics.name });
560
- return byeStats;
561
- }
562
- catch (err) {
563
- log.warn(`Caught error while parsing RTP stats, ${err}`, {
564
- file: UTILS_FILE,
565
- method: parseMediaQualityStatistics.name,
566
- });
567
- return DUMMY_METRICS;
568
- }
569
- }
570
- export const waitForMsecs = (msec) => new Promise((resolve) => {
571
- setTimeout(resolve, msec);
572
- });
573
- export function getCallingBackEnd(webex) {
574
- const entModels = webex.internal.device.features.entitlement.models;
575
- let callingBackend;
576
- if (webex.internal.device.callingBehavior === NATIVE_WEBEX_TEAMS_CALLING) {
577
- for (let i = 0; i < entModels.length; i += 1) {
578
- if (entModels[i][VALUES][KEY] === ENTITLEMENT_BASIC ||
579
- entModels[i][VALUES][KEY] === ENTITLEMENT_STANDARD) {
580
- callingBackend = CALLING_BACKEND.WXC;
581
- break;
582
- }
583
- else if (entModels[i][VALUES][KEY] === ENTITLEMENT_BROADWORKS_CONN) {
584
- callingBackend = CALLING_BACKEND.BWRKS;
585
- break;
586
- }
587
- }
588
- }
589
- else if (webex.internal.device.callingBehavior === NATIVE_SIP_CALL_TO_UCM) {
590
- callingBackend = CALLING_BACKEND.UCM;
591
- }
592
- else {
593
- callingBackend = CALLING_BACKEND.INVALID;
594
- }
595
- return callingBackend;
596
- }
597
- export async function getXsiActionEndpoint(webex, loggerContext, callingBackend) {
598
- try {
599
- switch (callingBackend) {
600
- case CALLING_BACKEND.WXC: {
601
- const userIdResponse = await webex.request({
602
- uri: `${webex.internal.services._serviceUrls.hydra}/${XSI_ACTION_ENDPOINT_ORG_URL_PARAM}`,
603
- method: HTTP_METHODS.GET,
604
- });
605
- const response = userIdResponse.body;
606
- const xsiEndpoint = response[ITEMS][0][XSI_ACTION_ENDPOINT];
607
- return xsiEndpoint;
608
- }
609
- case CALLING_BACKEND.BWRKS: {
610
- const bwTokenResponse = await webex.request({
611
- uri: `${webex.internal.services._serviceUrls.wdm}/${DEVICES}`,
612
- method: HTTP_METHODS.GET,
613
- });
614
- const response = bwTokenResponse.body;
615
- let xsiEndpoint = response[DEVICES][0][SETTINGS][BW_XSI_URL];
616
- if (response[DEVICES][0][SETTINGS][BW_XSI_URL].endsWith(BW_XSI_ENDPOINT_VERSION)) {
617
- xsiEndpoint = response[DEVICES][0][SETTINGS][BW_XSI_URL].slice(0, -5);
618
- }
619
- return xsiEndpoint;
620
- }
621
- default: {
622
- throw new Error('Calling backend is not identified, exiting....');
623
- }
624
- }
625
- }
626
- catch (err) {
627
- const errorInfo = err;
628
- serviceErrorCodeHandler(errorInfo, loggerContext);
629
- return errorInfo;
630
- }
631
- }
632
- export function getVgActionEndpoint(webex, callingBackend) {
633
- try {
634
- if (callingBackend && callingBackend === CALLING_BACKEND.UCM) {
635
- return webex.internal.services._serviceUrls['ucmgmt-gateway'];
636
- }
637
- throw new Error('Calling backend is not identified, exiting....');
638
- }
639
- catch (err) {
640
- const errorInfo = err;
641
- return errorInfo;
642
- }
643
- }
644
- export function getSortedVoicemailList(voiceMessageList, sortOrder) {
645
- if (sortOrder === SORT.DESC) {
646
- voiceMessageList.sort((voiceMail, nextVoiceMail) => nextVoiceMail[TIME][PLACEHOLDER_KEY] - voiceMail[TIME][PLACEHOLDER_KEY]);
647
- }
648
- else if (sortOrder === SORT.ASC) {
649
- voiceMessageList.sort((voiceMail, nextVoiceMail) => voiceMail[TIME][PLACEHOLDER_KEY] - nextVoiceMail[TIME][PLACEHOLDER_KEY]);
650
- }
651
- return voiceMessageList;
652
- }
653
- async function scimQuery(filter) {
654
- log.info(`Starting resolution for filter:- ${filter}`, {
655
- file: UTILS_FILE,
656
- method: 'scimQuery',
657
- });
658
- const sdkConnector = SDKConnector;
659
- const webex = sdkConnector.getWebex();
660
- const scimUrl = `${webex.internal.services._serviceUrls.identity}/${IDENTITY_ENDPOINT_RESOURCE}/${SCIM_ENDPOINT_RESOURCE}/${webex.internal.device.orgId}/${SCIM_USER_FILTER}`;
661
- const query = scimUrl + encodeURIComponent(filter);
662
- return webex.request({
663
- uri: query,
664
- method: HTTP_METHODS.GET,
665
- headers: {
666
- [CISCO_DEVICE_URL]: webex.internal.device.url,
667
- [SPARK_USER_AGENT]: CALLING_USER_AGENT,
668
- },
669
- service: ALLOWED_SERVICES.MOBIUS,
670
- });
671
- }
672
- export async function resolveCallerIdDisplay(filter) {
673
- let resolution;
674
- const displayResult = {};
675
- try {
676
- const response = await scimQuery(filter);
677
- resolution = response.body;
678
- log.info(`Number of records found for this user :- ${resolution.totalResults}`, {
679
- file: UTILS_FILE,
680
- method: 'resolveCallerIdDisplay',
681
- });
682
- }
683
- catch (err) {
684
- const res = err;
685
- log.warn(`Error response: - ${res.statusCode}`, {
686
- file: UTILS_FILE,
687
- method: 'resolveCallerIdDisplay',
688
- });
689
- }
690
- if (resolution?.totalResults && resolution.totalResults > 0) {
691
- const scimResource = resolution.Resources[0];
692
- displayResult.name = scimResource.displayName;
693
- const numberObj = scimResource.phoneNumbers.find((num) => num.primary) ||
694
- scimResource.phoneNumbers.find((num) => num.type.toLowerCase() === 'work');
695
- if (numberObj) {
696
- displayResult.num = numberObj.value;
697
- }
698
- else if (scimResource.phoneNumbers.length > 0) {
699
- log.info('Failure to resolve caller information. Setting number as caller ID', {
700
- file: UTILS_FILE,
701
- method: 'resolveCallerIdDisplay',
702
- });
703
- displayResult.num = scimResource.phoneNumbers[0].value;
704
- }
705
- const photo = scimResource.photos?.find((photo) => photo.type === 'thumbnail');
706
- displayResult.avatarSrc = photo ? photo.value : 'unknown';
707
- displayResult.id = scimResource.id;
708
- log.info(`Extracted details:- name: ${displayResult.name} , number: ${displayResult.num}, photo: ${displayResult.avatarSrc}, id: ${displayResult.id}`, {
709
- file: UTILS_FILE,
710
- method: 'resolveCallerIdDisplay',
711
- });
712
- }
713
- return displayResult;
714
- }
715
- export async function resolveCallerIdByName(name) {
716
- const displayResult = {};
717
- const sdkConnector = SDKConnector;
718
- const webex = sdkConnector.getWebex();
719
- const searchDirectory = (query) => {
720
- return webex.people.list({
721
- displayName: query,
722
- });
723
- };
724
- await searchDirectory(name).then((results) => {
725
- log.info(`DS Result: ${results}`, {
726
- file: UTILS_FILE,
727
- method: 'resolveCallerIdByName',
728
- });
729
- if (results && results.items && results.items.length > 0) {
730
- const resolution = results.items[0];
731
- displayResult.name = resolution.displayName;
732
- const id = Buffer.from(resolution.id, 'base64').toString('binary');
733
- displayResult.id = id.split('/').pop();
734
- const numObj = resolution.phoneNumbers.find((num) => num.type === 'work');
735
- if (numObj) {
736
- displayResult.num = numObj.value;
737
- }
738
- else if (resolution.phoneNumbers.length > 0) {
739
- displayResult.num = resolution.phoneNumbers[0].value;
740
- }
741
- displayResult.avatarSrc = resolution.avatar;
742
- log.info(`Extracted details:- name: ${displayResult.name} , number: ${displayResult.num}, photo: ${displayResult.avatarSrc}, id: ${displayResult.id}`, {
743
- file: UTILS_FILE,
744
- method: 'resolveCallerIdByName',
745
- });
746
- }
747
- });
748
- return displayResult;
749
- }
750
- export async function resolveContact(callingPartyInfo) {
751
- if (callingPartyInfo.userExternalId && callingPartyInfo.userExternalId.$) {
752
- return resolveCallerIdDisplay(`id eq "${callingPartyInfo.userExternalId.$}"`);
753
- }
754
- if (callingPartyInfo.name && callingPartyInfo.name.$) {
755
- return resolveCallerIdByName(callingPartyInfo.name.$);
756
- }
757
- return null;
758
- }
759
- export function storeVoicemailList(context, voiceMessageList) {
760
- const vmEncodedList = Buffer.from(JSON.stringify(voiceMessageList), 'utf8').toString('base64');
761
- sessionStorage.setItem(context, vmEncodedList.toString());
762
- }
763
- export function fetchVoicemailList(context, offset, offsetLimit, loggerContext) {
764
- let moreVoicemails = false;
765
- let requiredVoicemailList = [];
766
- try {
767
- const voicemailList = JSON.parse(Buffer.from(sessionStorage.getItem(context), 'base64').toString('utf8'));
768
- log.info(`Length of voicemail list: ${voicemailList.length}`, loggerContext);
769
- if (voicemailList.length > offset + offsetLimit) {
770
- moreVoicemails = true;
771
- }
772
- requiredVoicemailList = voicemailList.slice(offset, offset + offsetLimit);
773
- }
774
- catch (err) {
775
- log.warn(`Caught exception while fetching voicemail from storage. ${err}`, loggerContext);
776
- const errorInfo = err;
777
- serviceErrorCodeHandler(errorInfo, {});
778
- }
779
- return { messages: requiredVoicemailList, moreVMAvailable: moreVoicemails };
780
- }
781
- export function inferIdFromUuid(id, decodeType) {
782
- return Buffer.from(`${INFER_ID_CONSTANT}/${decodeType}/${id}`, 'binary').toString('base64');
783
- }
784
- function isValidServiceIndicator(indicator) {
785
- return Object.values(ServiceIndicator).some((v) => v === indicator);
786
- }
787
- function isValidServiceDomain(serviceData) {
788
- const regexp = /^[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,6}$/i;
789
- const { domain } = serviceData;
790
- if (!domain) {
791
- return serviceData.indicator === ServiceIndicator.CALLING;
792
- }
793
- return regexp.test(domain);
794
- }
795
- export function validateServiceData(serviceData) {
796
- if (!isValidServiceIndicator(serviceData.indicator)) {
797
- throw new Error(`Invalid service indicator, Allowed values are: ${Object.values(ServiceIndicator)}`);
798
- }
799
- if (!isValidServiceDomain(serviceData)) {
800
- throw new Error('Invalid service domain.');
801
- }
802
- }
1
+ import * as platform from 'platform';
2
+ import { createCallError } from '../Errors/catalog/CallError';
3
+ import { DEVICE_ERROR_CODE, ERROR_CODE, ERROR_TYPE, CALL_ERROR_CODE, } from '../Errors/types';
4
+ import { ALLOWED_SERVICES, CALLING_BACKEND, HTTP_METHODS, MobiusStatus, SORT, ServiceIndicator, } from './types';
5
+ import log from '../Logger';
6
+ import { createClientError } from '../Errors/catalog/CallingDeviceError';
7
+ import { BYTES_RECEIVED, BYTES_SENT, CALLING_USER_AGENT, CISCO_DEVICE_URL, CODEC_ID, DUMMY_METRICS, IDENTITY_ENDPOINT_RESOURCE, INBOUND_CODEC_MATCH, INBOUND_RTP, JITTER_BUFFER_DELAY, JITTER_BUFFER_EMITTED_COUNT, LOCAL_CANDIDATE_ID, MEDIA_ID, MEDIA_SOURCE, MIME_TYPE, NETWORK_TYPE, OUTBOUND_CODEC_MATCH, OUTBOUND_RTP, PACKETS_DISCARDED, PACKETS_LOST, PACKETS_RECEIVED, PACKETS_SENT, REMOTE_INBOUND_RTP, ROUND_TRIP_TIME_MEASUREMENTS, RTC_CODEC, RTC_ICE_CANDIDATE, RTC_ICE_CANDIDATE_PAIR, RTP_RX_STAT, RTP_TX_STAT, SCIM_ENDPOINT_RESOURCE, SCIM_USER_FILTER, SELECTED_CANDIDATE_PAIR_ID, SPARK_USER_AGENT, TARGET_BIT_RATE, TIMESTAMP, TOTAL_ROUND_TRIP_TIME, TOTAL_SAMPLES_DURATION, TRANSPORT, TYPE, URL_ENDPOINT, UTILS_FILE, } from '../CallingClient/constants';
8
+ import { DEVICES, ITEMS, SETTINGS, VALUES, KEY, TIME, PLACEHOLDER_KEY, XSI_ACTION_ENDPOINT_ORG_URL_PARAM, XSI_ACTION_ENDPOINT, INFER_ID_CONSTANT, BW_XSI_URL, ENTITLEMENT_BASIC, ENTITLEMENT_BROADWORKS_CONN, ENTITLEMENT_STANDARD, NATIVE_WEBEX_TEAMS_CALLING, NATIVE_SIP_CALL_TO_UCM, BW_XSI_ENDPOINT_VERSION, } from './constants';
9
+ import SDKConnector from '../SDKConnector';
10
+ import { LineStatus } from '../CallingClient/line/types';
11
+ import { createLineError } from '../Errors/catalog/LineError';
12
+ export function filterMobiusUris(mobiusServers, defaultMobiusUrl) {
13
+ const logContext = {
14
+ file: UTILS_FILE,
15
+ method: filterMobiusUris.name,
16
+ };
17
+ const urisArrayPrimary = [];
18
+ const urisArrayBackup = [];
19
+ if (mobiusServers?.primary?.uris) {
20
+ log.info('Adding Primary uris', logContext);
21
+ for (const uri of mobiusServers.primary.uris) {
22
+ urisArrayPrimary.push(`${uri}${URL_ENDPOINT}`);
23
+ }
24
+ }
25
+ if (mobiusServers?.backup?.uris) {
26
+ log.info('Adding Backup uris', logContext);
27
+ for (const uri of mobiusServers.backup.uris) {
28
+ urisArrayBackup.push(`${uri}${URL_ENDPOINT}`);
29
+ }
30
+ }
31
+ log.info('Adding Default uri', logContext);
32
+ if (!urisArrayPrimary.length && !urisArrayBackup.length) {
33
+ urisArrayPrimary.push(`${defaultMobiusUrl}${URL_ENDPOINT}`);
34
+ }
35
+ else {
36
+ urisArrayBackup.push(`${defaultMobiusUrl}${URL_ENDPOINT}`);
37
+ }
38
+ const primaryUris = [];
39
+ const backupUris = [];
40
+ for (let i = 0; i < urisArrayPrimary.length; i += 1) {
41
+ if (primaryUris.indexOf(urisArrayPrimary[i]) === -1) {
42
+ primaryUris.push(urisArrayPrimary[i]);
43
+ }
44
+ }
45
+ for (let i = 0; i < urisArrayBackup.length; i += 1) {
46
+ if (backupUris.indexOf(urisArrayBackup[i]) === -1) {
47
+ backupUris.push(urisArrayBackup[i]);
48
+ }
49
+ }
50
+ return { primary: primaryUris, backup: backupUris };
51
+ }
52
+ function updateCallErrorContext(errContext, type, message, correlationId, callError) {
53
+ const errObj = {};
54
+ errObj.context = errContext;
55
+ errObj.type = type;
56
+ errObj.message = message;
57
+ errObj.correlationId = correlationId;
58
+ callError.setCallError(errObj);
59
+ }
60
+ function updateLineErrorContext(errContext, type, message, status, lineError) {
61
+ const errObj = {};
62
+ errObj.context = errContext;
63
+ errObj.type = type;
64
+ errObj.message = message;
65
+ errObj.status = status;
66
+ lineError.setError(errObj);
67
+ }
68
+ function updateErrorContext(errContext, type, message, clientError) {
69
+ const errObj = {};
70
+ errObj.context = errContext;
71
+ errObj.type = type;
72
+ errObj.message = message;
73
+ clientError.setError(errObj);
74
+ }
75
+ export function emitFinalFailure(emitterCb, loggerContext) {
76
+ const clientError = createLineError('', {}, ERROR_TYPE.DEFAULT, LineStatus.INACTIVE);
77
+ updateLineErrorContext(loggerContext, ERROR_TYPE.SERVICE_UNAVAILABLE, 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.', LineStatus.INACTIVE, clientError);
78
+ emitterCb(clientError);
79
+ }
80
+ export async function handleRegistrationErrors(err, emitterCb, loggerContext, restoreRegCb) {
81
+ const lineError = createLineError('', {}, ERROR_TYPE.DEFAULT, LineStatus.INACTIVE);
82
+ const errorCode = Number(err.statusCode);
83
+ let finalError = false;
84
+ log.warn(`Status code: -> ${errorCode}`, loggerContext);
85
+ switch (errorCode) {
86
+ case ERROR_CODE.UNAUTHORIZED: {
87
+ finalError = true;
88
+ log.warn(`401 Unauthorized`, loggerContext);
89
+ updateLineErrorContext(loggerContext, ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', LineStatus.INACTIVE, lineError);
90
+ emitterCb(lineError, finalError);
91
+ break;
92
+ }
93
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
94
+ log.warn(`500 Internal Server Error`, loggerContext);
95
+ updateLineErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', LineStatus.INACTIVE, lineError);
96
+ emitterCb(lineError, finalError);
97
+ break;
98
+ }
99
+ case ERROR_CODE.SERVICE_UNAVAILABLE: {
100
+ log.warn(`503 Service Unavailable`, loggerContext);
101
+ updateLineErrorContext(loggerContext, ERROR_TYPE.SERVICE_UNAVAILABLE, 'An error occurred on the server while processing the request. Wait a moment and try again.', LineStatus.INACTIVE, lineError);
102
+ emitterCb(lineError, finalError);
103
+ break;
104
+ }
105
+ case ERROR_CODE.FORBIDDEN: {
106
+ log.warn(`403 Forbidden`, loggerContext);
107
+ const errorBody = err.body;
108
+ if (!errorBody) {
109
+ log.warn('Error response has no body, throwing default error', loggerContext);
110
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.', LineStatus.INACTIVE, lineError);
111
+ emitterCb(lineError, finalError);
112
+ return finalError;
113
+ }
114
+ const code = Number(errorBody.errorCode);
115
+ log.warn(`Error code found : ${code}`, loggerContext);
116
+ switch (code) {
117
+ case DEVICE_ERROR_CODE.DEVICE_LIMIT_EXCEEDED: {
118
+ const errorMessage = 'User device limit exceeded';
119
+ log.warn(errorMessage, loggerContext);
120
+ if (restoreRegCb) {
121
+ const caller = loggerContext.method || 'handleErrors';
122
+ await restoreRegCb(errorBody, caller);
123
+ }
124
+ break;
125
+ }
126
+ case DEVICE_ERROR_CODE.DEVICE_CREATION_DISABLED: {
127
+ const errorMessage = 'User is not configured for WebRTC calling. Please contact the administrator to resolve this issue.';
128
+ finalError = true;
129
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
130
+ log.warn(errorMessage, loggerContext);
131
+ emitterCb(lineError, true);
132
+ break;
133
+ }
134
+ case DEVICE_ERROR_CODE.DEVICE_CREATION_FAILED: {
135
+ const errorMessage = 'An unknown error occurred while provisioning the device. Wait a moment and try again.';
136
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
137
+ log.warn(errorMessage, loggerContext);
138
+ emitterCb(lineError, finalError);
139
+ break;
140
+ }
141
+ default: {
142
+ const errorMessage = 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.';
143
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
144
+ log.warn(errorMessage, loggerContext);
145
+ emitterCb(lineError, finalError);
146
+ }
147
+ }
148
+ break;
149
+ }
150
+ case ERROR_CODE.DEVICE_NOT_FOUND: {
151
+ finalError = true;
152
+ log.warn(`404 Device Not Found`, loggerContext);
153
+ updateLineErrorContext(loggerContext, ERROR_TYPE.NOT_FOUND, 'The client has unregistered. Please wait for the client to register before attempting the call. If error persists, sign out, sign back in and attempt the call.', LineStatus.INACTIVE, lineError);
154
+ emitterCb(lineError, finalError);
155
+ break;
156
+ }
157
+ default: {
158
+ updateLineErrorContext(loggerContext, ERROR_TYPE.DEFAULT, 'Unknown error', LineStatus.INACTIVE, lineError);
159
+ log.warn(`Unknown Error`, loggerContext);
160
+ emitterCb(lineError, finalError);
161
+ }
162
+ }
163
+ return finalError;
164
+ }
165
+ export async function handleCallingClientErrors(err, emitterCb, loggerContext) {
166
+ const clientError = createClientError('', {}, ERROR_TYPE.DEFAULT, MobiusStatus.DEFAULT);
167
+ const errorCode = Number(err.statusCode);
168
+ const finalError = false;
169
+ log.warn(`Status code: -> ${errorCode}`, loggerContext);
170
+ switch (errorCode) {
171
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
172
+ log.warn(`500 Internal Server Error`, loggerContext);
173
+ updateErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', clientError);
174
+ emitterCb(clientError, finalError);
175
+ break;
176
+ }
177
+ default: {
178
+ updateErrorContext(loggerContext, ERROR_TYPE.DEFAULT, 'Unknown error', clientError);
179
+ log.warn(`Unknown Error`, loggerContext);
180
+ emitterCb(clientError, finalError);
181
+ }
182
+ }
183
+ return finalError;
184
+ }
185
+ export async function handleCallErrors(emitterCb, errorLayer, retryCb, correlationId, err, caller, file) {
186
+ const loggerContext = {
187
+ file,
188
+ method: caller,
189
+ };
190
+ const callError = createCallError('', loggerContext, ERROR_TYPE.DEFAULT, '', errorLayer);
191
+ const errorCode = Number(err.statusCode);
192
+ log.warn(`Status code: ->${errorCode}`, loggerContext);
193
+ switch (errorCode) {
194
+ case ERROR_CODE.UNAUTHORIZED: {
195
+ log.warn(`401 Unauthorized`, loggerContext);
196
+ updateCallErrorContext(loggerContext, ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', correlationId, callError);
197
+ emitterCb(callError);
198
+ break;
199
+ }
200
+ case ERROR_CODE.FORBIDDEN:
201
+ case ERROR_CODE.SERVICE_UNAVAILABLE: {
202
+ const errorBody = err.body;
203
+ if (!errorBody) {
204
+ log.warn('Error response has no body, throwing default error', loggerContext);
205
+ updateCallErrorContext(loggerContext, err.statusCode === 403 ? ERROR_TYPE.FORBIDDEN_ERROR : ERROR_TYPE.SERVICE_UNAVAILABLE, err.statusCode === 403
206
+ ? 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.'
207
+ : 'An error occurred on the server while processing the request. Wait a moment and try again.', correlationId, callError);
208
+ emitterCb(callError);
209
+ return;
210
+ }
211
+ if (err.headers && 'retry-after' in err.headers && retryCb) {
212
+ const retryInterval = Number(err.headers['retry-after']);
213
+ log.warn(`Retry Interval received: ${retryInterval}`, loggerContext);
214
+ retryCb(retryInterval);
215
+ return;
216
+ }
217
+ const code = Number(errorBody.errorCode);
218
+ let message;
219
+ switch (code) {
220
+ case CALL_ERROR_CODE.INVALID_STATUS_UPDATE: {
221
+ message =
222
+ 'An invalid status update has been received for the call. Wait a moment and try again.';
223
+ break;
224
+ }
225
+ case CALL_ERROR_CODE.DEVICE_NOT_REGISTERED: {
226
+ message =
227
+ 'The client has unregistered. Please wait for the client to register before attempting the call. If error persists, sign out, sign back in and attempt the call.';
228
+ break;
229
+ }
230
+ case CALL_ERROR_CODE.CALL_NOT_FOUND: {
231
+ message = 'Call is not found on the server. Wait a moment and try again.';
232
+ break;
233
+ }
234
+ case CALL_ERROR_CODE.ERROR_PROCESSING: {
235
+ message =
236
+ 'An error occurred while processing the call on the server. Wait a moment and try again.';
237
+ break;
238
+ }
239
+ case CALL_ERROR_CODE.USER_BUSY: {
240
+ message = 'Called user is busy.';
241
+ break;
242
+ }
243
+ case CALL_ERROR_CODE.PARSING_ERROR: {
244
+ message =
245
+ 'An error occurred while parsing the provided information. Wait a moment and try again.';
246
+ break;
247
+ }
248
+ case CALL_ERROR_CODE.NOT_ACCEPTABLE: {
249
+ message =
250
+ 'An error occurred on the server while accepting the call. Wait a moment and try again. Please contact the administrator if this persists.';
251
+ break;
252
+ }
253
+ case CALL_ERROR_CODE.CALL_REJECTED: {
254
+ message =
255
+ 'Call rejected by the server. Wait a moment and try again. Please contact the administrator if this persists.';
256
+ break;
257
+ }
258
+ case CALL_ERROR_CODE.NOT_AVAILABLE: {
259
+ message =
260
+ 'Calling services not available. Wait a moment and try again. Please contact the administrator if this persists.';
261
+ break;
262
+ }
263
+ default: {
264
+ message = 'An unknown error occurred. Wait a moment and try again.';
265
+ }
266
+ }
267
+ updateCallErrorContext(loggerContext, err.statusCode === 403 ? ERROR_TYPE.FORBIDDEN_ERROR : ERROR_TYPE.SERVICE_UNAVAILABLE, message, correlationId, callError);
268
+ emitterCb(callError);
269
+ break;
270
+ }
271
+ case ERROR_CODE.DEVICE_NOT_FOUND: {
272
+ log.warn(`404 Call Not Found`, loggerContext);
273
+ updateCallErrorContext(loggerContext, ERROR_TYPE.NOT_FOUND, 'Call is no longer active. Wait a moment and try again.', correlationId, callError);
274
+ emitterCb(callError);
275
+ break;
276
+ }
277
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
278
+ log.warn(`500 Internal Server Error`, loggerContext);
279
+ updateCallErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred in the call. Wait a moment and try again.', correlationId, callError);
280
+ emitterCb(callError);
281
+ break;
282
+ }
283
+ default: {
284
+ log.warn(`Unknown Error`, loggerContext);
285
+ }
286
+ }
287
+ }
288
+ export async function serviceErrorCodeHandler(err, loggerContext) {
289
+ const errorCode = Number(err.statusCode);
290
+ const failureMessage = 'FAILURE';
291
+ switch (errorCode) {
292
+ case ERROR_CODE.BAD_REQUEST: {
293
+ log.warn(`400 Bad request`, loggerContext);
294
+ const errorDetails = {
295
+ statusCode: 400,
296
+ data: {
297
+ error: '400 Bad request',
298
+ },
299
+ message: failureMessage,
300
+ };
301
+ return errorDetails;
302
+ }
303
+ case ERROR_CODE.UNAUTHORIZED: {
304
+ log.warn(`401 User is unauthorised, possible token expiry`, loggerContext);
305
+ const errorDetails = {
306
+ statusCode: 401,
307
+ data: {
308
+ error: 'User is unauthorised, possible token expiry',
309
+ },
310
+ message: failureMessage,
311
+ };
312
+ return errorDetails;
313
+ }
314
+ case ERROR_CODE.FORBIDDEN: {
315
+ log.warn(`403 User request is forbidden`, loggerContext);
316
+ const errorDetails = {
317
+ statusCode: 403,
318
+ data: {
319
+ error: 'User request is forbidden',
320
+ },
321
+ message: failureMessage,
322
+ };
323
+ return errorDetails;
324
+ }
325
+ case ERROR_CODE.DEVICE_NOT_FOUND: {
326
+ log.warn(`404 User info not found`, loggerContext);
327
+ const errorDetails = {
328
+ statusCode: 404,
329
+ data: {
330
+ error: 'User info not found',
331
+ },
332
+ message: failureMessage,
333
+ };
334
+ return errorDetails;
335
+ }
336
+ case ERROR_CODE.REQUEST_TIMEOUT: {
337
+ log.warn(`408 Request to the server timedout`, loggerContext);
338
+ const errorDetails = {
339
+ statusCode: 408,
340
+ data: {
341
+ error: 'Request to the server timedout',
342
+ },
343
+ message: failureMessage,
344
+ };
345
+ return errorDetails;
346
+ }
347
+ case ERROR_CODE.NOT_IMPLEMENTED: {
348
+ log.warn(`501 Not Implemented error occurred`, loggerContext);
349
+ const errorDetails = {
350
+ statusCode: 501,
351
+ data: {
352
+ error: 'Method is not implemented at the backend',
353
+ },
354
+ message: failureMessage,
355
+ };
356
+ return errorDetails;
357
+ }
358
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
359
+ log.warn(`500 Internal server error occurred`, loggerContext);
360
+ const errorDetails = {
361
+ statusCode: 500,
362
+ data: {
363
+ error: 'Internal server error occurred',
364
+ },
365
+ message: failureMessage,
366
+ };
367
+ return errorDetails;
368
+ }
369
+ case ERROR_CODE.SERVICE_UNAVAILABLE: {
370
+ log.warn(`503 Unable to establish a connection with the server`, loggerContext);
371
+ const errorDetails = {
372
+ statusCode: 503,
373
+ data: {
374
+ error: 'Unable to establish a connection with the server',
375
+ },
376
+ message: failureMessage,
377
+ };
378
+ return errorDetails;
379
+ }
380
+ default: {
381
+ log.warn(`${errorCode || 422} Exception has occurred`, loggerContext);
382
+ const errorDetails = {
383
+ statusCode: errorCode || 422,
384
+ data: {
385
+ error: `${errorCode || 422} Exception has occurred`,
386
+ },
387
+ message: failureMessage,
388
+ };
389
+ return errorDetails;
390
+ }
391
+ }
392
+ }
393
+ export function parseMediaQualityStatistics(stats) {
394
+ if (!stats || navigator.userAgent.indexOf('Firefox') !== -1) {
395
+ log.info('RTCStatsReport is null, adding dummy stats', {
396
+ file: UTILS_FILE,
397
+ method: parseMediaQualityStatistics.name,
398
+ });
399
+ return DUMMY_METRICS;
400
+ }
401
+ try {
402
+ let type;
403
+ let id;
404
+ let inboundCodec;
405
+ let outboundCodec;
406
+ const localCandidates = {};
407
+ const candidatePairs = {};
408
+ const codecList = {};
409
+ const rxStat = {};
410
+ const txStat = {};
411
+ const vqPayload = {};
412
+ let jitterBufferDelay = 0;
413
+ let jitterBufferEmittedCount = 0;
414
+ let totalRoundTripTime = 0;
415
+ let roundTripTimeMeasurements = 0;
416
+ let selectedPair = '';
417
+ let bitRate = 0;
418
+ vqPayload.maxJitter = 0;
419
+ vqPayload.VoPktSizeMs = 20;
420
+ stats.forEach((report) => {
421
+ Object.keys(report).forEach((statName) => {
422
+ if (statName !== TIMESTAMP) {
423
+ if (!type || statName === TYPE) {
424
+ type = report[statName];
425
+ }
426
+ else if (!id || statName === MEDIA_ID) {
427
+ id = report[statName];
428
+ }
429
+ else if (id && id.indexOf(RTC_ICE_CANDIDATE_PAIR) !== -1) {
430
+ if (statName === LOCAL_CANDIDATE_ID) {
431
+ candidatePairs[id] = report[statName];
432
+ }
433
+ }
434
+ else if (id && id.indexOf(RTC_ICE_CANDIDATE) !== -1) {
435
+ if (statName === NETWORK_TYPE) {
436
+ localCandidates[id] = report[statName];
437
+ }
438
+ }
439
+ else if (id &&
440
+ (id.indexOf(INBOUND_CODEC_MATCH) !== -1 ||
441
+ id.indexOf(OUTBOUND_CODEC_MATCH) !== -1 ||
442
+ id.indexOf(RTC_CODEC) !== -1)) {
443
+ if (statName === MIME_TYPE) {
444
+ codecList[id] = report[statName];
445
+ }
446
+ }
447
+ else if (type && type === REMOTE_INBOUND_RTP) {
448
+ switch (statName) {
449
+ case TOTAL_ROUND_TRIP_TIME: {
450
+ totalRoundTripTime = report[statName];
451
+ break;
452
+ }
453
+ case ROUND_TRIP_TIME_MEASUREMENTS: {
454
+ roundTripTimeMeasurements = report[statName];
455
+ break;
456
+ }
457
+ default: {
458
+ }
459
+ }
460
+ }
461
+ else if (type && type === INBOUND_RTP) {
462
+ switch (statName) {
463
+ case CODEC_ID: {
464
+ inboundCodec = report[statName];
465
+ break;
466
+ }
467
+ case PACKETS_RECEIVED: {
468
+ rxStat.Pkt = report[statName];
469
+ break;
470
+ }
471
+ case BYTES_RECEIVED: {
472
+ rxStat.Oct = report[statName];
473
+ break;
474
+ }
475
+ case PACKETS_DISCARDED: {
476
+ rxStat.LatePkt = report[statName];
477
+ break;
478
+ }
479
+ case PACKETS_LOST: {
480
+ rxStat.LostPkt = report[statName];
481
+ break;
482
+ }
483
+ case JITTER_BUFFER_DELAY: {
484
+ jitterBufferDelay = report[statName];
485
+ break;
486
+ }
487
+ case JITTER_BUFFER_EMITTED_COUNT: {
488
+ jitterBufferEmittedCount = report[statName];
489
+ break;
490
+ }
491
+ default: {
492
+ }
493
+ }
494
+ }
495
+ else if (type && type === TRANSPORT) {
496
+ switch (statName) {
497
+ case SELECTED_CANDIDATE_PAIR_ID: {
498
+ selectedPair = report[statName];
499
+ break;
500
+ }
501
+ default: {
502
+ }
503
+ }
504
+ }
505
+ else if (type && type === OUTBOUND_RTP) {
506
+ switch (statName) {
507
+ case CODEC_ID: {
508
+ outboundCodec = report[statName];
509
+ break;
510
+ }
511
+ case PACKETS_SENT: {
512
+ txStat.Pkt = report[statName];
513
+ break;
514
+ }
515
+ case BYTES_SENT: {
516
+ txStat.Oct = report[statName];
517
+ break;
518
+ }
519
+ case TARGET_BIT_RATE: {
520
+ bitRate = report[statName];
521
+ break;
522
+ }
523
+ default: {
524
+ }
525
+ }
526
+ }
527
+ else if (type && type === MEDIA_SOURCE) {
528
+ switch (statName) {
529
+ case TOTAL_SAMPLES_DURATION: {
530
+ rxStat.Dur = report[statName];
531
+ txStat.Dur = report[statName];
532
+ break;
533
+ }
534
+ default: {
535
+ }
536
+ }
537
+ }
538
+ }
539
+ });
540
+ });
541
+ if (roundTripTimeMeasurements !== 0) {
542
+ vqPayload.VoOneWayDelayMs = totalRoundTripTime / (2 * roundTripTimeMeasurements);
543
+ }
544
+ else {
545
+ vqPayload.VoOneWayDelayMs = 0;
546
+ }
547
+ vqPayload.hwType = `${platform.os}/${platform.name}-${platform.version}`;
548
+ vqPayload.networkType = localCandidates[candidatePairs[selectedPair]];
549
+ rxStat.AvgJit = jitterBufferDelay / jitterBufferEmittedCount;
550
+ vqPayload.VoRxCodec = codecList[inboundCodec].split('/')[1];
551
+ const txVqPayload = {};
552
+ txVqPayload.VoTxCodec = codecList[outboundCodec].split('/')[1];
553
+ txVqPayload.rtpBitRate = bitRate;
554
+ const byeStats = {};
555
+ rxStat.VQMetrics = vqPayload;
556
+ txStat.VQMetrics = txVqPayload;
557
+ byeStats[RTP_RX_STAT] = rxStat;
558
+ byeStats[RTP_TX_STAT] = txStat;
559
+ log.log(JSON.stringify(byeStats), { file: UTILS_FILE, method: parseMediaQualityStatistics.name });
560
+ return byeStats;
561
+ }
562
+ catch (err) {
563
+ log.warn(`Caught error while parsing RTP stats, ${err}`, {
564
+ file: UTILS_FILE,
565
+ method: parseMediaQualityStatistics.name,
566
+ });
567
+ return DUMMY_METRICS;
568
+ }
569
+ }
570
+ export const waitForMsecs = (msec) => new Promise((resolve) => {
571
+ setTimeout(resolve, msec);
572
+ });
573
+ export function getCallingBackEnd(webex) {
574
+ const entModels = webex.internal.device.features.entitlement.models;
575
+ let callingBackend;
576
+ if (webex.internal.device.callingBehavior === NATIVE_WEBEX_TEAMS_CALLING) {
577
+ for (let i = 0; i < entModels.length; i += 1) {
578
+ if (entModels[i][VALUES][KEY] === ENTITLEMENT_BASIC ||
579
+ entModels[i][VALUES][KEY] === ENTITLEMENT_STANDARD) {
580
+ callingBackend = CALLING_BACKEND.WXC;
581
+ break;
582
+ }
583
+ else if (entModels[i][VALUES][KEY] === ENTITLEMENT_BROADWORKS_CONN) {
584
+ callingBackend = CALLING_BACKEND.BWRKS;
585
+ break;
586
+ }
587
+ }
588
+ }
589
+ else if (webex.internal.device.callingBehavior === NATIVE_SIP_CALL_TO_UCM) {
590
+ callingBackend = CALLING_BACKEND.UCM;
591
+ }
592
+ else {
593
+ callingBackend = CALLING_BACKEND.INVALID;
594
+ }
595
+ return callingBackend;
596
+ }
597
+ export async function getXsiActionEndpoint(webex, loggerContext, callingBackend) {
598
+ try {
599
+ switch (callingBackend) {
600
+ case CALLING_BACKEND.WXC: {
601
+ const userIdResponse = await webex.request({
602
+ uri: `${webex.internal.services._serviceUrls.hydra}/${XSI_ACTION_ENDPOINT_ORG_URL_PARAM}`,
603
+ method: HTTP_METHODS.GET,
604
+ });
605
+ const response = userIdResponse.body;
606
+ const xsiEndpoint = response[ITEMS][0][XSI_ACTION_ENDPOINT];
607
+ return xsiEndpoint;
608
+ }
609
+ case CALLING_BACKEND.BWRKS: {
610
+ const bwTokenResponse = await webex.request({
611
+ uri: `${webex.internal.services._serviceUrls.wdm}/${DEVICES}`,
612
+ method: HTTP_METHODS.GET,
613
+ });
614
+ const response = bwTokenResponse.body;
615
+ let xsiEndpoint = response[DEVICES][0][SETTINGS][BW_XSI_URL];
616
+ if (response[DEVICES][0][SETTINGS][BW_XSI_URL].endsWith(BW_XSI_ENDPOINT_VERSION)) {
617
+ xsiEndpoint = response[DEVICES][0][SETTINGS][BW_XSI_URL].slice(0, -5);
618
+ }
619
+ return xsiEndpoint;
620
+ }
621
+ default: {
622
+ throw new Error('Calling backend is not identified, exiting....');
623
+ }
624
+ }
625
+ }
626
+ catch (err) {
627
+ const errorInfo = err;
628
+ serviceErrorCodeHandler(errorInfo, loggerContext);
629
+ return errorInfo;
630
+ }
631
+ }
632
+ export function getVgActionEndpoint(webex, callingBackend) {
633
+ try {
634
+ if (callingBackend && callingBackend === CALLING_BACKEND.UCM) {
635
+ return webex.internal.services._serviceUrls['ucmgmt-gateway'];
636
+ }
637
+ throw new Error('Calling backend is not identified, exiting....');
638
+ }
639
+ catch (err) {
640
+ const errorInfo = err;
641
+ return errorInfo;
642
+ }
643
+ }
644
+ export function getSortedVoicemailList(voiceMessageList, sortOrder) {
645
+ if (sortOrder === SORT.DESC) {
646
+ voiceMessageList.sort((voiceMail, nextVoiceMail) => nextVoiceMail[TIME][PLACEHOLDER_KEY] - voiceMail[TIME][PLACEHOLDER_KEY]);
647
+ }
648
+ else if (sortOrder === SORT.ASC) {
649
+ voiceMessageList.sort((voiceMail, nextVoiceMail) => voiceMail[TIME][PLACEHOLDER_KEY] - nextVoiceMail[TIME][PLACEHOLDER_KEY]);
650
+ }
651
+ return voiceMessageList;
652
+ }
653
+ async function scimQuery(filter) {
654
+ log.info(`Starting resolution for filter:- ${filter}`, {
655
+ file: UTILS_FILE,
656
+ method: 'scimQuery',
657
+ });
658
+ const sdkConnector = SDKConnector;
659
+ const webex = sdkConnector.getWebex();
660
+ const scimUrl = `${webex.internal.services._serviceUrls.identity}/${IDENTITY_ENDPOINT_RESOURCE}/${SCIM_ENDPOINT_RESOURCE}/${webex.internal.device.orgId}/${SCIM_USER_FILTER}`;
661
+ const query = scimUrl + encodeURIComponent(filter);
662
+ return webex.request({
663
+ uri: query,
664
+ method: HTTP_METHODS.GET,
665
+ headers: {
666
+ [CISCO_DEVICE_URL]: webex.internal.device.url,
667
+ [SPARK_USER_AGENT]: CALLING_USER_AGENT,
668
+ },
669
+ service: ALLOWED_SERVICES.MOBIUS,
670
+ });
671
+ }
672
+ export async function resolveCallerIdDisplay(filter) {
673
+ let resolution;
674
+ const displayResult = {};
675
+ try {
676
+ const response = await scimQuery(filter);
677
+ resolution = response.body;
678
+ log.info(`Number of records found for this user :- ${resolution.totalResults}`, {
679
+ file: UTILS_FILE,
680
+ method: 'resolveCallerIdDisplay',
681
+ });
682
+ }
683
+ catch (err) {
684
+ const res = err;
685
+ log.warn(`Error response: - ${res.statusCode}`, {
686
+ file: UTILS_FILE,
687
+ method: 'resolveCallerIdDisplay',
688
+ });
689
+ }
690
+ if (resolution?.totalResults && resolution.totalResults > 0) {
691
+ const scimResource = resolution.Resources[0];
692
+ displayResult.name = scimResource.displayName;
693
+ const numberObj = scimResource.phoneNumbers.find((num) => num.primary) ||
694
+ scimResource.phoneNumbers.find((num) => num.type.toLowerCase() === 'work');
695
+ if (numberObj) {
696
+ displayResult.num = numberObj.value;
697
+ }
698
+ else if (scimResource.phoneNumbers.length > 0) {
699
+ log.info('Failure to resolve caller information. Setting number as caller ID', {
700
+ file: UTILS_FILE,
701
+ method: 'resolveCallerIdDisplay',
702
+ });
703
+ displayResult.num = scimResource.phoneNumbers[0].value;
704
+ }
705
+ const photo = scimResource.photos?.find((photo) => photo.type === 'thumbnail');
706
+ displayResult.avatarSrc = photo ? photo.value : 'unknown';
707
+ displayResult.id = scimResource.id;
708
+ log.info(`Extracted details:- name: ${displayResult.name} , number: ${displayResult.num}, photo: ${displayResult.avatarSrc}, id: ${displayResult.id}`, {
709
+ file: UTILS_FILE,
710
+ method: 'resolveCallerIdDisplay',
711
+ });
712
+ }
713
+ return displayResult;
714
+ }
715
+ export async function resolveCallerIdByName(name) {
716
+ const displayResult = {};
717
+ const sdkConnector = SDKConnector;
718
+ const webex = sdkConnector.getWebex();
719
+ const searchDirectory = (query) => {
720
+ return webex.people.list({
721
+ displayName: query,
722
+ });
723
+ };
724
+ await searchDirectory(name).then((results) => {
725
+ log.info(`DS Result: ${results}`, {
726
+ file: UTILS_FILE,
727
+ method: 'resolveCallerIdByName',
728
+ });
729
+ if (results && results.items && results.items.length > 0) {
730
+ const resolution = results.items[0];
731
+ displayResult.name = resolution.displayName;
732
+ const id = Buffer.from(resolution.id, 'base64').toString('binary');
733
+ displayResult.id = id.split('/').pop();
734
+ const numObj = resolution.phoneNumbers.find((num) => num.type === 'work');
735
+ if (numObj) {
736
+ displayResult.num = numObj.value;
737
+ }
738
+ else if (resolution.phoneNumbers.length > 0) {
739
+ displayResult.num = resolution.phoneNumbers[0].value;
740
+ }
741
+ displayResult.avatarSrc = resolution.avatar;
742
+ log.info(`Extracted details:- name: ${displayResult.name} , number: ${displayResult.num}, photo: ${displayResult.avatarSrc}, id: ${displayResult.id}`, {
743
+ file: UTILS_FILE,
744
+ method: 'resolveCallerIdByName',
745
+ });
746
+ }
747
+ });
748
+ return displayResult;
749
+ }
750
+ export async function resolveContact(callingPartyInfo) {
751
+ if (callingPartyInfo.userExternalId && callingPartyInfo.userExternalId.$) {
752
+ return resolveCallerIdDisplay(`id eq "${callingPartyInfo.userExternalId.$}"`);
753
+ }
754
+ if (callingPartyInfo.name && callingPartyInfo.name.$) {
755
+ return resolveCallerIdByName(callingPartyInfo.name.$);
756
+ }
757
+ return null;
758
+ }
759
+ export function storeVoicemailList(context, voiceMessageList) {
760
+ const vmEncodedList = Buffer.from(JSON.stringify(voiceMessageList), 'utf8').toString('base64');
761
+ sessionStorage.setItem(context, vmEncodedList.toString());
762
+ }
763
+ export function fetchVoicemailList(context, offset, offsetLimit, loggerContext) {
764
+ let moreVoicemails = false;
765
+ let requiredVoicemailList = [];
766
+ try {
767
+ const voicemailList = JSON.parse(Buffer.from(sessionStorage.getItem(context), 'base64').toString('utf8'));
768
+ log.info(`Length of voicemail list: ${voicemailList.length}`, loggerContext);
769
+ if (voicemailList.length > offset + offsetLimit) {
770
+ moreVoicemails = true;
771
+ }
772
+ requiredVoicemailList = voicemailList.slice(offset, offset + offsetLimit);
773
+ }
774
+ catch (err) {
775
+ log.warn(`Caught exception while fetching voicemail from storage. ${err}`, loggerContext);
776
+ const errorInfo = err;
777
+ serviceErrorCodeHandler(errorInfo, {});
778
+ }
779
+ return { messages: requiredVoicemailList, moreVMAvailable: moreVoicemails };
780
+ }
781
+ export function inferIdFromUuid(id, decodeType) {
782
+ return Buffer.from(`${INFER_ID_CONSTANT}/${decodeType}/${id}`, 'binary').toString('base64');
783
+ }
784
+ function isValidServiceIndicator(indicator) {
785
+ return Object.values(ServiceIndicator).some((v) => v === indicator);
786
+ }
787
+ function isValidServiceDomain(serviceData) {
788
+ const regexp = /^[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,6}$/i;
789
+ const { domain } = serviceData;
790
+ if (!domain) {
791
+ return serviceData.indicator === ServiceIndicator.CALLING;
792
+ }
793
+ return regexp.test(domain);
794
+ }
795
+ export function validateServiceData(serviceData) {
796
+ if (!isValidServiceIndicator(serviceData.indicator)) {
797
+ throw new Error(`Invalid service indicator, Allowed values are: ${Object.values(ServiceIndicator)}`);
798
+ }
799
+ if (!isValidServiceDomain(serviceData)) {
800
+ throw new Error('Invalid service domain.');
801
+ }
802
+ }