@wazo/sdk 0.37.24 → 0.37.28
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/README.md +96 -58
- package/dist/wazo-sdk.js +6 -6
- package/esm/__tests__/api-client.test.js +14 -14
- package/esm/__tests__/web-rtc-client.test.js +130 -108
- package/esm/api/agentd.js +1 -1
- package/esm/api/amid.js +2 -2
- package/esm/api/application.js +1 -1
- package/esm/api/auth.js +1 -1
- package/esm/api/call-logd.js +3 -3
- package/esm/api/calld.js +1 -1
- package/esm/api/chatd.js +1 -1
- package/esm/api/confd.js +1 -1
- package/esm/api/ctid-ng.js +4 -4
- package/esm/api/dird.js +3 -3
- package/esm/api/webhookd.js +2 -2
- package/esm/api-client.js +14 -14
- package/esm/checker/Checker.js +155 -133
- package/esm/checker/checks/aor.js +14 -14
- package/esm/checker/checks/api.js +14 -14
- package/esm/checker/checks/index.js +145 -123
- package/esm/checker/checks/wazo-websocket.js +16 -16
- package/esm/checker/checks/webrtc-transport.js +130 -108
- package/esm/checker/checks/webrtc.js +130 -108
- package/esm/domain/AdHocAPIConference.js +14 -14
- package/esm/domain/CallLog.js +1 -1
- package/esm/domain/CallSession.js +15 -0
- package/esm/domain/Contact.js +2 -2
- package/esm/domain/Features.js +14 -14
- package/esm/domain/Phone/CTIPhone.js +43 -28
- package/esm/domain/Phone/WebRTCPhone.js +126 -90
- package/esm/domain/SFUNotAvailableError.js +9 -0
- package/esm/domain/__tests__/CallLog.test.js +1 -1
- package/esm/domain/__tests__/CallSession.test.js +15 -0
- package/esm/domain/__tests__/Contact.test.js +2 -2
- package/esm/domain/__tests__/IndirectTransfer.test.js +15 -0
- package/esm/domain/__tests__/Room.test.js +15 -0
- package/esm/index.js +415 -346
- package/esm/lib/WazoSessionDescriptionHandler.js +10 -5
- package/esm/service/CallApi.js +14 -14
- package/esm/service/IssueReporter.js +2 -2
- package/esm/service/__tests__/IssueReporter.test.js +2 -2
- package/esm/service/getApiClient.js +14 -14
- package/esm/simple/Auth.js +404 -336
- package/esm/simple/Configuration.js +404 -336
- package/esm/simple/Directory.js +14 -14
- package/esm/simple/Phone.js +404 -336
- package/esm/simple/Websocket.js +18 -18
- package/esm/simple/index.js +408 -340
- package/esm/simple/room/LocalParticipant.js +408 -340
- package/esm/simple/room/Participant.js +408 -340
- package/esm/simple/room/RemoteParticipant.js +408 -340
- package/esm/simple/room/Room.js +409 -341
- package/esm/simple/room/SipRoom.js +408 -340
- package/esm/simple/room/Stream.js +408 -340
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +408 -340
- package/esm/simple/utils.js +408 -340
- package/esm/utils/__tests__/api-requester.test.js +1 -1
- package/esm/utils/api-requester.js +1 -1
- package/esm/web-rtc-client.js +130 -108
- package/esm/websocket-client.js +16 -16
- package/lib/__tests__/api-client.test.js +14 -14
- package/lib/__tests__/web-rtc-client.test.js +130 -108
- package/lib/api/agentd.js +1 -1
- package/lib/api/amid.js +2 -2
- package/lib/api/application.js +1 -1
- package/lib/api/auth.js +1 -1
- package/lib/api/call-logd.js +3 -3
- package/lib/api/calld.js +1 -1
- package/lib/api/chatd.js +1 -1
- package/lib/api/confd.js +1 -1
- package/lib/api/ctid-ng.js +4 -4
- package/lib/api/dird.js +3 -3
- package/lib/api/webhookd.js +2 -2
- package/lib/api-client.js +14 -14
- package/lib/checker/Checker.js +155 -133
- package/lib/checker/checks/aor.js +14 -14
- package/lib/checker/checks/api.js +14 -14
- package/lib/checker/checks/index.js +145 -123
- package/lib/checker/checks/wazo-websocket.js +16 -16
- package/lib/checker/checks/webrtc-transport.js +130 -108
- package/lib/checker/checks/webrtc.js +130 -108
- package/lib/domain/AdHocAPIConference.js +14 -14
- package/lib/domain/CallLog.js +1 -1
- package/lib/domain/CallSession.js +15 -0
- package/lib/domain/Contact.js +2 -2
- package/lib/domain/Features.js +14 -14
- package/lib/domain/Phone/CTIPhone.js +43 -28
- package/lib/domain/Phone/WebRTCPhone.js +126 -89
- package/lib/domain/SFUNotAvailableError.js +11 -0
- package/lib/domain/__tests__/CallLog.test.js +1 -1
- package/lib/domain/__tests__/CallSession.test.js +15 -0
- package/lib/domain/__tests__/Contact.test.js +2 -2
- package/lib/domain/__tests__/IndirectTransfer.test.js +15 -0
- package/lib/domain/__tests__/Room.test.js +15 -0
- package/lib/index.js +415 -346
- package/lib/lib/WazoSessionDescriptionHandler.js +10 -5
- package/lib/service/CallApi.js +14 -14
- package/lib/service/IssueReporter.js +2 -2
- package/lib/service/__tests__/IssueReporter.test.js +2 -2
- package/lib/service/getApiClient.js +14 -14
- package/lib/simple/Auth.js +404 -336
- package/lib/simple/Configuration.js +404 -336
- package/lib/simple/Directory.js +14 -14
- package/lib/simple/Phone.js +404 -336
- package/lib/simple/Websocket.js +18 -18
- package/lib/simple/index.js +408 -340
- package/lib/simple/room/LocalParticipant.js +408 -340
- package/lib/simple/room/Participant.js +408 -340
- package/lib/simple/room/RemoteParticipant.js +408 -340
- package/lib/simple/room/Room.js +409 -341
- package/lib/simple/room/SipRoom.js +408 -340
- package/lib/simple/room/Stream.js +408 -340
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +408 -340
- package/lib/simple/utils.js +408 -340
- package/lib/utils/__tests__/api-requester.test.js +1 -1
- package/lib/utils/api-requester.js +1 -1
- package/lib/web-rtc-client.js +130 -108
- package/lib/websocket-client.js +16 -16
- package/package.json +1 -1
- package/src/domain/CallSession.js +16 -0
- package/src/domain/Contact.js +1 -1
- package/src/domain/Phone/WebRTCPhone.js +25 -4
- package/src/domain/SFUNotAvailableError.js +7 -0
- package/src/index.js +2 -0
- package/src/lib/WazoSessionDescriptionHandler.js +8 -3
- package/src/simple/Phone.js +2 -1
- package/src/simple/index.js +2 -0
- package/src/utils/api-requester.js +1 -1
- package/src/web-rtc-client.js +27 -10
package/lib/websocket-client.js
CHANGED
|
@@ -45,11 +45,11 @@ const isMobile = () => typeof navigator !== 'undefined' && navigator.product ===
|
|
|
45
45
|
|
|
46
46
|
/* */
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
49
49
|
|
|
50
50
|
// Use a function here to be able to mock it in tests
|
|
51
51
|
const realFetch = () => {
|
|
52
|
-
if (typeof document !== 'undefined') {
|
|
52
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
53
53
|
// Browser
|
|
54
54
|
return window.fetch;
|
|
55
55
|
}
|
|
@@ -621,7 +621,7 @@ const BLACKLIST_EVENTS = [
|
|
|
621
621
|
];
|
|
622
622
|
|
|
623
623
|
const HEARTBEAT_ENGINE_VERSION = '20.09';
|
|
624
|
-
const logger
|
|
624
|
+
const logger = IssueReporter$1.loggerFor('wazo-ws');
|
|
625
625
|
const messageLogger = IssueReporter$1.loggerFor('wazo-ws-message');
|
|
626
626
|
|
|
627
627
|
class WebSocketClient extends Emitter {
|
|
@@ -670,19 +670,19 @@ class WebSocketClient extends Emitter {
|
|
|
670
670
|
}
|
|
671
671
|
|
|
672
672
|
connect() {
|
|
673
|
-
logger
|
|
673
|
+
logger.info('connect method started', { host: this.host, token: this.token });
|
|
674
674
|
this.socket = new ReconnectingWebSocket__default['default'](this._getUrl.bind(this), [], this.options);
|
|
675
675
|
if (this.options.binaryType) {
|
|
676
676
|
this.socket.binaryType = this.options.binaryType;
|
|
677
677
|
}
|
|
678
678
|
|
|
679
679
|
this.socket.onopen = () => {
|
|
680
|
-
logger
|
|
680
|
+
logger.info('on Wazo WS open', { method: 'connect', host: this.host });
|
|
681
681
|
this.eventEmitter.emit(SOCKET_EVENTS.ON_OPEN);
|
|
682
682
|
};
|
|
683
683
|
|
|
684
684
|
this.socket.onerror = event => {
|
|
685
|
-
logger
|
|
685
|
+
logger.error('on Wazo WS error', event.target);
|
|
686
686
|
this.eventEmitter.emit(SOCKET_EVENTS.ON_ERROR, event);
|
|
687
687
|
};
|
|
688
688
|
|
|
@@ -712,7 +712,7 @@ class WebSocketClient extends Emitter {
|
|
|
712
712
|
|
|
713
713
|
this.socket.onclose = event => {
|
|
714
714
|
// Can't be converted to JSON (circular structure)
|
|
715
|
-
logger
|
|
715
|
+
logger.info('on Wazo WS close', {
|
|
716
716
|
reason: event.reason,
|
|
717
717
|
code: event.code,
|
|
718
718
|
readyState: event.target.readyState,
|
|
@@ -730,12 +730,12 @@ class WebSocketClient extends Emitter {
|
|
|
730
730
|
};
|
|
731
731
|
|
|
732
732
|
this.socket.onerror = event => {
|
|
733
|
-
logger
|
|
733
|
+
logger.info('Wazo WS error', { message: event.message, code: event.code, readyState: event.target.readyState });
|
|
734
734
|
};
|
|
735
735
|
}
|
|
736
736
|
|
|
737
737
|
close(force = false) {
|
|
738
|
-
logger
|
|
738
|
+
logger.info('Wazo WS close', { socket: !!this.socket, host: this.host, token: this.token });
|
|
739
739
|
|
|
740
740
|
if (!this.socket) {
|
|
741
741
|
return;
|
|
@@ -753,7 +753,7 @@ class WebSocketClient extends Emitter {
|
|
|
753
753
|
|
|
754
754
|
updateToken(token ) {
|
|
755
755
|
this.token = token;
|
|
756
|
-
logger
|
|
756
|
+
logger.info('Wazo WS updating token', { url: this._getUrl(), token, socket: !!this.socket });
|
|
757
757
|
|
|
758
758
|
if (this.socket) {
|
|
759
759
|
// If still connected, send the token to the WS
|
|
@@ -771,7 +771,7 @@ class WebSocketClient extends Emitter {
|
|
|
771
771
|
}
|
|
772
772
|
|
|
773
773
|
startHeartbeat() {
|
|
774
|
-
logger
|
|
774
|
+
logger.info('Wazo WS start heartbeat', { host: this.host, token: this.token });
|
|
775
775
|
|
|
776
776
|
if (!this.socket) {
|
|
777
777
|
this.heartbeat.stop();
|
|
@@ -785,7 +785,7 @@ class WebSocketClient extends Emitter {
|
|
|
785
785
|
}
|
|
786
786
|
|
|
787
787
|
stopHeartbeat() {
|
|
788
|
-
logger
|
|
788
|
+
logger.info('Wazo WS stop heartbeat', { host: this.host, token: this.token });
|
|
789
789
|
|
|
790
790
|
this.heartbeat.stop();
|
|
791
791
|
}
|
|
@@ -815,7 +815,7 @@ class WebSocketClient extends Emitter {
|
|
|
815
815
|
}
|
|
816
816
|
|
|
817
817
|
reconnect(reason ) {
|
|
818
|
-
logger
|
|
818
|
+
logger.info('Wazo WS reconnect', { reason, socket: !!this.socket, host: this.host, token: this.token });
|
|
819
819
|
if (!this.socket) {
|
|
820
820
|
return;
|
|
821
821
|
}
|
|
@@ -871,7 +871,7 @@ class WebSocketClient extends Emitter {
|
|
|
871
871
|
this.close();
|
|
872
872
|
}
|
|
873
873
|
const url = `wss://${this.host || ''}/api/websocketd/?token=${this.token || ''}&version=${this.version}`;
|
|
874
|
-
logger
|
|
874
|
+
logger.log('Wazo WS url computed to reconnect', { url });
|
|
875
875
|
|
|
876
876
|
return url;
|
|
877
877
|
}
|
|
@@ -879,12 +879,12 @@ class WebSocketClient extends Emitter {
|
|
|
879
879
|
_onHeartbeat(message ) {
|
|
880
880
|
if (message.payload === 'pong') {
|
|
881
881
|
this.heartbeat.onHeartbeat();
|
|
882
|
-
logger
|
|
882
|
+
logger.log('on heartbeat received from Wazo WS');
|
|
883
883
|
}
|
|
884
884
|
}
|
|
885
885
|
|
|
886
886
|
async _onHeartbeatTimeout() {
|
|
887
|
-
logger
|
|
887
|
+
logger.log('heartbeat timed out', { host: this.host, token: this.token });
|
|
888
888
|
|
|
889
889
|
this.close();
|
|
890
890
|
this.eventEmitter.emit(SOCKET_EVENTS.ON_CLOSE, new Error('Websocket ping failure.'));
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import { SessionState } from 'sip.js/lib/api/session-state';
|
|
3
|
+
import type { Session } from 'sip.js/lib/api/session';
|
|
3
4
|
|
|
4
5
|
import Call from './Call';
|
|
5
6
|
import newFrom from '../utils/new-from';
|
|
@@ -12,8 +13,10 @@ type CallSessionArguments = {
|
|
|
12
13
|
callId: string,
|
|
13
14
|
callerNumber: string,
|
|
14
15
|
cameraEnabled: boolean,
|
|
16
|
+
creationTime?: ?Date,
|
|
15
17
|
dialedExtension?: string | null,
|
|
16
18
|
displayName: string,
|
|
19
|
+
endTime?: ?Date,
|
|
17
20
|
isCaller: boolean,
|
|
18
21
|
muted: boolean,
|
|
19
22
|
videoMuted: boolean,
|
|
@@ -30,6 +33,7 @@ type CallSessionArguments = {
|
|
|
30
33
|
screensharing: boolean,
|
|
31
34
|
recording: boolean,
|
|
32
35
|
recordingPaused: boolean,
|
|
36
|
+
sipSession?: Session,
|
|
33
37
|
};
|
|
34
38
|
|
|
35
39
|
export default class CallSession {
|
|
@@ -49,8 +53,12 @@ export default class CallSession {
|
|
|
49
53
|
|
|
50
54
|
callerNumber: string;
|
|
51
55
|
|
|
56
|
+
creationTime: ?Date;
|
|
57
|
+
|
|
52
58
|
startTime: number;
|
|
53
59
|
|
|
60
|
+
endTime: ?Date;
|
|
61
|
+
|
|
54
62
|
isCaller: boolean;
|
|
55
63
|
|
|
56
64
|
answered: boolean;
|
|
@@ -89,6 +97,8 @@ export default class CallSession {
|
|
|
89
97
|
|
|
90
98
|
recordingPaused: boolean;
|
|
91
99
|
|
|
100
|
+
sipSession: Session;
|
|
101
|
+
|
|
92
102
|
constructor({
|
|
93
103
|
answered,
|
|
94
104
|
answeredBySystem,
|
|
@@ -101,6 +111,8 @@ export default class CallSession {
|
|
|
101
111
|
paused,
|
|
102
112
|
ringing,
|
|
103
113
|
startTime,
|
|
114
|
+
creationTime,
|
|
115
|
+
endTime,
|
|
104
116
|
cameraEnabled,
|
|
105
117
|
dialedExtension,
|
|
106
118
|
sipCallId,
|
|
@@ -113,12 +125,15 @@ export default class CallSession {
|
|
|
113
125
|
recording,
|
|
114
126
|
recordingPaused,
|
|
115
127
|
videoRemotelyDowngraded,
|
|
128
|
+
sipSession,
|
|
116
129
|
}: CallSessionArguments) {
|
|
117
130
|
this.callId = callId;
|
|
118
131
|
this.sipCallId = sipCallId;
|
|
119
132
|
this.displayName = displayName;
|
|
120
133
|
this.number = number;
|
|
134
|
+
this.creationTime = creationTime;
|
|
121
135
|
this.startTime = startTime;
|
|
136
|
+
this.endTime = endTime;
|
|
122
137
|
this.isCaller = isCaller;
|
|
123
138
|
this.answered = answered;
|
|
124
139
|
this.answeredBySystem = answeredBySystem;
|
|
@@ -137,6 +152,7 @@ export default class CallSession {
|
|
|
137
152
|
this.recording = recording || false;
|
|
138
153
|
this.recordingPaused = recordingPaused || false;
|
|
139
154
|
this.videoRemotelyDowngraded = videoRemotelyDowngraded;
|
|
155
|
+
this.sipSession = sipSession;
|
|
140
156
|
|
|
141
157
|
// Useful to compare instead of instanceof with minified code
|
|
142
158
|
this.type = 'CallSession';
|
package/src/domain/Contact.js
CHANGED
|
@@ -30,6 +30,7 @@ export const ON_CAMERA_DISABLED = 'onCameraDisabled';
|
|
|
30
30
|
export const ON_CAMERA_RESUMED = 'onCameraResumed';
|
|
31
31
|
export const ON_CALL_CANCELED = 'onCallCanceled';
|
|
32
32
|
export const ON_CALL_FAILED = 'onCallFailed';
|
|
33
|
+
export const ON_CALL_REJECTED = 'onCallRejected';
|
|
33
34
|
export const ON_CALL_ENDED = 'onCallEnded';
|
|
34
35
|
export const ON_CALL_ENDING = 'onCallEnding';
|
|
35
36
|
export const ON_MESSAGE = 'onMessage';
|
|
@@ -74,6 +75,7 @@ export const events = [
|
|
|
74
75
|
ON_CAMERA_DISABLED,
|
|
75
76
|
ON_CALL_FAILED,
|
|
76
77
|
ON_CALL_ENDED,
|
|
78
|
+
ON_CALL_REJECTED,
|
|
77
79
|
ON_MESSAGE,
|
|
78
80
|
ON_REINVITE,
|
|
79
81
|
ON_TRACK,
|
|
@@ -203,6 +205,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
203
205
|
constraints,
|
|
204
206
|
audioOnly,
|
|
205
207
|
conference,
|
|
208
|
+
iceRestart,
|
|
206
209
|
});
|
|
207
210
|
|
|
208
211
|
if (!sipSession) {
|
|
@@ -429,6 +432,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
429
432
|
|
|
430
433
|
// Should be called before `_onCallTerminated` or the callCount will not decrement...
|
|
431
434
|
const callSession = this._createCallSession(sipSession);
|
|
435
|
+
callSession.endTime = new Date();
|
|
432
436
|
const wasCurrentSession = this._onCallTerminated(sipSession);
|
|
433
437
|
|
|
434
438
|
return this.eventEmitter.emit(ON_CALL_ENDED, callSession, wasCurrentSession);
|
|
@@ -614,7 +618,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
614
618
|
}
|
|
615
619
|
|
|
616
620
|
_onCallAccepted(sipSession: Session, cameraEnabled: boolean): CallSession {
|
|
617
|
-
logger.info('WebRTC phone -
|
|
621
|
+
logger.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
|
|
618
622
|
|
|
619
623
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
620
624
|
this.currentSipSession = sipSession;
|
|
@@ -683,6 +687,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
683
687
|
_onCallTerminated(sipSession: Session) {
|
|
684
688
|
logger.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
|
|
685
689
|
|
|
690
|
+
const sipSessionId = this.getSipSessionId(sipSession);
|
|
686
691
|
const callSession = this._createCallSession(sipSession);
|
|
687
692
|
const isCurrentSession = this.isCurrentCallSipSession(callSession);
|
|
688
693
|
const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
|
|
@@ -700,7 +705,6 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
700
705
|
}, 5);
|
|
701
706
|
}
|
|
702
707
|
|
|
703
|
-
const sipSessionId = this.getSipSessionId(sipSession);
|
|
704
708
|
if (sipSessionId) {
|
|
705
709
|
this.removeIncomingSessions(sipSessionId);
|
|
706
710
|
}
|
|
@@ -1126,7 +1130,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1126
1130
|
// @TODO: line is not used here
|
|
1127
1131
|
async makeCall(number: string, line: any, cameraEnabled?: boolean,
|
|
1128
1132
|
audioOnly: boolean = false, conference: boolean = false): Promise<?CallSession> {
|
|
1129
|
-
logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
|
|
1133
|
+
logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
|
|
1130
1134
|
if (!number) {
|
|
1131
1135
|
return Promise.resolve(null);
|
|
1132
1136
|
}
|
|
@@ -1150,6 +1154,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1150
1154
|
return Promise.resolve(null);
|
|
1151
1155
|
}
|
|
1152
1156
|
const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
|
|
1157
|
+
callSession.creationTime = new Date();
|
|
1153
1158
|
|
|
1154
1159
|
this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
|
|
1155
1160
|
|
|
@@ -1345,8 +1350,12 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1345
1350
|
}
|
|
1346
1351
|
|
|
1347
1352
|
const sessionId = this.incomingSessions[0];
|
|
1353
|
+
const sipSession = this.client.getSipSession(sessionId);
|
|
1354
|
+
if (!sipSession) {
|
|
1355
|
+
return null;
|
|
1356
|
+
}
|
|
1348
1357
|
|
|
1349
|
-
return this._createCallSession(
|
|
1358
|
+
return this._createCallSession(sipSession);
|
|
1350
1359
|
}
|
|
1351
1360
|
|
|
1352
1361
|
sendMessage(sipSession: Session = null, body: string, contentType: string = 'text/plain') {
|
|
@@ -1424,6 +1433,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1424
1433
|
callSession);
|
|
1425
1434
|
}
|
|
1426
1435
|
|
|
1436
|
+
callSession.creationTime = new Date();
|
|
1427
1437
|
this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
|
|
1428
1438
|
});
|
|
1429
1439
|
|
|
@@ -1463,6 +1473,13 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1463
1473
|
this.eventEmitter.emit(ON_CALL_ERROR, e);
|
|
1464
1474
|
});
|
|
1465
1475
|
|
|
1476
|
+
this.client.on(this.client.REJECTED, session => {
|
|
1477
|
+
logger.info('WebRTC call rejected', session.id);
|
|
1478
|
+
const callSession = this._createCallSession(session);
|
|
1479
|
+
callSession.endTime = new Date();
|
|
1480
|
+
this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
|
|
1481
|
+
});
|
|
1482
|
+
|
|
1466
1483
|
this.client.on(this.client.UNREGISTERED, () => {
|
|
1467
1484
|
logger.info('WebRTC unregistered');
|
|
1468
1485
|
this.eventEmitter.emit(ON_UNREGISTERED);
|
|
@@ -1677,6 +1694,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1677
1694
|
const number = identity ? identity.uri._normal.user : null;
|
|
1678
1695
|
const { state } = sipSession || {};
|
|
1679
1696
|
const sessionId = this.getSipSessionId(sipSession);
|
|
1697
|
+
fromSession = fromSession || this.callSessions[sessionId];
|
|
1680
1698
|
|
|
1681
1699
|
const callSession = new CallSession({
|
|
1682
1700
|
callId: fromSession && fromSession.callId,
|
|
@@ -1684,6 +1702,8 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1684
1702
|
sipStatus: state,
|
|
1685
1703
|
displayName: identity ? identity.displayName || number : number,
|
|
1686
1704
|
startTime: fromSession ? fromSession.startTime : new Date(),
|
|
1705
|
+
creationTime: fromSession ? fromSession.creationTime : null,
|
|
1706
|
+
endTime: fromSession ? fromSession.endTime : null,
|
|
1687
1707
|
answered: state === SessionState.Established,
|
|
1688
1708
|
paused: this.client.isCallHeld(sipSession),
|
|
1689
1709
|
isCaller: 'incoming' in extra ? !extra.incoming : false,
|
|
@@ -1694,6 +1714,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1694
1714
|
videoMuted: fromSession ? fromSession.isVideoMuted() : false,
|
|
1695
1715
|
recording: fromSession ? fromSession.isRecording() : false,
|
|
1696
1716
|
recordingPaused: false, // @TODO
|
|
1717
|
+
sipSession,
|
|
1697
1718
|
...extra,
|
|
1698
1719
|
});
|
|
1699
1720
|
|
package/src/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import IssueReporter from './service/IssueReporter';
|
|
|
9
9
|
// Domain
|
|
10
10
|
import BadResponse from './domain/BadResponse';
|
|
11
11
|
import ServerError from './domain/ServerError';
|
|
12
|
+
import SFUNotAvailableError from './domain/SFUNotAvailableError';
|
|
12
13
|
import Call from './domain/Call';
|
|
13
14
|
import CallLog from './domain/CallLog';
|
|
14
15
|
import Recording from './domain/Recording';
|
|
@@ -95,6 +96,7 @@ export default {
|
|
|
95
96
|
WazoWebSocketClient: WebSocketClient,
|
|
96
97
|
BadResponse,
|
|
97
98
|
ServerError,
|
|
99
|
+
SFUNotAvailableError,
|
|
98
100
|
Call,
|
|
99
101
|
CallSession,
|
|
100
102
|
CTIPhone,
|
|
@@ -62,11 +62,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
62
62
|
|
|
63
63
|
// $FlowFixMe
|
|
64
64
|
setRemoteSessionDescription(sessionDescription: RTCSessionDescriptionInit): Promise<void> {
|
|
65
|
-
|
|
65
|
+
try {
|
|
66
|
+
const result = super.setRemoteSessionDescription(sessionDescription);
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
this.eventEmitter.emit('setDescription', sessionDescription);
|
|
68
69
|
|
|
69
|
-
|
|
70
|
+
return result;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
// Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
|
package/src/simple/Phone.js
CHANGED
|
@@ -14,6 +14,7 @@ import IssueReporter from '../service/IssueReporter';
|
|
|
14
14
|
import Emitter from '../utils/Emitter';
|
|
15
15
|
|
|
16
16
|
import Wazo from './index';
|
|
17
|
+
import SFUNotAvailableError from '../domain/SFUNotAvailableError';
|
|
17
18
|
|
|
18
19
|
const logger = IssueReporter.loggerFor('simple-phone');
|
|
19
20
|
const sipLogger = IssueReporter.loggerFor('sip.js');
|
|
@@ -397,7 +398,7 @@ class Phone extends Emitter {
|
|
|
397
398
|
|
|
398
399
|
checkSfu() {
|
|
399
400
|
if (!this.hasSfu()) {
|
|
400
|
-
throw new
|
|
401
|
+
throw new SFUNotAvailableError();
|
|
401
402
|
}
|
|
402
403
|
}
|
|
403
404
|
|
package/src/simple/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { CanceledCallError } from '../web-rtc-client';
|
|
|
15
15
|
|
|
16
16
|
import BadResponse from '../domain/BadResponse';
|
|
17
17
|
import ServerError from '../domain/ServerError';
|
|
18
|
+
import SFUNotAvailableError from '../domain/SFUNotAvailableError';
|
|
18
19
|
import Call from '../domain/Call';
|
|
19
20
|
import CallLog from '../domain/CallLog';
|
|
20
21
|
import Recording from '../domain/Recording';
|
|
@@ -101,6 +102,7 @@ const Wazo = {
|
|
|
101
102
|
InvalidSubscription,
|
|
102
103
|
InvalidAuthorization,
|
|
103
104
|
CanceledCallError,
|
|
105
|
+
SFUNotAvailableError,
|
|
104
106
|
};
|
|
105
107
|
|
|
106
108
|
if (window) {
|
|
@@ -25,7 +25,7 @@ const logger = IssueReporter ? IssueReporter.loggerFor('api') : console;
|
|
|
25
25
|
|
|
26
26
|
// Use a function here to be able to mock it in tests
|
|
27
27
|
export const realFetch = () => {
|
|
28
|
-
if (typeof document !== 'undefined') {
|
|
28
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
29
29
|
// Browser
|
|
30
30
|
return window.fetch;
|
|
31
31
|
}
|
package/src/web-rtc-client.js
CHANGED
|
@@ -453,7 +453,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
call(number: string, enableVideo?: boolean, audioOnly: boolean = false, conference: boolean = false): Session {
|
|
456
|
-
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
456
|
+
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
457
457
|
const inviterOptions: Object = {
|
|
458
458
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
459
459
|
conference,
|
|
@@ -1529,6 +1529,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
1529
1529
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
1530
1530
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
1531
1531
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
1532
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
1532
1533
|
|
|
1533
1534
|
logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
1534
1535
|
|
|
@@ -1536,7 +1537,8 @@ export default class WebRTCClient extends Emitter {
|
|
|
1536
1537
|
constraints: {
|
|
1537
1538
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
1538
1539
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
1539
|
-
video: screenSharing ? (isDesktop
|
|
1540
|
+
video: screenSharing ? (isDesktop
|
|
1541
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
1540
1542
|
: this._getVideoConstraints(enableVideo),
|
|
1541
1543
|
screen: screenSharing,
|
|
1542
1544
|
desktop: isDesktop,
|
|
@@ -1871,12 +1873,14 @@ export default class WebRTCClient extends Emitter {
|
|
|
1871
1873
|
|
|
1872
1874
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
1873
1875
|
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1876
|
+
if (pc) {
|
|
1877
|
+
pc.oniceconnectionstatechange = () => {
|
|
1878
|
+
logger.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
1879
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
1880
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1880
1884
|
|
|
1881
1885
|
if (withEvent) {
|
|
1882
1886
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -2086,13 +2090,17 @@ export default class WebRTCClient extends Emitter {
|
|
|
2086
2090
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
2087
2091
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
2088
2092
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
2093
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
2089
2094
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
2090
2095
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
2096
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
2091
2097
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
2092
2098
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
2093
2099
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
2094
|
-
let audioBytesSent = 0;
|
|
2095
|
-
let audioBytesReceived = 0;
|
|
2100
|
+
let audioBytesSent = 0; // content + header
|
|
2101
|
+
let audioBytesReceived = 0; // content + header
|
|
2102
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
2103
|
+
let audioContentReceived = 0;
|
|
2096
2104
|
let videoBytesSent = 0;
|
|
2097
2105
|
let videoBytesReceived = 0;
|
|
2098
2106
|
let transportSent = 0;
|
|
@@ -2102,6 +2110,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
2102
2110
|
stats.forEach(report => {
|
|
2103
2111
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
2104
2112
|
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
2113
|
+
audioContentSent += Number(report.bytesSent);
|
|
2105
2114
|
}
|
|
2106
2115
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
2107
2116
|
audioBytesSent += Number(report.bytesSent);
|
|
@@ -2113,6 +2122,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
2113
2122
|
packetsLost += Number(report.packetsLost);
|
|
2114
2123
|
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
2115
2124
|
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
2125
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
2116
2126
|
}
|
|
2117
2127
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
2118
2128
|
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
@@ -2141,10 +2151,17 @@ export default class WebRTCClient extends Emitter {
|
|
|
2141
2151
|
});
|
|
2142
2152
|
|
|
2143
2153
|
networkStats.packetsLost = packetsLost;
|
|
2154
|
+
|
|
2144
2155
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
2145
2156
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
2146
2157
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
2147
2158
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
2159
|
+
|
|
2160
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
2161
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
2162
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
2163
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
2164
|
+
|
|
2148
2165
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
2149
2166
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
2150
2167
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|