@babblevoice/babble-drachtio-callmanager 3.0.0 → 3.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.
Files changed (2) hide show
  1. package/lib/call.js +313 -115
  2. package/package.json +1 -1
package/lib/call.js CHANGED
@@ -40,6 +40,18 @@ function parseuri( s ) {
40
40
  return {}
41
41
  }
42
42
 
43
+ /**
44
+ * Util to convert key names to lowercase
45
+ * @param { object } obj
46
+ * @returns
47
+ */
48
+ function keynameslower( obj ) {
49
+ return Object.keys( obj ).reduce( ( accumulator, currentvalue ) => {
50
+ accumulator[ currentvalue.toLowerCase() ] = obj[ currentvalue ]
51
+ return accumulator
52
+ }, {} )
53
+ }
54
+
43
55
  /*
44
56
  Enum for different reasons for hangup.
45
57
  */
@@ -357,6 +369,44 @@ class call {
357
369
  this.referingtouri
358
370
  }
359
371
 
372
+ /**
373
+ *
374
+ * @returns { entity }
375
+ */
376
+ #getentityforuac() {
377
+ if( "uac" == this.type ) {
378
+ return this.options.entity
379
+ }
380
+ }
381
+
382
+ /**
383
+ *
384
+ * @returns { entity }
385
+ */
386
+ #getentityforuas() {
387
+ if( !this._entity ) return
388
+
389
+ if( this._entity.uri ) {
390
+ if( !this._entity.username ) {
391
+ const uriparts = this._entity.uri.split( "@" )
392
+ this._entity.username = uriparts[ 0 ]
393
+ if( 1 < uriparts.length )
394
+ this._entity.realm = uriparts[ 1 ]
395
+ }
396
+ }
397
+
398
+ if( !this._entity.uri && this._entity.username && this._entity.realm ) {
399
+ this._entity.uri = this._entity.username + "@" + this._entity.realm
400
+ }
401
+
402
+ return {
403
+ "username": this._entity.username,
404
+ "realm": this._entity.realm,
405
+ "uri": this._entity.uri,
406
+ "display": this._entity.display?this._entity.display:""
407
+ }
408
+ }
409
+
360
410
  /**
361
411
  * Returns the entity if known (i.e. outbound or inbound authed).
362
412
  * @returns { Promise< entity > }
@@ -364,32 +414,23 @@ class call {
364
414
  get entity() {
365
415
 
366
416
  return ( async () => {
367
- if( !this._entity ) return
368
-
369
- if( this._entity.uri ) {
370
- if( !this._entity.username ) {
371
- const uriparts = this._entity.uri.split( "@" )
372
- this._entity.username = uriparts[ 0 ]
373
- if( 1 < uriparts.length )
374
- this._entity.realm = uriparts[ 1 ]
375
- }
376
- }
377
417
 
378
- if( !this._entity.uri && this._entity.username && this._entity.realm ) {
379
- this._entity.uri = this._entity.username + "@" + this._entity.realm
418
+ let e
419
+ if( "uac" == this.type ) {
420
+ e = this.#getentityforuac()
421
+ } else {
422
+ e = this.#getentityforuas()
380
423
  }
381
-
424
+
425
+ if( !e ) return
426
+
382
427
  const entitycalls = await callstore.getbyentity( this._entity.uri )
383
428
  let entitycallcount = 0
384
429
  if( false !== entitycalls ) entitycallcount = entitycalls.size
430
+ e.ccc = entitycallcount
431
+
432
+ return e
385
433
 
386
- return {
387
- "username": this._entity.username,
388
- "realm": this._entity.realm,
389
- "uri": this._entity.uri,
390
- "display": this._entity.display?this._entity.display:"",
391
- "ccc": entitycallcount
392
- }
393
434
  } )()
394
435
  }
395
436
 
@@ -438,8 +479,6 @@ class call {
438
479
  parsed = this._req.getParsedHeader( "p-asserted-identity" )
439
480
  } else if( this._req.has( "remote-party-id" ) ) {
440
481
  parsed = this._req.getParsedHeader( "remote-party-id" )
441
- } else {
442
- parsed = this._req.getParsedHeader( "from" )
443
482
  }
444
483
  return parsed
445
484
  }
@@ -468,119 +507,219 @@ class call {
468
507
  * We make an outbound call. i.e. we send an INVITE
469
508
  *
470
509
  * Exceptions
471
- * clicktocall - we send an INVITE but that is an inbound call
510
+ * partycalled/clicktocall - we send an INVITE but that is an inbound call
472
511
  * so the invite is i nthe opposie direction.
473
512
  * @returns { "inbound" | "outbound" }
474
513
  */
