@babblevoice/babble-drachtio-callmanager 2.3.21 → 2.3.22

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 CHANGED
@@ -1019,39 +1019,14 @@ class call {
1019
1019
  } )
1020
1020
  }
1021
1021
 
1022
- /* A simple implimentation if we are offered candidates */
1023
- static async _parsesdpcandidates( target, sdp ) {
1024
-
1025
- if( Array.isArray( sdp.media[ 0 ].candidates ) ) {
1026
- let candidates = sdp.media[ 0 ].candidates
1027
- if( 0 < candidates.length ) {
1028
- if( callmanager.options.ignoreipv6candidates ) {
1029
- candidates = candidates.filter( ( c ) => {
1030
- const ismatch = ipv6regex.test( c.ip )
1031
- return !ismatch
1032
- } )
1033
- }
1034
-
1035
- candidates.sort( ( l, r ) => { return r.priority - l.priority } )
1036
- target.port = candidates[ 0 ].port
1037
-
1038
- await new Promise( ( resolve ) => {
1039
- dns.lookup( candidates[ 0 ].ip, ( err, result ) => {
1040
- if( !err ) target.address = result
1041
- resolve()
1042
- } )
1043
- } )
1044
- }
1045
- }
1046
- }
1047
-
1048
1022
  async #answerparent() {
