@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 CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "module": "commonJS",
3
+ "module": "node16",
4
4
  "target": "es6",
5
- "moduleResolution": "node",
5
+ "moduleResolution": "node16",
6
6
  "checkJs": true
7
7
  },
8
8
  "include": [ "index.js", "babble/*.js", "babble/apps/*.js" ],
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 = /^(?:(?:[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
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, queuedcall ) => {
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, queuedcall )
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.uuid !== this.uuid && !child.state.established ) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/babble-drachtio-callmanager",
3
- "version": "3.3.2",
3
+ "version": "3.3.3",
4
4
  "description": "Call processing to create a PBX",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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[ "P-Asserted-Identity" ] ).to.equal( "\"\" <sip:0123456789@someotherrealm.com>" )
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": 1,
408
- "storebyuuid": 1,
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[ "Remote-Party-ID" ] ).to.equal( "\"\" <sip:0000000000@localhost.localdomain>" )
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( { "remote": {
840
- "display": "Kermit",
841
- "realm": "muppetshow.com",
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[ "P-Asserted-Identity" ] ).to.equal( "\"Kermit\" <sip:kermy@muppetshow.com>" )
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[ "Remote-Party-ID" ] ).to.equal( "\"Hello\" <sip:0000000000@localhost.localdomain>" )
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[ "Remote-Party-ID" ] ).to.equal( "\"\" <sip:012345789@localhost.localdomain>" )
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
 
@@ -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
  } )