475
514
  get direction() {
476
- if( this.options.clicktocall ) return "inbound"
515
+ if( this.options.partycalled ) return "inbound"
477
516
  return "uas"==this.type?"inbound":"outbound"
478
517
  }
479
518
 
519
+ #overridecallerid( startingpoint ) {
520
+
521
+ if( this.options.callerid ) {
522
+ if( "number" in this.options.callerid ) startingpoint.user = this.options.callerid.number
523
+ if( "name" in this.options.callerid ) startingpoint.name = this.options.callerid.name
524
+ if( "host" in this.options.callerid ) startingpoint.host = this.options.callerid.host
525
+ }
526
+ }
527
+
528
+ #overridecalledid( startingpoint ) {
529
+ startingpoint.privacy = this.options.privacy
530
+
531
+ if( this.options.calledid ) {
532
+ if( "number" in this.options.calledid ) {
533
+ startingpoint.user = this.options.calledid.number
534
+ startingpoint.uri = this.options.calledid.number + "@" + startingpoint.host
535
+ }
536
+ if( "name" in this.options.calledid ) startingpoint.name = this.options.calledid.name
537
+ }
538
+ }
539
+
540
+ #fromremoteheaders( startingpoint ) {
541
+ const parsed = this.#fixparseduriobj( this.#getremotefromheaders() )
542
+ if( parsed.uri ) startingpoint.uri = parsed.uri
543
+ if( parsed.user ) startingpoint.user = parsed.user
544
+ if( parsed.host ) startingpoint.host = parsed.host
545
+ }
546
+
547
+ #fromcontact( startingpoint ) {
548
+ const dest = parseuri( this.options.contact )
549
+ if( !dest ) return
550
+ startingpoint.uri = dest.uri
551
+ startingpoint.user = dest.user
552
+ startingpoint.host = dest.host
553
+ }
554
+
555
+ #fromdestination( startingpoint ) {
556
+ const dest = this.destination
557
+ startingpoint.user = dest.user
558
+ startingpoint.host = dest.host
559
+ }
560
+
561
+ #fromoutentity( startingpoint ) {
562
+
563
+ const entity = this.options.entity
564
+ if( entity ) {
565
+ startingpoint.name = entity.display
566
+ startingpoint.uri = entity.uri
567
+ startingpoint.user = entity.username
568
+ startingpoint.host = entity.realm
569
+ return true
570
+ }
571
+
572
+ return false
573
+ }
574
+
575
+ #frominentity( startingpoint ) {
576
+ const entity = this._entity
577
+
578
+ if( entity ) {
579
+ startingpoint.name = entity.display
580
+ startingpoint.uri = entity.uri
581
+ startingpoint.user = entity.username
582
+ startingpoint.host = entity.realm
583
+ return true
584
+ }
585
+
586
+ return false
587
+ }
588
+
589
+ #fromentity( startingpoint ) {
590
+
591
+ if( this.#fromoutentity( startingpoint ) ) return true
592
+ if( this.#frominentity( startingpoint ) ) return true
593
+
594
+ return false
595
+ }
596
+
597
+
480
598
  /**
481
- * Returns the called object. i.e.
482
- * If we are inbound then this is the destination
483
- * If we are outbound then this is the entity we are calling
484
- * @returns { remoteid }
599
+ * We have received an INVITE
600
+ * @param { object } startingpoint
485
601
  */
486
- get calledid() {
602
+ #calledidforuas( startingpoint ) {
603
+ this.#fromdestination( startingpoint )
604
+ }
605
+
606
+ /**
607
+ * We have sent an INVITE - which could also be 3rd party
608
+ * @param { object } startingpoint
609
+ */
610
+ #calledidforuac( startingpoint ) {
611
+ if( !this.#fromoutentity( startingpoint ) ) {
612
+ this.#fromcontact( startingpoint )
613
+ }
614
+ }
615
+
616
+
617
+ /**
618
+ * We have sent an INVITE - but it could be 3rd party
619
+ * @param { object } startingpoint
620
+ * @returns
621
+ */
622
+ #calleridforuac( startingpoint ) {
623
+ if( !this.#fromoutentity( startingpoint ) ) {
624
+ this.#fromcontact( startingpoint )
625
+ }
626
+ }
627
+
628
+ /**
629
+ * We have received an INVITE - so caller ID comes from headers / auth
630
+ * * @param { object } startingpoint
631
+ */
632
+ #calleridforuas( startingpoint ) {
633
+ this.#frominentity( startingpoint )
634
+ this.#fromremoteheaders( startingpoint )
635
+ }
487
636
 
