@babblevoice/projectrtp 2.6.0 → 2.6.2

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/Dockerfile CHANGED
@@ -11,12 +11,12 @@ RUN apk add --no-cache \
11
11
  cd libilbc-3.0.4; \
12
12
  cmake . -DCMAKE_INSTALL_LIBDIR=/lib -DCMAKE_INSTALL_INCLUDEDIR=/usr/include; cmake --build .; cmake --install .;
13
13
 
14
- WORKDIR /usr/local/lib/node_modules/@babblevoice/projectrtp/
14
+ WORKDIR /usr/src/projectrtp
15
15
  COPY . .
16
16
 
17
- RUN npm ci --no-optional --production && \
18
- rm -fr src/build/Release/obj.target && \
19
- rm -fr build/Release/obj.target/projectrtp
17
+ # a more correct to install this module into the global location
18
+ RUN npm install --production --build-from-source && \
19
+ npm install -g .
20
20
 
21
21
  FROM alpine:3.21 AS app
22
22
 
package/README.md CHANGED
@@ -66,7 +66,7 @@ If you wish to build outsode of a Docker image, there are npm target scripts for
66
66
 
67
67
  ```bash
68
68
  docker buildx prune
69
- docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:2.5.37_beta22 . --push
69
+ docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:2.6.2 . --push
70
70
  ```
71
71
 
72
72
  ### Dev build
package/binding.gyp CHANGED
@@ -33,12 +33,14 @@
33
33
  [
34
34
  "build_type=='prod'", {
35
35
  "cflags": [
36
- "-O3"
36
+ "-O3",
37
+ "-g"
37
38
  ]
38
39
  }
39
40
  ]
40
41
  ],
41
42
  "ldflags": [
43
+ "-g",
42
44
  "-Wl,-z,relro",
43
45
  "-Wl,-z,now",
44
46
  "-Wl,--export-dynamic" ],
