@babblevoice/babble-drachtio-callmanager 3.3.2 → 3.3.3
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/jsconfig.json +2 -2
- package/lib/call.js +24 -11
- package/package.json +1 -1
- package/test/interface/call.js +14 -11
- package/test/interface/sdp.js +75 -0
package/jsconfig.json
CHANGED
package/lib/call.js
CHANGED
|
@@ -10,7 +10,7 @@ const callstore = require( "./store.js" )
|
|
|
10
10
|
|
|
11
11
|
const sipauth = require( "@babblevoice/babble-drachtio-auth" )
|
|
12
12
|
|
|
13
|
-
const ipv6regex = /^(?:
|
|
13
|
+
const ipv6regex = /^(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/
|
|
14
14
|
const parseurire = /^(sips?):(?:([^\s>:@]+)(?::([^\s@>]+))?@)?([\w\-.]+)(?::(\d+))?((?:;[^\s=?>;]+(?:=[^\s?;]+)?)*)(?:\?(([^\s&=>]+=[^\s&=>]+)(&[^\s&=>]+=[^\s&=>]+)*))?$/
|
|
15
15
|
const parseuriparamsre = /([^;=]+)(=([^;=]+))?/g
|
|
16
16
|
const parseuriheadersre = /[^&=]+=[^&=]+/g
|
|
@@ -554,9 +554,9 @@ class call {
|
|
|
554
554
|
#fromcontact( startingpoint ) {
|
|
555
555
|
const dest = parseuri( this.options.contact )
|
|
556
556
|
if( !dest ) return
|
|
557
|
-
startingpoint.uri = dest.uri
|
|
558
|
-
startingpoint.user = dest.user
|
|
559
|
-
startingpoint.host = dest.host
|
|
557
|
+
if( dest.uri ) startingpoint.uri = dest.uri
|
|
558
|
+
if( dest.user ) startingpoint.user = dest.user
|
|
559
|
+
if( dest.host ) startingpoint.host = dest.host
|
|
560
560
|
}
|
|
561
561
|
|
|
562
562
|
#fromdestination( startingpoint ) {
|
|
@@ -657,7 +657,6 @@ class call {
|
|
|
657
657
|
this.#calleridforuac( startingpoint )
|
|
658
658
|
} else {
|
|
659
659
|
const other = this.other
|
|
660
|
-
|
|
661
660
|
if( other ) {
|
|
662
661
|
if( "uas" == other.type ) {
|
|
663
662
|
other.#calleridforuas( startingpoint )
|
|
@@ -731,6 +730,9 @@ class call {
|
|
|
731
730
|
* @param { string } c
|
|
732
731
|
*/
|
|
733
732
|
set callerid( c ) {
|
|
733
|
+
|
|
734
|
+
if( undefined == c ) return
|
|
735
|
+
|
|
734
736
|
if( !this.options.callerid ) this.options.callerid = {}
|
|
735
737
|
if( !this.options.callerid.number ) this.options.callerid.number = ""
|
|
736
738
|
|
|
@@ -742,6 +744,8 @@ class call {
|
|
|
742
744
|
*/
|
|
743
745
|
set calleridname( c ) {
|
|
744
746
|
|
|
747
|
+
if( undefined == c ) return
|
|
748
|
+
|
|
745
749
|
if( !this.options.callerid ) this.options.callerid = {}
|
|
746
750
|
if( !this.options.callerid.name ) this.options.callerid.name = ""
|
|
747
751
|
|
|
@@ -2621,7 +2625,7 @@ class call {
|
|
|
2621
2625
|
}
|
|
2622
2626
|
this._state._onhangup = true
|
|
2623
2627
|
|
|
2624
|
-
/* hangup our children */
|
|
2628
|
+
/* hangup our children but, no other relations - i.e. children of our parent */
|
|
2625
2629
|
const hangups = []
|
|
2626
2630
|
for( const child of this.children ) {
|
|
2627
2631
|
hangups.push( child.hangup( this.hangup_cause ) )
|
|
@@ -2704,12 +2708,19 @@ class call {
|
|
|
2704
2708
|
* Send an UPDATE. Use to updated called id, caller id, sdp etc. Send in dialog - TODO look how to send
|
|
2705
2709
|
* early as this is recomended in the RFC.
|
|
2706
2710
|
*/
|
|
2707
|
-
async update() {
|
|
2711
|
+
async update( remote ) {
|
|
2708
2712
|
|
|
2709
2713
|
/* if we are asked to update it suggests we have received new information and overrides should go */
|
|
2710
2714
|
delete this.options.callerid
|
|
2711
2715
|
delete this.options.calledid
|
|
2712
2716
|
|
|
2717
|
+
if( remote ) {
|
|
2718
|
+
if( remote.callerid ) {
|
|
2719
|
+
this.callerid = remote.callerid.number
|
|
2720
|
+
this.calleridname = remote.callerid.name
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2713
2724
|
this._em.emit( "call.updated", this )
|
|
2714
2725
|
callmanager.options.em.emit( "call.updated", this )
|
|
2715
2726
|
|
|
@@ -2841,11 +2852,11 @@ class call {
|
|
|
2841
2852
|
if( callbacks.prebridge ) return callbacks.prebridge( c )
|
|
2842
2853
|
}
|
|
2843
2854
|
|
|
2844
|
-
ourcallbacks.confirm = ( c,
|
|
2855
|
+
ourcallbacks.confirm = ( /** @type { call } */ c, /** @type { any } */ cookie ) => {
|
|
2845
2856
|
if( false !== waitonchildrenresolve ) {
|
|
2846
2857
|
waitonchildrenresolve( c )
|
|
2847
2858
|
waitonchildrenresolve = false
|
|
2848
|
-
if( callbacks.confirm ) callbacks.confirm( c,
|
|
2859
|
+
if( callbacks.confirm ) callbacks.confirm( c, cookie )
|
|
2849
2860
|
}
|
|
2850
2861
|
}
|
|
2851
2862
|
|
|
@@ -2953,17 +2964,19 @@ class call {
|
|
|
2953
2964
|
return this
|
|
2954
2965
|
}
|
|
2955
2966
|
|
|
2967
|
+
const hangups = []
|
|
2956
2968
|
if( this.parent ) {
|
|
2957
2969
|
for( const child of this.parent.children ) {
|
|
2958
|
-
if( child
|
|
2970
|
+
if( child !== this ) {
|
|
2959
2971
|
child.detach()
|
|
2960
2972
|
/* do not await - we do not want to delay the winner in
|
|
2961
2973
|
connecting by waiting for the completion of the hangups */
|
|
2962
|
-
child.hangup( hangupcodes.LOSE_RACE )
|
|
2974
|
+
hangups.push( child.hangup( hangupcodes.LOSE_RACE ) )
|
|
2963
2975
|
}
|
|
2964
2976
|
}
|
|
2965
2977
|
}
|
|
2966
2978
|
|
|
2979
|
+
await Promise.all( hangups )
|
|
2967
2980
|
callstore.set( this )
|
|
2968
2981
|
|
|
2969
2982
|
if ( this._dialog.sip )
|
package/package.json
CHANGED
package/test/interface/call.js
CHANGED
|
@@ -237,6 +237,7 @@ describe( "call object", function() {
|
|
|
237
237
|
"type": "callerid"
|
|
238
238
|
} )
|
|
239
239
|
|
|
240
|
+
/* when newuacv returns, only one of the contacts should hacve succeeded */
|
|
240
241
|
const child = await call.newuac( { "entity": { "uri": "1000@dummy" } } )
|
|
241
242
|
|
|
242
243
|
expect( await callstore.stats() ).to.deep.include( {
|
|
@@ -257,7 +258,7 @@ describe( "call object", function() {
|
|
|
257
258
|
child.update()
|
|
258
259
|
|
|
259
260
|
expect( requestoptions.method ).to.equal( "UPDATE" )
|
|
260
|
-
expect( requestoptions.headers[ "
|
|
261
|
+
expect( requestoptions.headers[ "remote-party-id" ] ).to.equal( "\"\" <sip:0123456789@someotherrealm.com>;party=calling;screen=yes" )
|
|
261
262
|
|
|
262
263
|
await call.hangup()
|
|
263
264
|
|
|
@@ -404,8 +405,8 @@ describe( "call object", function() {
|
|
|
404
405
|
expect( children[ 0 ].hangup_cause.reason ).equal( "USER_BUSY" )
|
|
405
406
|
|
|
406
407
|
expect( await callstore.stats() ).to.deep.include( {
|
|
407
|
-
"storebycallid":
|
|
408
|
-
"storebyuuid":
|
|
408
|
+
"storebycallid": 2,
|
|
409
|
+
"storebyuuid": 2,
|
|
409
410
|
"storebyentity": 0
|
|
410
411
|
} )
|
|
411
412
|
|
|
@@ -446,6 +447,9 @@ describe( "call object", function() {
|
|
|
446
447
|
expect( children[ 0 ].hangup_cause.reason ).equal( "REQUEST_TIMEOUT" )
|
|
447
448
|
expect( children[ 0 ].hangup_cause.src ).equal( "us" )
|
|
448
449
|
|
|
450
|
+
/* when we get here the clean up is on teh event loop */
|
|
451
|
+
await new Promise( resolve => setTimeout( resolve, 100 ) )
|
|
452
|
+
|
|
449
453
|
expect( await callstore.stats() ).to.deep.include( {
|
|
450
454
|
"storebycallid": 1,
|
|
451
455
|
"storebyuuid": 1,
|
|
@@ -785,7 +789,7 @@ describe( "call object", function() {
|
|
|
785
789
|
|
|
786
790
|
await call.newuac( options, { "early": ( c ) => c.hangup() } )
|
|
787
791
|
|
|
788
|
-
expect( createuacoptions.headers[ "
|
|
792
|
+
expect( createuacoptions.headers[ "remote-party-id" ] ).to.equal( "\"\" <sip:0000000000@localhost.localdomain>;party=calling;screen=yes" )
|
|
789
793
|
expect( createuacoptions.late ).to.be.true
|
|
790
794
|
} )
|
|
791
795
|
|
|
@@ -836,17 +840,16 @@ describe( "call object", function() {
|
|
|
836
840
|
let requestoptions
|
|
837
841
|
c._dialog.on( "request", ( options ) => requestoptions = options )
|
|
838
842
|
|
|
839
|
-
await c.update( { "
|
|
840
|
-
"
|
|
841
|
-
"
|
|
842
|
-
"username": "kermy"
|
|
843
|
+
await c.update( { "callerid": {
|
|
844
|
+
"name": "Kermit",
|
|
845
|
+
"number": "kermy"
|
|
843
846
|
} } )
|
|
844
847
|
|
|
845
848
|
c.hangup()
|
|
846
849
|
|
|
847
850
|
expect( requestoptions.method ).to.equal( "UPDATE" )
|
|
848
851
|
expect( requestoptions.body ).to.be.a( "string" )
|
|
849
|
-
expect( requestoptions.headers[ "
|
|
852
|
+
expect( requestoptions.headers[ "remote-party-id" ] ).to.equal( "\"Kermit\" <sip:kermy@localhost.localdomain>;party=calling;screen=yes" )
|
|
850
853
|
|
|
851
854
|
} )
|
|
852
855
|
|
|
@@ -1148,7 +1151,7 @@ describe( "call object", function() {
|
|
|
1148
1151
|
const c = await call.newuac( options )
|
|
1149
1152
|
|
|
1150
1153
|
/* no default configured */
|
|
1151
|
-
expect( c.options.headers[ "
|
|
1154
|
+
expect( c.options.headers[ "remote-party-id" ] ).to.equal( "\"Hello\" <sip:0000000000@localhost.localdomain>;party=calling;screen=yes" )
|
|
1152
1155
|
|
|
1153
1156
|
c._onhangup( "wire" )
|
|
1154
1157
|
|
|
@@ -1169,7 +1172,7 @@ describe( "call object", function() {
|
|
|
1169
1172
|
|
|
1170
1173
|
|
|
1171
1174
|
/* no default configured */
|
|
1172
|
-
expect( c.options.headers[ "
|
|
1175
|
+
expect( c.options.headers[ "remote-party-id" ] ).to.equal( "\"\" <sip:012345789@localhost.localdomain>;party=calling;screen=yes" )
|
|
1173
1176
|
|
|
1174
1177
|
c._onhangup( "wire" )
|
|
1175
1178
|
|
package/test/interface/sdp.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
const expect = require( "chai" ).expect
|
|
4
4
|
const sdp = require( "../../lib/sdp" )
|
|
5
5
|
|
|
6
|
+
const dns = require( "node:dns" )
|
|
7
|
+
|
|
6
8
|
describe( "sdp", function() {
|
|
7
9
|
|
|
8
10
|
it( "create new sdp object", async function() {
|
|
@@ -927,4 +929,77 @@ a=rtpmap:127 telephone-event/8000
|
|
|
927
929
|
expect( outsdpstring ).include( outsdpstring, "a=rtpmap:110 ilbc/8000" )
|
|
928
930
|
|
|
929
931
|
} )
|
|
932
|
+
|
|
933
|
+
it( "SDP IP V6 candidate", async () => {
|
|
934
|
+
const wsssdp = `v=0
|
|
935
|
+
o=- 4684977919666729506 2 IN IP4 127.0.0.1
|
|
936
|
+
s=-
|
|
937
|
+
t=0 0
|
|
938
|
+
a=group:BUNDLE 0
|
|
939
|
+
a=extmap-allow-mixed
|
|
940
|
+
a=msid-semantic: WMS 2e008e23-265a-42a0-ba6f-d147a9d0ca42
|
|
941
|
+
m=audio 28022 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
|
|
942
|
+
c=IN IP4 209.35.84.57
|
|
943
|
+
a=rtcp:9 IN IP4 0.0.0.0
|
|
944
|
+
a=candidate:1446275835 1 udp 2122129151 192.168.1.108 52396 typ host generation 0 network-id 1
|
|
945
|
+
a=candidate:1833640547 1 udp 2122063615 172.25.160.1 52397 typ host generation 0 network-id 4
|
|
946
|
+
a=candidate:3642338680 1 udp 2122262783 2a01:4b00:ea24:b300:10a8:8a7e:234c:3161 52398 typ host generation 0 network-id 2
|
|
947
|
+
a=candidate:4227024272 1 udp 2122197247 2a01:4b00:ea24:b300:f50b:e799:7a1:8cc3 52399 typ host generation 0 network-id 3
|
|
948
|
+
a=candidate:2218323828 1 udp 1685921535 209.35.84.57 28022 typ srflx raddr 192.168.1.108 rport 52396 generation 0 network-id 1
|
|
949
|
+
a=ice-ufrag:5emx
|
|
950
|
+
a=ice-pwd:T78uDKroul30L+4WytFCzZiv
|
|
951
|
+
a=ice-options:trickle
|
|
952
|
+
a=fingerprint:sha-256 AE:24:0F:8F:23:5C:EE:D5:F8:BD:EB:2C:86:15:13:44:A2:D1:30:9E:74:68:87:8C:50:80:F7:9A:6A:D9:3A:56
|
|
953
|
+
a=setup:actpass
|
|
954
|
+
a=mid:0
|
|
955
|
+
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
|
|
956
|
+
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
957
|
+
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
|
|
958
|
+
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
|
|
959
|
+
a=sendrecv
|
|
960
|
+
a=msid:2e008e23-265a-42a0-ba6f-d147a9d0ca42 ff52617f-a48b-454e-9d50-47367329f318
|
|
961
|
+
a=rtcp-mux
|
|
962
|
+
a=rtpmap:111 opus/48000/2
|
|
963
|
+
a=rtcp-fb:111 transport-cc
|
|
964
|
+
a=fmtp:111 minptime=10;useinbandfec=1
|
|
965
|
+
a=rtpmap:63 red/48000/2
|
|
966
|
+
a=fmtp:63 111/111
|
|
967
|
+
a=rtpmap:9 G722/8000
|
|
968
|
+
a=rtpmap:0 PCMU/8000
|
|
969
|
+
a=rtpmap:8 PCMA/8000
|
|
970
|
+
a=rtpmap:13 CN/8000
|
|
971
|
+
a=rtpmap:110 telephone-event/48000
|
|
972
|
+
a=rtpmap:126 telephone-event/8000
|
|
973
|
+
a=ssrc:2953770750 cname:/DZABa/Op+oV703F
|
|
974
|
+
a=ssrc:2953770750 msid:2e008e23-265a-42a0-ba6f-d147a9d0ca42 ff52617f-a48b-454e-9d50-47367329f318
|
|
975
|
+
`.replace( /\r\n/g, "\n" ).replace( /\n/g, "\r\n" )
|
|
976
|
+
|
|
977
|
+
const sdpobj = sdp.create( wsssdp )
|
|
978
|
+
const target = sdpobj.getaudio()
|
|
979
|
+
const ignoreipv6candidates = true
|
|
980
|
+
const ipv6regex = /^(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/
|
|
981
|
+
|
|
982
|
+
let candidates = sdpobj.sdp.media[ 0 ].candidates
|
|
983
|
+
if( 0 < candidates.length ) {
|
|
984
|
+
if( ignoreipv6candidates ) {
|
|
985
|
+
candidates = candidates.filter( ( c ) => {
|
|
986
|
+
const ismatch = ipv6regex.test( c.ip )
|
|
987
|
+
return !ismatch
|
|
988
|
+
} )
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
candidates.sort( ( l, r ) => { return r.priority - l.priority } )
|
|
992
|
+
target.port = candidates[ 0 ].port
|
|
993
|
+
|
|
994
|
+
await new Promise( ( resolve ) => {
|
|
995
|
+
dns.lookup( candidates[ 0 ].ip, ( err, result ) => {
|
|
996
|
+
if( !err ) target.address = result
|
|
997
|
+
resolve()
|
|
998
|
+
} )
|
|
999
|
+
} )
|
|
1000
|
+
|
|
1001
|
+
expect( target.address ).to.equal( "192.168.1.108" )
|
|
1002
|
+
expect( target.port ).to.equal( 52396 )
|
|
1003
|
+
}
|
|
1004
|
+
} )
|
|
930
1005
|
} )
|