@babblevoice/babble-drachtio-callmanager 1.6.13 → 1.6.14
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/lib/call.js +115 -119
- package/package.json +1 -1
- package/test/interface/call.js +11 -2
- package/test/interface/early.js +17 -11
package/lib/call.js
CHANGED
|
@@ -339,7 +339,7 @@ class call {
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
/**
|
|
342
|
-
* Set the entity information
|
|
342
|
+
* Set the entity information against this call. Itis either set by authentication
|
|
343
343
|
* or externally (for example if we auth by network location).
|
|
344
344
|
* Either ( e.uri ) or ( e.realm and e.username ) are required.
|
|
345
345
|
* @param { entity } e
|
|
@@ -460,6 +460,7 @@ class call {
|
|
|
460
460
|
|
|
461
461
|
if( !parsed ) parsed = {}
|
|
462
462
|
let parseduri = parseuri( parsed.uri )
|
|
463
|
+
if( !parseduri ) parseduri = { "user": parsed.user, "host": parsed.host }
|
|
463
464
|
if( !parsed.params ) parsed.params = {}
|
|
464
465
|
|
|
465
466
|
return {
|
|
@@ -880,49 +881,6 @@ class call {
|
|
|
880
881
|
} )
|
|
881
882
|
}
|
|
882
883
|
|
|
883
|
-
/**
|
|
884
|
-
Called from newuac when we are answered and we have a dialog,
|
|
885
|
-
this = child call (the new call - the bleg)
|
|
886
|
-
@private
|
|
887
|
-
*/
|
|
888
|
-
async _onanswer() {
|
|
889
|
-
|
|
890
|
-
let hangups = []
|
|
891
|
-
if( this.parent ) {
|
|
892
|
-
for( let child of this.parent.children ) {
|
|
893
|
-
if( child.uuid !== this.uuid ) {
|
|
894
|
-
child.detach()
|
|
895
|
-
/* do not await - we do not want to delay the winner in
|
|
896
|
-
connecting by waiting for the completion of the hangups */
|
|
897
|
-
hangups.push( child.hangup( hangupcodes.LOSE_RACE ) )
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
if( this.state.destroyed ) return this
|
|
903
|
-
callstore.set( this )
|
|
904
|
-
|
|
905
|
-
if( true === this.options.noAck ) {
|
|
906
|
-
await this._onlatebridge()
|
|
907
|
-
} else {
|
|
908
|
-
await this._onearlybridge()
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
this.established = true
|
|
912
|
-
this.sip.tags.remote = this._dialog.sip.remoteTag
|
|
913
|
-
|
|
914
|
-
let r = this._promises.resolve.newuac
|
|
915
|
-
this._promises.resolve.newuac = false
|
|
916
|
-
this._promises.reject.newuac = false
|
|
917
|
-
|
|
918
|
-
if( hangups.length > 0 ) {
|
|
919
|
-
await Promise.all( hangups )
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
if( r ) r( this )
|
|
923
|
-
return this
|
|
924
|
-
}
|
|
925
|
-
|
|
926
884
|
/* A simple implimentation if we are offered candidates */
|
|
927
885
|
static async _parsesdpcandidates( target, sdp ) {
|
|
928
886
|
|
|
@@ -994,6 +952,14 @@ class call {
|
|
|
994
952
|
}
|
|
995
953
|
}
|
|
996
954
|
|
|
955
|
+
/* are we still established? */
|
|
956
|
+
if( !this.established || this.state.destroyed ) return this
|
|
957
|
+
if( !this.channels.audio ) {
|
|
958
|
+
/* something bad has happened */
|
|
959
|
+
this.hangup( hangupcodes.NOT_ACCEPTABLE )
|
|
960
|
+
return this
|
|
961
|
+
}
|
|
962
|
+
|
|
997
963
|
this.channels.audio.mix( this.parent.channels.audio )
|
|
998
964
|
|
|
999
965
|
this._em.emit( "call.mix", this )
|
|
@@ -1105,7 +1071,7 @@ class call {
|
|
|
1105
1071
|
}
|
|
1106
1072
|
}
|
|
1107
1073
|
|
|
1108
|
-
if( this.children.length > 0 ) return this.children
|
|
1074
|
+
if( this.children.length > 0 ) return this.children.values().next().value
|
|
1109
1075
|
|
|
1110
1076
|
return false
|
|
1111
1077
|
}
|
|
@@ -2260,18 +2226,21 @@ class call {
|
|
|
2260
2226
|
|
|
2261
2227
|
this._sethangupcause( "us", reason )
|
|
2262
2228
|
|
|
2263
|
-
if( this.established ) {
|
|
2229
|
+
if( this.state.established ) {
|
|
2264
2230
|
try {
|
|
2265
2231
|
await this._dialog.destroy()
|
|
2266
2232
|
} catch( e ) { console.trace( e ) }
|
|
2267
2233
|
|
|
2268
|
-
} else if( "uac" === this.type
|
|
2234
|
+
} else if( "uac" === this.type &&
|
|
2235
|
+
this.state.trying ) {
|
|
2269
2236
|
try {
|
|
2270
|
-
|
|
2237
|
+
this.canceled = true
|
|
2238
|
+
if( this._req ) {
|
|
2239
|
+
this._req.cancel( ( err, cancel ) => {
|
|
2240
|
+
if( err ) console.trace( err )
|
|
2241
|
+
} )
|
|
2242
|
+
}
|
|
2271
2243
|
} catch( e ) { console.trace( e ) }
|
|
2272
|
-
|
|
2273
|
-
this.canceled = true
|
|
2274
|
-
|
|
2275
2244
|
} else {
|
|
2276
2245
|
try {
|
|
2277
2246
|
this._res.send( this.hangup_cause.sip )
|
|
@@ -2431,7 +2400,7 @@ class call {
|
|
|
2431
2400
|
@param { earlycallback } [ callbacks.early ] - callback to provide a call object with early call (pre dialog)
|
|
2432
2401
|
@param { confirmcallback } [ callbacks.confirm ] - called when a dialog is confirmed but before it is bridged with a parent - this provides an opportunity for another call to adopt this call
|
|
2433
2402
|
@param { failcallback } [ callbacks.fail ] - Called when child is terminated
|
|
2434
|
-
@return { Promise< call | false > } - returns a promise which resolves to a new call object if a dialog has been confirmed. If none are confirmed
|
|
2403
|
+
@return { Promise< call | false > } - returns a promise which resolves to a new call object if a dialog has been confirmed. If none are confirmed then return false. Each attempt is fed into callbacks.early.
|
|
2435
2404
|
*/
|
|
2436
2405
|
static async newuac( options, callbacks = {} ) {
|
|
2437
2406
|
|
|
@@ -2461,7 +2430,7 @@ class call {
|
|
|
2461
2430
|
return false
|
|
2462
2431
|
}
|
|
2463
2432
|
|
|
2464
|
-
|
|
2433
|
+
const numcontacts = contactinfo.contacts.length
|
|
2465
2434
|
let ourcallbacks = {}
|
|
2466
2435
|
let failcount = 0
|
|
2467
2436
|
|
|
@@ -2471,22 +2440,30 @@ class call {
|
|
|
2471
2440
|
} )
|
|
2472
2441
|
|
|
2473
2442
|
ourcallbacks.early = ( c ) => {
|
|
2474
|
-
othercalls.push( c )
|
|
2475
2443
|
if( callbacks.early ) callbacks.early( c )
|
|
2476
2444
|
}
|
|
2477
2445
|
|
|
2478
2446
|
ourcallbacks.fail = ( c ) => {
|
|
2479
2447
|
failcount++
|
|
2480
|
-
if( failcount >=
|
|
2448
|
+
if( failcount >= numcontacts ) {
|
|
2481
2449
|
/* we have no more to try */
|
|
2482
|
-
|
|
2450
|
+
if( false !== waitonchildrenresolve ) {
|
|
2451
|
+
waitonchildrenresolve( false )
|
|
2452
|
+
waitonchildrenresolve = false
|
|
2453
|
+
}
|
|
2483
2454
|
}
|
|
2484
2455
|
if( callbacks.fail ) callbacks.fail( c )
|
|
2485
2456
|
}
|
|
2486
2457
|
|
|
2487
2458
|
ourcallbacks.confirm = ( c ) => {
|
|
2488
|
-
|
|
2489
|
-
|
|
2459
|
+
if( false !== waitonchildrenresolve ) {
|
|
2460
|
+
waitonchildrenresolve( c )
|
|
2461
|
+
waitonchildrenresolve = false
|
|
2462
|
+
if( callbacks.confirm ) callbacks.confirm( c )
|
|
2463
|
+
return
|
|
2464
|
+
}
|
|
2465
|
+
c.hangup( hangupcodes.LOSE_RACE )
|
|
2466
|
+
if( callbacks.fail ) callbacks.fail( c )
|
|
2490
2467
|
}
|
|
2491
2468
|
|
|
2492
2469
|
for( let contact of contactinfo.contacts ) {
|
|
@@ -2499,17 +2476,6 @@ class call {
|
|
|
2499
2476
|
}
|
|
2500
2477
|
|
|
2501
2478
|
let child = await waitonchildrenpromise
|
|
2502
|
-
|
|
2503
|
-
if( child && !child.parent ) {
|
|
2504
|
-
/* we have to terminate other calls we generated as this
|
|
2505
|
-
will not happen in the call object without a parent */
|
|
2506
|
-
for( let other of othercalls ) {
|
|
2507
|
-
if( other.uuid !== child.uuid ) {
|
|
2508
|
-
other.detach()
|
|
2509
|
-
other.hangup( hangupcodes.LOSE_RACE )
|
|
2510
|
-
}
|
|
2511
|
-
}
|
|
2512
|
-
}
|
|
2513
2479
|
return child
|
|
2514
2480
|
}
|
|
2515
2481
|
|
|
@@ -2579,10 +2545,6 @@ class call {
|
|
|
2579
2545
|
newcall.options = { ...callmanager.options, ...newcall.options, ...options }
|
|
2580
2546
|
newcall.options.headers = tmpheaders
|
|
2581
2547
|
|
|
2582
|
-
newcall._timers.newuac = setTimeout( () => {
|
|
2583
|
-
newcall.hangup( hangupcodes.REQUEST_TIMEOUT )
|
|
2584
|
-
}, newcall.options.uactimeout )
|
|
2585
|
-
|
|
2586
2548
|
if( newcall.options.late ) {
|
|
2587
2549
|
newcall.options.noAck = true /* this is a MUST for late negotiation */
|
|
2588
2550
|
} else {
|
|
@@ -2612,67 +2574,101 @@ class call {
|
|
|
2612
2574
|
if( addressparts.port ) newcall.network.remote.port = addressparts.port
|
|
2613
2575
|
}
|
|
2614
2576
|
|
|
2615
|
-
|
|
2616
|
-
|
|
2577
|
+
try {
|
|
2578
|
+
newcall._dialog = await callmanager.options.srf.createUAC( options.contact, newcall.options, {
|
|
2579
|
+
cbRequest: ( err, req ) => {
|
|
2617
2580
|
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2581
|
+
if( !req ) {
|
|
2582
|
+
newcall.state.destroyed = true
|
|
2583
|
+
console.trace( "No req object??", err )
|
|
2584
|
+
return
|
|
2585
|
+
}
|
|
2623
2586
|
|
|
2624
|
-
|
|
2625
|
-
|
|
2587
|
+
newcall._timers.newuac = setTimeout( () => {
|
|
2588
|
+
newcall.hangup( hangupcodes.REQUEST_TIMEOUT )
|
|
2589
|
+
}, newcall.options.uactimeout )
|
|
2626
2590
|
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
"tags": {
|
|
2630
|
-
"local": req.getParsedHeader( "from" ).params.tag,
|
|
2631
|
-
"remote": ""
|
|
2632
|
-
},
|
|
2633
|
-
"contact": [ { "uri": options.contact } ]
|
|
2634
|
-
}
|
|
2591
|
+
newcall._req = req
|
|
2592
|
+
newcall.state.trying = true
|
|
2635
2593
|
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2594
|
+
newcall.sip = {
|
|
2595
|
+
"callid": req.getParsedHeader( "call-id" ),
|
|
2596
|
+
"tags": {
|
|
2597
|
+
"local": req.getParsedHeader( "from" ).params.tag,
|
|
2598
|
+
"remote": ""
|
|
2599
|
+
},
|
|
2600
|
+
"contact": [ { "uri": options.contact } ]
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2603
|
+
callstore.set( newcall )
|
|
2604
|
+
if( callbacks && callbacks.early ) callbacks.early( newcall )
|
|
2605
|
+
callmanager.options.em.emit( "call.new", newcall )
|
|
2606
|
+
},
|
|
2607
|
+
cbProvisional: async ( res ) => {
|
|
2608
|
+
newcall._res = res
|
|
2609
|
+
if( 180 === res.status ) {
|
|
2610
|
+
newcall._onring()
|
|
2611
|
+
} else if( 183 === res.status ) {
|
|
2612
|
+
await newcall._onearly()
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
if( newcall.canceled ) {
|
|
2616
|
+
newcall.hangup()
|
|
2617
|
+
}
|
|
2646
2618
|
}
|
|
2619
|
+
} )
|
|
2620
|
+
} catch ( err ) {
|
|
2621
|
+
|
|
2622
|
+
if( !newcall._state._hangup ) {
|
|
2623
|
+
if ( undefined !== err.status ) {
|
|
2624
|
+
let reason = hangupcodes.REQUEST_TERMINATED
|
|
2625
|
+
if( err.status in inboundsiperros ) reason = inboundsiperros[ err.status ]
|
|
2647
2626
|
|
|
2648
|
-
|
|
2649
|
-
newcall.
|
|
2627
|
+
newcall.state.destroyed = true
|
|
2628
|
+
if( newcall ) newcall._onhangup( "wire", reason )
|
|
2629
|
+
} else {
|
|
2630
|
+
console.trace( err )
|
|
2650
2631
|
}
|
|
2651
2632
|
}
|
|
2652
|
-
}
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2633
|
+
} finally {
|
|
2634
|
+
|
|
2635
|
+
if( newcall._timers.newuac ) clearTimeout( newcall._timers.newuac )
|
|
2636
|
+
newcall._timers.newuac = false
|
|
2656
2637
|
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2638
|
+
if( newcall.state.destroyed || newcall.state.canceled || newcall._state._hangup ) {
|
|
2639
|
+
if( callbacks && callbacks.fail ) callbacks.fail( newcall )
|
|
2640
|
+
return newcall
|
|
2660
2641
|
}
|
|
2661
|
-
} )
|
|
2662
2642
|
|
|
2663
|
-
|
|
2664
|
-
newcall._timers.newuac = false
|
|
2643
|
+
newcall.sdp.remote = sdpgen.create( newcall._dialog.remote.sdp )
|
|
2665
2644
|
|
|
2666
|
-
|
|
2645
|
+
if( newcall.state.destroyed ) return this
|
|
2646
|
+
newcall.established = true
|
|
2667
2647
|
|
|
2668
|
-
if(
|
|
2669
|
-
|
|
2670
|
-
|
|
2648
|
+
if( newcall.parent ) {
|
|
2649
|
+
for( const child of newcall.parent.children ) {
|
|
2650
|
+
if( child.uuid !== newcall.uuid && !child.state.established ) {
|
|
2651
|
+
child.detach()
|
|
2652
|
+
/* do not await - we do not want to delay the winner in
|
|
2653
|
+
connecting by waiting for the completion of the hangups */
|
|
2654
|
+
child.hangup( hangupcodes.LOSE_RACE )
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2671
2658
|
|
|
2672
|
-
|
|
2659
|
+
callstore.set( newcall )
|
|
2673
2660
|
|
|
2674
|
-
|
|
2675
|
-
|
|
2661
|
+
newcall.sip.tags.remote = newcall._dialog.sip.remoteTag
|
|
2662
|
+
|
|
2663
|
+
if( true === newcall.options.noAck ) {
|
|
2664
|
+
await newcall._onlatebridge()
|
|
2665
|
+
} else {
|
|
2666
|
+
await newcall._onearlybridge()
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
if( callbacks.confirm ) await callbacks.confirm( newcall )
|
|
2670
|
+
return newcall
|
|
2671
|
+
}
|
|
2676
2672
|
}
|
|
2677
2673
|
|
|
2678
2674
|
/**
|
package/package.json
CHANGED
package/test/interface/call.js
CHANGED
|
@@ -205,7 +205,7 @@ describe( "call object", function() {
|
|
|
205
205
|
expect( call.state.cleaned ).to.be.true
|
|
206
206
|
} )
|
|
207
207
|
|
|
208
|
-
it( `uas.newuac - create uac by entity with registrar
|
|
208
|
+
it( `uas.newuac - create uac by entity with registrar`, async function() {
|
|
209
209
|
|
|
210
210
|
let options = {
|
|
211
211
|
"registrar": {
|
|
@@ -228,6 +228,15 @@ describe( "call object", function() {
|
|
|
228
228
|
srfscenario.inbound()
|
|
229
229
|
} )
|
|
230
230
|
|
|
231
|
+
call._req.setparsedheader( "remote-party-id", {
|
|
232
|
+
"name": "",
|
|
233
|
+
"uri": "",
|
|
234
|
+
"user": "0123456789",
|
|
235
|
+
"host": "someotherrealm.com",
|
|
236
|
+
"params": { "privacy": false },
|
|
237
|
+
"type": "callerid"
|
|
238
|
+
} )
|
|
239
|
+
|
|
231
240
|
let child = await call.newuac( { "entity": { "uri": "1000@dummy" } } )
|
|
232
241
|
|
|
233
242
|
expect( await callstore.stats() ).to.deep.include( {
|
|
@@ -248,7 +257,7 @@ describe( "call object", function() {
|
|
|
248
257
|
child.update()
|
|
249
258
|
|
|
250
259
|
expect( requestoptions.method ).to.equal( "update" )
|
|
251
|
-
expect( requestoptions.headers[ "P-Preferred-Identity" ] ).to.equal( `"" <sip:
|
|
260
|
+
expect( requestoptions.headers[ "P-Preferred-Identity" ] ).to.equal( `"" <sip:0123456789@someotherrealm.com>` )
|
|
252
261
|
|
|
253
262
|
await call.hangup()
|
|
254
263
|
|
package/test/interface/early.js
CHANGED
|
@@ -311,15 +311,20 @@ a=sendrecv`.replace(/(\r\n|\n|\r)/gm, "\r\n")
|
|
|
311
311
|
|
|
312
312
|
it( `Create call and send 183 - early - SAVPF and 200 ok`, async () => {
|
|
313
313
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
314
|
+
/**
|
|
315
|
+
* Markdown - mermaid
|
|
316
|
+
sequenceDiagram
|
|
317
|
+
participant Phone
|
|
318
|
+
participant babble
|
|
319
|
+
participant Gateway
|
|
320
|
+
|
|
321
|
+
Phone->>babble: INVITE (1)
|
|
322
|
+
babble->>Gateway: INVITE (2)
|
|
323
|
+
Gateway->>babble: 183 w-sdp (3)
|
|
324
|
+
babble->>Phone: 183 w-sdp (4)
|
|
325
|
+
Gateway->>babble: Ok w-sdp (200)(5)
|
|
326
|
+
babble->>Phone: Ok w-sdp (200) (6)
|
|
327
|
+
*/
|
|
323
328
|
|
|
324
329
|
/* Setup the mock RTP server */
|
|
325
330
|
let srfscenario = new srf.srfscenario( { savpf: true } )
|
|
@@ -447,9 +452,10 @@ a=sendrecv`.replace(/(\r\n|\n|\r)/gm, "\r\n")
|
|
|
447
452
|
expect( channelmessages[ 2 ].remote.port ).to.equal( 48356 )
|
|
448
453
|
expect( channelmessages[ 2 ].remote.address ).to.equal( "82.19.206.102" )
|
|
449
454
|
expect( channelmessages[ 3 ].channel ).to.equal( "mix" )
|
|
450
|
-
|
|
451
|
-
expect( channelmessages[ 6 ].channel ).to.equal( "
|
|
455
|
+
/* with 183 we now get a second duplicate mix - this could be tidied but it is safe */
|
|
456
|
+
expect( channelmessages[ 6 ].channel ).to.equal( "mix" )
|
|
452
457
|
expect( channelmessages[ 7 ].channel ).to.equal( "close" )
|
|
458
|
+
expect( channelmessages[ 8 ].channel ).to.equal( "close" )
|
|
453
459
|
|
|
454
460
|
expect( msginfo.body ).to.include( "UDP/TLS/RTP/SAVPF" )
|
|
455
461
|
|