@wazo/sdk 0.48.3 → 0.49.1
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/dist/index.js +218 -16
- package/dist/index.mjs +217 -16
- package/dist/types/__tests__/web-rtc-client-multi-client.test.d.ts +2 -0
- package/dist/types/__tests__/web-rtc-client-multi-client.test.d.ts.map +1 -0
- package/dist/types/base-api-client.d.ts +6 -0
- package/dist/types/base-api-client.d.ts.map +1 -1
- package/dist/types/domain/Phone/WebRTCPhone.d.ts +3 -0
- package/dist/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/dist/types/domain/RefreshTokenError.d.ts +6 -0
- package/dist/types/domain/RefreshTokenError.d.ts.map +1 -0
- package/dist/types/domain/types.d.ts +1 -0
- package/dist/types/domain/types.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/simple/Phone.d.ts +4 -1
- package/dist/types/simple/Phone.d.ts.map +1 -1
- package/dist/types/simple/__tests__/Phone.test.d.ts +2 -0
- package/dist/types/simple/__tests__/Phone.test.d.ts.map +1 -0
- package/dist/types/simple/room/Room.d.ts +2 -1
- package/dist/types/simple/room/Room.d.ts.map +1 -1
- package/dist/types/web-rtc-client.d.ts +7 -0
- package/dist/types/web-rtc-client.d.ts.map +1 -1
- package/dist/wazo-sdk.js +217 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -79,6 +79,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
79
79
|
WazoApiClient: ()=>ApiClient,
|
|
80
80
|
BadResponse: ()=>BadResponse,
|
|
81
81
|
CTIPhone: ()=>CTIPhone,
|
|
82
|
+
RefreshTokenError: ()=>RefreshTokenError,
|
|
82
83
|
CallSession: ()=>CallSession,
|
|
83
84
|
Session: ()=>Session,
|
|
84
85
|
setOnRefreshTokenError: ()=>setOnRefreshTokenError,
|
|
@@ -97,7 +98,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
97
98
|
Contact: ()=>Contact,
|
|
98
99
|
setCurrentServer: ()=>setCurrentServer,
|
|
99
100
|
parsePhoneNumber: ()=>parsePhoneNumber,
|
|
100
|
-
SessionDescriptionHandler: ()=>
|
|
101
|
+
SessionDescriptionHandler: ()=>lib_WazoSessionDescriptionHandler,
|
|
101
102
|
default: ()=>src_0,
|
|
102
103
|
SFUNotAvailableError: ()=>SFUNotAvailableError,
|
|
103
104
|
Incall: ()=>Incall,
|
|
@@ -4039,6 +4040,14 @@ const auth = (client, baseUrl)=>({
|
|
|
4039
4040
|
getProviderAuthUrl: (userUuid, provider)=>client.post(`${baseUrl}/users/${userUuid}/external/${provider}`, {}),
|
|
4040
4041
|
deleteProviderToken: (userUuid, provider)=>client.delete(`${baseUrl}/users/${userUuid}/external/${provider}`)
|
|
4041
4042
|
});
|
|
4043
|
+
class RefreshTokenError extends Error {
|
|
4044
|
+
reason;
|
|
4045
|
+
constructor(reason){
|
|
4046
|
+
super(`Token refresh failed: ${reason}`);
|
|
4047
|
+
this.name = 'RefreshTokenError';
|
|
4048
|
+
this.reason = reason;
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4042
4051
|
const base_api_client_logger = IssueReporter ? IssueReporter.loggerFor('api') : console;
|
|
4043
4052
|
class BaseApiClient {
|
|
4044
4053
|
client;
|
|
@@ -4052,6 +4061,9 @@ class BaseApiClient {
|
|
|
4052
4061
|
refreshDomainName;
|
|
4053
4062
|
isMobile;
|
|
4054
4063
|
fetchOptions;
|
|
4064
|
+
refreshTokenErrorNotified = false;
|
|
4065
|
+
refreshTokenPromise = null;
|
|
4066
|
+
refreshTokenGeneration = 0;
|
|
4055
4067
|
constructor({ server, agent = null, refreshToken, clientId, isMobile = false, fetchOptions }){
|
|
4056
4068
|
this.updateParameters({
|
|
4057
4069
|
server,
|
|
@@ -4081,6 +4093,17 @@ class BaseApiClient {
|
|
|
4081
4093
|
return this.refreshTokenCallback();
|
|
4082
4094
|
}
|
|
4083
4095
|
async refreshTokenCallback() {
|
|
4096
|
+
if (this.refreshTokenPromise) return this.refreshTokenPromise;
|
|
4097
|
+
const generation = this.refreshTokenGeneration;
|
|
4098
|
+
const promise = this.performTokenRefresh(generation);
|
|
4099
|
+
this.refreshTokenPromise = promise;
|
|
4100
|
+
try {
|
|
4101
|
+
return await promise;
|
|
4102
|
+
} finally{
|
|
4103
|
+
if (this.refreshTokenPromise === promise) this.refreshTokenPromise = null;
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
async performTokenRefresh(generation) {
|
|
4084
4107
|
base_api_client_logger.info('refresh token callback called', {
|
|
4085
4108
|
refreshToken: obfuscateToken(this.refreshToken),
|
|
4086
4109
|
refreshBackend: this.refreshBackend,
|
|
@@ -4089,22 +4112,57 @@ class BaseApiClient {
|
|
|
4089
4112
|
refreshExpiration: this.refreshExpiration,
|
|
4090
4113
|
isMobile: this.isMobile
|
|
4091
4114
|
});
|
|
4092
|
-
if (!this.refreshToken)
|
|
4115
|
+
if (!this.refreshToken) {
|
|
4116
|
+
this.notifyRefreshTokenError(new RefreshTokenError('no_refresh_token'), 'no_refresh_token', generation);
|
|
4117
|
+
return null;
|
|
4118
|
+
}
|
|
4093
4119
|
try {
|
|
4094
4120
|
const session = await this.auth.refreshToken(this.refreshToken, this.refreshBackend, this.refreshExpiration, this.isMobile, this.refreshTenantId, this.refreshDomainName);
|
|
4095
|
-
if (!session)
|
|
4121
|
+
if (!session) {
|
|
4122
|
+
this.notifyRefreshTokenError(new RefreshTokenError('empty_session'), 'empty_session', generation);
|
|
4123
|
+
return null;
|
|
4124
|
+
}
|
|
4125
|
+
if (generation !== this.refreshTokenGeneration) {
|
|
4126
|
+
base_api_client_logger.info('ignoring stale token refresh success');
|
|
4127
|
+
return null;
|
|
4128
|
+
}
|
|
4096
4129
|
base_api_client_logger.info('token refreshed', {
|
|
4097
4130
|
token: obfuscateToken(session.token)
|
|
4098
4131
|
});
|
|
4099
|
-
|
|
4132
|
+
this.refreshTokenErrorNotified = false;
|
|
4133
|
+
this.refreshTokenGeneration += 1;
|
|
4100
4134
|
this.setToken(session.token);
|
|
4135
|
+
if (this.onRefreshToken) try {
|
|
4136
|
+
this.onRefreshToken(session.token, session);
|
|
4137
|
+
} catch (e) {
|
|
4138
|
+
base_api_client_logger.error('onRefreshToken handler failed', e);
|
|
4139
|
+
}
|
|
4101
4140
|
return session.token;
|
|
4102
4141
|
} catch (error) {
|
|
4103
4142
|
base_api_client_logger.error('token refresh, error', error);
|
|
4104
|
-
|
|
4143
|
+
this.notifyRefreshTokenError(error, void 0, generation);
|
|
4105
4144
|
}
|
|
4106
4145
|
return null;
|
|
4107
4146
|
}
|
|
4147
|
+
notifyRefreshTokenError(error, reason, generation = this.refreshTokenGeneration) {
|
|
4148
|
+
if (generation !== this.refreshTokenGeneration) {
|
|
4149
|
+
base_api_client_logger.info('ignoring stale token refresh failure', {
|
|
4150
|
+
reason
|
|
4151
|
+
});
|
|
4152
|
+
return;
|
|
4153
|
+
}
|
|
4154
|
+
if (reason) base_api_client_logger.error('token refresh failed', {
|
|
4155
|
+
reason
|
|
4156
|
+
});
|
|
4157
|
+
if (!this.onRefreshTokenError) return;
|
|
4158
|
+
if (this.refreshTokenErrorNotified) return;
|
|
4159
|
+
this.refreshTokenErrorNotified = true;
|
|
4160
|
+
try {
|
|
4161
|
+
this.onRefreshTokenError(error);
|
|
4162
|
+
} catch (e) {
|
|
4163
|
+
base_api_client_logger.error('onRefreshTokenError handler failed', e);
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4108
4166
|
setToken(token) {
|
|
4109
4167
|
this.client.setToken(token);
|
|
4110
4168
|
}
|
|
@@ -4112,7 +4170,16 @@ class BaseApiClient {
|
|
|
4112
4170
|
this.client.setTenant(tenant);
|
|
4113
4171
|
}
|
|
4114
4172
|
setRefreshToken(refreshToken) {
|
|
4173
|
+
const changed = refreshToken !== this.refreshToken;
|
|
4115
4174
|
this.refreshToken = refreshToken;
|
|
4175
|
+
if (refreshToken) {
|
|
4176
|
+
this.refreshTokenErrorNotified = false;
|
|
4177
|
+
if (changed) {
|
|
4178
|
+
this.refreshTokenGeneration += 1;
|
|
4179
|
+
this.refreshTokenPromise = null;
|
|
4180
|
+
this.client.refreshTokenPromise = null;
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4116
4183
|
}
|
|
4117
4184
|
setRequestTimeout(requestTimeout) {
|
|
4118
4185
|
this.client.setRequestTimeout(requestTimeout);
|
|
@@ -4870,7 +4937,7 @@ const wazoMediaStreamFactory = (constraints)=>{
|
|
|
4870
4937
|
if (constraints.screen && !constraints.desktop) return navigator.mediaDevices.getDisplayMedia.call(navigator.mediaDevices, constraints);
|
|
4871
4938
|
return navigator.mediaDevices.getUserMedia.call(navigator.mediaDevices, constraints);
|
|
4872
4939
|
};
|
|
4873
|
-
class
|
|
4940
|
+
class WazoSessionDescriptionHandler extends session_description_handler_namespaceObject.SessionDescriptionHandler {
|
|
4874
4941
|
gatheredCandidates;
|
|
4875
4942
|
eventEmitter;
|
|
4876
4943
|
isWeb;
|
|
@@ -5172,7 +5239,7 @@ class WazoSessionDescriptionHandler_WazoSessionDescriptionHandler extends sessio
|
|
|
5172
5239
|
return keysA.every((key, i)=>keysB[i] === key && this._constraintsEqual(a[key], b[key]));
|
|
5173
5240
|
}
|
|
5174
5241
|
}
|
|
5175
|
-
const
|
|
5242
|
+
const lib_WazoSessionDescriptionHandler = WazoSessionDescriptionHandler;
|
|
5176
5243
|
const lastIndexOf = (array, method)=>{
|
|
5177
5244
|
const start = array.length - 1;
|
|
5178
5245
|
for(let i = start; i >= 0; i--)if (method(array[i])) return i;
|
|
@@ -5242,8 +5309,12 @@ const toAssertedIdentity = (identity)=>{
|
|
|
5242
5309
|
};
|
|
5243
5310
|
const MAX_REGISTER_TRIES = 5;
|
|
5244
5311
|
const NO_ANSWER_TIMEOUT = 86400;
|
|
5312
|
+
let liveClientCount = 0;
|
|
5245
5313
|
class WebRTCClient extends Emitter {
|
|
5246
5314
|
clientId;
|
|
5315
|
+
_countedAsLive;
|
|
5316
|
+
_closed;
|
|
5317
|
+
lastTransportMessageAt;
|
|
5247
5318
|
config;
|
|
5248
5319
|
uaConfigOverrides;
|
|
5249
5320
|
userAgent;
|
|
@@ -5314,11 +5385,32 @@ class WebRTCClient extends Emitter {
|
|
|
5314
5385
|
web_rtc_client_logger.info('sdk webrtc constructor', {
|
|
5315
5386
|
clientId: this.clientId
|
|
5316
5387
|
});
|
|
5388
|
+
liveClientCount += 1;
|
|
5389
|
+
this._countedAsLive = true;
|
|
5390
|
+
this._closed = false;
|
|
5391
|
+
this.lastTransportMessageAt = null;
|
|
5392
|
+
if (liveClientCount > 1) web_rtc_client_logger.info('sdk webrtc multiple clients alive', {
|
|
5393
|
+
liveClientCount,
|
|
5394
|
+
clientId: this.clientId
|
|
5395
|
+
});
|
|
5317
5396
|
this.uaConfigOverrides = uaConfigOverrides;
|
|
5318
5397
|
this.config = config;
|
|
5319
5398
|
this.skipRegister = config.skipRegister;
|
|
5320
5399
|
this._buildConfig(config, session).then((newConfig)=>{
|
|
5321
5400
|
this.config = newConfig;
|
|
5401
|
+
if (this._closed) {
|
|
5402
|
+
web_rtc_client_logger.info('sdk webrtc constructor, client closed during config build, skipping UA creation', {
|
|
5403
|
+
clientId: this.clientId
|
|
5404
|
+
});
|
|
5405
|
+
return;
|
|
5406
|
+
}
|
|
5407
|
+
if (this.userAgent && !session) {
|
|
5408
|
+
web_rtc_client_logger.info('sdk webrtc constructor, userAgent already created, skipping', {
|
|
5409
|
+
clientId: this.clientId
|
|
5410
|
+
});
|
|
5411
|
+
return;
|
|
5412
|
+
}
|
|
5413
|
+
if (this.registerer) this._cleanupRegister();
|
|
5322
5414
|
this.userAgent = this.createUserAgent(uaConfigOverrides);
|
|
5323
5415
|
});
|
|
5324
5416
|
this.audioOutputDeviceId = config.audioDeviceOutput;
|
|
@@ -5377,6 +5469,19 @@ class WebRTCClient extends Emitter {
|
|
|
5377
5469
|
this.audio = media.audio;
|
|
5378
5470
|
}
|
|
5379
5471
|
createUserAgent(uaConfigOverrides) {
|
|
5472
|
+
this.lastTransportMessageAt = null;
|
|
5473
|
+
if (this.userAgent) {
|
|
5474
|
+
web_rtc_client_logger.warn('sdk webrtc, stopping existing UA before creating a new one', {
|
|
5475
|
+
clientId: this.clientId
|
|
5476
|
+
});
|
|
5477
|
+
this.userAgent.stop().catch((error)=>{
|
|
5478
|
+
web_rtc_client_logger.error('sdk webrtc, error stopping previous UA', {
|
|
5479
|
+
error: error?.message,
|
|
5480
|
+
clientId: this.clientId
|
|
5481
|
+
});
|
|
5482
|
+
});
|
|
5483
|
+
this.userAgent = null;
|
|
5484
|
+
}
|
|
5380
5485
|
const uaOptions = this._createUaOptions(uaConfigOverrides);
|
|
5381
5486
|
web_rtc_client_logger.info('sdk webrtc, creating UA', {
|
|
5382
5487
|
uaOptions: {
|
|
@@ -5406,6 +5511,7 @@ class WebRTCClient extends Emitter {
|
|
|
5406
5511
|
web_rtc_client_logger.warn('Transport connect error', e);
|
|
5407
5512
|
});
|
|
5408
5513
|
ua.transport.onMessage = (rawMessage)=>{
|
|
5514
|
+
this.lastTransportMessageAt = Date.now();
|
|
5409
5515
|
const message = parser_namespaceObject.Parser.parseMessage(rawMessage, ua.transport.logger);
|
|
5410
5516
|
ua.onTransportMessage(rawMessage);
|
|
5411
5517
|
this.eventEmitter.emit(MESSAGE, message);
|
|
@@ -5424,6 +5530,16 @@ class WebRTCClient extends Emitter {
|
|
|
5424
5530
|
isRegistered() {
|
|
5425
5531
|
return Boolean(this.registerer && this.registerer.state === registerer_state_namespaceObject.RegistererState.Registered);
|
|
5426
5532
|
}
|
|
5533
|
+
getLastTransportMessageAt() {
|
|
5534
|
+
return this.lastTransportMessageAt;
|
|
5535
|
+
}
|
|
5536
|
+
isTransportSuspect() {
|
|
5537
|
+
if (!this.isConnected()) return true;
|
|
5538
|
+
if (Object.keys(this.sipSessions).length > 0) return false;
|
|
5539
|
+
const threshold = this.config.transportSilenceThresholdMs;
|
|
5540
|
+
if (!threshold || !this.lastTransportMessageAt) return false;
|
|
5541
|
+
return Date.now() - this.lastTransportMessageAt > threshold;
|
|
5542
|
+
}
|
|
5427
5543
|
onConnect() {
|
|
5428
5544
|
web_rtc_client_logger.info('sdk webrtc connected', {
|
|
5429
5545
|
method: 'delegate.onConnect',
|
|
@@ -5447,6 +5563,23 @@ class WebRTCClient extends Emitter {
|
|
|
5447
5563
|
this.eventEmitter.emit(UNREGISTERED);
|
|
5448
5564
|
}
|
|
5449
5565
|
}
|
|
5566
|
+
async _isRegistrationHealthy() {
|
|
5567
|
+
if (!this.isTransportSuspect()) return true;
|
|
5568
|
+
web_rtc_client_logger.warn('sdk webrtc registered but transport suspect, re-registering', {
|
|
5569
|
+
clientId: this.clientId,
|
|
5570
|
+
connected: this.isConnected(),
|
|
5571
|
+
lastTransportMessageAt: this.lastTransportMessageAt
|
|
5572
|
+
});
|
|
5573
|
+
this._cleanupRegister();
|
|
5574
|
+
if (this.isConnected()) {
|
|
5575
|
+
this.connectionPromise = this._disconnectTransport(true);
|
|
5576
|
+
await this.connectionPromise;
|
|
5577
|
+
this.connectionPromise = null;
|
|
5578
|
+
const transport = this.userAgent?.transport;
|
|
5579
|
+
if (transport && transport.state !== transport_state_namespaceObject.TransportState.Disconnected) transport.transitionState(transport_state_namespaceObject.TransportState.Disconnected);
|
|
5580
|
+
}
|
|
5581
|
+
return false;
|
|
5582
|
+
}
|
|
5450
5583
|
async register(tries = 0) {
|
|
5451
5584
|
const logInfo = {
|
|
5452
5585
|
clientId: this.clientId,
|
|
@@ -5459,6 +5592,11 @@ class WebRTCClient extends Emitter {
|
|
|
5459
5592
|
skipRegister: this.skipRegister
|
|
5460
5593
|
};
|
|
5461
5594
|
this.forceClosed = false;
|
|
5595
|
+
this._closed = false;
|
|
5596
|
+
if (!this._countedAsLive) {
|
|
5597
|
+
this._countedAsLive = true;
|
|
5598
|
+
liveClientCount += 1;
|
|
5599
|
+
}
|
|
5462
5600
|
if (this.skipRegister) {
|
|
5463
5601
|
web_rtc_client_logger.info('sdk webrtc skip register...', logInfo);
|
|
5464
5602
|
return Promise.resolve();
|
|
@@ -5468,15 +5606,19 @@ class WebRTCClient extends Emitter {
|
|
|
5468
5606
|
web_rtc_client_logger.info('sdk webrtc recreating User Agent');
|
|
5469
5607
|
this.userAgent = this.createUserAgent(this.uaConfigOverrides);
|
|
5470
5608
|
}
|
|
5471
|
-
if (!this.userAgent
|
|
5472
|
-
web_rtc_client_logger.info('sdk webrtc registering aborted,
|
|
5473
|
-
return
|
|
5609
|
+
if (!this.userAgent) {
|
|
5610
|
+
web_rtc_client_logger.info('sdk webrtc registering aborted, no UA can be created');
|
|
5611
|
+
return;
|
|
5612
|
+
}
|
|
5613
|
+
if (this.isRegistered() && await this._isRegistrationHealthy()) {
|
|
5614
|
+
web_rtc_client_logger.info('sdk webrtc registering aborted, already registered');
|
|
5615
|
+
return;
|
|
5474
5616
|
}
|
|
5475
5617
|
if (this.connectionPromise || this.registerer?.waiting) {
|
|
5476
5618
|
web_rtc_client_logger.info('sdk webrtc registering aborted due to a registration in progress.', {
|
|
5477
5619
|
clientId: this.clientId
|
|
5478
5620
|
});
|
|
5479
|
-
return
|
|
5621
|
+
return;
|
|
5480
5622
|
}
|
|
5481
5623
|
const registerOptions = this._isWeb() ? {} : {
|
|
5482
5624
|
extraContactHeaderParams: [
|
|
@@ -5577,7 +5719,6 @@ class WebRTCClient extends Emitter {
|
|
|
5577
5719
|
web_rtc_client_logger.info('sdk webrtc unregistered', {
|
|
5578
5720
|
clientId: this.clientId
|
|
5579
5721
|
});
|
|
5580
|
-
if (this.registerer) this.registerer.stateChange.addListener(onRegisterStateChange);
|
|
5581
5722
|
this._cleanupRegister();
|
|
5582
5723
|
resolve();
|
|
5583
5724
|
}
|
|
@@ -5771,6 +5912,11 @@ class WebRTCClient extends Emitter {
|
|
|
5771
5912
|
force
|
|
5772
5913
|
});
|
|
5773
5914
|
this.forceClosed = force;
|
|
5915
|
+
this._closed = true;
|
|
5916
|
+
if (this._countedAsLive) {
|
|
5917
|
+
this._countedAsLive = false;
|
|
5918
|
+
liveClientCount = Math.max(0, liveClientCount - 1);
|
|
5919
|
+
}
|
|
5774
5920
|
this._cleanupMedia();
|
|
5775
5921
|
this.connectionPromise = null;
|
|
5776
5922
|
Object.values(this.audioElements).forEach((audioElement)=>{
|
|
@@ -6698,7 +6844,7 @@ class WebRTCClient extends Emitter {
|
|
|
6698
6844
|
...options.peerConnectionConfiguration || {}
|
|
6699
6845
|
}
|
|
6700
6846
|
};
|
|
6701
|
-
return new
|
|
6847
|
+
return new lib_WazoSessionDescriptionHandler(uaLogger, wazoMediaStreamFactory, sdhOptions, isWeb, session);
|
|
6702
6848
|
},
|
|
6703
6849
|
transportOptions: {
|
|
6704
6850
|
traceSip: uaOptionsOverrides?.traceSip || false,
|
|
@@ -8659,6 +8805,15 @@ class WebRTCPhone extends Emitter {
|
|
|
8659
8805
|
isRegistered() {
|
|
8660
8806
|
return this.client && this.client.isRegistered();
|
|
8661
8807
|
}
|
|
8808
|
+
isConnected() {
|
|
8809
|
+
return Boolean(this.client?.isConnected());
|
|
8810
|
+
}
|
|
8811
|
+
isTransportSuspect() {
|
|
8812
|
+
return !this.client || this.client.isTransportSuspect();
|
|
8813
|
+
}
|
|
8814
|
+
getLastTransportMessageAt() {
|
|
8815
|
+
return this.client?.getLastTransportMessageAt() ?? null;
|
|
8816
|
+
}
|
|
8662
8817
|
enableRinging() {
|
|
8663
8818
|
WebRTCPhone_logger.info('WebRTC enable ringing');
|
|
8664
8819
|
this.ringingEnabled = true;
|
|
@@ -8978,8 +9133,9 @@ class WebRTCPhone extends Emitter {
|
|
|
8978
9133
|
const { state } = sipSession || {};
|
|
8979
9134
|
const sessionId = this.getSipSessionId(sipSession);
|
|
8980
9135
|
fromSession = fromSession || this.callSessions[sessionId];
|
|
9136
|
+
const headerCallId = sipSession?.request?.getHeader?.('X-Wazo-Call-ID');
|
|
8981
9137
|
const callSession = new CallSession({
|
|
8982
|
-
callId: fromSession
|
|
9138
|
+
callId: fromSession?.callId || headerCallId || '',
|
|
8983
9139
|
sipCallId: sessionId,
|
|
8984
9140
|
sipStatus: state,
|
|
8985
9141
|
displayName: identity ? identity.displayName || number : number,
|
|
@@ -9614,6 +9770,7 @@ const protocolDebugMessages = [
|
|
|
9614
9770
|
class Phone_Phone extends Emitter {
|
|
9615
9771
|
client;
|
|
9616
9772
|
phone;
|
|
9773
|
+
connectInFlight;
|
|
9617
9774
|
session;
|
|
9618
9775
|
sipLine;
|
|
9619
9776
|
SessionState;
|
|
@@ -9683,10 +9840,37 @@ class Phone_Phone extends Emitter {
|
|
|
9683
9840
|
this.sipLine = sipLine || this.getPrimaryWebRtcLine();
|
|
9684
9841
|
if (!this.sipLine) throw new Error('Sorry, no sip lines found for this user');
|
|
9685
9842
|
options.userUuid = session.uuid || '';
|
|
9686
|
-
this.connectWithCredentials(server, this.sipLine, session.displayName(), options);
|
|
9843
|
+
return this.connectWithCredentials(server, this.sipLine, session.displayName(), options);
|
|
9687
9844
|
}
|
|
9688
|
-
connectWithCredentials(server, sipLine, displayName, rawOptions = {}) {
|
|
9845
|
+
async connectWithCredentials(server, sipLine, displayName, rawOptions = {}) {
|
|
9689
9846
|
if (this.phone) return;
|
|
9847
|
+
if (this.connectInFlight) {
|
|
9848
|
+
Phone_logger.info('connectWithCredentials: connection already in progress, reusing it and ignoring this call\'s arguments', {
|
|
9849
|
+
server,
|
|
9850
|
+
sipLineId: sipLine?.id
|
|
9851
|
+
});
|
|
9852
|
+
return this.connectInFlight;
|
|
9853
|
+
}
|
|
9854
|
+
this.connectInFlight = this._connectWithCredentials(server, sipLine, displayName, rawOptions).finally(()=>{
|
|
9855
|
+
this.connectInFlight = null;
|
|
9856
|
+
});
|
|
9857
|
+
return this.connectInFlight;
|
|
9858
|
+
}
|
|
9859
|
+
async _connectWithCredentials(server, sipLine, displayName, rawOptions = {}) {
|
|
9860
|
+
if (this.client) {
|
|
9861
|
+
Phone_logger.warn('connectWithCredentials: closing previous client before creating a new one');
|
|
9862
|
+
try {
|
|
9863
|
+
await this.client.close();
|
|
9864
|
+
} catch (error) {
|
|
9865
|
+
Phone_logger.error('connectWithCredentials: error while closing previous client', {
|
|
9866
|
+
message: error?.message
|
|
9867
|
+
});
|
|
9868
|
+
}
|
|
9869
|
+
if (this.phone) {
|
|
9870
|
+
Phone_logger.info('connectWithCredentials: phone connected while closing previous client, keeping it');
|
|
9871
|
+
return;
|
|
9872
|
+
}
|
|
9873
|
+
}
|
|
9690
9874
|
const [host, port = 443] = server.split(':');
|
|
9691
9875
|
const options = rawOptions;
|
|
9692
9876
|
options.media = options.media || {
|
|
@@ -9723,6 +9907,24 @@ class Phone_Phone extends Emitter {
|
|
|
9723
9907
|
}
|
|
9724
9908
|
this.phone = null;
|
|
9725
9909
|
}
|
|
9910
|
+
async reset() {
|
|
9911
|
+
Phone_logger.info('phone reset', {
|
|
9912
|
+
phone: !!this.phone,
|
|
9913
|
+
client: !!this.client
|
|
9914
|
+
});
|
|
9915
|
+
await this.disconnect().catch((error)=>{
|
|
9916
|
+
Phone_logger.error('reset: error while disconnecting phone', {
|
|
9917
|
+
message: error?.message
|
|
9918
|
+
});
|
|
9919
|
+
});
|
|
9920
|
+
if (this.client) await this.client.close().catch((error)=>{
|
|
9921
|
+
Phone_logger.error('reset: error while closing client', {
|
|
9922
|
+
message: error?.message
|
|
9923
|
+
});
|
|
9924
|
+
});
|
|
9925
|
+
this.phone = null;
|
|
9926
|
+
this.client = null;
|
|
9927
|
+
}
|
|
9726
9928
|
async call(extension, withCamera = false, rawSipLine = null, audioOnly = false, conference = false) {
|
|
9727
9929
|
if (!this.phone) return;
|
|
9728
9930
|
const sipLine = rawSipLine || this.getPrimaryWebRtcLine();
|