@exotel-npm-dev/webrtc-client-sdk 1.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.
- package/package.json +25 -0
- package/src/api/callAPI/Call.js +83 -0
- package/src/api/callAPI/CallDetails.js +74 -0
- package/src/api/omAPI/Diagnostics.js +644 -0
- package/src/api/omAPI/DiagnosticsFSM.js +142 -0
- package/src/api/omAPI/DiagnosticsFSM.ts +378 -0
- package/src/api/omAPI/DiagnosticsListener.js +95 -0
- package/src/api/omAPI/FSM.js +126 -0
- package/src/api/omAPI/WebrtcLogger.js +55 -0
- package/src/api/omAPI/js-finite-state-machine.js +126 -0
- package/src/api/omAPI/log/index.js +8 -0
- package/src/api/omAPI/log/index.ts +3 -0
- package/src/api/omAPI/log/levels.js +13 -0
- package/src/api/omAPI/log/levels.ts +10 -0
- package/src/api/omAPI/log/logger-factory.js +115 -0
- package/src/api/omAPI/log/logger-factory.ts +119 -0
- package/src/api/omAPI/log/logger.js +41 -0
- package/src/api/omAPI/log/logger.ts +42 -0
- package/src/api/registerAPI/RegisterListener.js +43 -0
- package/src/constants/ErrorConstants.js +6 -0
- package/src/constants/common.js +12 -0
- package/src/listeners/CallCtrlerDummy.js +8 -0
- package/src/listeners/CallListener.js +38 -0
- package/src/listeners/Callback.js +176 -0
- package/src/listeners/ExWebClient.js +468 -0
- package/src/listeners/ExotelVoiceClientListener.js +45 -0
- package/src/listeners/SessionListeners.js +123 -0
- package/src/phone.json +75 -0
- package/src/phoneDetailsAPI.js +43 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import { Call } from "../api/callAPI/Call";
|
|
2
|
+
import { CallController } from "./CallCtrlerDummy";
|
|
3
|
+
import { CallListener } from '../listeners/CallListener';
|
|
4
|
+
import { DoRegister as DoRegisterRL } from '../api/registerAPI/RegisterListener';
|
|
5
|
+
import { UnRegister as UnRegisterRL } from '../api/registerAPI/RegisterListener';
|
|
6
|
+
import { ExotelVoiceClientListener } from '../listeners/ExotelVoiceClientListener';
|
|
7
|
+
import { SessionListener as SessionListenerSL } from '../listeners/SessionListeners';
|
|
8
|
+
|
|
9
|
+
import { initDiagnostics as initDiagnosticsDL} from '../api/omAPI/DiagnosticsListener';
|
|
10
|
+
import { startNetworkDiagnostics as startNetworkDiagnosticsDL} from '../api/omAPI/DiagnosticsListener';
|
|
11
|
+
import { stopNetworkDiagnostics as stopNetworkDiagnosticsDL} from '../api/omAPI/DiagnosticsListener';
|
|
12
|
+
import { startSpeakerDiagnosticsTest as startSpeakerDiagnosticsTestDL} from '../api/omAPI/DiagnosticsListener';
|
|
13
|
+
import { stopSpeakerDiagnosticsTest as stopSpeakerDiagnosticsTestDL} from '../api/omAPI/DiagnosticsListener';
|
|
14
|
+
import { startMicDiagnosticsTest as startMicDiagnosticsTestDL} from '../api/omAPI/DiagnosticsListener';
|
|
15
|
+
import { stopMicDiagnosticsTest as stopMicDiagnosticsTestDL } from '../api/omAPI/DiagnosticsListener';
|
|
16
|
+
import { closeDiagnostics as closeDiagnosticsDL} from '../api/omAPI/DiagnosticsListener';
|
|
17
|
+
|
|
18
|
+
import { callbacks } from '../listeners/Callback';
|
|
19
|
+
import { registerCallback } from '../listeners/Callback';
|
|
20
|
+
import { sessionCallback } from '../listeners/Callback';
|
|
21
|
+
import { webrtcTroubleshooterEventBus } from "./Callback";
|
|
22
|
+
|
|
23
|
+
import { webrtcLogger } from "../api/omAPI/WebrtcLogger";
|
|
24
|
+
var webrtcSIPPhone = require('@exotel-npm-dev/webrtc-core-sdk/src/webrtcSIPPhone').webrtcSIPPhone;
|
|
25
|
+
|
|
26
|
+
var intervalId;
|
|
27
|
+
var intervalIDMap = new Map();
|
|
28
|
+
|
|
29
|
+
var logger = webrtcLogger();
|
|
30
|
+
|
|
31
|
+
function sleep(ms) {
|
|
32
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* FQDN for fetching IP
|
|
37
|
+
*/
|
|
38
|
+
function fetchPublicIP(sipAccountInfo) {
|
|
39
|
+
var publicIp = "";
|
|
40
|
+
const pc = new RTCPeerConnection({ iceServers: [ {urls: 'stun:stun.l.google.com:19302'} ] });
|
|
41
|
+
pc.createDataChannel('');
|
|
42
|
+
pc.createOffer().then(offer => pc.setLocalDescription(offer))
|
|
43
|
+
pc.onicecandidate = (ice) => {
|
|
44
|
+
if (!ice || !ice.candidate || !ice.candidate.candidate) {
|
|
45
|
+
logger.log("all done.");
|
|
46
|
+
pc.close();
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
logger.log("iceCandidate =" + ice.candidate.candidate);
|
|
50
|
+
let split = ice.candidate.candidate.split(" ");
|
|
51
|
+
if (split[7] === "host") {
|
|
52
|
+
logger.log(`fetchPublicIP:Local IP : ${split[4]}`);
|
|
53
|
+
} else {
|
|
54
|
+
logger.log(`fetchPublicIP:External IP : ${split[4]}`);
|
|
55
|
+
publicIp = `${split[4]}`
|
|
56
|
+
logger.log("fetchPublicIP:Public IP :" + publicIp);
|
|
57
|
+
localStorage.setItem("contactHost", publicIp);
|
|
58
|
+
pc.close();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
sleep(500).then(function () {
|
|
62
|
+
logger.log("fetchPublicIP: public ip = ", publicIp)
|
|
63
|
+
if (publicIp == "") {
|
|
64
|
+
sipAccountInfo.contactHost = window.localStorage.getItem('contactHost');
|
|
65
|
+
} else {
|
|
66
|
+
sipAccountInfo.contactHost = publicIp;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
export function ExDelegationHandler(exClient_) {
|
|
74
|
+
var exClient = exClient_;
|
|
75
|
+
this.setTestingMode = function(mode) {
|
|
76
|
+
logger.log("delegationHandler: setTestingMode\n");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.onCallStatSipJsSessionEvent = function(ev) {
|
|
80
|
+
logger.log("delegationHandler: onCallStatSipJsSessionEvent\n");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.sendWebRTCEventsToFSM = function(eventType, sipMethod) {
|
|
84
|
+
logger.log("delegationHandler: sendWebRTCEventsToFSM\n");
|
|
85
|
+
logger.log("delegationHandler: eventType\n", eventType);
|
|
86
|
+
logger.log("delegationHandler: sipMethod\n", sipMethod);
|
|
87
|
+
if (sipMethod == "CONNECTION") {
|
|
88
|
+
exClient.registerEventCallback(eventType, exClient.userName)
|
|
89
|
+
} else if (sipMethod == "CALL") {
|
|
90
|
+
exClient.callEventCallback(eventType, exClient.userName,exClient.call)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.playBeepTone = function() {
|
|
95
|
+
logger.log("delegationHandler: playBeepTone\n");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.onStatPeerConnectionIceGatheringStateChange = function(iceGatheringState) {
|
|
99
|
+
logger.log("delegationHandler: onStatPeerConnectionIceGatheringStateChange\n");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.onCallStatIceCandidate = function(ev,icestate) {
|
|
103
|
+
logger.log("delegationHandler: onCallStatIceCandidate\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.onCallStatNegoNeeded = function(icestate) {
|
|
107
|
+
logger.log("delegationHandler: onCallStatNegoNeeded\n");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.onCallStatSignalingStateChange = function(cstate) {
|
|
111
|
+
logger.log("delegationHandler: onCallStatSignalingStateChange\n");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.onStatPeerConnectionIceConnectionStateChange = function() {
|
|
115
|
+
logger.log("delegationHandler: onStatPeerConnectionIceConnectionStateChange\n");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.onStatPeerConnectionConnectionStateChange = function() {
|
|
119
|
+
logger.log("delegationHandler: onStatPeerConnectionConnectionStateChange\n");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.onGetUserMediaSuccessCallstatCallback = function() {
|
|
123
|
+
logger.log("delegationHandler: onGetUserMediaSuccessCallstatCallback\n");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.onGetUserMediaErrorCallstatCallback = function() {
|
|
127
|
+
logger.log("delegationHandler: onGetUserMediaErrorCallstatCallback\n");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.onCallStatAddStream = function() {
|
|
131
|
+
logger.log("delegationHandler: onCallStatAddStream\n");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
this.onCallStatRemoveStream = function() {
|
|
135
|
+
logger.log("delegationHandler: onCallStatRemoveStream\n");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this.setWebRTCFSMMapper = function(stack) {
|
|
139
|
+
logger.log("delegationHandler: setWebRTCFSMMapper : Initialisation complete \n");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
this.onCallStatSipJsTransportEvent = function() {
|
|
143
|
+
logger.log("delegationHandler: onCallStatSipJsTransportEvent\n");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this.onCallStatSipSendCallback = function() {
|
|
147
|
+
logger.log("delegationHandler: onCallStatSipSendCallback\n");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this.onCallStatSipRecvCallback = function() {
|
|
151
|
+
logger.log("delegationHandler: onCallStatSipRecvCallback\n");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
this.stopCallStat = function() {
|
|
155
|
+
logger.log("delegationHandler: stopCallStat\n");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.onRecieveInvite = function() {
|
|
159
|
+
logger.log("delegationHandler: onRecieveInvite\n");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.onPickCall = function() {
|
|
163
|
+
logger.log("delegationHandler: onPickCall\n");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
this.onRejectCall = function() {
|
|
167
|
+
logger.log("delegationHandler: onRejectCall\n");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
this.onCreaterAnswer = function() {
|
|
171
|
+
logger.log("delegationHandler: onCreaterAnswer\n");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.onSettingLocalDesc = function() {
|
|
175
|
+
logger.log("delegationHandler: onSettingLocalDesc\n");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
this.initGetStats = function(pc, callid, username) {
|
|
179
|
+
logger.log("delegationHandler: initGetStats\n");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
this.onRegisterWebRTCSIPEngine = function(engine) {
|
|
183
|
+
logger.log("delegationHandler: onRegisterWebRTCSIPEngine, engine=\n", engine);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function ExSynchronousHandler() {
|
|
188
|
+
|
|
189
|
+
this.onFailure = function() {
|
|
190
|
+
logger.log("synchronousHandler: onFailure, phone is offline.\n");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.onResponse = function() {
|
|
194
|
+
logger.log("synchronousHandler: onResponse, phone is connected.\n");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export const ExotelWebClient = {
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
ctrlr : null,
|
|
203
|
+
call : null,
|
|
204
|
+
eventListener : null,
|
|
205
|
+
callListener : null,
|
|
206
|
+
/* OLD-Way to be revisited for multile phone support */
|
|
207
|
+
//this.webRTCPhones = {};
|
|
208
|
+
|
|
209
|
+
sipAccountInfo : null,
|
|
210
|
+
|
|
211
|
+
initWebrtc : (sipAccountInfo_,
|
|
212
|
+
RegisterEventCallBack, CallListenerCallback, SessionCallback) => {
|
|
213
|
+
|
|
214
|
+
if (!ExotelWebClient.eventListener) {
|
|
215
|
+
ExotelWebClient.eventListener = new ExotelVoiceClientListener();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!ExotelWebClient.callListener) {
|
|
219
|
+
ExotelWebClient.callListener = new CallListener();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!ExotelWebClient.ctrlr) {
|
|
223
|
+
ExotelWebClient.ctrlr = new CallController();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (!ExotelWebClient.call) {
|
|
227
|
+
ExotelWebClient.call = new Call();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
logger.log("Exotel Client Initialised with " + JSON.stringify(sipAccountInfo_))
|
|
231
|
+
ExotelWebClient.sipAccountInfo = sipAccountInfo_;
|
|
232
|
+
if ( !ExotelWebClient.sipAccountInfo["userName"] || !ExotelWebClient.sipAccountInfo["sipdomain"] || !ExotelWebClient.sipAccountInfo["port"]) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
ExotelWebClient.sipAccountInfo["sipUri"] = "wss://" + ExotelWebClient.sipAccountInfo["userName"] + "@" + ExotelWebClient.sipAccountInfo["sipdomain"] + ":" + ExotelWebClient.sipAccountInfo["port"];
|
|
236
|
+
|
|
237
|
+
callbacks.initializeCallback(CallListenerCallback);
|
|
238
|
+
registerCallback.initializeRegisterCallback(RegisterEventCallBack);
|
|
239
|
+
logger.log("Initializing session callback")
|
|
240
|
+
sessionCallback.initializeSessionCallback(SessionCallback);
|
|
241
|
+
ExotelWebClient.setEventListener(ExotelWebClient.eventListener);
|
|
242
|
+
return true;
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
DoRegister : () => {
|
|
246
|
+
DoRegisterRL(ExotelWebClient.sipAccountInfo, ExotelWebClient)
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
UnRegister : () => {
|
|
250
|
+
UnRegisterRL(ExotelWebClient.sipAccountInfo, ExotelWebClient)
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
initDiagnostics : (saveDiagnosticsCallback, keyValueSetCallback) => {
|
|
254
|
+
initDiagnosticsDL(saveDiagnosticsCallback, keyValueSetCallback)
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
closeDiagnostics : () => {
|
|
258
|
+
closeDiagnosticsDL()
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
startSpeakerDiagnosticsTest : () => {
|
|
262
|
+
startSpeakerDiagnosticsTestDL()
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
stopSpeakerDiagnosticsTest : (speakerTestResponse='none') => {
|
|
266
|
+
stopSpeakerDiagnosticsTestDL(speakerTestResponse)
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
startMicDiagnosticsTest : () => {
|
|
270
|
+
startMicDiagnosticsTestDL()
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
stopMicDiagnosticsTest : (micTestResponse='none') => {
|
|
274
|
+
stopMicDiagnosticsTestDL(micTestResponse)
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
startNetworkDiagnostics : () => {
|
|
278
|
+
startNetworkDiagnosticsDL()
|
|
279
|
+
ExotelWebClient.DoRegister()
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
stopNetworkDiagnostics : () => {
|
|
283
|
+
stopNetworkDiagnosticsDL()
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
SessionListener : () => {
|
|
287
|
+
SessionListenerSL()
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* function that returns the instance of the call controller object object
|
|
292
|
+
*/
|
|
293
|
+
|
|
294
|
+
getCallController :() => {
|
|
295
|
+
return ExotelWebClient.ctrlr;
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
getCall :() => {
|
|
299
|
+
if (!ExotelWebClient.call) {
|
|
300
|
+
ExotelWebClient.call = call = new Call();
|
|
301
|
+
}
|
|
302
|
+
return ExotelWebClient.call;
|
|
303
|
+
},
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Dummy function to set the event listener object
|
|
307
|
+
*/
|
|
308
|
+
setEventListener :(eventListener) => {
|
|
309
|
+
ExotelWebClient.eventListener = eventListener;
|
|
310
|
+
},
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Event listener for registration, any change in registration state will trigger the callback here
|
|
315
|
+
* @param {*} event
|
|
316
|
+
* @param {*} phone
|
|
317
|
+
* @param {*} param
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
registerEventCallback :(event, phone, param) => {
|
|
321
|
+
|
|
322
|
+
logger.log("Dialer: registerEventCallback: Received ---> " + event + 'phone....', phone + 'param....', param)
|
|
323
|
+
if (event === "connected") {
|
|
324
|
+
/**
|
|
325
|
+
* When registration is successful then send the phone number of the same to UI
|
|
326
|
+
*/
|
|
327
|
+
ExotelWebClient.eventListener.onInitializationSuccess(phone);
|
|
328
|
+
} else if( event === "failed_to_start" || event === "transport_error"){
|
|
329
|
+
/**
|
|
330
|
+
* If registration fails
|
|
331
|
+
*/
|
|
332
|
+
ExotelWebClient.eventListener.onInitializationFailure(phone);
|
|
333
|
+
} else if( event === "sent_request"){
|
|
334
|
+
/**
|
|
335
|
+
* If registration request waiting...
|
|
336
|
+
*/
|
|
337
|
+
ExotelWebClient.eventListener.onInitializationWaiting(phone);
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
/**
|
|
341
|
+
* Event listener for calls, any change in sipjsphone will trigger the callback here
|
|
342
|
+
* @param {*} event
|
|
343
|
+
* @param {*} phone
|
|
344
|
+
* @param {*} param
|
|
345
|
+
*/
|
|
346
|
+
callEventCallback :(event, phone, param) => {
|
|
347
|
+
logger.log("Dialer: callEventCallback: Received ---> " + event + 'param sent....' + param + 'for phone....' + phone)
|
|
348
|
+
if (event === "i_new_call") {
|
|
349
|
+
callListener.onIncomingCall(param,phone)
|
|
350
|
+
} else if (event === "connected") {
|
|
351
|
+
callListener.onCallEstablished(param,phone);
|
|
352
|
+
} else if (event === "terminated") {
|
|
353
|
+
callListener.onCallEnded(param,phone);
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Event listener for diagnostic tests, any change in diagnostic tests will trigger this callback
|
|
359
|
+
* @param {*} event
|
|
360
|
+
* @param {*} phone
|
|
361
|
+
* @param {*} param
|
|
362
|
+
*/
|
|
363
|
+
diagnosticEventCallback :(event, phone, param) => {
|
|
364
|
+
webrtcTroubleshooterEventBus.sendDiagnosticEvent(event, phone, param)
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Function to unregister a phone
|
|
369
|
+
* @param {*} sipAccountInfo
|
|
370
|
+
*/
|
|
371
|
+
unregister :(sipAccountInfo) => {
|
|
372
|
+
// webrtcSIPPhone.unregister(sipAccountInfo)
|
|
373
|
+
webrtcSIPPhone.sipUnRegisterWebRTC();
|
|
374
|
+
},
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
webRTCStatusCallbackHandler :(msg1, arg1) => {
|
|
378
|
+
logger.log("webRTCStatusCallbackHandler: " + msg1 + " " + arg1)
|
|
379
|
+
},
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* initialize function called when user wants to register client
|
|
383
|
+
*/
|
|
384
|
+
initialize :(uiContext, hostName,subscriberName,
|
|
385
|
+
displayName,accountSid,subscriberToken,
|
|
386
|
+
sipAccountInfo) => {
|
|
387
|
+
|
|
388
|
+
let wssPort = sipAccountInfo.port;
|
|
389
|
+
let wsPort = 4442;
|
|
390
|
+
ExotelWebClient.sipAccntInfo = {
|
|
391
|
+
'userName':'',
|
|
392
|
+
'authUser':'',
|
|
393
|
+
'domain':'',
|
|
394
|
+
'sipdomain':'',
|
|
395
|
+
'displayname':'',
|
|
396
|
+
'accountSid':'',
|
|
397
|
+
'secret':'',
|
|
398
|
+
'sipUri':'',
|
|
399
|
+
'security':'',
|
|
400
|
+
'port':'',
|
|
401
|
+
'contactHost':''
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
logger.log('Sending register for the number..', subscriberName);
|
|
405
|
+
|
|
406
|
+
fetchPublicIP(sipAccountInfo);
|
|
407
|
+
|
|
408
|
+
/* Temporary till we figure out the arguments - Start */
|
|
409
|
+
ExotelWebClient.domain = hostName = sipAccountInfo.domain;
|
|
410
|
+
ExotelWebClient.sipdomain = sipAccountInfo.sipdomain;
|
|
411
|
+
ExotelWebClient.accountName = ExotelWebClient.userName = sipAccountInfo.userName;
|
|
412
|
+
ExotelWebClient.authUser = subscriberName = sipAccountInfo.authUser;
|
|
413
|
+
ExotelWebClient.displayName = sipAccountInfo.displayName;
|
|
414
|
+
ExotelWebClient.accountSid = 'exotelt1';
|
|
415
|
+
ExotelWebClient.subscriberToken = sipAccountInfo.secret;
|
|
416
|
+
ExotelWebClient.secret = ExotelWebClient.password = sipAccountInfo.secret;
|
|
417
|
+
ExotelWebClient.security = sipAccountInfo.security;
|
|
418
|
+
ExotelWebClient.port = sipAccountInfo.port;
|
|
419
|
+
ExotelWebClient.contactHost = sipAccountInfo.contactHost;
|
|
420
|
+
ExotelWebClient.sipWsPort = 5061;
|
|
421
|
+
ExotelWebClient.sipPort = 5061;
|
|
422
|
+
ExotelWebClient.sipSecurePort = 5062;
|
|
423
|
+
/* Temporary till we figure out the arguments - End */
|
|
424
|
+
|
|
425
|
+
/* This is permanent -Start */
|
|
426
|
+
let webrtcPort = wssPort;
|
|
427
|
+
|
|
428
|
+
if (ExotelWebClient.security === 'ws') {
|
|
429
|
+
webrtcPort = wsPort;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
ExotelWebClient.sipAccntInfo['userName'] = userName;
|
|
435
|
+
ExotelWebClient.sipAccntInfo['authUser'] = subscriberName;
|
|
436
|
+
ExotelWebClient.sipAccntInfo['domain'] = hostName;
|
|
437
|
+
ExotelWebClient.sipAccntInfo['sipdomain'] = ExotelWebClient.sipdomain;
|
|
438
|
+
ExotelWebClient.sipAccntInfo['accountName'] = userName;
|
|
439
|
+
ExotelWebClient.sipAccntInfo['secret'] = ExotelWebClient.password;
|
|
440
|
+
ExotelWebClient.sipAccntInfo['sipuri'] = ExotelWebClient.sipuri;
|
|
441
|
+
ExotelWebClient.sipAccntInfo['security'] = ExotelWebClient.security;
|
|
442
|
+
ExotelWebClient.sipAccntInfo['port'] = ExotelWebClient.webrtcPort;
|
|
443
|
+
ExotelWebClient.sipAccntInfo['contactHost'] = ExotelWebClient.contactHost;
|
|
444
|
+
localStorage.setItem('contactHost', ExotelWebClient.contactHost);
|
|
445
|
+
/* This is permanent -End */
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Call the webclient function inside this and pass register and call callbacks as arg
|
|
449
|
+
*/
|
|
450
|
+
var synchronousHandler = new ExSynchronousHandler(ExotelWebClient);
|
|
451
|
+
var delegationHandler = new ExDelegationHandler(ExotelWebClient);
|
|
452
|
+
|
|
453
|
+
var userName = userName;
|
|
454
|
+
/* OLD-Way to be revisited for multile phone support */
|
|
455
|
+
//webRTCPhones[userName] = webRTC;
|
|
456
|
+
|
|
457
|
+
/* New-Way */
|
|
458
|
+
webrtcSIPPhone.registerPhone("sipjs",delegationHandler);
|
|
459
|
+
webrtcSIPPhone.registerWebRTCClient(ExotelWebClient.sipAccntInfo, synchronousHandler);
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Store the intervalID against a map
|
|
463
|
+
*/
|
|
464
|
+
intervalIDMap.set(userName, intervalId);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export default ExotelWebClient;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { registerCallback } from "./Callback";
|
|
2
|
+
import { diagnosticsCallback } from "./Callback";
|
|
3
|
+
|
|
4
|
+
export class ExotelVoiceClientListener{
|
|
5
|
+
onInitializationSuccess(phone) {
|
|
6
|
+
/**
|
|
7
|
+
* Abstract class for Initialization Success
|
|
8
|
+
*/
|
|
9
|
+
registerCallback.initializeRegister("registered", phone);
|
|
10
|
+
/**
|
|
11
|
+
* Triggers UI callback to indicate the status of the registered phone
|
|
12
|
+
*/
|
|
13
|
+
registerCallback.triggerRegisterCallback();
|
|
14
|
+
diagnosticsCallback.triggerKeyValueSetCallback("userReg", "registered", phone);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
onInitializationFailure(phone){
|
|
18
|
+
/**
|
|
19
|
+
* If register fails send error message to Callback function
|
|
20
|
+
*/
|
|
21
|
+
registerCallback.initializeRegister("unregistered", phone);
|
|
22
|
+
registerCallback.triggerRegisterCallback();
|
|
23
|
+
diagnosticsCallback.triggerKeyValueSetCallback("userReg", "unregistered", phone);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
onInitializationWaiting(phone){
|
|
27
|
+
/**
|
|
28
|
+
* If register fails send error message to Callback function
|
|
29
|
+
*/
|
|
30
|
+
registerCallback.initializeRegister("sent_request", phone);
|
|
31
|
+
registerCallback.triggerRegisterCallback();
|
|
32
|
+
diagnosticsCallback.triggerKeyValueSetCallback("userReg", "sent_request", phone);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
onLog(LogLevel, tag, message){
|
|
36
|
+
/**
|
|
37
|
+
* To get SDK logs
|
|
38
|
+
*/
|
|
39
|
+
}
|
|
40
|
+
onAuthenticationFailure(){
|
|
41
|
+
/**
|
|
42
|
+
* In case if there is any authentication error in registration, handle here
|
|
43
|
+
*/
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { sessionCallback } from './Callback';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { FetchTabInfo } from '../constants/common';
|
|
4
|
+
import { webrtcLogger } from "../api/omAPI/WebrtcLogger"
|
|
5
|
+
|
|
6
|
+
var logger = webrtcLogger()
|
|
7
|
+
/**
|
|
8
|
+
* Session listeners is invoked when user opens two tabs, the data in tab 1 is
|
|
9
|
+
* copied into tab 2
|
|
10
|
+
*/
|
|
11
|
+
export function SessionListener () {
|
|
12
|
+
|
|
13
|
+
const channel = new BroadcastChannel('app-data');
|
|
14
|
+
channel.addEventListener ('message', (event) => {
|
|
15
|
+
if(event.data.message == "re-register-needed"){
|
|
16
|
+
/** Send the hash to app seeking for reregistration */
|
|
17
|
+
sessionCallback.initializeSession('re-register', event.data.hashMsg);
|
|
18
|
+
sessionCallback.triggerSessionCallback();
|
|
19
|
+
}else if(event.data.message == 'logout'){
|
|
20
|
+
sessionCallback.initializeSession('logout', '');
|
|
21
|
+
sessionCallback.triggerSessionCallback();
|
|
22
|
+
}else if(event.data.message == 'login-successful'){
|
|
23
|
+
const loginObj = {
|
|
24
|
+
phone: window.localStorage.getItem('currentUser'),
|
|
25
|
+
tabHash: event.data.tabHash
|
|
26
|
+
}
|
|
27
|
+
sessionCallback.initializeSession('login-successful', JSON.stringify(loginObj));
|
|
28
|
+
sessionCallback.triggerSessionCallback();
|
|
29
|
+
}else if(window.sessionStorage.getItem("activeSessionTab") !== null){
|
|
30
|
+
if(event.data.callState !== null && event.data.callState !== undefined){
|
|
31
|
+
sessionCallback.initializeSession(event.data.callState, event.data.callNumber);
|
|
32
|
+
}
|
|
33
|
+
sessionCallback.triggerSessionCallback();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Add listeners for all storage events
|
|
38
|
+
*/
|
|
39
|
+
window.localStorage.setItem('REQUESTING_SHARED_CREDENTIALS', Date.now().toString())
|
|
40
|
+
window.localStorage.removeItem('REQUESTING_SHARED_CREDENTIALS')
|
|
41
|
+
|
|
42
|
+
const credentials = {
|
|
43
|
+
user: window.sessionStorage.getItem('user'),
|
|
44
|
+
selectedPhone: window.localStorage.getItem('selectedPhone'),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
window.addEventListener('storage', (event) => {
|
|
48
|
+
/**
|
|
49
|
+
* When user tries to duplicate tab, this gets called in Tab1
|
|
50
|
+
*/
|
|
51
|
+
if(event.key === 'REQUESTING_SHARED_CREDENTIALS' && credentials) {
|
|
52
|
+
window.localStorage.setItem('CREDENTIALS_SHARING', JSON.stringify(credentials))
|
|
53
|
+
window.localStorage.removeItem('CREDENTIALS_SHARING')
|
|
54
|
+
/**
|
|
55
|
+
* When the data is to be shared between two tabs then add the current state onto that session storage
|
|
56
|
+
*/
|
|
57
|
+
//sessionCallback.triggerSessionCallback();
|
|
58
|
+
}
|
|
59
|
+
if(event.key === 'CREDENTIALS_SHARING' && credentials !== null){
|
|
60
|
+
|
|
61
|
+
const newData = JSON.parse(event.newValue);
|
|
62
|
+
if(event.newValue !== null){
|
|
63
|
+
window.sessionStorage.setItem('user', newData.user);
|
|
64
|
+
window.sessionStorage.setItem('isAuthenticated', true);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Fetch the array of tabs and add the tab, put it on session also
|
|
68
|
+
*/
|
|
69
|
+
const currentTab = {
|
|
70
|
+
tabID: uuidv4(),
|
|
71
|
+
tabType: 'child',
|
|
72
|
+
tabStatus: 'active'
|
|
73
|
+
}
|
|
74
|
+
const tabArr = JSON.parse(window.localStorage.getItem('tabs'));
|
|
75
|
+
/** Based on activeSessionTab id fetch the type */
|
|
76
|
+
|
|
77
|
+
if(window.sessionStorage.getItem('activeSessionTab') !== null && window.sessionStorage.getItem('activeSessionTab') == "parent0"){
|
|
78
|
+
logger.log('Adding a child tab spawned from parent....');
|
|
79
|
+
/** In order to keep tabID same for all the child ones, we are using below IF to distinguish */
|
|
80
|
+
|
|
81
|
+
if(tabArr.length > 1 && window.sessionStorage.getItem('activeSessionTab') == "parent0") {
|
|
82
|
+
if(!document.hidden){
|
|
83
|
+
const lastIndex = (tabArr.length) - 1;
|
|
84
|
+
window.sessionStorage.setItem('activeSessionTab', tabArr[lastIndex].tabID);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}else {
|
|
88
|
+
tabArr.push(currentTab);
|
|
89
|
+
window.localStorage.removeItem('tabs');
|
|
90
|
+
window.localStorage.setItem('tabs', JSON.stringify(tabArr));
|
|
91
|
+
const lastIndex = (tabArr.length) - 1;
|
|
92
|
+
window.sessionStorage.setItem('activeSessionTab', tabArr[lastIndex].tabID);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
} else {
|
|
97
|
+
/** pull from the tabarray and then add it to the session storage */
|
|
98
|
+
|
|
99
|
+
const lastIndex = (tabArr.length) - 1;
|
|
100
|
+
window.sessionStorage.setItem('activeSessionTab', tabArr[lastIndex].tabID);
|
|
101
|
+
}
|
|
102
|
+
//window.localStorage.setItem('selectedPhone', newData.selectedPhone);
|
|
103
|
+
return;
|
|
104
|
+
//}
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* When a tab is closed
|
|
109
|
+
*/
|
|
110
|
+
if(event.key === 'CREDENTIALS_FLUSH' && credentials){
|
|
111
|
+
window.sessionStorage.removeItem('user');
|
|
112
|
+
window.sessionStorage.removeItem('selectedPhone');
|
|
113
|
+
window.sessionStorage.removeItem('isAuthenticated')
|
|
114
|
+
window.sessionStorage.removeItem('activeSession');
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* When any tab is closed, active call gets terminated
|
|
118
|
+
*/
|
|
119
|
+
if(event.key === 'CALL_FLUSH'){
|
|
120
|
+
window.sessionStorage.removeItem('activeSession');
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
};
|