637
+ #callerid() {
488
638
  const startingpoint = {
489
639
  "name": "",
490
640
  "uri": "",
491
641
  "user": "0000000000",
492
642
  "host": "localhost.localdomain",
493
643
  "privacy": true === this.options.privacy,
494
- "type": "calledid"
644
+ "type": "callerid"
495
645
  }
496
646
 
497
- if( "outbound" === this.direction ) {
498
- if( this.parent ) {
499
- const dest = this.parent.destination
500
- startingpoint.user = dest.user
501
- startingpoint.host = dest.host
647
+ if( "uas" == this.type ) this.#calleridforuas( startingpoint )
648
+ else {
649
+ if( this.options.partycalled ) {
650
+ this.#calleridforuac( startingpoint )
502
651
  } else {
503
- const dest = parseuri( this.options.contact )
504
- startingpoint.user = dest.user
505
- startingpoint.host = dest.host
506
- }
507
-
508
- } else { /* inbound */
509
- if( this.parent ) {
510
- const dest = this.parent.destination
511
- startingpoint.user = dest.user
512
- startingpoint.host = dest.host
513
- } else {
514
- const dest = this.destination
515
- startingpoint.user = dest.user
516
- startingpoint.host = dest.host
517
- }
518
- }
519
-
520
- startingpoint.privacy = this.options.privacy
652
+ const other = this.other
521
653
 
522
- if( this.options.calledid ) {
523
- if( "number" in this.options.calledid ) {
524
- startingpoint.user = this.options.calledid.number
525
- startingpoint.uri = this.options.calledid.number + "@" + startingpoint.host
654
+ if( other ) {
655
+ if( "uas" == other.type ) {
656
+ other.#calleridforuas( startingpoint )
657
+ other.#overridecallerid( startingpoint )
658
+ } else {
659
+ other.#calledidforuac( startingpoint )
660
+ }
661
+ } else {
662
+ this.#calleridforuac( startingpoint )
663
+ }
526
664
  }
527
- if( "name" in this.options.calledid ) startingpoint.name = this.options.calledid.name
528
665
  }
529
666
 
667
+ this.#overridecallerid( startingpoint )
530
668
  return startingpoint
531
669
  }
532
670
 
533
671
  /**
534
672
  * @returns { remoteid }
535
673
  */
536
- // eslint-disable-next-line complexity
537
674
  get callerid() {
675
+ return this.#callerid()
676
+ }
538
677
 
539
- let startingpoint = {
678
+ #calledid() {
679
+ const startingpoint = {
540
680
  "name": "",
541
681
  "uri": "",
542
682
  "user": "0000000000",
543
683
  "host": "localhost.localdomain",
544
684
  "privacy": true === this.options.privacy,
545
- "type": "callerid"
685
+ "type": "calledid"
546
686
  }
547
687
 
548
- if( "outbound" === this.direction ) {
549
- if( this.parent ) {
550
- startingpoint = this.parent.callerid
551
- } else {
552
- const parseduri = parseuri( this.options.contact )
553
- if( parseduri.user ) {
554
- startingpoint.uri = this.options.contact
555
- startingpoint.user = parseduri.user
556
- startingpoint.host = parseduri.host
688
+ if( "uas" == this.type ) this.#calledidforuas( startingpoint )
689
+ else {
690
+ if( !this.options.partycalled ) this.#calledidforuac( startingpoint )
691
+
692
+ const other = this.other
693
+
694
+ if( other ) {
695
+ if( "uas" == other.type ) {
696
+ if( this.options.partycalled ) {
697
+ other.#calleridforuas( startingpoint )
698
+ } else {
699
+ other.#calledidforuas( startingpoint )
700
+ }
701
+ } else {
702
+ other.#calledidforuac( startingpoint )
557
703
  }
558
- }
559
- } else { /* inbound */
560
- if( this._entity ) {
561
- startingpoint.name = this._entity.display
562
- startingpoint.uri = this._entity.uri
563
- startingpoint.user = this._entity.username
564
- startingpoint.host = this._entity.realm
565
- } else {
566
- let parsed = this.#getremotefromheaders()
567
- parsed = this.#fixparseduriobj( parsed )
568
-
569
- startingpoint.uri = parsed.uri
570
- startingpoint.user = parsed.user
571
- startingpoint.host = parsed.host
704
+ other.#overridecalledid( startingpoint )
572
705
  }
573
706
  }
574
707
 
575
- if( this.options.callerid ) {
576
- if( "number" in this.options.callerid ) startingpoint.user = this.options.callerid.number
577
- if( "name" in this.options.callerid ) startingpoint.name = this.options.callerid.name
578
- if( "host" in this.options.callerid ) startingpoint.host = this.options.callerid.host
579
- }
708
+ this.#overridecalledid( startingpoint )
580
709
 
581
710
  return startingpoint
582
711
  }
583
712
 
713
+ /**
714
+ * Returns the called object. i.e.
715
+ * If we are inbound then this is the destination
716
+ * If we are outbound then this is the entity we are calling
717
+ * @returns { remoteid }
718
+ */
719
+ get calledid() {
720
+ return this.#calledid()
721
+ }
722
+
584
723
  /**
585
724
  * @param { string } c
586
725
  */
@@ -997,6 +1136,7 @@ class call {
997
1136
  adopt( other, mix ) {
998
1137
  other.parent = this
999
1138
  this.children.add( other )
1139
+ other.moh = this.moh
1000
1140
 
1001
1141
  /* maintain privacy */
1002
1142
  other.options.privacy = this.options.privacy
@@ -1196,7 +1336,13 @@ class call {
1196
1336
  */
1197
1337
  get other() {
1198
1338
  if( this.parent ) return this.parent
1339
+ return this.child
1340
+ }
1199
1341
 
1342
+ /**
1343
+ * Return specifically first child - prefer established otherwise first
1344
+ */
1345
+ get child() {
1200
1346
  /* first established */
1201
1347
  for( const child of this.children ) {
1202
1348
  if( child.established ) {
@@ -1714,7 +1860,7 @@ class call {
1714
1860
  * @returns { Promise } resolves on timeout or when unmix happens
1715
1861
  * @private
1716
1862
  */
1717
- _hold( direction = "recvonly" ) {
1863
+ _hold( direction = "inactive" ) {
1718
1864
 
1719
1865
  if( this.state.held ) return
1720
1866
  this.state.held = true
@@ -1855,10 +2001,15 @@ class call {
1855
2001
  Send out pre-modified SDP to get the audio to the new location.
1856
2002
  This method might be use, but there are problems - so when it is used
1857
2003
  it can be re-written but should use a mthod to create a codec - which is the
1858
- same as used elsewhere.
2004
+ same as used elsewhere. If a bond has been attached to the call, we will
2005
+ try to reuse an existing channel.
2006
+ @param { object } [ channeldef ]
1859
2007
  @private
1860
2008
  */
1861
- async reinvite() {
2009
+ async reinvite( channeldef ) {
2010
+
2011
+ if ( !channeldef )
2012
+ channeldef = await this.#createchannelremotedef()
1862
2013
 
1863
2014
  const remotesdp = await this._dialog.modify( this.sdp.local.toString() )
1864
2015
  .catch( ( e ) => {
@@ -1872,10 +2023,31 @@ class call {
1872
2023
  this.sdp.remote.setdynamepayloadtypes( this.sdp.local )
1873
2024
  }
1874
2025
 
1875
- const channeldef = await this.#createchannelremotedef()
1876
- if( channeldef ) /* we should always get in here */
1877
- this.channels.audio.remote( channeldef.remote )
2026
+ }
2027
+
2028
+ /**
2029
+ Mix two calls. If the two calls are on a different node
2030
+ the second call is bonded and reinvited.
2031
+ @param { call } othercall - our call object which is early
2032
+ @private
2033
+ */
2034
+ async mix( othercall ) {
2035
+ if ( othercall.channels.audio
2036
+ && othercall.channels.audio.connection.instance
2037
+ != this.channels.audio.connection.instance ) {
2038
+
2039
+ const channeldef = await othercall.#createchannelremotedef()
2040
+
2041
+ const oldchannel = othercall.channels.audio
2042
+ // eslint-disable-next-line require-atomic-updates
2043
+ othercall.channels.audio = await this.channels.audio.openchannel( channeldef, othercall._handlechannelevents.bind( othercall ) )
2044
+
2045
+ await othercall.bond( this ).reinvite( channeldef )
1878
2046
 
2047
+ await oldchannel.close()
2048
+ }
2049
+
2050
+ await this.channels.audio.mix( othercall.channels.audio )
1879
2051
  }
1880
2052
 
1881
2053
  /**
@@ -2256,19 +2428,24 @@ class call {
2256
2428
  } )
2257
2429
  } )
2258
2430
 
2431
+ /*
2432
+ TODO - this is wrong. If we want to include this - it is not the REFER CSEQ that jssip
2433
+ is looking for - it is the cseq of the INVITE.
2259
2434
  const id = this._req.get( "cseq" ).match( /(\d+)/ )[ 0 ]
2435
+ Leave out for now - as this works for us.
2436
+ */
2260
2437
  try {
2261
- await this._notifyreferstart( id )
2438
+ await this._notifyreferstart()
2262
2439
  } catch( e ) {
2263
2440
  console.trace( e )
2264
- this._notifyreferfail( id )
2441
+ this._notifyreferfail()
2265
2442
  return
2266
2443
  }
2267
2444
 
2268
2445
  /* Link logically and mix */
2269
2446
  a_1.adopt( c_1, true )
2270
2447
 
2271
- this._notifyrefercomplete( id )
2448
+ this._notifyrefercomplete()
2272
2449
 
2273
2450
  a_1.state.refered = true
2274
2451
 
@@ -2579,7 +2756,7 @@ class call {
2579
2756
  }
2580
2757
  }
2581
2758
 
2582
- options.headers[ "Max-Forwards" ] = maxforwards
2759
+ options.headers[ "max-forwards" ] = maxforwards
2583
2760
 
2584
2761
  if( !options.orphan && !options.parent ) {
2585
2762
  options.parent = this
@@ -2700,7 +2877,7 @@ class call {
2700
2877
  /* TODO: this is a hack. projectrtp has become too complicated with both a listen and connect
2701
2878
  mechanism. This is causing problems in code like this. There is no interface to
2702
2879
  detect which mode the channel is in - but the channels property will exist on a connect
2703
- style channel. projectrtp will get a rewrite to support only one. */
2880
+ style channel. projectrtp will getrelatives a rewrite to support only one. */
2704
2881
  if( relatedcall && relatedcall.channels.audio && relatedcall.channels.audio.channels ) {
2705
2882
  this.channels.audio = await this.other.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2706
2883
  return
@@ -2818,10 +2995,16 @@ class call {
2818
2995
  }
2819
2996
 
2820
2997
  /**
2998
+ * https://www.ietf.org/proceedings/50/I-D/sip-privacy-01.txt
2821
2999
  * @returns { object }
2822
3000
  */
2823
3001
  #configcalleridfornewuac() {
2824
3002
 
3003
+ let party = ";party=calling"
3004
+ if( this.options.partycalled ) {
3005
+ party = ";party=called"
3006
+ }
3007
+
2825
3008
  const callerid = this.callerid
2826
3009
  const calleridstr = `"${callerid.name}" <sip:${callerid.user}@${callerid.host}>`
2827
3010
 
@@ -2834,12 +3017,20 @@ class call {
2834
3017
  RFC 3325 - should we also consider the P-Preferred-Identity header?
2835
3018
  P-Asserted-Identity?
2836
3019
  */
2837
- this.options.headers[ "Remote-Party-ID" ] = calleridstr + ";party=calling;screen=yes" + privacy
2838
- this.options.headers[ "From" ] = calleridstr
3020
+ this.options.headers[ "remote-party-id" ] = calleridstr + party + ";screen=yes" + privacy
3021
+ this.options.headers[ "from" ] = calleridstr
2839
3022
 
2840
3023
  return { user: callerid.user, realm: callerid.host }
2841
3024
  }
2842
3025
 
3026
+
3027
+ #configureto() {
3028
+ if( this.options.headers[ "to" ] ) return
3029
+ if( !this.options.entity ) return
3030
+
3031
+ this.options.headers[ "to" ] = "<sip:" + this.options.entity.uri + ">"
3032
+ }
3033
+
2843
3034
  /**
2844
3035
  *
2845
3036
  * @param { string } contactstr
@@ -2848,16 +3039,19 @@ class call {
2848
3039
 
2849
3040
  const parts = parseuri( contactstr )
2850
3041
 
2851
- if( this.options.clicktocall ) this.options.autoanswer = true
3042
+ if( this.options.clicktocall ) {
3043
+ this.options.partycalled = true
3044
+ this.options.autoanswer = true
3045
+ }
2852
3046
 
2853
3047
  if( !this.options.contactparams ) this.options.contactparams = ""
2854
3048
  if( true === this.options.autoanswer ) {
2855
- this.options.headers[ "Call-Info" ] = `<sip:${parts.host}>;answer-after=0`
2856
- this.options.headers[ "Alert-Info" ] = "auto-answer"
3049
+ this.options.headers[ "call-info" ] = `<sip:${parts.host}>;answer-after=0`
3050
+ this.options.headers[ "alert-info" ] = "auto-answer"
2857
3051
  this.options.contactparams += ";intercom=true"
2858
3052
  } else if ( "number" == typeof this.options.autoanswer ) {
2859
- this.options.headers[ "Call-Info" ] = `<sip:${parts.host}>;answer-after=${this.options.autoanswer}`
2860
- this.options.headers[ "Alert-Info" ] = "auto-answer"
3053
+ this.options.headers[ "call-info" ] = `<sip:${parts.host}>;answer-after=${this.options.autoanswer}`
3054
+ this.options.headers[ "alert-info" ] = "auto-answer"
2861
3055
  this.options.contactparams += ";intercom=true"
2862
3056
  }
2863
3057
  }
@@ -2914,6 +3108,7 @@ class call {
2914
3108
  * @property { object } [ uactimeout ] - override the deault timeout
2915
3109
  * @property { true | number } [ autoanswer ] - if true add call-info to auto answer, if number delay to add
2916
3110
  * @property { boolean } [ clicktocall ] - if set to true, will set autoanswer to true and swap the source and desination on caller ID
3111
+ * @property { boolean } [ partycalled ] - reverses the direction of the call from the invite
2917
3112
  * @property { boolean } [ late ] - late negotiation
2918
3113
  * @property { boolean } [ privacy ] - sets the privacy
2919
3114
  * @property { entity } [ entity ] - used to store this call against and look up a contact string if not supplied.
@@ -2964,6 +3159,7 @@ class call {
2964
3159
  * @param { newuaccallbacks } [ callbacks ]
2965
3160
  * @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.
2966
3161
  */
3162
+ // eslint-disable-next-line complexity
2967
3163
  static async newuac( options, callbacks = {} ) {
2968
3164
 
2969
3165
  if( !options.contact && !options.entity ) return false
@@ -2982,24 +3178,26 @@ class call {
2982
3178
 
2983
3179
  newcall.bond( options.bond )
2984
3180
 
3181
+ // spread is not recursive
3182
+ newcall.options = { ...newcall.options, ...options }
3183
+ const tmpheaders = { ...callmanager.options.headers, ...newcall.options.headers, ...options.headers }
3184
+ newcall.options.headers = keynameslower( tmpheaders )
3185
+
2985
3186
  if( options.entity ) {
2986
3187
  newcall.entity = options.entity
2987
3188
  callstore.set( newcall )
3189
+
2988
3190
  }
2989
3191
 
2990
- // spread is not recursive
2991
- newcall.options = { ...newcall.options, ...options }
2992
- const tmpheaders = { ...callmanager.options.headers, ...newcall.options.headers, ...options.headers }
2993
- newcall.options.headers = tmpheaders
2994
-
2995
3192
  newcall.#configcalleridfornewuac()
3193
+ newcall.#configureto()
2996
3194
  newcall.import()
2997
3195
 
2998
3196
  newcall.#configautoanswerfornewuac( options.contact )
2999
3197
 
3000
- newcall.options.headers[ "Allow-Events" ] = "talk, hold, presence, as-feature-event, dialog, call-info, sla, include-session-description, message-summary, refer"
3001
- newcall.options.headers[ "Allow" ] = "INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE"
3002
- newcall.options.headers[ "Supported" ] = "timer, path, replaces"
3198
+ newcall.options.headers[ "allow-events" ] = "talk, hold, presence, as-feature-event, dialog, call-info, sla, include-session-description, message-summary, refer"
3199
+ newcall.options.headers[ "allow" ] = "INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE"
3200
+ newcall.options.headers[ "supported" ] = "timer, path, replaces"
3003
3201
 
3004
3202
  newcall.#confignetwork( options )
3005
3203
  await newcall.#openchannelsfornewuac()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/babble-drachtio-callmanager",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "Call processing to create a PBX",
5
5
  "main": "index.js",
6
6
  "scripts": {