package/lib/server.js CHANGED
@@ -103,8 +103,9 @@ class channel {
103
103
  openresolve
104
104
 
105
105
  /**
106
+ * listening or connection
106
107
  * @private
107
- * @type { string }
108
+ * @type { "l" | "c" }
108
109
  */
109
110
  ctype
110
111
 
@@ -346,6 +347,7 @@ class channel {
346
347
  const newchannel = new channel()
347
348
  if( cb ) newchannel.em.on( "all", cb )
348
349
 
350
+ newchannel.ctype = this.ctype
349
351
  newchannel.connection = this.connection
350
352
  newchannel.channels = this.channels
351
353
  newchannel.channels.push( newchannel )
@@ -541,7 +543,7 @@ class channel {
541
543
  }
542
544
 
543
545
  /**
544
- * We have received teh open confirm message so we should action it
546
+ * We have received the open confirm message so we should action it
545
547
  * @private
546
548
  * @param { object } msg
547
549
  * @returns { boolean } - is further processing required
@@ -592,14 +594,17 @@ class channel {
592
594
  }
593
595
 
594
596
  #cleanupsharedchannels() {
595
- if( this.channels ) {
596
- // adjust with filter
597
- const index = this.channels.indexOf( this )
598
- if( -1 < index ) this.channels.splice( index, 1 )
599
- if( this.ctype == "c" && 0 === this.channels.length && this.connection.sock ) {
600
- this.connection.sock.destroy()
601
- }
602
- }
597
+ if( !this.channels ) return
598
+
599
+ // adjust with filter
600
+ const index = this.channels.indexOf( this )
601
+ if( -1 < index ) this.channels.splice( index, 1 )
602
+
603
+ if( "c" !== this.ctype ) return
604
+ if( 0 !== this.channels.length ) return
605
+ if( !this.connection.sock ) return
606
+
607
+ this.connection.sock.destroy()
603
608
  }
604
609
 
605
610
  #haserror( msg ) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/projectrtp",
3
- "version": "2.6.0",
3
+ "version": "2.6.2",
4
4
  "description": "A scalable Node addon RTP server",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -83,6 +83,7 @@ projectrtpchannel::projectrtpchannel( unsigned short port ):
83
83
  ssrcin( 0 ),
84
84
  ssrcout( 0 ),
85
85
  tsout( 0 ),
86
+ eventtsout( 0 ),
86
87
  snout( 0 ),
87
88
  send( true ),
88
89
  recv( true ),
@@ -710,20 +711,33 @@ bool projectrtpchannel::recordercompleted( const channelrecorder::pointer& rec )
710
711
  }
711
712
 
712
713
  /**
713
- * @brief Helper function for checkfordtmf - signal back to our control server that an event has been received.
714
- *
714
+ * Helper function for checkfordtmf -
715
+ * 1. stop player if set to stop on event
716
+ * 2. signal back to our control server that an event has been received.
717
+ * 3. forward to other channels we are mixing with
715
718
  */
716
719
  static char dtmfchars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', 'A', 'B', 'C', 'D', 'F' };
717
720
  void projectrtpchannel::sendtelevent( void ) {
718
721
  auto self = shared_from_this();
719
- SpinLockGuard guard( this->playerlock );
720
722
 
721
- if( this->player && this->player->doesinterupt() ) {
722
- postdatabacktojsfromthread( self, "play", "end", "telephone-event" );
723
- this->player = nullptr;
723
+ {
724
+ SpinLockGuard guard( this->playerlock );
725
+
726
+ if( this->player && this->player->doesinterupt() ) {
727
+ postdatabacktojsfromthread( self, "play", "end", "telephone-event" );
728
+ this->player = nullptr;
729
+ }
724
730
  }
725
731
 
726
732
  postdatabacktojsfromthread( self, "telephone-event", std::string( 1, dtmfchars[ this->lasttelephoneevent ] ) );
733
+
734
+ if( !this->mixing ) return;
735
+
736
+ {
737
+ SpinLockGuard guard( this->mixerlock );
738
+ this->mixer->senddtmf( self, dtmfchars[ this->lasttelephoneevent ] );
739
+ }
740
+
727
741
  }
728
742
  /*
729
743
  ## checkfordtmf
@@ -1233,19 +1247,26 @@ void projectrtpchannel::dounmix( void ) {
1233
1247
  }
1234
1248
  }
1235
1249
 
1236
- /*
1237
- ## dtmf
1238
- Queue digits to send as RFC 2833.
1239
- */
1250
+ /**
1251
+ * Queue digits to send as RFC 2833.
1252
+ */
1240
1253
  void projectrtpchannel::dtmf( std::string digits ) {
1241
1254
  SpinLockGuard guard( this->queuddigitslock );
1242
1255
  this->queueddigits += digits;
1243
1256
  }
1244
1257
 
1245
- const char volume = 10;
1258
+ /**
1259
+ * Queue digit to send as RFC 2833.
1260
+ */
1261
+ void projectrtpchannel::dtmf( char digit ) {
1262
+ SpinLockGuard guard( this->queuddigitslock );
1263
+ this->queueddigits += digit;
1264
+ }
1265
+
1266
+ const char volume = 13;
1246
1267
  const char endofevent = 0x80;
1247
1268
 
1248
- const int numevents = 3;
1269
+ const int numevents = 10;
1249
1270
  const int numendevents = 3;
1250
1271
 
1251
1272
  /*
@@ -1265,9 +1286,7 @@ void projectrtpchannel::senddtmf( void ) {
1265
1286
  }
1266
1287
  }
1267
1288
 
1268
- if( 0 == tosend ) {
1269
- return;
1270
- }
1289
+ if( 0 == tosend ) return;
1271
1290
 
1272
1291
  /*
1273
1292
  RFC 2833:
@@ -1297,9 +1316,18 @@ void projectrtpchannel::senddtmf( void ) {
1297
1316
 
1298
1317
  if( this->dtmfsendcount <= numevents ) {
1299
1318
  rtppacket *dst = this->gettempoutbuf();
1319
+ /* the timestamp is fixed to the start of the event */
1320
+ if( 0 == this->dtmfsendcount ) {
1321
+ this->eventtsout = this->tsout;
1322
+ }
1323
+
1324
+ dst->settimestamp( this->eventtsout );
1300
1325
  dst->setpayloadtype( this->rfc2833pt );
1301
1326
  dst->setpayloadlength( 4 );
1302
- uint8_t *pl = dst->getpayload();
1327
+ uint8_t *pl = dst->getpayload();
1328
+
1329
+ dst->setmarker( 0 == this->dtmfsendcount );
1330
+
1303
1331
  pl[ 0 ] = tosend;
1304
1332
  pl[ 1 ] = volume; /* end of event & reserved & volume */
1305
1333
  uint16_t *tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
@@ -1310,8 +1338,9 @@ void projectrtpchannel::senddtmf( void ) {
1310
1338
  } else {
1311
1339
  /* end packet */
1312
1340
  rtppacket *dst = this->gettempoutbuf();
1341
+
1342
+ dst->settimestamp( this->eventtsout );
1313
1343
  dst->setpayloadtype( this->rfc2833pt );
1314
- dst->setmarker();
1315
1344
  dst->setpayloadlength( 4 );
1316
1345
  uint8_t *pl = dst->getpayload();
1317
1346
  pl[ 0 ] = tosend;
@@ -114,12 +114,14 @@ public:
114
114
  bool mix( projectrtpchannel::pointer other );
115
115
  bool unmix( void );
116
116
  void dtmf( std::string digits );
117
+ void dtmf( char digit );
117
118
  rtppacket *gettempoutbuf( void );
118
119
 
119
120
  std::atomic_uint32_t codec;
120
121
  uint32_t ssrcin;
121
122
  uint32_t ssrcout;
122
123
  uint32_t tsout;
124
+ uint32_t eventtsout;
123
125
  uint16_t snout;
124
126
 
125
127
  /* do we send, do we receive */
@@ -85,11 +85,6 @@ void projectchannelmux::mixall( void ) {
85
85
 
86
86
  if( !chan->checkfordtmf( src ) ) break;
87
87
 
88
- for( auto& dtmfchan: this->channels ) {
89
- if( dtmfchan->recv && chan.get() != dtmfchan.get() ) {
90
- this->postrtpdata( chan, dtmfchan, src );
91
- }
92
- }
93
88
  /* remove the DTMF packet */
94
89
  {
95
90
  SpinLockGuard guard( chan->rtpbufferlock );
@@ -175,8 +170,8 @@ void projectchannelmux::mix2( void ) {
175
170
  }
176
171
  }
177
172
 
173
+ /* process but ignore and look for next other packet */
178
174
  if( !chan1->checkfordtmf( src ) ) break;
179
- this->postrtpdata( chan1, chan2, src );
180
175
  }
181
176
  this->postrtpdata( chan1, chan2, src );
182
177
 
@@ -205,11 +200,25 @@ void projectchannelmux::mix2( void ) {
205
200
  }
206
201
 
207
202
  if( !chan2->checkfordtmf( src ) ) break;
208
- this->postrtpdata( chan2, chan1, src );
209
203
  }
204
+
210
205
  this->postrtpdata( chan2, chan1, src );
211
206
  }
212
207
 
208
+ /**
209
+ * Called from a channel which has received DTMF - we forward onto all other channels,
210
+ * this is likely to have been called from mix2 and mixall. NB this only queues
211
+ * the digit on the outbound - we have to actuall send them as well.
212
+ */
213
+ void projectchannelmux::senddtmf( projectrtpchannelptr from, char digit ) {
214
+ for( auto& chan: this->channels ) {
215
+ if( chan.get() == from.get() ) continue;
216
+ if( !chan->recv ) continue;
217
+
218
+ chan->dtmf( digit );
219
+ }
220
+ }
221
+
213
222
  bool projectchannelmux::channelremoverequested( const projectrtpchannelptr& chan ) {
214
223
  if( chan->removemixer || chan->_requestclose || (!chan->active) ) {
215
224
  chan->dounmix();
@@ -267,7 +276,7 @@ void projectchannelmux::handletick( const boost::system::error_code& error ) {
267
276
 
268
277
  for( auto& chan: workingchannels ) {
269
278
  chan->senddtmf();
270
- chan->writerecordings(); //////////////////// crash here -> channel -> soundfile - there is a problem with the CODEC - this can remove recorders from channel
279
+ chan->writerecordings();
271
280
  chan->checkidlerecv(); // this can call doclose() - recorders might be destroyed now
272
281
  chan->endticktimer();
273
282
 
@@ -35,6 +35,7 @@ public:
35
35
  inline size_t size() { return this->channels.size(); }
36
36
  void addchannel( projectrtpchannelptr chan );
37
37
  void addchannels( projectrtpchannelptr chana, projectrtpchannelptr chanb );
38
+ void senddtmf( projectrtpchannelptr from, char digit );
38
39
  void go( void );
39
40
 
40
41
  private:
@@ -5,6 +5,11 @@ const dgram = require( "dgram" )
5
5
 
6
6
  const pcap = require( "./pcap" )
7
7
 
8
+ const pkcountperdtmfdigit = 14 /* defined in projectrtpchannel::senddtmf */
9
+ const pausebetweendtmfdigits = 200 /* mS 10 pks ref projectrtpchannel::senddtmf */
10
+ const timeperdtmfdigit = ( pkcountperdtmfdigit * 20 /* mS */ ) + pausebetweendtmfdigits
11
+ const dtmfeventduration = ( ( pkcountperdtmfdigit - 2) * 160 )
12
+
8
13
  /*
9
14
  i.e. the RTP payload
10
15
  str = "80 e5 03 b5 00 02 44 a0 1e e3 61 fb 03 0a 00 a0 4c d1"
@@ -168,9 +173,13 @@ describe( "dtmf", function() {
168
173
  } )
169
174
 
170
175
 
171
- it( "single channel and request rtp server to send 2833", function( done ) {
176
+ it( "single channel and request rtp server to send 2833", async function() {
172
177
  /* TODO - check tre fuller structure of an RTP event (duration, volume, etc) */
173
178
  /* create our RTP/UDP endpoint */
179
+
180
+ let done
181
+ const finished = new Promise( resolve => done = resolve )
182
+
174
183
  const server = dgram.createSocket( "udp4" )
175
184
  let dtmfpkcount = 0
176
185
  server.on( "message", function( msg ) {
@@ -182,41 +191,46 @@ describe( "dtmf", function() {
182
191
  }
183
192
  } )
184
193
 
185
- this.timeout( 3000 )
186
- this.slow( 2500 )
194
+ this.timeout( 5000 )
195
+ this.slow( 4000 )
187
196
 
188
197
  server.bind()
189
- server.on( "listening", async function() {
198
+ await new Promise( resolve => server.on( "listening", resolve ) )
190
199
 
191
- const ourport = server.address().port
200
+ const ourport = server.address().port
192
201
 
193
- let expectedmessagecount = 0
194
- const expectedmessages = [
195
- { action: "close" }
196
- ]
202
+ let expectedmessagecount = 0
203
+ const expectedmessages = [
204
+ { action: "close" }
205
+ ]
197
206
 
198
- const channel = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": ourport, "codec": 0 } }, function( d ) {
207
+ const channel = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": ourport, "codec": 0 } }, function( d ) {
199
208
 
200
- expect( d ).to.deep.include( expectedmessages[ expectedmessagecount ] )
201
- expectedmessagecount++
209
+ expect( d ).to.deep.include( expectedmessages[ expectedmessagecount ] )
210
+ expectedmessagecount++
202
211
 
203
- if( "close" === d.action ) {
204
- server.close()
205
- expect( dtmfpkcount ).to.equal( 2*7 )
206
- done()
207
- }
208
- } )
212
+ if( "close" === d.action ) {
213
+ server.close()
214
+ done()
215
+ }
216
+ } )
209
217
 
210
- expect( channel.echo() ).to.be.true
218
+ expect( channel.echo() ).to.be.true
211
219
 
212
- /* send a packet every 20mS x 50 */
213
- for( let i = 0; 50 > i; i ++ ) {
214
- sendpk( i, i*160, i*20, channel.local.port, server )
215
- }
220
+ /* send a packet every 20mS x 50 */
221
+ for( let i = 0; 50 > i; i ++ ) {
222
+ sendpk( i, i*160, i*20, channel.local.port, server )
223
+ }
224
+
225
+ await new Promise( resolve => setTimeout( resolve, 400 ) )
226
+ channel.dtmf( "#1" )
227
+
228
+ await new Promise( resolve => setTimeout( resolve, 1000 ) )
229
+ channel.close()
230
+ await finished
231
+
232
+ expect( dtmfpkcount ).to.equal( 2*pkcountperdtmfdigit )
216
233
 
217
- setTimeout( () => channel.dtmf( "#1" ), 400 )
218
- setTimeout( () => channel.close(), 1000 )
219
- } )
220
234
  } )
221
235
 
222
236
 
@@ -274,7 +288,7 @@ describe( "dtmf", function() {
274
288
 
275
289
  await new Promise( ( resolve ) => { setTimeout( () => resolve(), 400 ) } )
276
290
  channela.dtmf( "*9F" )
277
- await new Promise( ( resolve ) => { setTimeout( () => resolve(), 800 ) } )
291
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 3 * timeperdtmfdigit ) } )
278
292
  channela.close()
