@babblevoice/babble-drachtio-callmanager 2.1.1 → 2.2.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/index.js +2 -1
- package/lib/call.js +42 -17
- package/package.json +1 -1
- package/test/interface/sdp.js +57 -2
package/index.js
CHANGED
|
@@ -12,7 +12,8 @@ const default_options = {
|
|
|
12
12
|
"rfc2833": true, /* Enable RFC 2833 - DTMF */
|
|
13
13
|
"late": false, /* Late negotiation */
|
|
14
14
|
"registrar": false, /* our registrar object or falsey */
|
|
15
|
-
"referauthrequired": true
|
|
15
|
+
"referauthrequired": true,
|
|
16
|
+
"ignoreipv6candidates": true /* ipv6 does not work in projectrtp */
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/**
|
package/lib/call.js
CHANGED
|
@@ -11,6 +11,8 @@ const callstore = require( "./store.js" )
|
|
|
11
11
|
|
|
12
12
|
const sipauth = require( "@babblevoice/babble-drachtio-auth" )
|
|
13
13
|
|
|
14
|
+
const ipv6regex = /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm
|
|
15
|
+
|
|
14
16
|
/*
|
|
15
17
|
Enum for different reasons for hangup.
|
|
16
18
|
*/
|
|
@@ -910,8 +912,15 @@ class call {
|
|
|
910
912
|
static async _parsesdpcandidates( target, sdp ) {
|
|
911
913
|
|
|
912
914
|
if( Array.isArray( sdp.media[ 0 ].candidates ) ) {
|
|
913
|
-
|
|
915
|
+
let candidates = sdp.media[ 0 ].candidates
|
|
914
916
|
if( 0 < candidates.length ) {
|
|
917
|
+
if( callmanager.options.ignoreipv6candidates ) {
|
|
918
|
+
candidates = candidates.filter( ( c ) => {
|
|
919
|
+
const ismatch = ipv6regex.test( c.ip )
|
|
920
|
+
return !ismatch
|
|
921
|
+
} )
|
|
922
|
+
}
|
|
923
|
+
|
|
915
924
|
candidates.sort( ( l, r ) => { return r.priority - l.priority } )
|
|
916
925
|
target.port = candidates[ 0 ].port
|
|
917
926
|
|
|
@@ -1037,10 +1046,8 @@ class call {
|
|
|
1037
1046
|
} else {
|
|
1038
1047
|
channeldef = call._createchannelremotedef( target.address, target.port, target.audio.payloads[ 0 ] )
|
|
1039
1048
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
if( other && other.channels.audio ) this.channels.audio = await other.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
|
|
1043
|
-
else this.channels.audio = await projectrtp.openchannel( channeldef, this._handlechannelevents.bind( this ) )
|
|
1049
|
+
|
|
1050
|
+
await this.#openrelatedchannel()
|
|
1044
1051
|
|
|
1045
1052
|
this.sdp.local = sdpgen.create()
|
|
1046
1053
|
.addcodecs( this.selectedcodec )
|
|
@@ -1069,7 +1076,7 @@ class call {
|
|
|
1069
1076
|
|
|
1070
1077
|
/**
|
|
1071
1078
|
Sometimes we don't care who if we are the parent or child - we just want the other party
|
|
1072
|
-
@return {object|bool} returns call object or if none false
|
|
1079
|
+
@return { object|bool } returns call object or if none false
|
|
1073
1080
|
*/
|
|
1074
1081
|
get other() {
|
|
1075
1082
|
if( this.parent ) return this.parent
|
|
@@ -1347,23 +1354,25 @@ class call {
|
|
|
1347
1354
|
*/
|
|
1348
1355
|
async #openchannelsforanswer( channeldef ) {
|
|
1349
1356
|
if( this.channels.audio ) {
|
|
1357
|
+
/* we have already opened a channel (probably early now answering) */
|
|
1350
1358
|
this.channels.audio.remote( channeldef.remote )
|
|
1351
1359
|
} else {
|
|
1352
|
-
|
|
1353
|
-
this
|
|
1360
|
+
|
|
1361
|
+
await this.#openrelatedchannel( channeldef )
|
|
1362
|
+
|
|
1354
1363
|
this.sdp.local = sdpgen.create()
|
|
1355
1364
|
.addcodecs( this.selectedcodec )
|
|
1356
|
-
.setconnectionaddress(
|
|
1357
|
-
.setaudioport(
|
|
1365
|
+
.setconnectionaddress( this.channels.audio.local.address )
|
|
1366
|
+
.setaudioport( this.channels.audio.local.port )
|
|
1358
1367
|
|
|
1359
1368
|
if( this.options.rfc2833 ) {
|
|
1360
1369
|
this.sdp.local.addcodecs( "2833" )
|
|
1361
1370
|
}
|
|
1362
1371
|
|
|
1363
1372
|
if( this._iswebrtc ) {
|
|
1364
|
-
this.sdp.local.addssrc(
|
|
1365
|
-
.secure(
|
|
1366
|
-
.addicecandidates(
|
|
1373
|
+
this.sdp.local.addssrc( this.channels.audio.local.ssrc )
|
|
1374
|
+
.secure( this.channels.audio.local.dtls.fingerprint, channeldef.remote.dtls.mode )
|
|
1375
|
+
.addicecandidates( this.channels.audio.local.address, this.channels.audio.local.port, this.channels.audio.local.icepwd )
|
|
1367
1376
|
.rtcpmux()
|
|
1368
1377
|
}
|
|
1369
1378
|
}
|
|
@@ -1379,13 +1388,13 @@ class call {
|
|
|
1379
1388
|
if( !this.selectedcodec ) {
|
|
1380
1389
|
return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
|
|
1381
1390
|
}
|
|
1391
|
+
|
|
1392
|
+
this.sdp.remote.select( this.selectedcodec )
|
|
1382
1393
|
|
|
1383
1394
|
const remoteaudio = this.sdp.remote.getaudio()
|
|
1384
1395
|
if( !remoteaudio ) {
|
|
1385
1396
|
return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
|
|
1386
1397
|
}
|
|
1387
|
-
|
|
1388
|
-
this.sdp.remote.select( this.selectedcodec )
|
|
1389
1398
|
|
|
1390
1399
|
await call._parsesdpcandidates( remoteaudio, this.sdp.remote.sdp )
|
|
1391
1400
|
|
|
@@ -2478,6 +2487,22 @@ class call {
|
|
|
2478
2487
|
return child
|
|
2479
2488
|
}
|
|
2480
2489
|
|
|
2490
|
+
/**
|
|
2491
|
+
* If any of our one of our related calls has a channel open
|
|
2492
|
+
* try and use it. NB (other favours the answered if not then the first)
|
|
2493
|
+
* It will use the channel on that call.
|
|
2494
|
+
* @param { object } [ channeldef ]
|
|
2495
|
+
*/
|
|
2496
|
+
async #openrelatedchannel( channeldef ) {
|
|
2497
|
+
|
|
2498
|
+
const relatedcall = this.other
|
|
2499
|
+
if( relatedcall && relatedcall.channels.audio )
|
|
2500
|
+
this.channels.audio = await relatedcall.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
|
|
2501
|
+
else
|
|
2502
|
+
this.channels.audio = await projectrtp.openchannel( channeldef, this._handlechannelevents.bind( this ) )
|
|
2503
|
+
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2481
2506
|
/**
|
|
2482
2507
|
*
|
|
2483
2508
|
*/
|
|
@@ -2485,8 +2510,8 @@ class call {
|
|
|
2485
2510
|
if( this.options.late ) {
|
|
2486
2511
|
this.options.noAck = true /* this is a MUST for late negotiation */
|
|
2487
2512
|
} else {
|
|
2488
|
-
|
|
2489
|
-
|
|
2513
|
+
|
|
2514
|
+
await this.#openrelatedchannel()
|
|
2490
2515
|
|
|
2491
2516
|
this.sdp.local = sdpgen.create().addcodecs( this.options.preferedcodecs )
|
|
2492
2517
|
this.sdp.local.setaudioport( this.channels.audio.local.port )
|
package/package.json
CHANGED
package/test/interface/sdp.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
const expect = require( "chai" ).expect
|
|
4
|
-
const sdp = require( "../../lib/sdp
|
|
5
|
-
const call = require( "../../lib/call
|
|
4
|
+
const sdp = require( "../../lib/sdp" )
|
|
5
|
+
const call = require( "../../lib/call" )
|
|
6
|
+
const callmanager = require( "../../index" )
|
|
6
7
|
|
|
7
8
|
describe( "sdp", function() {
|
|
8
9
|
|
|
@@ -643,4 +644,58 @@ a=rtcp-mux`
|
|
|
643
644
|
expect( bvdesktopinvite200sdpobj.intersection( ourcodecs, true ) ).to.equal( "g722" )
|
|
644
645
|
expect( magrathea200sdpobj.intersection( ourcodecs, true ) ).to.equal( "pcma" )
|
|
645
646
|
} )
|
|
647
|
+
|
|
648
|
+
it( "outbound example - inc ipv6", async () => {
|
|
649
|
+
|
|
650
|
+
const sdpstr = `v=0
|
|
651
|
+
o=- 7873703533563891424 2 IN IP4 127.0.0.1
|
|
652
|
+
s=-
|
|
653
|
+
t=0 0
|
|
654
|
+
a=group:BUNDLE 0
|
|
655
|
+
a=extmap-allow-mixed
|
|
656
|
+
a=msid-semantic: WMS a46039f4-1857-410e-b1cc-215c09878068
|
|
657
|
+
m=audio 41645 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
|
|
658
|
+
c=IN IP4 86.169.150.38
|
|
659
|
+
a=rtcp:9 IN IP4 0.0.0.0
|
|
660
|
+
a=candidate:532873972 1 udp 2122131711 2a00:23c6:e093:a801:6722:f7bb:aeeb:5e04 39087 typ host generation 0 network-id 4 network-cost 10
|
|
661
|
+
a=candidate:226183667 1 udp 1685987071 86.169.150.38 41645 typ srflx raddr 172.17.0.1 rport 41645 generation 0 network-id 2
|
|
662
|
+
a=ice-ufrag:c97P
|
|
663
|
+
a=ice-pwd:sK0NGVPIIx4/qEX+tCVW5dzH
|
|
664
|
+
a=ice-options:trickle
|
|
665
|
+
a=fingerprint:sha-256 0F:37:28:0F:66:1B:7E:D5:36:A4:EB:2D:D4:A8:6E:33:69:31:3B:D4:7B:71:0B:DE:41:09:D1:6C:1E:56:02:1C
|
|
666
|
+
a=setup:actpass
|
|
667
|
+
a=mid:0
|
|
668
|
+
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
|
|
669
|
+
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
670
|
+
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
|
|
671
|
+
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
|
|
672
|
+
a=sendrecv
|
|
673
|
+
a=msid:a46039f4-1857-410e-b1cc-215c09878068 ce8c9c25-2ea0-4079-aaa5-54f771d53310
|
|
674
|
+
a=rtcp-mux
|
|
675
|
+
a=rtpmap:111 opus/48000/2
|
|
676
|
+
a=rtcp-fb:111 transport-cc
|
|
677
|
+
a=fmtp:111 minptime=10;useinbandfec=1
|
|
678
|
+
a=rtpmap:63 red/48000/2
|
|
679
|
+
a=fmtp:63 111/111
|
|
680
|
+
a=rtpmap:9 G722/8000
|
|
681
|
+
a=rtpmap:0 PCMU/8000
|
|
682
|
+
a=rtpmap:8 PCMA/8000
|
|
683
|
+
a=rtpmap:13 CN/8000
|
|
684
|
+
a=rtpmap:110 telephone-event/48000
|
|
685
|
+
a=rtpmap:126 telephone-event/8000
|
|
686
|
+
a=ssrc:222390620 cname:q7Is0hRbTrTbcMJM
|
|
687
|
+
a=ssrc:222390620 msid:a46039f4-1857-410e-b1cc-215c09878068 ce8c9c25-2ea0-4079-aaa5-54f771d53310
|
|
688
|
+
`
|
|
689
|
+
callmanager.callmanager( { srf: { use: () => {} } } )
|
|
690
|
+
const sdpobj = sdp.create( sdpstr )
|
|
691
|
+
const target = {}
|
|
692
|
+
await call._parsesdpcandidates( target, sdpobj.sdp )
|
|
693
|
+
sdpobj.intersection( "g722", true )
|
|
694
|
+
|
|
695
|
+
/* our default is to ignore IPv6 addresses (until projectrtp supports it) */
|
|
696
|
+
expect( target.port ).to.equal( 41645 )
|
|
697
|
+
expect( target.address ).to.equal( "86.169.150.38" )
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
} )
|
|
646
701
|
} )
|