@babblevoice/babble-drachtio-callmanager 3.5.6 → 3.5.7

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 +84 -31
  2. package/package.json +1 -1
package/lib/call.js CHANGED
@@ -113,18 +113,6 @@ class SipError extends Error {
113
113
  }
114
114
  }
115
115
 
116
- /* Reverse codes - include inbound error codes.
117
- If not in this list we return REQUEST_TERMINATED during creation */
118
- /*
119
- const inboundsiperros = {
120
- 486: hangupcodes.USER_BUSY,
121
- 408: hangupcodes.REQUEST_TIMEOUT,
122
- 404: hangupcodes.UNALLOCATED_NUMBER,
123
- 603: hangupcodes.DECLINED
124
- }
125
- */
126
-
127
-
128
116
  const inboundsiperros = {}
129
117
  const hangupcodeskeys = Object.keys( hangupcodes )
130
118
  for (let i = 0; i < hangupcodeskeys.length; i++) {
@@ -219,6 +207,13 @@ class call {
219
207
  "closed": {
220
208
  "audio": []
221
209
  },
210
+ "secure": {
211
+ "audio": {
212
+ "offer": true,
213
+ "dtlscontroller": false,
214
+ "reinvite": false
215
+ }
216
+ },
222
217
  "count": 0
223
218
  }
224
219
 
@@ -1201,6 +1196,7 @@ class call {
1201
1196
 
1202
1197
  /* we have this._res */
1203
1198
  this.sdp.remote = sdpgen.create( this._res.msg.body )
1199
+ this.#parsesrtpsetup()
1204
1200
  await this.answer( { "early": true } )
1205
1201
 
1206
1202
  if( !this.parent || this.parent.state.established ) return
@@ -1269,6 +1265,8 @@ class call {
1269
1265
  return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1270
1266
  }
1271
1267
 
1268
+ this.#parsesrtpsetup()
1269
+
1272
1270
  this.sdp.remote.setdynamepayloadtypes( this.sdp.local )
1273
1271
 
1274
1272
  const channeldef = await this.#createchannelremotedef()
@@ -1294,6 +1292,8 @@ class call {
1294
1292
  else
1295
1293
  this.sdp.remote = sdpgen.create( this._req.msg.body )
1296
1294
 
1295
+ this.#parsesrtpsetup()
1296
+
1297
1297
  const selectedcodec = this.sdp.remote.intersection( this.options.preferedcodecs, true )
1298
1298
  if( !selectedcodec ) {
1299
1299
  return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
@@ -1321,7 +1321,7 @@ class call {
1321
1321
  if( this._iswebrtc ) {
1322
1322
  const ch = this.channels.audio
1323
1323
  this.sdp.local.addssrc( ch.local.ssrc )
1324
- .secure( ch.local.dtls.fingerprint, channeldef.remote.dtls.mode )
1324
+ .secure( ch.local.dtls.fingerprint, this.#getsrtpsetup( this.channels.secure.audio ) )
1325
1325
  .addicecandidates( ch.local.address, ch.local.port, ch.local.icepwd )
1326
1326
  .rtcpmux()
1327
1327
  }
@@ -1651,7 +1651,7 @@ class call {
1651
1651
 
1652
1652
  if( this._iswebrtc ) {
1653
1653
  this.sdp.local.addssrc( this.channels.audio.local.ssrc )
1654
- .secure( this.channels.audio.local.dtls.fingerprint, channeldef.remote.dtls.mode )
1654
+ .secure( this.channels.audio.local.dtls.fingerprint, this.#getsrtpsetup( this.channels.secure.audio ) )
1655
1655
  .addicecandidates( this.channels.audio.local.address, this.channels.audio.local.port, this.channels.audio.local.icepwd )
1656
1656
  .rtcpmux()
1657
1657
  }
@@ -2197,6 +2197,8 @@ class call {
2197
2197
 
2198
2198
  #getsdpformodify( req ) {
2199
2199
  const sdp = sdpgen.create( req.msg.body )
2200
+
2201
+ this.#parsesrtpsetup( sdp )
2200
2202
  const media = sdp.getmedia()
2201
2203
 
2202
2204
  let ip
@@ -2267,8 +2269,7 @@ class call {
2267
2269
  by AWOL... */
2268
2270
  this._timers.seinterval = setInterval( async () => {
2269
2271
 
2270
- try{
2271
-
2272
+ try {
2272
2273
  if( this.destroyed ) {
2273
2274
  /* this should be done - but we are still running */
2274
2275
  clearInterval( this._timers.seinterval )
@@ -2279,8 +2280,9 @@ class call {
2279
2280
 
2280
2281
  if( this._iswebrtc && this.channels && this.channels.audio ) {
2281
2282
  /* we are sending invite so we MUST offer be actpass */
2283
+ this.channels.secure.audio.offer = true
2282
2284
  this.sdp.local
2283
- .secure( this.channels.audio.local.dtls.fingerprint ,"actpass" )
2285
+ .secure( this.channels.audio.local.dtls.fingerprint, this.#getsrtpsetup( this.channels.secure.audio ) )
2284
2286
  }
2285
2287
 
2286
2288
  const opts = {
@@ -2334,17 +2336,14 @@ class call {
2334
2336
  // The application must respond, using the res parameter provided.
2335
2337
  if( "INVITE" !== req.msg.method ) return
2336
2338
 
2339
+ this.channels.secure.audio.reinvite = true
2340
+ const sdp = this.#getsdpformodify( req )
2341
+
2337
2342
  if( this._iswebrtc && this.channels && this.channels.audio ) {
2338
- /* I cannot figure out these rules - after reading RFC 3264 and 4145
2339
- I have fixed it like this as this is required by Chrome - but I am unsure why it is demanding this */
2340
- let mode = "passive"
2341
- if( "uas" == this.type ) mode = "active"
2342
2343
  this.sdp.local
2343
- .secure( this.channels.audio.local.dtls.fingerprint, mode )
2344
+ .secure( this.channels.audio.local.dtls.fingerprint, this.#getsrtpsetup( this.channels.secure.audio ) )
2344
2345
  }
2345
2346
 
2346
- const sdp = this.#getsdpformodify( req )
2347
-
2348
2347
  /* this was tested against jssip - which I don't think is correct. It was sending us
2349
2348
  sendonly when placing the call on hold. It didn't change the connection IP (although it did set the rtcp connection ip to 0.0.0.0!). */
2350
2349
  let d = sdp.media.direction
@@ -2634,6 +2633,59 @@ class call {
2634
2633
  return target
2635
2634
  }
2636
2635
 
2636
+ /**
2637
+ * I cannot figure out these rules - after reading RFC 3264 and 4145
2638
+ * I have fixed it like this as this is required by Chrome - but I am unsure why it is demanding this
2639
+ * This is for our local SDP - i.e. from our perspective.
2640
+ * @param { object } secure - the secure object i.e. this.channels.secure.audio
2641
+ * @returns { "passive" | "active" | "actpass" }
2642
+ */
2643
+ #getsrtpsetup( secure ) {
2644
+ if( secure.offer ) {
2645
+ /* ref: https://datatracker.ietf.org/doc/html/draft-ietf-rtcweb-jsep-14#page-34 offer MUST be actpass */
2646
+ secure.dtlscontroller = false
2647
+ secure.offer = false
2648
+ return "actpass"
2649
+ }
2650
+
2651
+ return secure.dtlscontroller ? "active" : "passive"
2652
+ }
2653
+
2654
+ /**
2655
+ * Parses our remote SDP to decide if we are the controller or not.
2656
+ * TODO - parse SDP for other streams.
2657
+ * @param { object } [ sdp ] - the sdp object - or leave if use our remote
2658
+ * @returns
2659
+ */
2660
+ #parsesrtpsetup( sdp ) {
2661
+ if( !sdp ) sdp = this.sdp.remote
2662
+ if( !sdp ) return
2663
+
2664
+ const audio = sdp.getmedia( "audio" )
2665
+ if( !audio ) return
2666
+
2667
+ if( "passive" == audio.setup ||
2668
+ ( "actpass" == audio.setup && !this.channels.secure.audio.reinvite ) ) {
2669
+ /* we might also have to re-negotiate our rtp server - but this should keep it in the right direction */
2670
+ this.channels.secure.audio.dtlscontroller = true
2671
+ this.channels.secure.audio.reinvite = false
2672
+ } else if( "active" == audio.setup ) {
2673
+ this.channels.secure.audio.dtlscontroller = false
2674
+ }
2675
+
2676
+ this.channels.secure.audio.offer = false
2677
+ }
2678
+
2679
+ /**
2680
+ * Get the mode string for our media server perspective.
2681
+ * @param { object } media object returned by sdp.getmedia()
2682
+ * @returns { "active" | "passive" }
2683
+ */
2684
+ #getsrtpsetupforchannel( media ) {
2685
+ if( "active" == media.setup ) return "passive"
2686
+ else return "active"
2687
+ }
2688
+
2637
2689
  /**
2638
2690
  * Returns and object we can pass into an openchannel function,
2639
2691
  * { remote: {} } - the remote can be passed into set remote on
@@ -2663,14 +2715,14 @@ class call {
2663
2715
 
2664
2716
  if( iswebrtc ) {
2665
2717
 
2666
- const hash = this.sdp.remote.sdp.media[ 0 ].fingerprint.hash
2667
- let mode = "active"
2668
- if( "active" == this.sdp.remote.sdp.media[ 0 ].setup ) mode = "passive" /* act|pass|actpass */
2669
-
2718
+ const audio = this.sdp.remote.getmedia( "audio" )
2719
+ if( !audio ) return
2720
+
2721
+ const hash = audio.fingerprint.hash
2670
2722
  if( hash ) {
2671
2723
  chandef.remote.dtls = {
2672
2724
  "fingerprint": { hash },
2673
- mode
2725
+ "mode": this.#getsrtpsetupforchannel( audio )
2674
2726
  }
2675
2727
  }
2676
2728
  }
@@ -3104,10 +3156,10 @@ class call {
3104
3156
 
3105
3157
  /* DTLS is only supported ( outbound ) on websocket connections */
3106
3158
  if( this._iswebrtc ) {
3159
+ this.channels.secure.audio.offer = true
3107
3160
  this.sdp.local
3108
3161
  .addssrc( this.channels.audio.local.ssrc )
3109
- /* ref: https://datatracker.ietf.org/doc/html/draft-ietf-rtcweb-jsep-14#page-34 offer MUST be actpass */
3110
- .secure( this.channels.audio.local.dtls.fingerprint ,"actpass" )
3162
+ .secure( this.channels.audio.local.dtls.fingerprint, this.#getsrtpsetup( this.channels.secure.audio ) )
3111
3163
  .addicecandidates( this.channels.audio.local.address, this.channels.audio.local.port, this.channels.audio.local.icepwd )
3112
3164
  .rtcpmux()
3113
3165
  }
@@ -3550,6 +3602,7 @@ class call {
3550
3602
  if( c._req.msg && c._req.msg.body ) {
3551
3603
  c.sdp.remote = sdpgen.create( c._req.msg.body )
3552
3604
  c.sdp.remote.intersection( callmanager.options.preferedcodecs, true )
3605
+ c.#parsesrtpsetup()
3553
3606
  }
3554
3607
 
3555
3608
  /* set a timer using the default */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/babble-drachtio-callmanager",
3
- "version": "3.5.6",
3
+ "version": "3.5.7",
4
4
  "description": "Call processing to create a PBX",
5
5
  "main": "index.js",
6
6
  "scripts": {