279
293
 
280
294
  await finished
@@ -282,18 +296,14 @@ describe( "dtmf", function() {
282
296
  clienta.close()
283
297
  clientb.close()
284
298
 
285
- expect( dtmfpks.length ).to.equal( 3*7 )
299
+ expect( dtmfpks.length ).to.equal( 3*pkcountperdtmfdigit )
286
300
  expect( dtmfpks[ 0 ].event.id ).to.equal( 10 )
287
301
  expect( dtmfpks[ 0 ].event.duration ).to.equal( 160 )
288
302
  expect( dtmfpks[ 0 ].event.eoe ).to.be.false
289
303
 
290
- expect( dtmfpks[ 4 ].event.id ).to.equal( 10 )
291
- expect( dtmfpks[ 4 ].event.duration ).to.equal( 800 )
292
- expect( dtmfpks[ 4 ].event.eoe ).to.be.true
293
-
294
- expect( dtmfpks[ 6 ].event.id ).to.equal( 10 )
295
- expect( dtmfpks[ 6 ].event.duration ).to.equal( 800 )
296
- expect( dtmfpks[ 6 ].event.eoe ).to.be.true
304
+ expect( dtmfpks[ pkcountperdtmfdigit - 3 ].event.id ).to.equal( 10 )
305
+ expect( dtmfpks[ pkcountperdtmfdigit - 3 ].event.duration ).to.equal( dtmfeventduration )
306
+ expect( dtmfpks[ pkcountperdtmfdigit - 3 ].event.eoe ).to.be.true
297
307
 
298
308
  } )