1049
1023
  if( this.parent ) {
1050
1024
  if( !this.parent.established ) {
1051
- await this.parent.answer()
1052
- .catch( ( err ) => {
1053
- console.trace( err )
1054
- } )
1025
+ try {
1026
+ await this.parent.answer()
1027
+ } catch( e ) {
1028
+ console.trace( e )
1029
+ }
1055
1030
 
1056
1031
  if( !this.parent.established ) {
1057
1032
  return this.hangup( hangupcodes.USER_GONE )
@@ -1091,35 +1066,19 @@ class call {
1091
1066
  this._addevents( this._dialog )
1092
1067
 
1093
1068
  this.sdp.remote = sdpgen.create( this._dialog.remote.sdp )
1094
- this.selectedcodec = this.sdp.remote.intersection( this.options.preferedcodecs, true )
1095
- if( !this.selectedcodec ) {
1069
+
1070
+ if( !this.sdp.remote.intersection( this.options.preferedcodecs, true ) ) {
1096
1071
  return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1097
1072
  }
1098
1073
 
1099
- const target = this.sdp.remote.getaudio()
1100
- if( !target ) return
1074
+ this.sdp.remote.setdynamepayloadtypes( this.sdp.local )
1101
1075
 
1102
- let channeldef
1103
- if( this._iswebrtc ) {
1104
- let actpass = "active"
1105
- if( "active" == this.sdp.remote.sdp.media[ 0 ].setup ) actpass = "passive" /* act|pass|actpass */
1106
-
1107
- await call._parsesdpcandidates( target, this.sdp.remote.sdp )
1108
-
1109
- channeldef = call._createchannelremotedef(
1110
- target.address,
1111
- target.port,
1112
- target.audio.payloads[ 0 ],
1113
- this.sdp.remote.sdp.media[ 0 ].fingerprint.hash,
1114
- actpass ).remote
1115
- } else {
1116
- channeldef = call._createchannelremotedef( target.address, target.port, target.audio.payloads[ 0 ] ).remote
1117
- }
1118
-
1119
- this.channels.audio.remote( channeldef )
1076
+ const channeldef = await this.#createchannelremotedef()
1077
+ if( !channeldef )
1078
+ return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1120
1079
 
1080
+ this.channels.audio.remote( channeldef.remote )
1121
1081
  await this.#answerparent()
1122
-
1123
1082
  return this
1124
1083
  }
1125
1084
 
@@ -1132,38 +1091,24 @@ class call {
1132
1091
  */
1133
1092
  async _onlatebridge() {
1134
1093
 
1135
- /* Calculate the best codec for both legs - find a common codec if possible
1136
- if not - transcode */
1137
1094
  this.sdp.remote = sdpgen.create( this._req.msg.body )
1138
1095
 
1139
- this.selectedcodec = this.sdp.remote.intersection( this.options.preferedcodecs, true )
1140
- if( !this.selectedcodec ) {
1096
+ const selectedcodec = this.sdp.remote.intersection( this.options.preferedcodecs, true )
1097
+ if( !selectedcodec ) {
1141
1098
  return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1142
1099
  }
1143
1100
 
1144
- const target = this.sdp.remote.getaudio()
1145
- if( !target ) return
1146
- let channeldef
1147
- if( this._iswebrtc ) {
1148
- let actpass = "active"
1149
- if( "act" == this.sdp.remote.sdp.media[ 0 ].setup ) actpass = "passive" /* act|pass|actpass */
1150
-
1151
- channeldef = call._createchannelremotedef(
1152
- target.address,
1153
- target.port,
1154
- target.audio.payloads[ 0 ],
1155
- this.sdp.remote.sdp.media[ 0 ].fingerprint.hash,
1156
- actpass )
1157
- } else {
1158
- channeldef = call._createchannelremotedef( target.address, target.port, target.audio.payloads[ 0 ] )
1159
- }
1101
+ const channeldef = await this.#createchannelremotedef()
1102
+ if( !channeldef )
1103
+ return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1160
1104
 
1161
1105
  await this.#openrelatedchannel()
1162
1106
 
1163
1107
  this.sdp.local = sdpgen.create()
1164
- .addcodecs( this.selectedcodec )
1108
+ .addcodecs( selectedcodec )
1165
1109
  .setconnectionaddress( this.channels.audio.local.address )
1166
1110
  .setaudioport( this.channels.audio.local.port )
1111
+ .setdynamepayloadtypes( this.sdp.remote )
1167
1112
 
1168
1113
  if( true === this.options.rfc2833 ) {
1169
1114
  this.sdp.local.addcodecs( "2833" )
@@ -1476,9 +1421,10 @@ class call {
1476
1421
  await this.#openrelatedchannel( channeldef )
1477
1422
 
1478
1423
  this.sdp.local = sdpgen.create()
1479
- .addcodecs( this.selectedcodec )
1424
+ .addcodecs( this.sdp.remote.selected.name )
1480
1425
  .setconnectionaddress( this.channels.audio.local.address )
1481
1426
  .setaudioport( this.channels.audio.local.port )
1427
+ .setdynamepayloadtypes( this.sdp.remote )
1482
1428
 
1483
1429
  this.#checkandadd2833()
1484
1430
 
@@ -1498,30 +1444,14 @@ class call {
1498
1444
  */
1499
1445
  async #choosecodecforanswer() {
1500
1446
  if( this._req.msg && this._req.msg.body ) {
1501
- this.selectedcodec = this.sdp.remote.intersection( this.options.preferedcodecs, true )
1502
- if( !this.selectedcodec ) {
1503
- return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1504
- }
1505
1447
 
1506
- this.sdp.remote.select( this.selectedcodec )
1507
-
1508
- const remoteaudio = this.sdp.remote.getaudio()
1509
- if( !remoteaudio ) {
1448
+ if( !this.sdp.remote.intersection( this.options.preferedcodecs, true ) ) {
1510
1449
  return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1511
1450
  }
1512
-
1513
- await call._parsesdpcandidates( remoteaudio, this.sdp.remote.sdp )
1514
-
1515
- const channeldef = call._createchannelremotedef( remoteaudio.address, remoteaudio.port, remoteaudio.audio.payloads[ 0 ] )
1516
-
1517
- if( this._iswebrtc ) {
1518
- channeldef.remote.dtls = {
1519
- "fingerprint": this.sdp.remote.sdp.media[ 0 ].fingerprint,
1520
- "mode": "passive" === this.sdp.remote.sdp.media[ 0 ].setup?"active":"passive" /* prefer passive for us */
1521
- }
1522
1451
 
1523
- channeldef.remote.icepwd = this.sdp.remote.sdp.media[ 0 ].icePwd
1524
- }
1452
+ const channeldef = await this.#createchannelremotedef()
1453
+ if( !channeldef )
1454
+ return this.hangup( hangupcodes.INCOMPATIBLE_DESTINATION )
1525
1455
 
1526
1456
  /* We might have already opened our audio when we received 183 (early). */
1527
1457
  await this.#openchannelsforanswer( channeldef )
@@ -1669,6 +1599,7 @@ class call {
1669
1599
  } )
1670
1600
 
1671
1601
  this._timers.anyevent = setTimeout( () => {
1602
+
1672
1603
  const r = this._promises.resolve.channelevent
1673
1604
  this._promises.promise.channelevent = undefined
1674
1605
  this._promises.resolve.channelevent = undefined
@@ -1861,7 +1792,7 @@ class call {
1861
1792
  }
1862
1793
 
1863
1794
  /**
1864
- Send out modified SDP to get the audio to the new location.
1795
+ Send out pre-modified SDP to get the audio to the new location.
1865
1796
  This method might be use, but there are problems - so when it is used
1866
1797
  it can be re-written but should use a mthod to create a codec - which is the
1867
1798
  same as used elsewhere.
@@ -1869,35 +1800,22 @@ class call {
1869
1800
  */
1870
1801
  async reinvite() {
1871
1802
 
1872
- this.sdp.local = sdpgen.create().addcodecs( this.selectedcodec )
1873
- this.sdp.local.setaudioport( this.channels.audio.local.port )
1874
- .setconnectionaddress( this.channels.audio.local.address )
1875
-
1876
- this.#checkandadd2833()
1877
-
1878
- /* DTLS is only supported ( outbound ) on websocket connections */
1879
- if( this._iswebrtc ) {
1880
- this.sdp.local
1881
- .addssrc( this.channels.audio.local.ssrc )
1882
- .secure( this.channels.audio.local.dtls.fingerprint ,"passive" )
1883
- .addicecandidates( this.channels.audio.local.address, this.channels.audio.local.port, this.channels.audio.local.icepwd )
1884
- .rtcpmux()
1885
- }
1886
-
1887
1803
  const remotesdp = await this._dialog.modify( this.sdp.local.toString() )
1888
1804
  .catch( ( e ) => {
1889
1805
  console.trace( e )
1890
1806
  } )
1807
+
1808
+ if( this.destroyed ) return
1891
1809
 
1892
- if( remotesdp )
1810
+ if( remotesdp ) {
1893
1811
  this.sdp.remote = sdpgen.create( remotesdp )
1812
+ this.sdp.remote.setdynamepayloadtypes( this.sdp.local )
1813
+ }
1894
1814
 
1895
- const target = this.sdp.remote.getaudio()
1896
- if( target ) /* we should always get in here */
1897
- this.channels.audio.remote( call._createchannelremotedef( target.address, target.port, this.selectedcodec ).remote )
1815
+ const channeldef = await this.#createchannelremotedef()
1816
+ if( channeldef ) /* we should always get in here */
1817
+ this.channels.audio.remote( channeldef.remote )
1898
1818
 
1899
- /* Now inform our RTP server also - we might need to wait until the target has completed so need a notify mechanism */
1900
- this.channels.audio.direction( { "send": true, "recv": true } )
1901
1819
  }
1902
1820
 
1903
1821
  /**
@@ -2270,29 +2188,81 @@ class call {
2270
2188
  }
2271
2189
 
2272
2190
  /**
2273
- Helper function to create a channel target definition
2274
- @private
2275
- @param { string } address - remote address (ip)
2276
- @param { number } port - remote port
2277
- @param { number } codec
2278
- @param { string } [ fingerprint ] - remote sha 256 fingerprint
2279
- @param { string } [ mode ] - "active"|"passive"
2280
- */
2281
- static _createchannelremotedef( address, port, codec, fingerprint, mode /* active|passive */ ) {
2282
- const chandef = {
2283
- "remote": {
2284
- "address": address,
2285
- "port": port,
2286
- "codec": codec
2191
+ * Obtain IP address from SDP - including looking at candidates if required
2192
+ * @param { boolean } parsecandidates - check the candidates in sdp also
2193
+ * @returns { Promise< object | undefined > }
2194
+ */
2195
+ async #getremotetarget( parsecandidates ) {
2196
+
2197
+ const target = this.sdp.remote.getaudio()
2198
+ if( !target ) return
2199
+ if( !parsecandidates ) return target
2200
+
2201
+ const sdp = this.sdp.remote.sdp
2202
+
2203
+ if( Array.isArray( sdp.media[ 0 ].candidates ) ) {
2204
+ let candidates = sdp.media[ 0 ].candidates
2205
+ if( 0 < candidates.length ) {
2206
+ if( callmanager.options.ignoreipv6candidates ) {
2207
+ candidates = candidates.filter( ( c ) => {
2208
+ const ismatch = ipv6regex.test( c.ip )
2209
+ return !ismatch
2210
+ } )
2211
+ }
2212
+
2213
+ candidates.sort( ( l, r ) => { return r.priority - l.priority } )
2214
+ target.port = candidates[ 0 ].port
2215
+
2216
+ await new Promise( ( resolve ) => {
2217
+ dns.lookup( candidates[ 0 ].ip, ( err, result ) => {
2218
+ if( !err ) target.address = result
2219
+ resolve()
2220
+ } )
2221
+ } )
2287
2222
  }
2288
2223
  }
2289
2224
 
2290
- if( fingerprint ) {
2291
- chandef.remote.dtls = {
2292
- "fingerprint": {
2293
- "hash": fingerprint
2294
- },
2295
- "mode": mode
2225
+ return target
2226
+ }
2227
+
2228
+ /**
2229
+ * Returns and object we can pass into an openchannel function,
2230
+ * { remote: {} } - the remote can be passed into set remote on
2231
+ * an already open channel.
2232
+ * @returns { Promise< object | undefined > }
2233
+ */
2234
+ async #createchannelremotedef() {
2235
+
2236
+ const iswebrtc = this._iswebrtc
2237
+ const target = await this.#getremotetarget( iswebrtc )
2238
+
2239
+ if( !target ) return
2240
+ const address = target.address
2241
+ const port = target.port
2242
+
2243
+ const codec = this.sdp.remote.selected
2244
+ if( !codec ) return
2245
+
2246
+ const chandef = {
2247
+ "remote": { address, port, codec: codec.pt }
2248
+ }
2249
+
2250
+ /* dynamic payload types */
2251
+ const dpts = this.sdp.remote.getdynamicpayloadtypes()
2252
+ if( "rfc2833" in dpts ) chandef.remote.rfc2833pt = dpts.rfc2833.payload
2253
+ if( "ilbc" in dpts ) chandef.remote.ilbcpt = dpts.ilbc.payload
2254
+
2255
+ if( iswebrtc ) {
2256
+
2257
+ const hash = this.sdp.remote.sdp.media[ 0 ].fingerprint.hash
2258
+ let mode = "active"
2259
+ if( "active" == this.sdp.remote.sdp.media[ 0 ].setup ) mode = "passive" /* act|pass|actpass */
2260
+
2261
+ if( hash ) {
2262
+ chandef.remote.dtls = {
2263
+ "fingerprint": { hash },
2264
+ mode
2265
+ }
2296
2266
  }
2297
2267
  }
2298
2268
  return chandef
@@ -2340,11 +2310,11 @@ class call {
2340
2310
  this._promises.resolve.auth = undefined
2341
2311
  if( authreject ) authreject( new SipError( hangupcodes.REQUEST_TIMEOUT, "Auth timed out (cleanup)" ) )
2342
2312
 
2343
- const chanev = this._promises.reject.channelevent
2313
+ const chanev = this._promises.resolve.channelevent
2344
2314
  this._promises.resolve.channelevent = undefined
2345
2315
  this._promises.reject.channelevent = undefined
2346
2316
  this._promises.promise.channelevent = undefined
2347
- if( chanev ) chanev( Error( "Call hungup" ) )
2317
+ if( chanev ) chanev()
2348
2318
 
2349
2319
  const resolves = []
2350
2320
  for ( const [ key, value ] of Object.entries( this._promises.resolve ) ) {
@@ -2729,8 +2699,9 @@ class call {
2729
2699
 
2730
2700
  await this.#openrelatedchannel( channeldef )
2731
2701
 
2732
- this.sdp.local = sdpgen.create().addcodecs( this.options.preferedcodecs )
2733
- this.sdp.local.setaudioport( this.channels.audio.local.port )
2702
+ this.sdp.local = sdpgen.create()
2703
+ .addcodecs( this.options.preferedcodecs )
2704
+ .setaudioport( this.channels.audio.local.port )
2734
2705
  .setconnectionaddress( this.channels.audio.local.address )
2735
2706
 
2736
2707
  this.#checkandadd2833()
@@ -2761,8 +2732,6 @@ class call {
2761
2732
  return this
2762
2733
  }
2763
2734
 
2764
- this.sdp.remote = sdpgen.create( this._dialog.remote.sdp )
2765
-
2766
2735
  if( this.parent ) {
2767
2736
  for( const child of this.parent.children ) {
2768
2737
  if( child.uuid !== this.uuid && !child.state.established ) {
@@ -3144,6 +3113,7 @@ class call {
3144
3113
 
3145
3114
  if( c._req.msg && c._req.msg.body ) {
3146
3115
  c.sdp.remote = sdpgen.create( c._req.msg.body )
3116
+ c.sdp.remote.intersection( callmanager.options.preferedcodecs, true )
3147
3117
  }
3148
3118
 
3149
3119
  /* set a timer using the default */
package/lib/sdp.js CHANGED
@@ -11,6 +11,15 @@ const crypto = require( "crypto" )
11
11
  */
12
12
  let sessionidcounter = Math.floor( Math.random() * 100000 )
13
13
 
14
+
15
+ const prtpcodecpts = {
16
+ "pcmu": 0,
17
+ "pcma": 8,
18
+ "g722": 9,
19
+ "ilbc": 97,
20
+ "2833": 101
21
+ }
22
+
14
23
  class codecconv {
15
24
 
16
25
  #pt2name = {
@@ -174,6 +183,7 @@ function getconfigforpt( audio, pt ) {
174
183
  class sdp {
175
184
 
176
185
  #dynamicpts
186
+ #selected
177
187
 
178
188
  constructor( sdp ) {
179
189
 
@@ -296,8 +306,8 @@ class sdp {
296
306
  if ( m ) {
297
307
 
298
308
  let payloads = m.payloads
299
- if ( this.selected !== undefined ) {
300
- payloads = [ this.selected ]
309
+ if ( this.#selected !== undefined ) {
310
+ payloads = [ this.#selected ]
301
311
  }
302
312
 
303
313
  let address
@@ -353,13 +363,31 @@ class sdp {
353
363
  select( codec ) {
354
364
  if ( isNaN( codec ) ) {
355
365
  if ( undefined === this.#dynamicpts.hascodec( codec ) ) return
356
- codec = this.#dynamicpts.getcodec( codec )
366
+ codec = this.#dynamicpts.getpt( codec )
357
367
  }
358
- this.selected = Number( codec )
368
+ this.#selected = codec
359
369
 
360
370
  return this
361
371
  }
362
372
 
373
+ /**
374
+ * @returns { object | undefined }
375
+ * @property { string } name - the name of the codec - i.e. pcma
376
+ * @property { number } pt - the payload type (static) used for prtp
377
+ * @property { number } dpt - the dynamic payload type negotiated for this session
378
+ */
379
+ get selected() {
380
+
381
+ if( undefined === this.#selected ) return undefined
382
+
383
+ const name = this.#dynamicpts.getcodec( this.#selected )
384
+ return {
385
+ name,
386
+ pt: prtpcodecpts[ name ],
387
+ dpt: this.#selected
388
+ }
389
+ }
390
+
363
391
  static create( from ) {
364
392
  return new sdp( from )
365
393
  }
@@ -619,6 +647,59 @@ class sdp {
619
647
 
620
648
  }
621
649
 
650
+ /**
651
+ * @returns { object } an object of codec name to payload type
652
+ * i.e.
653
+ * {
654
+ * "ilbc": { payload: 101, codec: "iLBC", rate: 8000 }
655
+ * }
656
+ * NB: it only returns a) our supported codecs and b) dynamic codecs - pcma, pcmu, g722 are statically defined
657
+ */
658
+ getdynamicpayloadtypes() {
659
+ const retval = {}
660
+
661
+ this.sdp.media.forEach( ( v ) => {
662
+ if( "rtp" in v ) {
663
+ v.rtp.forEach( r => {
664
+ const cname = r.codec.toLowerCase()
665
+ switch( cname ) {
666
+ case "ilbc":
667
+ if( 8000 == r.rate )
668
+ retval[ cname ] = r
669
+ break
670
+ case "telephone-event":
671
+ if( 8000 == r.rate )
672
+ retval[ "rfc2833" ] = r
673
+ }
674
+ } )
675
+ }
676
+ } )
677
+
678
+ return retval
679
+ }
680
+
681
+ /**
682
+ * Takes an object as returned by getdynamicpayloadtypes on another object
683
+ * to set the dynameic payloadtypes on this object
684
+ * @param { sdp } othersdp
685
+ */
686
+ setdynamepayloadtypes( othersdp ) {
687
+
688
+ if( !othersdp ) return this
689
+
690
+ const o = othersdp.getdynamicpayloadtypes()
691
+
692
+ if( "ilbc" in o && 8000 == o.ilbc.rate ) {
693
+ this.#dynamicpts.setdynamicpt( "ilbc", "ilbc", o.ilbc.payload )
694
+ }
695
+
696
+ if( "rfc2833" in o && 8000 == o.rfc2833.rate ) {
697
+ this.#dynamicpts.setdynamicpt( "2833", "telephone-event", o.rfc2833.payload )
698
+ }
699
+
700
+ return this
701
+ }
702
+
622
703
  toString() {
623
704
 
624
705
  /* We need to convert payloads back to string to stop a , being added */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/babble-drachtio-callmanager",
3
- "version": "2.3.21",
3
+ "version": "2.3.22",
4
4
  "description": "Call processing to create a PBX",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,16 +18,16 @@ describe( "call sdp generation", function() {
18
18
  let callnumber = 0
19
19
  const callcount = 6
20
20
  const codecsselected = []
21
- const c = await new Promise( ( done ) => {
21
+ await new Promise( ( resolve ) => {
22
22
  srfscenario.oncall( async ( call ) => {
23
23
  await call.answer()
24
24
 
25
- codecsselected.push( call.selectedcodec )
25
+ codecsselected.push( call.sdp.remote.selected.name )
26
26
  callnumber++
27
27
 
28
28
  call.hangup()
29
29
 
30
- if( callcount == callnumber ) done()
30
+ if( callcount == callnumber ) resolve()
31
31
  } )
32
32
 
33
33
  for( let i = 0; i < callcount; i++ ) {
@@ -2,8 +2,6 @@
2
2
 
3
3
  const expect = require( "chai" ).expect
4
4
  const sdp = require( "../../lib/sdp" )
5
- const call = require( "../../lib/call" )
6
- const callmanager = require( "../../index" )
7
5
 
8
6
  describe( "sdp", function() {
9
7
 
@@ -325,11 +323,9 @@ a=rtpmap:8 PCMA/8000`
325
323
  const oursdp = sdp.create( testsdp )
326
324
  const remoteaudio = oursdp.getaudio()
327
325
 
328
- const def = call._createchannelremotedef( remoteaudio.address, remoteaudio.port, remoteaudio.audio.payloads[ 0 ] )
329
-
330
- expect( def.remote.address ).to.equal( "213.166.4.136" )
331
- expect( def.remote.port ).to.equal( 48380 )
332
- expect( def.remote.codec ).to.equal( 8 )
326
+ expect( remoteaudio.address ).to.equal( "213.166.4.136" )
327
+ expect( remoteaudio.port ).to.equal( 48380 )
328
+ expect( remoteaudio.audio.payloads[ 0 ] ).to.equal( 8 )
333
329
  } )
334
330
 
335
331
  it( "another real life example", async function() {
@@ -686,11 +682,11 @@ a=rtpmap:126 telephone-event/8000
686
682
  a=ssrc:222390620 cname:q7Is0hRbTrTbcMJM
687
683
  a=ssrc:222390620 msid:a46039f4-1857-410e-b1cc-215c09878068 ce8c9c25-2ea0-4079-aaa5-54f771d53310
688
684
  `
689
- callmanager.callmanager( { srf: { use: () => {} } } )
685
+
690
686
  const sdpobj = sdp.create( sdpstr )
691
- const target = {}
692
- await call._parsesdpcandidates( target, sdpobj.sdp )
693
- sdpobj.intersection( "g722", true )
687
+ const target = sdpobj.getaudio()
688
+
689
+ expect( sdpobj.intersection( "g722", true ) ).to.equal( "g722" )
694
690
 
695
691
  /* our default is to ignore IPv6 addresses (until projectrtp supports it) */
696
692
  expect( target.port ).to.equal( 41645 )
@@ -799,9 +795,45 @@ a=rtpmap:127 telephone-event/8000`
799
795
 
800
796
  const sdpilbc = sdp.create( ilbcpt )
801
797
 
798
+ const expectdps = {
799
+ ilbc: { payload: 110, codec: "iLBC", rate: 8000 },
800
+ rfc2833: { payload: 127, codec: "telephone-event", rate: 8000 }
801
+ }
802
+
803
+ expect( sdpilbc.getdynamicpayloadtypes() ).to.deep.equal( expectdps )
804
+
802
805
  expect( sdpilbc.has( "ilbc" ) ).to.be.true
803
806
  expect( sdpilbc.has( "pcma" ) ).to.be.true
804
807
  expect( sdpilbc.has( "pcmu" ) ).to.be.true
805
808
  expect( sdpilbc.has( "g722" ) ).to.be.true
809
+
810
+ const othersdp = sdp.create().addcodecs( "ilbc 2833" ).setdynamepayloadtypes( sdpilbc )
811
+
812
+ expect( othersdp.toString() ).to.match( new RegExp( `v=0
813
+ o=- \\d+ 0 IN IP4 127.0.0.1
814
+ s=project
815
+ c=IN IP4 127.0.0.1
816
+ t=0 0
817
+ m=audio 0 RTP/AVP 97 101
818
+ a=rtpmap:110 ilbc/8000
819
+ a=rtpmap:127 telephone-event/8000
820
+ a=fmtp:110 mode=20
821
+ a=fmtp:127 0-16
822
+ a=ptime:20
823
+ a=sendrecv
824
+ `.replace( /\r\n/g, "\n" ).replace( /\n/g, "\r\n" ) ) )
825
+
826
+ sdpilbc.select( "pcma" )
827
+
828
+ const audio = sdpilbc.getaudio()
829
+
830
+ expect( audio.port ).to.equal( 63000 )
831
+ expect( audio.address ).to.equal( "82.19.206.102" )
832
+ expect( audio.audio.payloads[ 0 ] ).to.equal( 8 )
833
+
834
+ expect( sdpilbc.selected ).to.deep.equal( { name: "pcma", pt: 8, dpt: 8 } )
835
+ sdpilbc.select( "ilbc" )
836
+ expect( sdpilbc.selected ).to.deep.equal( { name: "ilbc", pt: 97, dpt: 110 } )
837
+
806
838
  } )
807
839
  } )