@exotel-npm-dev/webrtc-client-sdk 1.0.24 → 3.0.0

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.
@@ -2,21 +2,21 @@ import { Call } from "../api/callAPI/Call";
2
2
  import { DoRegister as DoRegisterRL, UnRegister as UnRegisterRL } from '../api/registerAPI/RegisterListener';
3
3
  import { CallListener } from '../listeners/CallListener';
4
4
  import { ExotelVoiceClientListener } from '../listeners/ExotelVoiceClientListener';
5
- import { SessionListener as SessionListenerSL } from '../listeners/SessionListeners';
5
+ import { SessionListener } from '../listeners/SessionListeners';
6
6
  import { CallController } from "./CallCtrlerDummy";
7
7
 
8
8
  import { closeDiagnostics as closeDiagnosticsDL, initDiagnostics as initDiagnosticsDL, startMicDiagnosticsTest as startMicDiagnosticsTestDL, startNetworkDiagnostics as startNetworkDiagnosticsDL, startSpeakerDiagnosticsTest as startSpeakerDiagnosticsTestDL, stopMicDiagnosticsTest as stopMicDiagnosticsTestDL, stopNetworkDiagnostics as stopNetworkDiagnosticsDL, stopSpeakerDiagnosticsTest as stopSpeakerDiagnosticsTestDL } from '../api/omAPI/DiagnosticsListener';
9
9
 
10
- import { callbacks, registerCallback, sessionCallback } from '../listeners/Callback';
10
+ import { Callback, RegisterCallback, SessionCallback } from '../listeners/Callback';
11
11
  import { webrtcTroubleshooterEventBus } from "./Callback";
12
12
 
13
- import { webrtcSIPPhone } from '@exotel-npm-dev/webrtc-core-sdk';
13
+ import { WebrtcSIPPhone, getLogger } from "@exotel-npm-dev/webrtc-core-sdk";
14
14
  import { CallDetails } from "../api/callAPI/CallDetails";
15
-
15
+ import LogManager from '../api/LogManager.js';
16
+ const phonePool = new Map();
16
17
  var intervalId;
17
18
  var intervalIDMap = new Map();
18
-
19
- var logger = webrtcSIPPhone.getLogger();
19
+ const logger = getLogger();
20
20
 