299
309
 
@@ -354,7 +364,7 @@ describe( "dtmf", function() {
354
364
 
355
365
  await new Promise( ( resolve ) => { setTimeout( () => resolve(), 400 ) } )
356
366
  channela.dtmf( "*9F" )
357
- await new Promise( ( resolve ) => { setTimeout( () => resolve(), 800 ) } )
367
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 3 * timeperdtmfdigit ) } )
358
368
  channela.close()
359
369
 
360
370
  await finished
@@ -362,7 +372,7 @@ describe( "dtmf", function() {
362
372
  clienta.close()
363
373
  clientb.close()
364
374
 
365
- expect( dtmfpkcount ).to.equal( 3*7 )
375
+ expect( dtmfpkcount ).to.equal( 3*pkcountperdtmfdigit )
366
376
  } )
367
377
 
368
378
  it( "3 channels mixing and request rtp server to send 2833 to one", async function() {
@@ -436,14 +446,14 @@ describe( "dtmf", function() {
436
446
 
437
447
  await new Promise( ( resolve ) => { setTimeout( () => resolve(), 100 ) } )
438
448
  channela.dtmf( "*9ABD" )
439
- await new Promise( ( resolve ) => { setTimeout( () => resolve(), 1500 ) } )
449
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 5 * timeperdtmfdigit ) } )
440
450
  channela.close()
441
451
 
442
452
  clienta.close()
443
453
  clientb.close()
444
454
  clientc.close()
445
455
 
446
- expect( dtmfpks.length ).to.equal( 5*7 )
456
+ expect( dtmfpks.length ).to.equal( 5*pkcountperdtmfdigit )
447
457
 
448
458
  await finished
449
459
  } )
