@wazo/sdk 0.38.4 → 0.38.7
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 +4 -4
- package/dist/wazo-sdk.js +2 -2
- package/esm/__tests__/api-client.test.js +6 -0
- package/esm/__tests__/web-rtc-client.test.js +88 -3
- package/esm/api/calld.js +6 -0
- package/esm/api/ctid-ng.js +6 -0
- package/esm/api-client.js +6 -0
- package/esm/checker/Checker.js +38 -3
- package/esm/checker/checks/aor.js +6 -0
- package/esm/checker/checks/api.js +6 -0
- package/esm/checker/checks/index.js +38 -3
- package/esm/checker/checks/webrtc-transport.js +38 -3
- package/esm/checker/checks/webrtc.js +38 -3
- package/esm/domain/AdHocAPIConference.js +6 -0
- package/esm/domain/Call.js +6 -0
- package/esm/domain/CallSession.js +1 -1
- package/esm/domain/Features.js +6 -0
- package/esm/domain/Phone/CTIPhone.js +7 -1
- package/esm/domain/Phone/WebRTCPhone.js +3 -3
- package/esm/domain/__tests__/Call.test.js +6 -0
- package/esm/domain/__tests__/CallSession.test.js +1 -1
- package/esm/domain/__tests__/IndirectTransfer.test.js +1 -1
- package/esm/domain/__tests__/Line.test.js +5 -5
- package/esm/domain/__tests__/Room.test.js +1 -1
- package/esm/index.js +42 -8
- package/esm/lib/WazoSessionDescriptionHandler.js +30 -1
- package/esm/service/CallApi.js +6 -0
- package/esm/service/getApiClient.js +6 -0
- package/esm/simple/Auth.js +42 -8
- package/esm/simple/Configuration.js +42 -8
- package/esm/simple/Directory.js +6 -0
- package/esm/simple/Phone.js +42 -8
- package/esm/simple/Softphone.js +1 -2
- package/esm/simple/index.js +42 -8
- package/esm/simple/room/LocalParticipant.js +42 -8
- package/esm/simple/room/Participant.js +42 -8
- package/esm/simple/room/RemoteParticipant.js +42 -8
- package/esm/simple/room/Room.js +42 -8
- package/esm/simple/room/SipRoom.js +42 -8
- package/esm/simple/room/Stream.js +42 -8
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +42 -8
- package/esm/simple/utils.js +42 -8
- package/esm/utils/__tests__/sdp.test.js +50 -0
- package/esm/utils/sdp.js +19 -1
- package/esm/web-rtc-client.js +38 -3
- package/lib/__tests__/api-client.test.js +6 -0
- package/lib/__tests__/web-rtc-client.test.js +88 -3
- package/lib/api/calld.js +6 -0
- package/lib/api/ctid-ng.js +6 -0
- package/lib/api-client.js +6 -0
- package/lib/checker/Checker.js +38 -3
- package/lib/checker/checks/aor.js +6 -0
- package/lib/checker/checks/api.js +6 -0
- package/lib/checker/checks/index.js +38 -3
- package/lib/checker/checks/webrtc-transport.js +38 -3
- package/lib/checker/checks/webrtc.js +38 -3
- package/lib/domain/AdHocAPIConference.js +6 -0
- package/lib/domain/Call.js +6 -0
- package/lib/domain/CallSession.js +1 -1
- package/lib/domain/Features.js +6 -0
- package/lib/domain/Phone/CTIPhone.js +7 -1
- package/lib/domain/Phone/WebRTCPhone.js +3 -3
- package/lib/domain/__tests__/Call.test.js +6 -0
- package/lib/domain/__tests__/CallSession.test.js +1 -1
- package/lib/domain/__tests__/IndirectTransfer.test.js +1 -1
- package/lib/domain/__tests__/Line.test.js +5 -5
- package/lib/domain/__tests__/Room.test.js +1 -1
- package/lib/index.js +42 -8
- package/lib/lib/WazoSessionDescriptionHandler.js +30 -1
- package/lib/service/CallApi.js +6 -0
- package/lib/service/getApiClient.js +6 -0
- package/lib/simple/Auth.js +42 -8
- package/lib/simple/Configuration.js +42 -8
- package/lib/simple/Directory.js +6 -0
- package/lib/simple/Phone.js +42 -8
- package/lib/simple/Softphone.js +1 -2
- package/lib/simple/index.js +42 -8
- package/lib/simple/room/LocalParticipant.js +42 -8
- package/lib/simple/room/Participant.js +42 -8
- package/lib/simple/room/RemoteParticipant.js +42 -8
- package/lib/simple/room/Room.js +42 -8
- package/lib/simple/room/SipRoom.js +42 -8
- package/lib/simple/room/Stream.js +42 -8
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +42 -8
- package/lib/simple/utils.js +42 -8
- package/lib/utils/__tests__/sdp.test.js +50 -0
- package/lib/utils/sdp.js +19 -0
- package/lib/web-rtc-client.js +38 -3
- package/package.json +1 -1
- package/src/__tests__/web-rtc-client.test.js +50 -0
- package/src/domain/Call.js +6 -0
- package/src/domain/CallSession.js +1 -1
- package/src/domain/Phone/WebRTCPhone.js +2 -2
- package/src/domain/__tests__/Line.test.js +5 -5
- package/src/lib/WazoSessionDescriptionHandler.js +13 -2
- package/src/simple/Softphone.js +1 -2
- package/src/utils/__tests__/sdp.test.js +33 -1
- package/src/utils/sdp.js +18 -0
- package/src/web-rtc-client.js +2 -2
package/lib/web-rtc-client.js
CHANGED
|
@@ -789,6 +789,24 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
789
789
|
return fixed;
|
|
790
790
|
};
|
|
791
791
|
|
|
792
|
+
const addIcesInAllBundles = (sdp ) => {
|
|
793
|
+
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
794
|
+
|
|
795
|
+
const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
|
|
796
|
+
if (!mediaWithCandidate) {
|
|
797
|
+
return sdp;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const { candidates } = mediaWithCandidate;
|
|
801
|
+
|
|
802
|
+
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
803
|
+
...media,
|
|
804
|
+
candidates: media.candidates || candidates,
|
|
805
|
+
}));
|
|
806
|
+
|
|
807
|
+
return sdpParser__default['default'].write(parsedSdp);
|
|
808
|
+
};
|
|
809
|
+
|
|
792
810
|
/* global RTCSessionDescriptionInit, navigator */
|
|
793
811
|
|
|
794
812
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
@@ -887,6 +905,14 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
887
905
|
wazoLogger.trace('onicecandidate', event.candidate ? event.candidate.candidate : { done: true });
|
|
888
906
|
if (event.candidate) {
|
|
889
907
|
this.gatheredCandidates.push(parseCandidate(event.candidate.candidate));
|
|
908
|
+
|
|
909
|
+
// When receiving a `srflx` or a `relay` candidate, consider the negotiation done.
|
|
910
|
+
if (event.candidate.candidate.indexOf('srflx') !== -1 || event.candidate.candidate.indexOf('relay') !== -1) {
|
|
911
|
+
wazoLogger.info('A valid ice was found, triggering ice gathering complete callback.', {
|
|
912
|
+
ice: event.candidate.candidate,
|
|
913
|
+
});
|
|
914
|
+
this.iceGatheringComplete();
|
|
915
|
+
}
|
|
890
916
|
}
|
|
891
917
|
};
|
|
892
918
|
|
|
@@ -910,7 +936,10 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
910
936
|
|
|
911
937
|
// Check if we got ICEs
|
|
912
938
|
if (sdp.indexOf('a=candidate') !== -1) {
|
|
913
|
-
return
|
|
939
|
+
return {
|
|
940
|
+
type: description.type,
|
|
941
|
+
sdp: addIcesInAllBundles(sdp),
|
|
942
|
+
};
|
|
914
943
|
}
|
|
915
944
|
|
|
916
945
|
wazoLogger.info('No ICE candidates found in SDP, fixing it with gathered ices', this.gatheredCandidates);
|
|
@@ -3610,6 +3639,7 @@ const RECORD_STATE_ACTIVE = 'active';
|
|
|
3610
3639
|
|
|
3611
3640
|
|
|
3612
3641
|
|
|
3642
|
+
|
|
3613
3643
|
|
|
3614
3644
|
|
|
3615
3645
|
|
|
@@ -3620,6 +3650,7 @@ const RECORD_STATE_ACTIVE = 'active';
|
|
|
3620
3650
|
|
|
3621
3651
|
|
|
3622
3652
|
|
|
3653
|
+
|
|
3623
3654
|
|
|
3624
3655
|
|
|
3625
3656
|
|
|
@@ -3648,6 +3679,7 @@ class Call {
|
|
|
3648
3679
|
|
|
3649
3680
|
|
|
3650
3681
|
|
|
3682
|
+
|
|
3651
3683
|
|
|
3652
3684
|
|
|
3653
3685
|
|
|
@@ -3672,6 +3704,7 @@ class Call {
|
|
|
3672
3704
|
calleeNumber: plain.peer_caller_id_number,
|
|
3673
3705
|
dialedExtension: plain.dialed_extension,
|
|
3674
3706
|
isCaller: plain.is_caller,
|
|
3707
|
+
isVideo: plain.is_video,
|
|
3675
3708
|
muted: plain.muted,
|
|
3676
3709
|
onHold: plain.on_hold,
|
|
3677
3710
|
status: plain.status,
|
|
@@ -3695,6 +3728,7 @@ class Call {
|
|
|
3695
3728
|
calleeNumber,
|
|
3696
3729
|
dialedExtension,
|
|
3697
3730
|
isCaller,
|
|
3731
|
+
isVideo,
|
|
3698
3732
|
lineId,
|
|
3699
3733
|
muted,
|
|
3700
3734
|
onHold,
|
|
@@ -3718,6 +3752,7 @@ class Call {
|
|
|
3718
3752
|
this.startingTime = startingTime;
|
|
3719
3753
|
this.talkingToIds = talkingToIds || [];
|
|
3720
3754
|
this.recording = recording;
|
|
3755
|
+
this.isVideo = !!isVideo;
|
|
3721
3756
|
|
|
3722
3757
|
// Useful to compare instead of instanceof with minified code
|
|
3723
3758
|
this.type = 'Call';
|
|
@@ -6420,11 +6455,11 @@ class WebRTCClient extends Emitter {
|
|
|
6420
6455
|
});
|
|
6421
6456
|
}
|
|
6422
6457
|
|
|
6423
|
-
changeAudioInputDevice(id , session ) {
|
|
6458
|
+
changeAudioInputDevice(id , session , force ) {
|
|
6424
6459
|
const currentId = this.getAudioDeviceId();
|
|
6425
6460
|
logger.info('setting audio input device', { id, currentId, session: !!session });
|
|
6426
6461
|
|
|
6427
|
-
if (id === currentId) {
|
|
6462
|
+
if (!force && id === currentId) {
|
|
6428
6463
|
return null;
|
|
6429
6464
|
}
|
|
6430
6465
|
|
package/package.json
CHANGED
|
@@ -43,3 +43,53 @@ describe('WebRTC client', () => {
|
|
|
43
43
|
expect(client.isAudioMuted(oldKindUnmuted)).toBeFalsy();
|
|
44
44
|
});
|
|
45
45
|
});
|
|
46
|
+
|
|
47
|
+
describe('changeAudioInputDevice', () => {
|
|
48
|
+
const defaultId = 'default';
|
|
49
|
+
const deviceId = 'device1';
|
|
50
|
+
const constraints = { audio: { deviceId: { exact: defaultId } }, video: null };
|
|
51
|
+
|
|
52
|
+
const session = {
|
|
53
|
+
sessionDescriptionHandler: {
|
|
54
|
+
peerConnection: {
|
|
55
|
+
getSenders: () => [{ track: { kind: 'audio', enabled: true } }],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const stream = {};
|
|
61
|
+
const getAudioTracksMock = jest.fn(() => []);
|
|
62
|
+
Object.defineProperty(stream, 'getAudioTracks', {
|
|
63
|
+
value: getAudioTracksMock,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const getUserMediaMock = jest.fn(async () => {
|
|
67
|
+
return new Promise(resolve => {
|
|
68
|
+
resolve(stream);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
Object.defineProperty(global.navigator, 'mediaDevices', {
|
|
73
|
+
value: {
|
|
74
|
+
getUserMedia: getUserMediaMock,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should change the audio input track if the provided id is different', async () => {
|
|
79
|
+
client.setMediaConstraints(constraints);
|
|
80
|
+
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
81
|
+
expect(client.changeAudioInputDevice(deviceId, session)).toBeTruthy();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should NOT change the audio input track if the provided id is the same', async () => {
|
|
85
|
+
client.setMediaConstraints(constraints);
|
|
86
|
+
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
87
|
+
expect(client.changeAudioInputDevice(defaultId, session)).toBeFalsy();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should change the audio input track if the provided id is the same and force param is TRUE', async () => {
|
|
91
|
+
client.setMediaConstraints(constraints);
|
|
92
|
+
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
93
|
+
expect(client.changeAudioInputDevice(defaultId, session, true)).toBeTruthy();
|
|
94
|
+
});
|
|
95
|
+
});
|
package/src/domain/Call.js
CHANGED
|
@@ -15,6 +15,7 @@ type CallResponse = {
|
|
|
15
15
|
dialed_extension: string,
|
|
16
16
|
status: string,
|
|
17
17
|
is_caller: boolean,
|
|
18
|
+
is_video?: boolean,
|
|
18
19
|
line_id: ?number,
|
|
19
20
|
creation_time: string,
|
|
20
21
|
on_hold: boolean,
|
|
@@ -27,6 +28,7 @@ type CallArguments = {
|
|
|
27
28
|
id: string,
|
|
28
29
|
sipCallId: string,
|
|
29
30
|
isCaller: boolean,
|
|
31
|
+
isVideo?: boolean,
|
|
30
32
|
callerName: string,
|
|
31
33
|
callerNumber: string,
|
|
32
34
|
calleeName: string,
|
|
@@ -53,6 +55,7 @@ export default class Call {
|
|
|
53
55
|
dialedExtension: string;
|
|
54
56
|
lineId: ?number;
|
|
55
57
|
isCaller: boolean;
|
|
58
|
+
isVideo: boolean;
|
|
56
59
|
onHold: boolean;
|
|
57
60
|
muted: boolean;
|
|
58
61
|
status: string;
|
|
@@ -77,6 +80,7 @@ export default class Call {
|
|
|
77
80
|
calleeNumber: plain.peer_caller_id_number,
|
|
78
81
|
dialedExtension: plain.dialed_extension,
|
|
79
82
|
isCaller: plain.is_caller,
|
|
83
|
+
isVideo: plain.is_video,
|
|
80
84
|
muted: plain.muted,
|
|
81
85
|
onHold: plain.on_hold,
|
|
82
86
|
status: plain.status,
|
|
@@ -100,6 +104,7 @@ export default class Call {
|
|
|
100
104
|
calleeNumber,
|
|
101
105
|
dialedExtension,
|
|
102
106
|
isCaller,
|
|
107
|
+
isVideo,
|
|
103
108
|
lineId,
|
|
104
109
|
muted,
|
|
105
110
|
onHold,
|
|
@@ -123,6 +128,7 @@ export default class Call {
|
|
|
123
128
|
this.startingTime = startingTime;
|
|
124
129
|
this.talkingToIds = talkingToIds || [];
|
|
125
130
|
this.recording = recording;
|
|
131
|
+
this.isVideo = !!isVideo;
|
|
126
132
|
|
|
127
133
|
// Useful to compare instead of instanceof with minified code
|
|
128
134
|
this.type = 'Call';
|
|
@@ -390,7 +390,7 @@ export default class CallSession {
|
|
|
390
390
|
ringing: call.isRinging(),
|
|
391
391
|
answered: call.isUp(),
|
|
392
392
|
answeredBySystem: call.isUp() && call.talkingToIds.length === 0,
|
|
393
|
-
cameraEnabled:
|
|
393
|
+
cameraEnabled: call.isVideo,
|
|
394
394
|
dialedExtension: call.dialedExtension,
|
|
395
395
|
call,
|
|
396
396
|
conference: false, // @FIXME?
|
|
@@ -668,10 +668,10 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
668
668
|
this.audioRingVolume = volume;
|
|
669
669
|
}
|
|
670
670
|
|
|
671
|
-
changeAudioInputDevice(id: string) {
|
|
671
|
+
changeAudioInputDevice(id: string, force: ?boolean) {
|
|
672
672
|
logger.info('WebRTC phone - changeAudio input device', { deviceId: id });
|
|
673
673
|
|
|
674
|
-
return this.client.changeAudioInputDevice(id, this.currentSipSession);
|
|
674
|
+
return this.client.changeAudioInputDevice(id, this.currentSipSession, force);
|
|
675
675
|
}
|
|
676
676
|
|
|
677
677
|
changeVideoInputDevice(id: ?string) {
|
|
@@ -11,7 +11,7 @@ describe('Line domain', () => {
|
|
|
11
11
|
username: 'ipcor1pj',
|
|
12
12
|
links: [
|
|
13
13
|
{
|
|
14
|
-
href: 'https://stack.
|
|
14
|
+
href: 'https://stack.example.com/api/confd/1.1/endpoints/sip/19',
|
|
15
15
|
rel: 'endpoint_sip',
|
|
16
16
|
},
|
|
17
17
|
],
|
|
@@ -25,7 +25,7 @@ describe('Line domain', () => {
|
|
|
25
25
|
context: 'default',
|
|
26
26
|
links: [
|
|
27
27
|
{
|
|
28
|
-
href: 'https://stack.
|
|
28
|
+
href: 'https://stack.example.com/api/confd/1.1/extensions/59',
|
|
29
29
|
rel: 'extensions',
|
|
30
30
|
},
|
|
31
31
|
],
|
|
@@ -33,7 +33,7 @@ describe('Line domain', () => {
|
|
|
33
33
|
],
|
|
34
34
|
links: [
|
|
35
35
|
{
|
|
36
|
-
href: 'https://stack.
|
|
36
|
+
href: 'https://stack.example.com/api/confd/1.1/lines/8',
|
|
37
37
|
rel: 'lines',
|
|
38
38
|
},
|
|
39
39
|
],
|
|
@@ -51,7 +51,7 @@ describe('Line domain', () => {
|
|
|
51
51
|
context: 'default',
|
|
52
52
|
links: [
|
|
53
53
|
{
|
|
54
|
-
href: 'https://stack.
|
|
54
|
+
href: 'https://stack.example.com/api/confd/1.1/extensions/59',
|
|
55
55
|
rel: 'extensions',
|
|
56
56
|
},
|
|
57
57
|
],
|
|
@@ -61,7 +61,7 @@ describe('Line domain', () => {
|
|
|
61
61
|
id: 19,
|
|
62
62
|
links: [
|
|
63
63
|
{
|
|
64
|
-
href: 'https://stack.
|
|
64
|
+
href: 'https://stack.example.com/api/confd/1.1/endpoints/sip/19',
|
|
65
65
|
rel: 'endpoint_sip',
|
|
66
66
|
},
|
|
67
67
|
],
|
|
@@ -12,7 +12,7 @@ import { SessionDescriptionHandler }
|
|
|
12
12
|
import { SessionDescriptionHandlerOptions }
|
|
13
13
|
from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-options';
|
|
14
14
|
import IssueReporter from '../service/IssueReporter';
|
|
15
|
-
import { fixSdp, parseCandidate } from '../utils/sdp';
|
|
15
|
+
import { addIcesInAllBundles, fixSdp, parseCandidate } from '../utils/sdp';
|
|
16
16
|
|
|
17
17
|
const wazoLogger = IssueReporter ? IssueReporter.loggerFor('webrtc-sdh') : console;
|
|
18
18
|
|
|
@@ -110,6 +110,14 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
110
110
|
wazoLogger.trace('onicecandidate', event.candidate ? event.candidate.candidate : { done: true });
|
|
111
111
|
if (event.candidate) {
|
|
112
112
|
this.gatheredCandidates.push(parseCandidate(event.candidate.candidate));
|
|
113
|
+
|
|
114
|
+
// When receiving a `srflx` or a `relay` candidate, consider the negotiation done.
|
|
115
|
+
if (event.candidate.candidate.indexOf('srflx') !== -1 || event.candidate.candidate.indexOf('relay') !== -1) {
|
|
116
|
+
wazoLogger.info('A valid ice was found, triggering ice gathering complete callback.', {
|
|
117
|
+
ice: event.candidate.candidate,
|
|
118
|
+
});
|
|
119
|
+
this.iceGatheringComplete();
|
|
120
|
+
}
|
|
113
121
|
}
|
|
114
122
|
};
|
|
115
123
|
|
|
@@ -133,7 +141,10 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
133
141
|
|
|
134
142
|
// Check if we got ICEs
|
|
135
143
|
if (sdp.indexOf('a=candidate') !== -1) {
|
|
136
|
-
return
|
|
144
|
+
return {
|
|
145
|
+
type: description.type,
|
|
146
|
+
sdp: addIcesInAllBundles(sdp),
|
|
147
|
+
};
|
|
137
148
|
}
|
|
138
149
|
|
|
139
150
|
wazoLogger.info('No ICE candidates found in SDP, fixing it with gathered ices', this.gatheredCandidates);
|
package/src/simple/Softphone.js
CHANGED
|
@@ -120,8 +120,7 @@ class Softphone {
|
|
|
120
120
|
window.addEventListener('message', this._onMessage.bind(this), false);
|
|
121
121
|
|
|
122
122
|
if (!server) {
|
|
123
|
-
|
|
124
|
-
server = 'stack.dev.wazo.io';
|
|
123
|
+
throw new Error('`server` is not set');
|
|
125
124
|
}
|
|
126
125
|
|
|
127
126
|
const config: Object = { server };
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
fixSdp,
|
|
10
10
|
fixBundle,
|
|
11
11
|
toggleVideoDirection,
|
|
12
|
-
hasAnActiveVideo,
|
|
12
|
+
hasAnActiveVideo, addIcesInAllBundles,
|
|
13
13
|
} from '../sdp';
|
|
14
14
|
|
|
15
15
|
const goodSdp = `
|
|
@@ -174,4 +174,36 @@ describe('SDP utils', () => {
|
|
|
174
174
|
expect(hasAnActiveVideo(inactiveVideo)).toBeFalsy();
|
|
175
175
|
});
|
|
176
176
|
});
|
|
177
|
+
|
|
178
|
+
describe('Adding candidate in all bundles ', () => {
|
|
179
|
+
it('should add candidate everywhere', async () => {
|
|
180
|
+
const audioWithoutCandidate = `
|
|
181
|
+
c=IN IP4 203.0.113.1
|
|
182
|
+
m=audio 54400 RTP/SAVPF 0 96
|
|
183
|
+
m=video 54400 RTP/SAVPF 0 96
|
|
184
|
+
a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
|
|
185
|
+
a=candidate:3996450952 1 udp 41819903 14.72.21.2 65092 typ relay raddr 0.0.0.0 rport 0 generation 0 network-id 3 network-cost 10
|
|
186
|
+
`;
|
|
187
|
+
const fixedAudioWithoutCandidate = sdpParser.parse(addIcesInAllBundles(audioWithoutCandidate));
|
|
188
|
+
|
|
189
|
+
expect(fixedAudioWithoutCandidate.media[0].candidates[0].type).toBe('host');
|
|
190
|
+
expect(fixedAudioWithoutCandidate.media[0].candidates[1].type).toBe('relay');
|
|
191
|
+
expect(fixedAudioWithoutCandidate.media[1].candidates[0].type).toBe('host');
|
|
192
|
+
expect(fixedAudioWithoutCandidate.media[1].candidates[1].type).toBe('relay');
|
|
193
|
+
|
|
194
|
+
// It should not add candidate if already present
|
|
195
|
+
const audioWithCandidate = `
|
|
196
|
+
c=IN IP4 203.0.113.1
|
|
197
|
+
m=audio 54400 RTP/SAVPF 0 96
|
|
198
|
+
a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ srflx
|
|
199
|
+
|
|
200
|
+
m=video 54400 RTP/SAVPF 0 96
|
|
201
|
+
a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
|
|
202
|
+
`;
|
|
203
|
+
const fixedAudioWithCandidate = sdpParser.parse(addIcesInAllBundles(audioWithCandidate));
|
|
204
|
+
|
|
205
|
+
expect(fixedAudioWithCandidate.media[0].candidates[0].type).toBe('srflx');
|
|
206
|
+
expect(fixedAudioWithCandidate.media[1].candidates[0].type).toBe('host');
|
|
207
|
+
});
|
|
208
|
+
});
|
|
177
209
|
});
|
package/src/utils/sdp.js
CHANGED
|
@@ -120,3 +120,21 @@ export const fixSdp = (sdp: string, candidates: Object[], forcePort: boolean = t
|
|
|
120
120
|
|
|
121
121
|
return fixed;
|
|
122
122
|
};
|
|
123
|
+
|
|
124
|
+
export const addIcesInAllBundles = (sdp: string) => {
|
|
125
|
+
const parsedSdp = sdpParser.parse(sdp);
|
|
126
|
+
|
|
127
|
+
const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
|
|
128
|
+
if (!mediaWithCandidate) {
|
|
129
|
+
return sdp;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const { candidates } = mediaWithCandidate;
|
|
133
|
+
|
|
134
|
+
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
135
|
+
...media,
|
|
136
|
+
candidates: media.candidates || candidates,
|
|
137
|
+
}));
|
|
138
|
+
|
|
139
|
+
return sdpParser.write(parsedSdp);
|
|
140
|
+
};
|
package/src/web-rtc-client.js
CHANGED
|
@@ -1070,11 +1070,11 @@ export default class WebRTCClient extends Emitter {
|
|
|
1070
1070
|
});
|
|
1071
1071
|
}
|
|
1072
1072
|
|
|
1073
|
-
changeAudioInputDevice(id: string, session: ?Inviter) {
|
|
1073
|
+
changeAudioInputDevice(id: string, session: ?Inviter, force: ?boolean) {
|
|
1074
1074
|
const currentId = this.getAudioDeviceId();
|
|
1075
1075
|
logger.info('setting audio input device', { id, currentId, session: !!session });
|
|
1076
1076
|
|
|
1077
|
-
if (id === currentId) {
|
|
1077
|
+
if (!force && id === currentId) {
|
|
1078
1078
|
return null;
|
|
1079
1079
|
}
|
|
1080
1080
|
|