21
21
  function sleep(ms) {
22
22
  return new Promise(resolve => setTimeout(resolve, ms));
@@ -26,129 +26,115 @@ function sleep(ms) {
26
26
  * FQDN for fetching IP
27
27
  */
28
28
  function fetchPublicIP(sipAccountInfo) {
29
- var publicIp = "";
30
- const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
31
- pc.createDataChannel('');
32
- pc.createOffer().then(offer => pc.setLocalDescription(offer))
33
- pc.onicecandidate = (ice) => {
34
- if (!ice || !ice.candidate || !ice.candidate.candidate) {
35
- logger.log("all done.");
36
- pc.close();
37
- return "";
38
- }
39
- logger.log("iceCandidate =" + ice.candidate.candidate);
40
- let split = ice.candidate.candidate.split(" ");
41
- if (split[7] === "host") {
42
- logger.log(`fetchPublicIP:Local IP : ${split[4]}`);
43
- } else {
44
- logger.log(`fetchPublicIP:External IP : ${split[4]}`);
45
- publicIp = `${split[4]}`
46
- logger.log("fetchPublicIP:Public IP :" + publicIp);
47
- localStorage.setItem("contactHost", publicIp);
48
- pc.close();
49
- }
50
- };
51
- sleep(500).then(function () {
52
- logger.log("fetchPublicIP: public ip = ", publicIp)
53
- if (publicIp == "") {
54
- sipAccountInfo.contactHost = window.localStorage.getItem('contactHost');
55
- } else {
56
- sipAccountInfo.contactHost = publicIp;
57
- }
29
+ return new Promise((resolve) => {
30
+ var publicIp = "";
31
+ const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
32
+ pc.createDataChannel('');
33
+ pc.createOffer().then(offer => pc.setLocalDescription(offer))
34
+ pc.onicecandidate = (ice) => {
35
+ if (!ice || !ice.candidate || !ice.candidate.candidate) {
36
+ pc.close();
37
+ resolve();
38
+ return;
39
+ }
40
+ logger.log("iceCandidate =" + ice.candidate.candidate);
41
+ let split = ice.candidate.candidate.split(" ");
42
+ if (split[7] === "host") {
43
+ logger.log(`fetchPublicIP:Local IP : ${split[4]}`);
44
+ } else {
45
+ logger.log(`fetchPublicIP:External IP : ${split[4]}`);
46
+ publicIp = `${split[4]}`
47
+ logger.log("fetchPublicIP:Public IP :" + publicIp);
48
+ localStorage.setItem("contactHost", publicIp);
49
+ pc.close();
50
+ resolve();
51
+ }
52
+ };
53
+ setTimeout(() => {
54
+ logger.log("fetchPublicIP: public ip = ", publicIp)
55
+ if (publicIp == "") {
56
+ sipAccountInfo.contactHost = window.localStorage.getItem('contactHost');
57
+ } else {
58
+ sipAccountInfo.contactHost = publicIp;
59
+ }
60
+ resolve();
61
+ }, 1000);
58
62
  });
59
- return;
60
- };
61
-
63
+ }
62
64
 
63
- export function ExDelegationHandler(exClient_) {
64
- var exClient = exClient_;
65
- this.setTestingMode = function (mode) {
65
+ class ExDelegationHandler {
66
+ constructor(exClient) {
67
+ this.exClient = exClient;
68
+ }
69
+ setTestingMode(mode) {
66
70
  logger.log("delegationHandler: setTestingMode\n");
67
71
  }
68
-
69
- this.onCallStatSipJsSessionEvent = function (ev) {
70
- logger.log("delegationHandler: onCallStatSipJsSessionEvent\n");
72
+ onCallStatSipJsSessionEvent(ev) {
73
+ logger.log("delegationHandler: onCallStatSipJsSessionEvent", ev);
71
74
  }
72
-
73
- this.sendWebRTCEventsToFSM = function (eventType, sipMethod) {
75
+ sendWebRTCEventsToFSM(eventType, sipMethod) {
74
76
  logger.log("delegationHandler: sendWebRTCEventsToFSM\n");
75
77
  logger.log("delegationHandler: eventType\n", eventType);
76
78
  logger.log("delegationHandler: sipMethod\n", sipMethod);
79
+
77
80
  if (sipMethod == "CONNECTION") {
78
- exClient.registerEventCallback(eventType, exClient.userName)
81
+ this.exClient.registerEventCallback(eventType, this.exClient.userName);
79
82
  } else if (sipMethod == "CALL") {
80
- exClient.callEventCallback(eventType, exClient.callFromNumber, exClient.call)
83
+ this.exClient.callEventCallback(eventType, this.exClient.callFromNumber, this.exClient.call);
81
84
  }
82
85
  }
83
-
84
- this.playBeepTone = function () {
86
+ playBeepTone() {
85
87
  logger.log("delegationHandler: playBeepTone\n");
86
88
  }
87
-
88
- this.onStatPeerConnectionIceGatheringStateChange = function (iceGatheringState) {
89
+ onStatPeerConnectionIceGatheringStateChange(iceGatheringState) {
89
90
  logger.log("delegationHandler: onStatPeerConnectionIceGatheringStateChange\n");
90
91
  }
91
-
92
- this.onCallStatIceCandidate = function (ev, icestate) {
92
+ onCallStatIceCandidate(ev, icestate) {
93
93
  logger.log("delegationHandler: onCallStatIceCandidate\n");
94
94
  }
95
-
96
- this.onCallStatNegoNeeded = function (icestate) {
95
+ onCallStatNegoNeeded(icestate) {
97
96
  logger.log("delegationHandler: onCallStatNegoNeeded\n");
98
97
  }
99
-
100
- this.onCallStatSignalingStateChange = function (cstate) {
98
+ onCallStatSignalingStateChange(cstate) {
101
99
  logger.log("delegationHandler: onCallStatSignalingStateChange\n");
102
100
  }
103
-
104
- this.onStatPeerConnectionIceConnectionStateChange = function () {
101
+ onStatPeerConnectionIceConnectionStateChange() {
105
102
  logger.log("delegationHandler: onStatPeerConnectionIceConnectionStateChange\n");
106
103
  }
107
-
108
- this.onStatPeerConnectionConnectionStateChange = function () {
104
+ onStatPeerConnectionConnectionStateChange() {
109
105
  logger.log("delegationHandler: onStatPeerConnectionConnectionStateChange\n");
110
106
  }
111
-
112
- this.onGetUserMediaSuccessCallstatCallback = function () {
107
+ onGetUserMediaSuccessCallstatCallback() {
113
108
  logger.log("delegationHandler: onGetUserMediaSuccessCallstatCallback\n");
114
109
  }
115
-
116
- this.onGetUserMediaErrorCallstatCallback = function () {
110
+ onGetUserMediaErrorCallstatCallback() {
117
111
  logger.log("delegationHandler: onGetUserMediaErrorCallstatCallback\n");
118
112
  }
119
-
120
- this.onCallStatAddStream = function () {
113
+ onCallStatAddStream() {
121
114
  logger.log("delegationHandler: onCallStatAddStream\n");
122
115
  }
123
-
124
- this.onCallStatRemoveStream = function () {
116
+ onCallStatRemoveStream() {
125
117
  logger.log("delegationHandler: onCallStatRemoveStream\n");
126
118
  }
127
-
128
- this.setWebRTCFSMMapper = function (stack) {
119
+ setWebRTCFSMMapper(stack) {
129
120
  logger.log("delegationHandler: setWebRTCFSMMapper : Initialisation complete \n");
130
121
  }
131
-
132
- this.onCallStatSipJsTransportEvent = function () {
122
+ onCallStatSipJsTransportEvent() {
133
123
  logger.log("delegationHandler: onCallStatSipJsTransportEvent\n");
134
124
  }
135
-
136
- this.onCallStatSipSendCallback = function () {
125
+ onCallStatSipSendCallback() {
137
126
  logger.log("delegationHandler: onCallStatSipSendCallback\n");
138
127
  }
139
-
140
- this.onCallStatSipRecvCallback = function () {
128
+ onCallStatSipRecvCallback() {
141
129
  logger.log("delegationHandler: onCallStatSipRecvCallback\n");
142
130
  }
143
-
144
- this.stopCallStat = function () {
131
+ stopCallStat() {
145
132
  logger.log("delegationHandler: stopCallStat\n");
146
133
  }
147
-
148
- this.onRecieveInvite = function (incomingSession) {
134
+ onRecieveInvite(incomingSession) {
149
135
  logger.log("delegationHandler: onRecieveInvite\n");
150
136
  const obj = incomingSession.incomingInviteRequest.message.headers;
151
- exClient.callFromNumber = incomingSession.incomingInviteRequest.message.from.displayName;
137
+ this.exClient.callFromNumber = incomingSession.incomingInviteRequest.message.from.displayName;
152
138
  if (obj.hasOwnProperty("X-Exotel-Callsid")) {
153
139
  CallDetails.callSid = obj['X-Exotel-Callsid'][0].raw;
154
140
  }
@@ -170,45 +156,41 @@ export function ExDelegationHandler(exClient_) {
170
156
  }
171
157
  CallDetails.sipHeaders = result;
172
158
  }
173
-
174
- this.onPickCall = function () {
159
+ onPickCall() {
175
160
  logger.log("delegationHandler: onPickCall\n");
176
161
  }
177
-
178
- this.onRejectCall = function () {
162
+ onRejectCall() {
179
163
  logger.log("delegationHandler: onRejectCall\n");
180
164
  }
181
-
182
- this.onCreaterAnswer = function () {
165
+ onCreaterAnswer() {
183
166
  logger.log("delegationHandler: onCreaterAnswer\n");
184
167
  }
185
-
186
- this.onSettingLocalDesc = function () {
168
+ onSettingLocalDesc() {
187
169
  logger.log("delegationHandler: onSettingLocalDesc\n");
188
170
  }
189
-
190
- this.initGetStats = function (pc, callid, username) {
171
+ initGetStats(pc, callid, username) {
191
172
  logger.log("delegationHandler: initGetStats\n");
192
173
  }
193
-
194
- this.onRegisterWebRTCSIPEngine = function (engine) {
174
+ onRegisterWebRTCSIPEngine(engine) {
195
175
  logger.log("delegationHandler: onRegisterWebRTCSIPEngine, engine=\n", engine);
196
176
  }
197
177
  }
198
178
 
199
- export function ExSynchronousHandler() {
200
-
201
- this.onFailure = function () {
179
+ class ExSynchronousHandler {
180
+ onFailure() {
202
181
  logger.log("synchronousHandler: onFailure, phone is offline.\n");
203
182
  }
204
-
205
- this.onResponse = function () {
183
+ onResponse() {
206
184
  logger.log("synchronousHandler: onResponse, phone is connected.\n");
207
185
  }
208
186
  }
209
187
 
210
- export class ExotelWebClient {
188
+ export { ExDelegationHandler, ExSynchronousHandler };
211
189
 
190
+ export class ExotelWebClient {
191
+ /**
192
+ * @param {Object} sipAccntInfo
193
+ */
212
194
 
213
195
 
214
196
  ctrlr = null;
@@ -220,49 +202,119 @@ export class ExotelWebClient {
220
202
  unregisterInitiated = false;
221
203
  registrationInProgress = false;
222
204
  isReadyToRegister = true;
223
- /* OLD-Way to be revisited for multile phone support */
224
- //this.webRTCPhones = {};
205
+
225
206
 
226
207
  sipAccountInfo = null;
208
+ clientSDKLoggerCallback = null;
209
+ callbacks = null;
210
+ registerCallback = null;
211
+ sessionCallback = null;
212
+ logger = getLogger();
213
+
214
+ constructor() {
215
+ // Initialize properties
216
+ this.ctrlr = null;
217
+ this.call = null;
218
+ this.eventListener = null;
219
+ this.callListener = null;
220
+ this.callFromNumber = null;
221
+ this.shouldAutoRetry = false;
222
+ this.unregisterInitiated = false;
223
+ this.registrationInProgress = false;
224
+ this.currentSIPUserName = "";
225
+ this.isReadyToRegister = true;
226
+ this.sipAccountInfo = null;
227
+ this.clientSDKLoggerCallback = null;
228
+ this.callbacks = new Callback();
229
+ this.registerCallback = new RegisterCallback();
230
+ this.sessionCallback = new SessionCallback();
231
+ this.logger = getLogger();
232
+
233
+ // Register logger callback
234
+ this.logger.registerLoggerCallback((type, message, args) => {
235
+ LogManager.onLog(type, message, args);
236
+ if (this.clientSDKLoggerCallback) {
237
+ this.clientSDKLoggerCallback("log", message, args);
238
+ }
239
+ });
240
+ }
241
+
227
242
 
228
- initWebrtc = (sipAccountInfo_,
243
+ initWebrtc = async (sipAccountInfo_,
229
244
  RegisterEventCallBack, CallListenerCallback, SessionCallback) => {
245
+ const userName = sipAccountInfo_?.userName;
246
+ if (!userName) return false;
247
+
248
+ // --- Duplicate registration guard ---
249
+ if (phonePool.has(userName)) {
250
+ if (this.currentSIPUserName == "" || this.currentSIPUserName !== userName) {
251
+ logger.warn(`ExWebClient: initWebrtc: [Dup‑Reg] ${userName} already in use – init rejected`);
252
+ return false;
253
+ }
254
+ }
255
+ this.currentSIPUserName = userName;
256
+ phonePool.set(userName, null);
230
257
 
231
258
  if (!this.eventListener) {
232
- this.eventListener = new ExotelVoiceClientListener();
259
+ this.eventListener = new ExotelVoiceClientListener(this.registerCallback);
233
260
  }
234
261
 
235
262
  if (!this.callListener) {
236
- this.callListener = new CallListener();
263
+ this.callListener = new CallListener(this.callbacks);
237
264
  }
238
265
 
239
- if (!this.ctrlr) {
240
- this.ctrlr = new CallController();
266
+ if (!this.sessionListener) {
267
+ this.sessionListener = new SessionListener(this.sessionCallback);
241
268
  }
242
269
 
243
- if (!this.call) {
244
- this.call = new Call();
270
+ if (!this.ctrlr) {
271
+ this.ctrlr = new CallController();
245
272
  }
246
273
 
247
- logger.log("Exotel Client Initialised with " + JSON.stringify(sipAccountInfo_))
274
+ logger.log("ExWebClient: initWebrtc: Exotel Client Initialised with " + JSON.stringify(sipAccountInfo_))
248
275
  this.sipAccountInfo = sipAccountInfo_;
249
276
  if (!this.sipAccountInfo["userName"] || !this.sipAccountInfo["sipdomain"] || !this.sipAccountInfo["port"]) {
250
277
  return false;
251
278
  }
252
279
  this.sipAccountInfo["sipUri"] = "wss://" + this.sipAccountInfo["userName"] + "@" + this.sipAccountInfo["sipdomain"] + ":" + this.sipAccountInfo["port"];
253
-
254
- callbacks.initializeCallback(CallListenerCallback);
255
- registerCallback.initializeRegisterCallback(RegisterEventCallBack);
256
- logger.log("Initializing session callback")
257
- sessionCallback.initializeSessionCallback(SessionCallback);
280
+
281
+ // Register callbacks using the correct methods
282
+ this.callbacks.registerCallback('call', CallListenerCallback);
283
+ this.registerCallback.initializeRegisterCallback(RegisterEventCallBack);
284
+ logger.log("ExWebClient: initWebrtc: Initializing session callback")
285
+ this.sessionCallback.initializeSessionCallback(SessionCallback);
258
286
  this.setEventListener(this.eventListener);
287
+
288
+ // Wait for public IP before registering
289
+ await fetchPublicIP(this.sipAccountInfo);
290
+
291
+ // Create phone instance if it wasn't created in constructor
292
+ if (!this.phone) {
293
+ this.userName = this.sipAccountInfo.userName;
294
+ let phone = phonePool.get(this.userName);
295
+ if (!phone) {
296
+ phone = new WebrtcSIPPhone(this.userName);
297
+ phonePool.set(this.userName, phone);
298
+ }
299
+ this.phone = phone;
300
+ this.webrtcSIPPhone = this.phone;
301
+ }
302
+
303
+ // Initialize the phone with SIP engine
304
+ this.webrtcSIPPhone.registerPhone("sipjs", new ExDelegationHandler(this));
305
+
306
+ // Create call instance after phone is initialized
307
+ if (!this.call) {
308
+ this.call = new Call(this.webrtcSIPPhone);
309
+ }
310
+
259
311
  return true;
260
312
  };
261
313
 
262
314
  DoRegister = () => {
263
- logger.log("ExWebClient:DoRegister Entry")
315
+ logger.log("ExWebClient: DoRegister: Entry")
264
316
  if (!this.isReadyToRegister) {
265
- logger.warn("ExWebClient:DoRegister SDK is not ready to register");
317
+ logger.warn("ExWebClient: DoRegister: SDK is not ready to register");
266
318
  return false;
267
319
  }
268
320
  DoRegisterRL(this.sipAccountInfo, this);
@@ -270,7 +322,7 @@ export class ExotelWebClient {
270
322
  };
271
323
 
272
324
  UnRegister = () => {
273
- logger.log("ExWebClient:UnRegister Entry")
325
+ logger.log("ExWebClient: UnRegister: Entry")
274
326
  UnRegisterRL(this.sipAccountInfo, this)
275
327
  };
276
328
 
@@ -283,11 +335,11 @@ export class ExotelWebClient {
283
335
  };
284
336
 
285
337
  startSpeakerDiagnosticsTest = () => {
286
- startSpeakerDiagnosticsTestDL()
338
+ startSpeakerDiagnosticsTestDL(this.webrtcSIPPhone);
287
339
  };
288
340
 
289
341
  stopSpeakerDiagnosticsTest = (speakerTestResponse = 'none') => {
290
- stopSpeakerDiagnosticsTestDL(speakerTestResponse)
342
+ stopSpeakerDiagnosticsTestDL(speakerTestResponse, this.webrtcSIPPhone);
291
343
  };
292
344
 
293
345
  startMicDiagnosticsTest = () => {
@@ -307,13 +359,9 @@ export class ExotelWebClient {
307
359
  stopNetworkDiagnosticsDL()
308
360
  };
309
361
 
310
- SessionListener = () => {
311
- SessionListenerSL()
362
+ SessionListenerMethod = () => {
312
363
  };
313
364
 
314
- /**
315
- * function that returns the instance of the call controller object object
316
- */
317
365
 
318
366
  getCallController = () => {
319
367
  return this.ctrlr;
@@ -321,14 +369,12 @@ export class ExotelWebClient {
321
369
 
322
370
  getCall = () => {
323
371
  if (!this.call) {
324
- this.call = call = new Call();
372
+ this.call = new Call(this.webrtcSIPPhone);
325
373
  }
326
374
  return this.call;
327
375
  };
328
376
 
329
- /**
330
- * Dummy function to set the event listener object
331
- */
377
+
332
378
  setEventListener = (eventListener) => {
333
379
  this.eventListener = eventListener;
334
380
  };
@@ -342,38 +388,21 @@ export class ExotelWebClient {
342
388
  */
343
389
 
344
390
  registerEventCallback = (event, phone, param) => {
391
+ logger.log("ExWebClient: registerEventCallback: Received ---> " +
392
+ event, [phone, param]);
393
+
394
+ const lowerCaseEvent = event.toLowerCase();
345
395
 
346
- logger.log("Dialer: registerEventCallback: Received ---> " + event + 'phone....', phone + 'param....', param)
347
- if (event === "connected") {
348
- /**
349
- * When registration is successful then send the phone number of the same to UI
350
- */
351
- this.eventListener.onInitializationSuccess(phone);
396
+ if (lowerCaseEvent === "registered") {
352
397
  this.registrationInProgress = false;
353
- if (this.unregisterInitiated) {
354
- logger.log("ExWebClient:registerEventCallback unregistering due to unregisterInitiated");
355
- this.unregisterInitiated = false;
356
- this.unregister();
357
- }
358
- } else if (event === "failed_to_start" || event === "transport_error") {
359
- /**
360
- * If registration fails
361
- */
362
- this.eventListener.onInitializationFailure(phone);
363
- if (this.unregisterInitiated) {
364
- this.shouldAutoRetry = false;
365
- this.unregisterInitiated = false;
366
- this.isReadyToRegister = true;
367
- }
368
- if (this.shouldAutoRetry) {
369
- logger.log("ExWebClient:registerEventCallback Autoretrying");
370
- DoRegisterRL(this.sipAccountInfo, this, 5000);
371
- }
372
- } else if (event === "sent_request") {
373
- /**
374
- * If registration request waiting...
375
- */
376
- this.eventListener.onInitializationWaiting(phone);
398
+ this.unregisterInitiated = false;
399
+ this.isReadyToRegister = false;
400
+ this.eventListener.onRegistrationStateChanged("registered", phone);
401
+ } else if (lowerCaseEvent === "unregistered" || lowerCaseEvent === "terminated") {
402
+ this.registrationInProgress = false;
403
+ this.unregisterInitiated = false;
404
+ this.isReadyToRegister = true;
405
+ this.eventListener.onRegistrationStateChanged("unregistered", phone);
377
406
  }
378
407
  };
379
408
  /**
@@ -383,9 +412,14 @@ export class ExotelWebClient {
383
412
  * @param {*} param
384
413
  */
385
414
  callEventCallback = (event, phone, param) => {
386
- logger.log("Dialer: callEventCallback: Received ---> " + event + 'param sent....' + param + 'for phone....' + phone)
415
+ logger.log("ExWebClient: callEventCallback: Received ---> " + event + 'param sent....' + param + 'for phone....' + phone)
387
416
  if (event === "i_new_call") {
388
- this.callListener.onIncomingCall(param, phone)
417
+ if (!this.call) {
418
+ this.call = new Call(param); // param is the session
419
+ }
420
+ this.callListener.onIncomingCall(param, phone);
421
+ } else if (event === "ringing" || event === "accept_reject") {
422
+ this.callListener.onRinging(param, phone);
389
423
  } else if (event === "connected") {
390
424
  this.callListener.onCallEstablished(param, phone);
391
425
  } else if (event === "terminated") {
@@ -408,24 +442,26 @@ export class ExotelWebClient {
408
442
  * @param {*} sipAccountInfo
409
443
  */
410
444
  unregister = (sipAccountInfo) => {
411
- logger.log("ExWebClient:unregister Entry");
445
+ logger.log("ExWebClient: unregister: Entry");
412
446
  this.shouldAutoRetry = false;
413
447
  this.unregisterInitiated = true;
414
448
  if (!this.registrationInProgress) {
415
- setTimeout(function () {
416
- webrtcSIPPhone.sipUnRegisterWebRTC();
417
- }, 500);
449
+ setTimeout(() => {
450
+ const phone = phonePool[this.userName] || this.webrtcSIPPhone;
451
+ if (phone) {
452
+ phone.sipUnRegisterWebRTC();
453
+ phone.disconnect?.();
454
+ }
455
+ }, 500);
418
456
  }
419
- };
420
-
457
+ };
458
+
421
459
 
422
460
  webRTCStatusCallbackHandler = (msg1, arg1) => {
423
- logger.log("webRTCStatusCallbackHandler: " + msg1 + " " + arg1)
461
+ logger.log("ExWebClient: webRTCStatusCallbackHandler: " + msg1 + " " + arg1)
424
462
  };
425
463
 
426
- /**
427
- * initialize function called when user wants to register client
428
- */
464
+
429
465
  initialize = (uiContext, hostName, subscriberName,
430
466
  displayName, accountSid, subscriberToken,
431
467
  sipAccountInfo) => {
@@ -449,11 +485,10 @@ export class ExotelWebClient {
449
485
  'contactHost': ''
450
486
  }
451
487
 
452
- logger.log('Sending register for the number..', subscriberName);
488
+ logger.log('ExWebClient: initialize: Sending register for the number..', subscriberName);
453
489
 
454
490
  fetchPublicIP(sipAccountInfo);
455
491
 
456
- /* Temporary till we figure out the arguments - Start */
457
492
  this.domain = hostName = sipAccountInfo.domain;
458
493
  this.sipdomain = sipAccountInfo.sipdomain;
459
494
  this.accountName = this.userName = sipAccountInfo.userName;
@@ -469,9 +504,7 @@ export class ExotelWebClient {
469
504
  this.sipWsPort = 5061;
470
505
  this.sipPort = 5061;
471
506
  this.sipSecurePort = 5062;
472
- /* Temporary till we figure out the arguments - End */
473
507
 
474
- /* This is permanent -Start */
475
508
  let webrtcPort = wssPort;
476
509
 
477
510
  if (this.security === 'ws') {
@@ -492,38 +525,28 @@ export class ExotelWebClient {
492
525
  this.sipAccntInfo['port'] = webrtcPort;
493
526
  this.sipAccntInfo['contactHost'] = this.contactHost;
494
527
  localStorage.setItem('contactHost', this.contactHost);
495
- /* This is permanent -End */
496
528
 
497
- /**
498
- * Call the webclient function inside this and pass register and call callbacks as arg
499
- */
500
- var synchronousHandler = new ExSynchronousHandler(this);
529
+
530
+ var synchronousHandler = new ExSynchronousHandler();
501
531
  var delegationHandler = new ExDelegationHandler(this);
502
532
 
503
533
  var userName = this.userName;
504
- /* OLD-Way to be revisited for multile phone support */
505
- //webRTCPhones[userName] = webRTC;
506
534
 
507
- /* New-Way */
508
- webrtcSIPPhone.registerPhone("sipjs", delegationHandler);
509
- webrtcSIPPhone.registerWebRTCClient(this.sipAccntInfo, synchronousHandler);
510
535
 
511
- /**
512
- * Store the intervalID against a map
513
- */
536
+ this.webrtcSIPPhone.registerPhone("sipjs", delegationHandler);
537
+ this.webrtcSIPPhone.registerWebRTCClient(this.sipAccntInfo, synchronousHandler);
538
+ phonePool[this.userName] = this.webrtcSIPPhone;
539
+
540
+
514
541
  intervalIDMap.set(userName, intervalId);
515
542
  };
516
543
 
517
544
  checkClientStatus = (callback) => {
518
- // using this function , first it will check mic permission is given or not
519
- // then it will check if transport is intialize or not
520
- // then it will check if user is registered or not
521
- // based on this we can evaludate SDK is ready for call
522
545
  var constraints = { audio: true, video: false };
523
546
  navigator.mediaDevices
524
547
  .getUserMedia(constraints)
525
548
  .then(function (mediaStream) {
526
- var transportState = webrtcSIPPhone.getTransportState();
549
+ var transportState = this.webrtcSIPPhone.getTransportState();
527
550
  transportState = transportState.toLowerCase();
528
551
  switch (transportState) {
529
552
  case "":
@@ -535,7 +558,7 @@ export class ExotelWebClient {
535
558
  break;
536
559
 
537
560
  default:
538
- var registerationState = webrtcSIPPhone.getRegistrationState();
561
+ var registerationState = this.webrtcSIPPhone.getRegistrationState();
539
562
  registerationState = registerationState.toLowerCase();
540
563
  switch (registerationState) {
541
564
  case "":
@@ -557,32 +580,46 @@ export class ExotelWebClient {
557
580
  }
558
581
  })
559
582
  .catch(function (error) {
560
- logger.log("something went wrong during checkClientStatus ", error);
583
+ logger.log("ExWebClient: checkClientStatus: something went wrong during checkClientStatus ", error);
561
584
  callback("media_permission_denied");
562
585
  });
563
586
  };
564
587
 
565
588
  changeAudioInputDevice(deviceId, onSuccess, onError) {
566
- logger.log(`in changeAudioInputDevice() of ExWebClient.js`);
567
- webrtcSIPPhone.changeAudioInputDevice(deviceId, onSuccess, onError);
589
+ logger.log(`ExWebClient: changeAudioInputDevice: Entry`);
590
+ this.webrtcSIPPhone.changeAudioInputDevice(deviceId, onSuccess, onError);
568
591
  }
569
592
 
570
593
  changeAudioOutputDevice(deviceId, onSuccess, onError) {
571
- logger.log(`in changeAudioOutputDevice() of ExWebClient.js`);
572
- webrtcSIPPhone.changeAudioOutputDevice(deviceId, onSuccess, onError);
594
+ logger.log(`ExWebClient: changeAudioOutputDevice: Entry`);
595
+ this.webrtcSIPPhone.changeAudioOutputDevice(deviceId, onSuccess, onError);
596
+ }
597
+
598
+ downloadLogs() {
599
+ logger.log(`ExWebClient: downloadLogs: Entry`);
600
+ LogManager.downloadLogs();
573
601
  }
574
602
 
575
603
  setPreferredCodec(codecName) {
576
- logger.log("ExWebClient:setPreferredCodec entry");
577
- webrtcSIPPhone.setPreferredCodec(codecName);
604
+ logger.log("ExWebClient: setPreferredCodec: Entry");
605
+ if (!this.webrtcSIPPhone || !this.webrtcSIPPhone.phone) {
606
+ logger.warn("ExWebClient: setPreferredCodec: Phone not initialized");
607
+ return;
608
+ }
609
+ this.webrtcSIPPhone.setPreferredCodec(codecName);
578
610
  }
579
611
 
580
612
  registerLoggerCallback(callback) {
581
- logger.registerLoggerCallback(callback);
613
+ this.clientSDKLoggerCallback = callback;
582
614
  }
583
615
 
584
616
  registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback, onDeviceChangeCallback) {
585
- webrtcSIPPhone.registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback, onDeviceChangeCallback);
617
+ logger.log("ExWebClient: registerAudioDeviceChangeCallback: Entry");
618
+ if (!this.webrtcSIPPhone) {
619
+ logger.warn("ExWebClient: registerAudioDeviceChangeCallback: webrtcSIPPhone not initialized");
620
+ return;
621
+ }
622
+ this.webrtcSIPPhone.registerAudioDeviceChangeCallback(audioInputDeviceChangeCallback, audioOutputDeviceChangeCallback, onDeviceChangeCallback);
586
623
  }
587
624
  }
588
625