@@ -721,9 +731,9 @@ describe( "dtmf", function() {
721
731
 
722
732
  await finished
723
733
 
734
+ expect( dtmfpkcount ).to.be.within( ( pkcountperdtmfdigit * 2 ) - 4 , pkcountperdtmfdigit * 2 ) /* allow loss */
724
735
  expect( endpointapkcount ).to.be.within( 30, 51 )
725
- expect( endpointbpkcount ).to.be.within( 30, 51 )
726
- expect( dtmfpkcount ).to.be.within( 4, 8 )
736
+ expect( endpointbpkcount - dtmfpkcount ).to.be.within( 30, 51 )
727
737
 
728
738
  expect( receivedmessages.length ).to.equal( 5 )
729
739
 
@@ -742,7 +752,7 @@ describe( "dtmf", function() {
742
752
  } )
743
753
 
744
754
 
745
- it( "mix 2 channels - pcmu <-> pcma and send DTMF different 2833 pt", async function() {
755
+ it( "wefwef mix 2 channels - pcmu <-> pcma and send DTMF different 2833 pt", async function() {
746
756
 
747
757
  /*
748
758
  When mixing 2 channels, we expect the second leg to receive the 2833 packets
@@ -864,11 +874,11 @@ describe( "dtmf", function() {
864
874
  await finished
865
875
 
866
876
  expect( endpointapkcount ).to.be.within( 30, 51 )
867
- expect( endpointbpkcount ).to.be.within( 30, 51 )
877
+ expect( endpointbpkcount - dtmfpkcount ).to.be.within( 30, 51 )
868
878
 
869
879
  expect( receivedmessages.length ).to.equal( 5 )
870
880
 
871
- expect( dtmfpkcount ).to.be.within( 4, 8 )
881
+ expect( dtmfpkcount ).to.be.within( ( pkcountperdtmfdigit * 2 ) - 4 , pkcountperdtmfdigit * 2 ) /* allow loss */
872
882
 
873
883
  expect( receivedmessages[ 0 ].action ).to.equal( "mix" )
874
884
  expect( receivedmessages[ 1 ].action ).to.equal( "telephone-event" )
@@ -936,13 +946,13 @@ describe( "dtmf", function() {
936
946
  } )
937
947
 
938
948
  endpointa.bind()
939
- await new Promise( ( r ) => { endpointa.on( "listening", function() { r() } ) } )
949
+ await new Promise( ( resolve ) => { endpointa.on( "listening", function() { resolve() } ) } )
940
950
 
941
951
  endpointb.bind()
942
- await new Promise( ( r ) => { endpointb.on( "listening", function() { r() } ) } )
952
+ await new Promise( ( resolve ) => { endpointb.on( "listening", function() { resolve() } ) } )
943
953
 
944
954
  endpointc.bind()
945
- await new Promise( ( r ) => { endpointc.on( "listening", function() { r() } ) } )
955
+ await new Promise( ( resolve ) => { endpointc.on( "listening", function() { resolve() } ) } )
946
956
 
947
957
  const receveiedmessages = []
948
958
 
@@ -1053,13 +1063,13 @@ describe( "dtmf", function() {
1053
1063
  ] )
1054
1064
 
1055
1065
  expect( endpointapkcount ).to.be.within( 59, 70 )
1056
- expect( endpointbpkcount ).to.be.within( 59, 70 )
1057
- expect( endpointcpkcount ).to.be.within( 59, 70 )
1066
+ expect( endpointbpkcount - dtmfbpkcount ).to.be.within( 59, 70 )
1067
+ expect( endpointcpkcount - dtmfcpkcount ).to.be.within( 59, 70 )
1058
1068
 
1059
1069
  // 3 after we return to the event loop and enter the callback with close event.
1060
1070
  expect( dtmfapkcount ).to.equal( 0 )
1061
- expect( dtmfbpkcount ).to.be.within( 4, 8 )
1062
- expect( dtmfcpkcount ).to.be.within( 4, 8 )
1071
+ expect( dtmfbpkcount ).to.be.within( ( pkcountperdtmfdigit * 2 ) - 4, pkcountperdtmfdigit * 2 )
1072
+ expect( dtmfcpkcount ).to.be.within( ( pkcountperdtmfdigit * 2 ) - 4, pkcountperdtmfdigit * 2 )
1063
1073
 
1064
1074
  expect( receveiedmessages[ 0 ].action ).to.equal( "mix" )
1065
1075
  expect( receveiedmessages[ 1 ].action ).to.equal( "mix" )
@@ -407,11 +407,10 @@ describe( "record", function() {
407
407
  this.slow( 7000 )
408
408
 
409
409
  let done
410
- const finished = new Promise( ( r ) => done = r )
410
+ const finished = new Promise( ( resolve ) => done = resolve )
411
411
 
412
412
  /* create our RTP/UDP endpoint */
413
413
  const server = dgram.createSocket( "udp4" )
414
- let channel
415
414
 
416
415
  /* generate our data */
417
416
  const startsilenceseconds = 1
@@ -430,44 +429,41 @@ describe( "record", function() {
430
429
  ] )
431
430
 
432
431
  server.on( "message", function() {} )
433
-
434
432
  server.bind()
433
+ await new Promise( resolve => server.on( "listening", resolve ) )
434
+
435
435
  const receivedmessages = []
436
+ const channel = await prtp.projectrtp.openchannel( { "remote": { "address": "localhost", "port": server.address().port, "codec": 0 } }, function( d ) {
437
+ receivedmessages.push( d )
438
+ if( "close" !== d.action ) return
436
439
 
437
- server.on( "listening", async function() {
440
+ done()
441
+ } )
438
442
 
439
- channel = await prtp.projectrtp.openchannel( { "remote": { "address": "localhost", "port": server.address().port, "codec": 0 } }, function( d ) {
440
- receivedmessages.push( d )
441
- if( "close" === d.action ) {
442
- done()
443
- }
444
- } )
443
+ expect( channel.record( {
444
+ "file": "/tmp/dualrecording.wav"
445
+ } ) ).to.be.true
445
446
 
446
- expect( channel.record( {
447
- "file": "/tmp/dualrecording.wav"
448
- } ) ).to.be.true
447
+ expect( channel.record( {
448
+ "file": "/tmp/dualrecordingpower.wav",
449
+ "startabovepower": 40,
450
+ "finishbelowpower": 200,
451
+ "minduration": 200,
452
+ "maxduration": 3500,
453
+ "poweraveragepackets": 10 /* faster response */
454
+ } ) ).to.be.true
449
455
 
450
- expect( channel.record( {
451
- "file": "/tmp/dualrecordingpower.wav",
452
- "startabovepower": 40,
453
- "finishbelowpower": 200,
454
- "minduration": 200,
455
- "maxduration": 3500,
456
- "poweraveragepackets": 10 /* faster response */
457
- } ) ).to.be.true
458
-
459
- /* something to record */
460
- expect( channel.echo() ).to.be.true
456
+ /* something to record */
457
+ expect( channel.echo() ).to.be.true
461
458
 
462
- for( let i = 0; i < 50*totalseconds; i ++ ) {
463
- sendpk( i, i, channel.local.port, server, sendbuffer )
464
- }
465
- } )
459
+ for( let i = 0; i < 50*totalseconds; i ++ ) {
460
+ sendpk( i, i, channel.local.port, server, sendbuffer )
461
+ }
466
462
 
467
- setTimeout( () => channel.close(), totalseconds * 1000 )
463
+ await new Promise( resolve => setTimeout( resolve, totalseconds * 1000 ) )
464
+ channel.close()
468
465
  await finished
469
-
470
- server.close()
466
+ await new Promise( resolve => server.close( () => resolve() ) )
471
467
 
472
468
  let stats = fs.statSync( "/tmp/dualrecordingpower.wav" )
473
469
  expect( stats.size ).to.be.within( 30000 , 41000 )
@@ -52,10 +52,15 @@ describe( "rtpproxy server", function() {
52
52
  } )
53
53
 
54
54
  let closereceived = false
55
- n.setmessagehandler( "close", () => {
55
+ n.setmessagehandler( "close", ( msg ) => {
56
+
57
+ n.sendmessage( {
58
+ "action": "close",
59
+ "id": msg.id,
60
+ "uuid": msg.uuid
61
+ } )
62
+
56
63
  closereceived = true
57
- n.destroy()
58
- p.destroy()
59
64
  } )
60
65
 
61
66
  const ourport = getnextport()
@@ -80,9 +85,10 @@ describe( "rtpproxy server", function() {
80
85
  expect( channel.uuid ).that.is.a( "string" )
81
86
  expect( channel.id ).that.is.a( "string" )
82
87
 
83
- channel.close()
88
+ await channel.close()
84
89
 
85
- await new Promise( ( r ) => { setTimeout( () => r(), 10 ) } )
90
+ n.destroy()
91
+ p.destroy()
86
92
 
87
93
  expect( closereceived ).to.be.true
88
94
  } )
@@ -108,12 +114,12 @@ describe( "rtpproxy server", function() {
108
114
  receivedecho = true
109
115
  } )
110
116
 
111
- let closeresolve
112
- const closereceived = new Promise( resolve => closeresolve = resolve )
113
- n.setmessagehandler( "close", () => {
114
- n.destroy()
115
- p.destroy()
116
- closeresolve()
117
+ n.setmessagehandler( "close", ( msg ) => {
118
+ n.sendmessage( {
119
+ "action": "close",
120
+ "id": msg.id,
121
+ "uuid": msg.uuid
122
+ } )
117
123
  } )
118
124
 
119
125
  const ourport = getnextport()
@@ -121,10 +127,11 @@ describe( "rtpproxy server", function() {
121
127
  await n.connect( ourport )
122
128
  const channel = await prtp.openchannel()
123
129
  channel.echo()
124
- channel.close()
130
+ await channel.close()
131
+
132
+ n.destroy()
133
+ p.destroy()
125
134
 
126
- /* this will only resolve when close received */
127
- await closereceived
128
135
 
129
136
  expect( receivedecho ).to.be.true
130
137
  } )
@@ -154,12 +161,12 @@ describe( "rtpproxy server", function() {
154
161
  expect( msg ).to.have.property( "digits" ).that.is.a( "string" ).to.equal( "#123" )
155
162
  } )
156
163
 
157
- let closeresolve
158
- const closereceived = new Promise( resolve => closeresolve = resolve )
159
- n.setmessagehandler( "close", () => {
160
- n.destroy()
161
- p.destroy()
162
- closeresolve()
164
+ n.setmessagehandler( "close", ( msg ) => {
165
+ n.sendmessage( {
166
+ "action": "close",
167
+ "id": msg.id,
168
+ "uuid": msg.uuid
169
+ } )
163
170
  } )
164
171
 
165
172
  const ourport = getnextport()
@@ -167,9 +174,10 @@ describe( "rtpproxy server", function() {
167
174
  await n.connect( ourport )
168
175
  const channel = await prtp.openchannel()
169
176
  channel.dtmf( "#123" )
170
- channel.close()
177
+ await channel.close()
171
178
 
172
- await closereceived
179
+ n.destroy()
180
+ p.destroy()
173
181
 
174
182
  expect( reveiveddtmf ).to.be.true
175
183
  } )
@@ -197,12 +205,12 @@ describe( "rtpproxy server", function() {
197
205
  let unmxmsg = {}
198
206
  n.setmessagehandler( "unmix", ( msg ) => unmxmsg = msg )
199
207
 
200
- let closeresolve
201
- const closereceived = new Promise( resolve => closeresolve = resolve )
202
- n.setmessagehandler( "close", () => {
203
- n.destroy()
204
- p.destroy()
205
- closeresolve()
208
+ n.setmessagehandler( "close", ( msg ) => {
209
+ n.sendmessage( {
210
+ "action": "close",
211
+ "id": msg.id,
212
+ "uuid": msg.uuid
213
+ } )
206
214
  } )
207
215
 
208
216
  const ourport = getnextport()
@@ -213,10 +221,13 @@ describe( "rtpproxy server", function() {
213
221
  channela.mix( channelb )
214
222
  channela.unmix()
215
223
 
216
- channela.close()
217
- channelb.close()
224
+ await Promise.all( [
225
+ channela.close(),
226
+ channelb.close()
227
+ ] )
218
228
 
219
- await closereceived
229
+ n.destroy()
230
+ p.destroy()
220
231
 
221
232
  expect( mxmsg ).to.have.property( "channel" ).that.is.a( "string" ).to.equal( "mix" )
222
233
  expect( mxmsg ).to.have.property( "other" ).that.is.a( "object" )
@@ -250,7 +261,13 @@ describe( "rtpproxy server", function() {
250
261
  } )
251
262
  } )
252
263
 
253
- n.setmessagehandler( "close", () => {} )
264
+ n.setmessagehandler( "close", ( msg ) => {
265
+ n.sendmessage( {
266
+ "action": "close",
267
+ "id": msg.id,
268
+ "uuid": msg.uuid
269
+ } )
270
+ } )
254
271
 
255
272
  n2.setmessagehandler( "open", ( msg ) => {
256
273
  n2.sendmessage( {
@@ -266,7 +283,13 @@ describe( "rtpproxy server", function() {
266
283
 
267
284
  } )
268
285
 
269
- n2.setmessagehandler( "close", () => {} )
286
+ n2.setmessagehandler( "close", ( msg ) => {
287
+ n.sendmessage( {
288
+ "action": "close",
289
+ "id": msg.id,
290
+ "uuid": msg.uuid
291
+ } )
292
+ } )
270
293
 
271
294
  const ourport = getnextport()
272
295
  const p = await prtp.proxy.listen( undefined, "127.0.0.1", ourport )
@@ -276,10 +299,11 @@ describe( "rtpproxy server", function() {
276
299
  const channel1 = await prtp.openchannel()
277
300
  const channel2 = await prtp.openchannel()
278
301
 
279
- channel1.close()
280
- channel2.close()
281
-
282
- await new Promise( ( r ) => { setTimeout( () => r(), 10 ) } )
302
+ await Promise.all( [
303
+ channel1.close(),
304
+ channel2.close()
305
+ ] )
306
+
283
307
 
284
308
  n.destroy()
285
309
  n2.destroy()
@@ -314,12 +338,12 @@ describe( "rtpproxy server", function() {
314
338
  remotereceived = true
315
339
  } )
316
340
 
317
- let closeresolve
318
- const closereceived = new Promise( resolve => closeresolve = resolve )
319
- n.setmessagehandler( "close", () => {
320
- n.destroy()
321
- p.destroy()
322
- closeresolve()
341
+ n.setmessagehandler( "close", ( msg ) => {
342
+ n.sendmessage( {
343
+ "action": "close",
344
+ "id": msg.id,
345
+ "uuid": msg.uuid
346
+ } )
323
347
  } )
324
348
 
325
349
  const ourport = getnextport()
@@ -328,8 +352,9 @@ describe( "rtpproxy server", function() {
328
352
  const channel = await prtp.openchannel()
329
353
  channel.remote( "wouldbearemoteobject" )
330
354
 
331
- channel.close()
332
- await closereceived
355
+ await channel.close()
356
+ n.destroy()
357
+ p.destroy()
333
358
 
334
359
  expect( remotereceived ).to.be.true
335
360
  } )
@@ -370,11 +395,15 @@ describe( "rtpproxy server", function() {
370
395
  let recmsg
371
396
  n.setmessagehandler( "record", ( msg ) => {
372
397
  recmsg = msg
373
- channel.close()
398
+ done()
374
399
  } )
375
400
 
376
- n.setmessagehandler( "close", () => {
377
- done()
401
+ n.setmessagehandler( "close", ( msg ) => {
402
+ n.sendmessage( {
403
+ "action": "close",
404
+ "id": msg.id,
405
+ "uuid": msg.uuid
406
+ } )
378
407
  } )
379
408
 
380
409
  const ourport = getnextport()
@@ -384,6 +413,7 @@ describe( "rtpproxy server", function() {
384
413
  channel.play( "wouldbeaplayobject" )
385
414
 
386
415
  await completed
416
+ await channel.close()
387
417
 
388
418
  n.destroy()
389
419
  p.destroy()
@@ -400,7 +430,7 @@ describe( "rtpproxy server", function() {
400
430
  expect( playmsg ).to.have.property( "uuid" ).that.is.a( "string" )
401
431
  expect( playmsg ).to.have.property( "soup" ).that.is.a( "string" ).to.equal( "wouldbeaplayobject" )
402
432
 
403
- expect( channel.history ).to.be.an( "array" ).to.have.length( 6 )
433
+ expect( channel.history ).to.be.an( "array" ).to.have.length( 7 )
404
434
 
405
435
  } )
406
436
 
@@ -437,12 +467,17 @@ describe( "rtpproxy server", function() {
437
467
  "uuid": msg.uuid
438
468
  } )
439
469
 
440
- setTimeout( () => channel.close(), 10 )
441
- } )
442
- n.setmessagehandler( "close", () => {
443
470
  done()
444
471
  } )
445
472
 
473
+ n.setmessagehandler( "close", ( msg ) => {
474
+ n.sendmessage( {
475
+ "action": "close",
476
+ "id": msg.id,
477
+ "uuid": msg.uuid
478
+ } )
479
+ } )
480
+
446
481
  const ourport = getnextport()
447
482
  const p = await prtp.proxy.listen( undefined, "127.0.0.1", ourport )
448
483
  await n.connect( ourport )
@@ -450,6 +485,7 @@ describe( "rtpproxy server", function() {
450
485
  channel.direction( { send: false, recv: false } )
451
486
 
452
487
  await completed
488
+ await channel.close()
453
489
 
454
490
  n.destroy()
455
491
  p.destroy()
@@ -482,16 +518,12 @@ describe( "rtpproxy server", function() {
482
518
  } )
483
519
  } )
484
520
 
485
- let closeresolv
486
- const closepromise = new Promise( ( r ) => closeresolv = r )
487
521
  n.setmessagehandler( "close", ( msg, sendmessage ) => {
488
522
  sendmessage( {
489
523
  "action": "close",
490
524
  "uuid": msg.uuid,
491
525
  "id": msg.id
492
526
  } )
493
-
494
- closeresolv()
495
527
  } )
496
528
 
497
529
  const chnl = await prtp.openchannel()
@@ -500,9 +532,7 @@ describe( "rtpproxy server", function() {
500
532
  expect( chnl ).to.have.property( "local" ).that.is.a( "object" )
501
533
  expect( chnl.local ).to.have.property( "port" ).that.is.a( "number" )
502
534
  expect( chnl.local ).to.have.property( "address" ).that.is.a( "string" )
503
- chnl.close()
504
-
505
- await closepromise
535
+ await chnl.close()
506
536
 
507
537
  n.destroy()
508
538
 
@@ -554,15 +584,13 @@ describe( "rtpproxy server", function() {
554
584
  } )
555
585
  } )
556
586
 
557
- let closeresolv
558
- const closepromise = new Promise( ( r ) => closeresolv = r )
587
+
559
588
  n.setmessagehandler( "close", ( msg, sendmessage ) => {
560
589
  sendmessage( {
561
590
  "action": "close",
562
591
  "uuid": msg.uuid,
563
592
  "id": msg.id
564
593
  } )
565
- closeresolv()
566
594
  } )
567
595
 
568
596
  n2.setmessagehandler( "close", ( msg, sendmessage ) => {
@@ -571,7 +599,6 @@ describe( "rtpproxy server", function() {
571
599
  "uuid": msg.uuid,
572
600
  "id": msg.id
573
601
  } )
574
- closeresolv()
575
602
  } )
576
603
 
577
604
  const chnl = await prtp.openchannel()
@@ -579,10 +606,10 @@ describe( "rtpproxy server", function() {
579
606
 
580
607
  expect( chnl.connection ).to.be.equal( chnl2.connection )
581
608
 
582
- chnl.close()
583
- chnl2.close()
584
-
585
- await closepromise
609
+ Promise.all( [
610
+ chnl.close(),
611
+ chnl2.close()
612
+ ] )
586
613
 
587
614
  n.destroy()
588
615
  n2.destroy()