@babblevoice/babble-drachtio-callmanager 3.7.2 → 3.7.4
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 +1 -1
- package/lib/call.js +185 -65
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -8,7 +8,7 @@ const default_options = {
|
|
|
8
8
|
"preferedcodecs": "g722 ilbc pcmu pcma",
|
|
9
9
|
//"transcode": true, - this never made it into the software - TODO
|
|
10
10
|
"uactimeout": 30000, /* timeout when calling a client */
|
|
11
|
-
"seexpire":
|
|
11
|
+
"seexpire": 1800*1000, /* session expires timeout mS recomended in RFC 4028 - 30 minutes */
|
|
12
12
|
"rfc2833": true, /* Enable RFC 2833 - DTMF */
|
|
13
13
|
"late": false, /* Late negotiation */
|
|
14
14
|
"registrar": false, /* our registrar object or falsey */
|
package/lib/call.js
CHANGED
|
@@ -14,7 +14,12 @@ const net = require( "net" )
|
|
|
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
|
|
17
|
+
const sessionexpirevaluere = /^(\d+)(?:;refresher=(uac|uas))?$/
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param { string } s
|
|
22
|
+
*/
|
|
18
23
|
function parseuri( s ) {
|
|
19
24
|
if( "object" === typeof s )
|
|
20
25
|
return s
|
|
@@ -27,6 +32,7 @@ function parseuri( s ) {
|
|
|
27
32
|
user: r[ 2 ],
|
|
28
33
|
password: r[ 3 ],
|
|
29
34
|
host: r[ 4 ],
|
|
35
|
+
uri: r[ 2 ] + "@" + r[ 4 ],
|
|
30
36
|
port: +r[ 5 ],
|
|
31
37
|
params: (r[ 6 ].match( parseuriparamsre ) || [] )
|
|
32
38
|
.map( function( s ) { return s.split( "=" ) } )
|
|
@@ -153,6 +159,9 @@ let callmanager = {
|
|
|
153
159
|
class call {
|
|
154
160
|
|
|
155
161
|
#noack = false
|
|
162
|
+
#seexpire = callmanager.options.seexpire
|
|
163
|
+
#refresher = "uac"
|
|
164
|
+
#expirelasttouch = +new Date()
|
|
156
165
|
|
|
157
166
|
/**
|
|
158
167
|
* Construct our call object with all defaults, including a default UUID.
|
|
@@ -478,14 +487,19 @@ class call {
|
|
|
478
487
|
}
|
|
479
488
|
|
|
480
489
|
/**
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
490
|
+
* @typedef remoteid
|
|
491
|
+
* @property { string } [ schema ]
|
|
492
|
+
* @property { string } [ password ]
|
|
493
|
+
* @property { number } [ port ]
|
|
494
|
+
* @property { Array } [ headers ]
|
|
495
|
+
* @property { string } host
|
|
496
|
+
* @property { string } user
|
|
497
|
+
* @property { string } name
|
|
498
|
+
* @property { string } uri
|
|
499
|
+
* @property { boolean } privacy
|
|
500
|
+
* @property { object } [ params ]
|
|
501
|
+
* @property { string } type - "callerid" | "calledid"
|
|
502
|
+
*/
|
|
489
503
|
|
|
490
504
|
|
|
491
505
|
/**
|
|
@@ -494,6 +508,8 @@ class call {
|
|
|
494
508
|
*/
|
|
495
509
|
#getremotefromheaders() {
|
|
496
510
|
let parsed = {}
|
|
511
|
+
if( !this._req ) return parsed
|
|
512
|
+
|
|
497
513
|
if( this._req.has( "p-asserted-identity" ) ) {
|
|
498
514
|
parsed = this._req.getParsedHeader( "p-asserted-identity" )
|
|
499
515
|
} else if( this._req.has( "remote-party-id" ) ) {
|
|
@@ -510,9 +526,14 @@ class call {
|
|
|
510
526
|
return this._req.getParsedHeader( hdr )
|
|
511
527
|
}
|
|
512
528
|
|
|
529
|
+
/**
|
|
530
|
+
*
|
|
531
|
+
* @param { object } parsed
|
|
532
|
+
* @returns
|
|
533
|
+
*/
|
|
513
534
|
#fixparseduriobj( parsed ) {
|
|
514
535
|
|
|
515
|
-
if( !parsed ) parsed = { name: "" }
|
|
536
|
+
if( !parsed ) parsed = { name: "", user: "", host: "", uri: "", privacy: false, type: "callerid" }
|
|
516
537
|
const name = parsed.name
|
|
517
538
|
|
|
518
539
|
if( !parsed.uri && parsed.user && parsed.host ) parsed.uri = parsed.user + "@" + parsed.host
|
|
@@ -540,7 +561,7 @@ class call {
|
|
|
540
561
|
*/
|
|
541
562
|
get direction() {
|
|
542
563
|
if( this.options.partycalled ) return "inbound"
|
|
543
|
-
return "uas"
|
|
564
|
+
return "uas"===this.type?"inbound":"outbound"
|
|
544
565
|
}
|
|
545
566
|
|
|
546
567
|
/**
|
|
@@ -572,6 +593,11 @@ class call {
|
|
|
572
593
|
}
|
|
573
594
|
}
|
|
574
595
|
|
|
596
|
+
/**
|
|
597
|
+
*
|
|
598
|
+
* @param { object } startingpoint
|
|
599
|
+
* @returns
|
|
600
|
+
*/
|
|
575
601
|
#fromremoteheaders( startingpoint ) {
|
|
576
602
|
const parsed = this.#fixparseduriobj( this.#getremotefromheaders() )
|
|
577
603
|
if( parsed.uri ) startingpoint.uri = parsed.uri
|
|
@@ -580,7 +606,32 @@ class call {
|
|
|
580
606
|
if( parsed.name ) startingpoint.name = parsed.name
|
|
581
607
|
}
|
|
582
608
|
|
|
609
|
+
/**
|
|
610
|
+
*
|
|
611
|
+
* @param { object } startingpoint
|
|
612
|
+
* @returns { boolean }
|
|
613
|
+
*/
|
|
614
|
+
#fromrefertouri( startingpoint ) {
|
|
615
|
+
if( !this.referingtouri ) return false
|
|
616
|
+
|
|
617
|
+
const referdest = parseuri( this.referingtouri )
|
|
618
|
+
|
|
619
|
+
if( !referdest ) return
|
|
620
|
+
|
|
621
|
+
if( referdest.uri ) startingpoint.uri = referdest.uri
|
|
622
|
+
if( referdest.user ) startingpoint.user = referdest.user
|
|
623
|
+
if( referdest.host ) startingpoint.host = referdest.host
|
|
624
|
+
|
|
625
|
+
return true
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
*
|
|
630
|
+
* @param { object } startingpoint
|
|
631
|
+
* @returns
|
|
632
|
+
*/
|
|
583
633
|
#fromcontact( startingpoint ) {
|
|
634
|
+
|
|
584
635
|
const dest = parseuri( this.options.contact )
|
|
585
636
|
if( !dest ) return
|
|
586
637
|
if( dest.uri ) startingpoint.uri = dest.uri
|
|
@@ -588,12 +639,22 @@ class call {
|
|
|
588
639
|
if( dest.host ) startingpoint.host = dest.host
|
|
589
640
|
}
|
|
590
641
|
|
|
642
|
+
/**
|
|
643
|
+
*
|
|
644
|
+
* @param { object } startingpoint
|
|
645
|
+
* @returns
|
|
646
|
+
*/
|
|
591
647
|
#fromdestination( startingpoint ) {
|
|
592
648
|
const dest = this.destination
|
|
593
649
|
startingpoint.user = dest.user
|
|
594
650
|
startingpoint.host = dest.host
|
|
595
651
|
}
|
|
596
652
|
|
|
653
|
+
/**
|
|
654
|
+
*
|
|
655
|
+
* @param { object } startingpoint
|
|
656
|
+
* @returns
|
|
657
|
+
*/
|
|
597
658
|
#fromoutentity( startingpoint ) {
|
|
598
659
|
|
|
599
660
|
const entity = this.options.entity
|
|
@@ -608,18 +669,21 @@ class call {
|
|
|
608
669
|
return false
|
|
609
670
|
}
|
|
610
671
|
|
|
672
|
+
/**
|
|
673
|
+
*
|
|
674
|
+
* @param { object } startingpoint
|
|
675
|
+
* @returns
|
|
676
|
+
*/
|
|
611
677
|
#frominentity( startingpoint ) {
|
|
612
678
|
const entity = this._entity
|
|
679
|
+
if( !entity ) return false
|
|
613
680
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
return true
|
|
620
|
-
}
|
|
681
|
+
startingpoint.name = entity.display
|
|
682
|
+
startingpoint.uri = entity.uri
|
|
683
|
+
startingpoint.user = entity.username
|
|
684
|
+
startingpoint.host = entity.realm
|
|
685
|
+
return true
|
|
621
686
|
|
|
622
|
-
return false
|
|
623
687
|
}
|
|
624
688
|
|
|
625
689
|
/**
|
|
@@ -675,18 +739,19 @@ class call {
|
|
|
675
739
|
"type": "callerid"
|
|
676
740
|
}
|
|
677
741
|
|
|
678
|
-
if( "uas"
|
|
742
|
+
if( "uas" === this.type ) this.#calleridforuas( startingpoint )
|
|
679
743
|
else {
|
|
680
744
|
if( this.options.partycalled ) {
|
|
681
745
|
this.#calleridforuac( startingpoint )
|
|
682
746
|
} else {
|
|
683
747
|
const other = this.other
|
|
684
748
|
if( other ) {
|
|
685
|
-
if( "uas"
|
|
749
|
+
if( "uas" === other.type ) {
|
|
686
750
|
other.#calleridforuas( startingpoint )
|
|
687
751
|
other.#overridecallerid( startingpoint )
|
|
688
752
|
} else {
|
|
689
753
|
other.#calledidforuac( startingpoint )
|
|
754
|
+
if( this.type !== other.type ) other.#fromrefertouri( startingpoint )
|
|
690
755
|
}
|
|
691
756
|
} else {
|
|
692
757
|
|
|
@@ -800,10 +865,10 @@ class call {
|
|
|
800
865
|
*/
|
|
801
866
|
|
|
802
867
|
/**
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
868
|
+
* Return the destination of the call.
|
|
869
|
+
* If not present returns the contact.
|
|
870
|
+
* @return { object } destination - parsed uri
|
|
871
|
+
*/
|
|
807
872
|
get destination() {
|
|
808
873
|
if( undefined !== this.referingtouri ) {
|
|
809
874
|
const parsed = parseuri( this.referingtouri )
|
|
@@ -816,7 +881,7 @@ class call {
|
|
|
816
881
|
|
|
817
882
|
/**
|
|
818
883
|
Return the contact of the call.
|
|
819
|
-
@return {
|
|
884
|
+
@return { object } destination - parsed uri
|
|
820
885
|
*/
|
|
821
886
|
get contact() {
|
|
822
887
|
if( "uac" == this.type ) {
|
|
@@ -1305,7 +1370,7 @@ class call {
|
|
|
1305
1370
|
async _onearlybridge() {
|
|
1306
1371
|
if( this.destroyed ) return
|
|
1307
1372
|
|
|
1308
|
-
this
|
|
1373
|
+
this.#addevents( this._dialog )
|
|
1309
1374
|
|
|
1310
1375
|
this.sdp.remote = sdpgen.create( this._dialog.remote.sdp )
|
|
1311
1376
|
|
|
@@ -1391,7 +1456,7 @@ class call {
|
|
|
1391
1456
|
|
|
1392
1457
|
this._dialog = await this._dialog.ack( this.sdp.local.toString() )
|
|
1393
1458
|
this.established = true
|
|
1394
|
-
this
|
|
1459
|
+
this.#addevents( this._dialog )
|
|
1395
1460
|
|
|
1396
1461
|
await this.#answerparent()
|
|
1397
1462
|
|
|
@@ -1793,19 +1858,23 @@ class call {
|
|
|
1793
1858
|
return
|
|
1794
1859
|
}
|
|
1795
1860
|
|
|
1861
|
+
const headers = {
|
|
1862
|
+
"User-Agent": "project",
|
|
1863
|
+
"Supported": "replaces, timer",
|
|
1864
|
+
"Require": "timer",
|
|
1865
|
+
"Session-Expires": `${this.#seexpire/1000};refresher=${this.#refresher}`
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1796
1868
|
const dialog = await callmanager.options.srf.createUAS( this._req, this._res, {
|
|
1797
1869
|
localSdp: this.sdp.local.toString(),
|
|
1798
|
-
headers
|
|
1799
|
-
"User-Agent": "project",
|
|
1800
|
-
"Supported": "replaces"
|
|
1801
|
-
}
|
|
1870
|
+
headers
|
|
1802
1871
|
} )
|
|
1803
1872
|
|
|
1804
1873
|
this.#setdialog( dialog )
|
|
1805
1874
|
this.sip.tags.local = dialog.sip.localTag
|
|
1806
1875
|
callstore.set( this )
|
|
1807
1876
|
|
|
1808
|
-
this
|
|
1877
|
+
this.#addevents( this._dialog )
|
|
1809
1878
|
this._em.emit( "call.answered", this )
|
|
1810
1879
|
callmanager.options.em.emit( "call.answered", this )
|
|
1811
1880
|
|
|
@@ -2406,51 +2475,77 @@ class call {
|
|
|
2406
2475
|
}
|
|
2407
2476
|
|
|
2408
2477
|
/**
|
|
2409
|
-
|
|
2410
|
-
|
|
2478
|
+
* Allow a good margin of error - but hangup if we have disappeared
|
|
2479
|
+
*/
|
|
2480
|
+
#hasseexpiredexpired() {
|
|
2481
|
+
|
|
2482
|
+
const now = +new Date()
|
|
2483
|
+
if( ( now - this.#expirelasttouch ) > ( this.#seexpire * 2 ) ) {
|
|
2484
|
+
this.hangup( hangupcodes.USER_GONE )
|
|
2485
|
+
return true
|
|
2486
|
+
}
|
|
2487
|
+
return false
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
/**
|
|
2491
|
+
*
|
|
2492
|
+
*/
|
|
2493
|
+
#checkthischannelforwebrtcdirection() {
|
|
2494
|
+
if( this._iswebrtc && this.channels && this.channels.audio ) {
|
|
2495
|
+
/* we are sending invite so we MUST offer be actpass */
|
|
2496
|
+
this.channels.secure.audio.offer = true
|
|
2497
|
+
this.sdp.local
|
|
2498
|
+
.secure( this.channels.audio.local.dtls.fingerprint, this.#getsrtpsetup( this.channels.secure.audio ) )
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
/**
|
|
2503
|
+
* Add events for the drachtio dialog object that this object requires.
|
|
2504
|
+
* @param { object } dialog
|
|
2411
2505
|
*/
|
|
2412
|
-
|
|
2506
|
+
#addevents( dialog ) {
|
|
2413
2507
|
|
|
2414
2508
|
/* Drachtio doesn't appear to have finished SE support, i.e. it sends
|
|
2415
2509
|
a regular INVITE when we set the Supported: timer and Session-Expires headers
|
|
2416
2510
|
but it doesn't appear to indicate to us when it does fail. It most cases our
|
|
2417
2511
|
RTP stall timer will kick in first, but if a call is placed on hold followed
|
|
2418
|
-
by AWOL...
|
|
2512
|
+
by AWOL... My new startegy is we perform teh reinvite - if we are the refresher
|
|
2513
|
+
which should refresh any timer in Drachtio - and we check for revites and timeouts. */
|
|
2419
2514
|
this._timers.seinterval = setInterval( async () => {
|
|
2420
2515
|
|
|
2421
2516
|
try {
|
|
2422
|
-
if( this.destroyed ) {
|
|
2423
|
-
/* this should be done - but we are still running */
|
|
2517
|
+
if( this.destroyed || this.#hasseexpiredexpired() ) {
|
|
2424
2518
|
clearInterval( this._timers.seinterval )
|
|
2425
2519
|
return
|
|
2426
2520
|
}
|
|
2427
2521
|
|
|
2522
|
+
if( this.#refresher !== this.type ) return
|
|
2428
2523
|
if( "function" != typeof dialog.request ) return
|
|
2429
2524
|
|
|
2430
|
-
|
|
2431
|
-
/* we are sending invite so we MUST offer be actpass */
|
|
2432
|
-
this.channels.secure.audio.offer = true
|
|
2433
|
-
this.sdp.local
|
|
2434
|
-
.secure( this.channels.audio.local.dtls.fingerprint, this.#getsrtpsetup( this.channels.secure.audio ) )
|
|
2435
|
-
}
|
|
2525
|
+
this.#checkthischannelforwebrtcdirection()
|
|
2436
2526
|
|
|
2437
2527
|
const opts = {
|
|
2438
|
-
|
|
2439
|
-
|
|
2528
|
+
method: "INVITE",
|
|
2529
|
+
body: this.sdp.local.toString(),
|
|
2530
|
+
headers: this.options.headers
|
|
2440
2531
|
}
|
|
2441
2532
|
|
|
2442
2533
|
const res = await dialog.request( opts )
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
} )
|
|
2447
|
-
|
|
2448
|
-
if( !this.destroyed && 200 != res.msg.status ) {
|
|
2534
|
+
|
|
2535
|
+
if( this.destroyed ) return
|
|
2536
|
+
if( 200 != res.msg.status ) {
|
|
2449
2537
|
this.hangup( hangupcodes.USER_GONE )
|
|
2538
|
+
return
|
|
2450
2539
|
}
|
|
2451
|
-
} catch( e ) { /* empty */ }
|
|
2452
2540
|
|
|
2453
|
-
|
|
2541
|
+
this.#expirelasttouch = +new Date()
|
|
2542
|
+
|
|
2543
|
+
} catch( e ) {
|
|
2544
|
+
console.trace( e )
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
}, this.#seexpire * 0.45 )
|
|
2548
|
+
this.#expirelasttouch = +new Date()
|
|
2454
2549
|
|
|
2455
2550
|
dialog.on( "destroy", ( /* req */ ) => {
|
|
2456
2551
|
if( this._state._hangup ) return
|
|
@@ -2483,6 +2578,7 @@ class call {
|
|
|
2483
2578
|
|
|
2484
2579
|
dialog.on( "modify", ( req, res ) => {
|
|
2485
2580
|
// The application must respond, using the res parameter provided.
|
|
2581
|
+
this.#expirelasttouch = +new Date()
|
|
2486
2582
|
if( "INVITE" !== req.msg.method ) return
|
|
2487
2583
|
|
|
2488
2584
|
this.channels.secure.audio.reinvite = true
|
|
@@ -2514,6 +2610,7 @@ class call {
|
|
|
2514
2610
|
|
|
2515
2611
|
dialog.on( "refer", async ( req, res ) => {
|
|
2516
2612
|
try {
|
|
2613
|
+
this.#expirelasttouch = +new Date()
|
|
2517
2614
|
/*
|
|
2518
2615
|
We only support the xfer of 2 legged calls. The xfered call will pick up
|
|
2519
2616
|
the auth from the transferee. For example, inbound anonymous call, gets handled
|
|
@@ -3576,19 +3673,17 @@ class call {
|
|
|
3576
3673
|
*/
|
|
3577
3674
|
#configcalleridfornewuac() {
|
|
3578
3675
|
|
|
3676
|
+
const callerid = this.callerid
|
|
3677
|
+
const calleridrem = this.callerid
|
|
3678
|
+
|
|
3579
3679
|
let party = ";party=calling"
|
|
3580
3680
|
if( this.options.partycalled ) {
|
|
3581
3681
|
party = ";party=called"
|
|
3682
|
+
this.#fromrefertouri( calleridrem )
|
|
3582
3683
|
}
|
|
3583
3684
|
|
|
3584
|
-
const
|
|
3585
|
-
|
|
3586
|
-
let calleridstr = `<sip:${callerid.user}@${callerid.host}>`
|
|
3587
|
-
|
|
3588
|
-
if ( callerid.name )
|
|
3589
|
-
calleridstr = `"${callerid.name}"` + " " + calleridstr
|
|
3590
|
-
else
|
|
3591
|
-
calleridstr = `"${callerid.user}"` + " " + calleridstr
|
|
3685
|
+
const calleridstr = `"${callerid.name?callerid.name:callerid.user}" <sip:${callerid.user}@${callerid.host}>`
|
|
3686
|
+
const calleridstrrem = `"${calleridrem.name?calleridrem.name:calleridrem.user}" <sip:${calleridrem.user}@${calleridrem.host}>`
|
|
3592
3687
|
|
|
3593
3688
|
let privacy = ""
|
|
3594
3689
|
if( true === this.options.privacy ) {
|
|
@@ -3599,7 +3694,7 @@ class call {
|
|
|
3599
3694
|
RFC 3325 - should we also consider the P-Preferred-Identity header?
|
|
3600
3695
|
P-Asserted-Identity?
|
|
3601
3696
|
*/
|
|
3602
|
-
this.options.headers[ "remote-party-id" ] =
|
|
3697
|
+
this.options.headers[ "remote-party-id" ] = calleridstrrem + party + ";screen=yes" + privacy
|
|
3603
3698
|
this.options.headers[ "from" ] = calleridstr
|
|
3604
3699
|
|
|
3605
3700
|
return { user: callerid.user, realm: callerid.host }
|
|
@@ -3693,7 +3788,7 @@ class call {
|
|
|
3693
3788
|
* @property { boolean } [ clicktocall ] - if set to true, will set autoanswer to true and swap the source and desination on caller ID, set to true for both caller and called
|
|
3694
3789
|
* @property { boolean } [ partycalled ] - reverses the direction of the call from the invite, from the point of view of the called in a 3pcc context
|
|
3695
3790
|
* @property { boolean } [ partycaller ] - reverses the direction of the call from the invite, from the point of view of the caller in a 3pcc context
|
|
3696
|
-
|
|
3791
|
+
* @property { boolean } [ late ] - late negotiation
|
|
3697
3792
|
* @property { boolean } [ privacy ] - sets the privacy
|
|
3698
3793
|
* @property { entity } [ entity ] - used to store this call against and look up a contact string if not supplied.
|
|
3699
3794
|
* @property { object } [ entity ]
|
|
@@ -3785,6 +3880,8 @@ class call {
|
|
|
3785
3880
|
newcall.options.headers[ "allow-events" ] = "talk, hold, presence, as-feature-event, dialog, call-info, sla, include-session-description, message-summary, refer"
|
|
3786
3881
|
newcall.options.headers[ "allow" ] = "INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE"
|
|
3787
3882
|
newcall.options.headers[ "supported" ] = "timer, path, replaces"
|
|
3883
|
+
newcall.options.headers[ "min-se" ] = "90"
|
|
3884
|
+
newcall.options.headers[ "session-expires" ] = `${callmanager.options.seexpire/1000}`
|
|
3788
3885
|
|
|
3789
3886
|
newcall.#confignetwork( options )
|
|
3790
3887
|
await newcall.#openchannelsfornewuac()
|
|
@@ -3860,6 +3957,7 @@ class call {
|
|
|
3860
3957
|
return newcall
|
|
3861
3958
|
}
|
|
3862
3959
|
|
|
3960
|
+
newcall.#parsesessionexpires( newdialog.res )
|
|
3863
3961
|
newcall.parseallow( newdialog.res )
|
|
3864
3962
|
|
|
3865
3963
|
newcall.#setdialog( newdialog )
|
|
@@ -3892,10 +3990,30 @@ class call {
|
|
|
3892
3990
|
this.established = true
|
|
3893
3991
|
}
|
|
3894
3992
|
|
|
3993
|
+
/**
|
|
3994
|
+
*
|
|
3995
|
+
* @param { object } req
|
|
3996
|
+
*/
|
|
3997
|
+
#parsesessionexpires( req ) {
|
|
3998
|
+
if( !req ) return
|
|
3999
|
+
const se = req.get( "Session-Expires" )
|
|
4000
|
+
if( !se ) return
|
|
4001
|
+
|
|
4002
|
+
const results = se.match( sessionexpirevaluere )
|
|
4003
|
+
let expiresin = parseInt( results[ 1 ] )
|
|
4004
|
+
|
|
4005
|
+
/* min and max values */
|
|
4006
|
+
if( 90 > expiresin ) expiresin = 90
|
|
4007
|
+
if( 3600 < expiresin ) expiresin = 3600
|
|
4008
|
+
this.#seexpire = expiresin * 1000 /* mS */
|
|
4009
|
+
|
|
4010
|
+
if( results[ 2 ] ) this.#refresher = results[ 2 ]
|
|
4011
|
+
}
|
|
4012
|
+
|
|
3895
4013
|
/**
|
|
3896
4014
|
* Take as input a request or a response.
|
|
3897
|
-
*
|
|
3898
4015
|
* @param { object } req
|
|
4016
|
+
* @private - apart from test
|
|
3899
4017
|
*/
|
|
3900
4018
|
parseallow( req ) {
|
|
3901
4019
|
if( !req || !req.get ) return
|
|
@@ -3927,6 +4045,7 @@ class call {
|
|
|
3927
4045
|
const c = new call()
|
|
3928
4046
|
|
|
3929
4047
|
c.type = "uas"
|
|
4048
|
+
c.#refresher = "uas"
|
|
3930
4049
|
|
|
3931
4050
|
/**
|
|
3932
4051
|
@typedef { Object } source
|
|
@@ -3956,6 +4075,7 @@ class call {
|
|
|
3956
4075
|
*/
|
|
3957
4076
|
c._res = res
|
|
3958
4077
|
|
|
4078
|
+
c.#parsesessionexpires( req )
|
|
3959
4079
|
c.parseallow( req )
|
|
3960
4080
|
|
|
3961
4081
|
await callstore.set( c )
|