@babblevoice/projectrtp 2.5.31 → 2.5.35

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
@@ -1,7 +1,7 @@
1
1
 
2
2
  # docker build . -t <your username>/projectrtp
3
3
  # I have tied this to version alpine 3.16 as 3.17 has an exception symbol dynamic linking issue.
4
- FROM alpine:3.16 as builder
4
+ FROM alpine:3.20 AS builder
5
5
 
6
6
 
7
7
  WORKDIR /usr/src/
@@ -20,7 +20,7 @@ COPY . .
20
20
  RUN npm ci --no-optional --production;\
21
21
  rm -fr src/build/Release/obj.target
22
22
 
23
- FROM alpine:3.16 as app
23
+ FROM alpine:3.20 AS app
24
24
 
25
25
  RUN apk add --no-cache \
26
26
  spandsp tiff gnutls libsrtp libc6-compat openssl ca-certificates nodejs npm
package/README.md CHANGED
@@ -60,7 +60,7 @@ If you wish to build outsode of a Docker image, there are npm target scripts for
60
60
 
61
61
  ```bash
62
62
  docker buildx prune
63
- docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:2.5.29 . --push
63
+ docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:2.5.35 . --push
64
64
  ```
65
65
 
66
66
  ## Example scripts
package/binding.gyp ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "projectrtp",
5
+ "defines": [ "NODE_MODULE", "BOOST_NO_EXCEPTIONS", "BOOST_EXCEPTION_DISABLE", "NAPI_DISABLE_CPP_EXCEPTIONS" ],
6
+ "cflags_cc!": [ "-fno-rtti" ],
7
+ "cflags_cc": [
8
+ "-O3",
9
+ "-g",
10
+ "-Wall",
11
+ "-fstack-protector-strong",
12
+ "-std=c++20",
13
+ "-Weffc++" ],
14
+ "ldflags": [
15
+ "-Wl,-z,relro",
16
+ "-Wl,-z,now",
17
+ "-Wl,--export-dynamic" ],
18
+ "libraries": [
19
+ "-lrt",
20
+ "-lspandsp",
21
+ "-lilbc",
22
+ "-lgnutls",
23
+ "-lsrtp2" ],
24
+ "sources": [
25
+ "src/boostexception.cpp",
26
+ "src/projectrtpfirfilter.cpp",
27
+ "src/projectrtpnodemain.cpp",
28
+ "src/projectrtpbuffer.cpp",
29
+ "src/projectrtppacket.cpp",
30
+ "src/projectrtprawsound.cpp",
31
+ "src/projectrtpcodecx.cpp",
32
+ "src/projectrtpchannelrecorder.cpp",
33
+ "src/projectrtpsoundfile.cpp",
34
+ "src/projectrtpsoundsoup.cpp",
35
+ "src/projectrtptonegen.cpp",
36
+ "src/projectrtpchannel.cpp",
37
+ "src/projectrtpchannelmux.cpp",
38
+ "src/projectrtpsrtp.cpp",
39
+ "src/projectrtpstun.cpp" ],
40
+ "include_dirs": [
41
+ "src"
42
+ ]
43
+ }
44
+ ]
45
+ }
package/index.js CHANGED
@@ -10,7 +10,7 @@ const { spawnSync } = require( "child_process" )
10
10
 
11
11
  let localaddress = "127.0.0.1"
12
12
  let privateaddress = "127.0.0.1"
13
- const bin = "./src/build/Release/projectrtp"
13
+ const bin = "./build/Release/projectrtp"
14
14
 
15
15
 
16
16
  /**
package/lib/server.js CHANGED
@@ -106,6 +106,12 @@ class channel {
106
106
  */
107
107
  openresolve
108
108
 
109
+ /**
110
+ * @private
111
+ * @type { string }
112
+ */
113
+ ctype
114
+
109
115
  /**
110
116
  * @private
111
117
  * @type { function }
@@ -218,6 +224,7 @@ class channel {
218
224
  static _createforlisten( request, remotenode, cb, openresolve, openreject ) {
219
225
 
220
226
  const newchannel = new channel( request.id )
227
+ newchannel.ctype = "l"
221
228
 
222
229
  newchannel.connection = remotenode
223
230
  if( cb ) newchannel.em.on( "all", cb )
@@ -246,6 +253,9 @@ class channel {
246
253
  static _createforconnect( options, cb, openresolve, openreject ) {
247
254
 
248
255
  const newchannel = new channel( options.id )
256
+
257
+ newchannel.ctype = "c"
258
+
249
259
  if( cb ) newchannel.em.on( "all", cb )
250
260
  const connecttonode = randomconnectnode()
251
261
  return new Promise( connectresolve => {
@@ -590,7 +600,7 @@ class channel {
590
600
  // adjust with filter
591
601
  const index = this.channels.indexOf( this )
592
602
  if( -1 < index ) this.channels.splice( index, 1 )
593
- if( 0 === this.channels.length && this.connection.sock ) {
603
+ if( this.ctype == "c" && 0 === this.channels.length && this.connection.sock ) {
594
604
  this.connection.sock.destroy()
595
605
  }
596
606
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/projectrtp",
3
- "version": "2.5.31",
3
+ "version": "2.5.35",
4
4
  "description": "A scalable Node addon RTP server",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -14,14 +14,14 @@
14
14
  "check": "tsc --checkJs --noEmit --target es6 --module commonjs --skipLibCheck *.js test/**/*.js; ./node_modules/eslint/bin/eslint.js ./",
15
15
  "docs": "jsdoc -c jsdoc.conf.json ./README.md",
16
16
  "stress": "node stress/index.js",
17
- "build:dev": "cd src; node-gyp build --debug",
18
- "build": "cd src; node-gyp build",
19
- "configure:dev": "cd src; node-gyp configure --debug",
20
- "configure": "cd src; node-gyp configure",
21
- "rebuild:dev": "cd src; node-gyp configure --debug; node-gyp rebuild --debug",
22
- "rebuild": "cd src; node-gyp configure; node-gyp rebuild",
23
- "clean": "cd src; node-gyp clean",
24
- "install": "npm run rebuild"
17
+ "configure:dev": "node-gyp configure --debug",
18
+ "configure": "node-gyp configure",
19
+ "rebuild:dev": "node-gyp configure --debug; node-gyp rebuild --debug",
20
+ "clean": "node-gyp clean",
21
+ "build:dev": "node-gyp configure build --debug",
22
+ "build": "node-gyp configure build",
23
+ "rebuild": "node-gyp rebuild",
24
+ "install": "node-gyp rebuild"
25
25
  },
26
26
  "repository": {
27
27
  "type": "git",
@@ -34,6 +34,7 @@
34
34
  },
35
35
  "homepage": "https://github.com/babblevoice/projectrtp#readme",
36
36
  "dependencies": {
37
+ "node-addon-api": "^8.2.2",
37
38
  "uuid": "^9.0.0"
38
39
  },
39
40
  "keywords": [
@@ -48,7 +49,7 @@
48
49
  "@types/node": "^12.20.55",
49
50
  "@types/uuid": "^9.0.0",
50
51
  "chai": "^4.3.7",
51
- "eslint": "^8.29.0",
52
+ "eslint": "^9.15.0",
52
53
  "fft-js": "^0.0.12",
53
54
  "jsdoc": "^4.0.0",
54
55
  "mocha": "^10.2.0",
@@ -0,0 +1,24 @@
1
+
2
+ #ifdef BOOST_NO_EXCEPTIONS
3
+
4
+ #include <boost/throw_exception.hpp>
5
+ #include <stdexcept>
6
+ #include <iostream>
7
+
8
+ /*
9
+ Provided exception handlers when BOOST_NO_EXCEPTIONS is defined
10
+ */
11
+
12
+ namespace boost {
13
+ void throw_exception( const std::exception& e ) {
14
+ std::cerr << "Boost exception: " << e.what() << std::endl;
15
+ std::terminate();
16
+ }
17
+
18
+ void throw_exception( const std::exception& e, const boost::source_location& ) {
19
+ std::cerr << "Boost exception with location: " << e.what() << std::endl;
20
+ std::terminate();
21
+ }
22
+ }
23
+
24
+ #endif
package/src/globals.h CHANGED
@@ -50,8 +50,19 @@ private:
50
50
  std::shared_ptr< void > d; // Copied from Request
51
51
  };
52
52
 
53
- /* useful macros for use with std::atomic_bool */
54
- #define AQUIRESPINLOCK( l ) while( l.exchange( true, std::memory_order_acquire ) )
55
- #define RELEASESPINLOCK( l ) l.store( false, std::memory_order_release )
53
+ /* Use spin locks for effiencent protection and ensure unlock */
54
+ struct SpinLockGuard {
55
+ std::atomic_bool& lock;
56
+
57
+ SpinLockGuard( std::atomic_bool& l ) : lock( l ) {
58
+ while( lock.exchange( true, std::memory_order_acquire ) ) {
59
+ // Spin until the lock is acquired
60
+ }
61
+ }
62
+
63
+ ~SpinLockGuard() {
64
+ lock.store(false, std::memory_order_release);
65
+ }
66
+ };
56
67
 
57
68
  #endif /* PROJECTRTPGLOBALS_H */
@@ -26,10 +26,10 @@ std::atomic< std::uint32_t > channelscreated{ 0 };
26
26
  * Get the next available port.
27
27
  */
28
28
  unsigned short getavailableport( void ) {
29
- AQUIRESPINLOCK( availableportslock );
29
+ SpinLockGuard guard( availableportslock );
30
+
30
31
  auto ourport = availableports.front();
31
32
  availableports.pop();
32
- RELEASESPINLOCK( availableportslock );
33
33
 
34
34
  channelscreated.fetch_add( 1 );
35
35
 
@@ -41,11 +41,8 @@ unsigned short getavailableport( void ) {
41
41
  * @returns { size_t }
42
42
  */
43
43
  auto getvailableportsize() {
44
- AQUIRESPINLOCK( availableportslock );
45
- auto availableportssize = availableports.size();
46
- RELEASESPINLOCK( availableportslock );
47
-
48
- return availableportssize;
44
+ SpinLockGuard guard( availableportslock );
45
+ return availableports.size();
49
46
  }
50
47
 
51
48
  /**
@@ -55,10 +52,10 @@ auto getvailableportsize() {
55
52
  void projectrtpchannel::returnavailableport( void ) {
56
53
 
57
54
  if( 0 == this->port ) return;
58
- AQUIRESPINLOCK( availableportslock );
55
+ SpinLockGuard guard( availableportslock );
56
+
59
57
  availableports.push( this->port );
60
58
  this->port = 0;
61
- RELEASESPINLOCK( availableportslock );
62
59
 
63
60
  channelscreated.fetch_sub( 1 );
64
61
  }
@@ -230,9 +227,10 @@ void projectrtpchannel::remote( std::string address,
230
227
  }
231
228
  } );
232
229
 
233
- AQUIRESPINLOCK( this->rtpdtlslock );
234
- this->rtpdtls = newsession;
235
- RELEASESPINLOCK( this->rtpdtlslock );
230
+ {
231
+ SpinLockGuard guard( this->rtpdtlslock );
232
+ this->rtpdtls = newsession;
233
+ }
236
234
  }
237
235
 
238
236
  this->receivedrtp = false;
@@ -426,15 +424,17 @@ void projectrtpchannel::doclose( void ) {
426
424
  postdatabacktojsfromthread( shared_from_this(), "play", "end", "channelclosed" );
427
425
  }
428
426
 
429
- AQUIRESPINLOCK( this->newplaylock );
430
- this->player = nullptr;
431
- this->newplaydef = nullptr;
432
- RELEASESPINLOCK( this->newplaylock );
427
+ {
428
+ SpinLockGuard guard( this->newplaylock );
429
+ this->player = nullptr;
430
+ this->newplaydef = nullptr;
431
+ }
433
432
 
434
433
  /* close our session if we have one */
435
- AQUIRESPINLOCK( this->rtpdtlslock );
436
- this->rtpdtls = nullptr;
437
- RELEASESPINLOCK( this->rtpdtlslock );
434
+ {
435
+ SpinLockGuard dtlsguard( this->rtpdtlslock );
436
+ this->rtpdtls = nullptr;
437
+ }
438
438
 
439
439
  /* close up any remaining recorders */
440
440
  for( auto& rec: this->recorders ) {
@@ -499,7 +499,7 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
499
499
  if( this->mixing ) {
500
500
  this->setnexttick();
501
501
  return;
502
- };
502
+ }
503
503
 
504
504
  this->startticktimer();
505
505
 
@@ -517,14 +517,16 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
517
517
 
518
518
  rtppacket *src;
519
519
  do {
520
- AQUIRESPINLOCK( this->rtpbufferlock );
521
- src = this->inbuff->pop();
522
- RELEASESPINLOCK( this->rtpbufferlock );
523
-
524
- AQUIRESPINLOCK( this->rtpdtlslock );
525
- dtlssession::pointer currentdtlssession = this->rtpdtls;
526
- RELEASESPINLOCK( this->rtpdtlslock );
520
+ {
521
+ SpinLockGuard guard( this->rtpbufferlock );
522
+ src = this->inbuff->pop();
523
+ }
527
524
 
525
+ dtlssession::pointer currentdtlssession;
526
+ {
527
+ SpinLockGuard guarddtls( this->rtpdtlslock );
528
+ currentdtlssession = this->rtpdtls;
529
+ }
528
530
 
529
531
  if( nullptr != currentdtlssession &&
530
532
  !currentdtlssession->rtpdtlshandshakeing ) {
@@ -545,19 +547,20 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
545
547
  {
546
548
  bool playerreplaced = false;
547
549
  bool playernew = false;
548
- AQUIRESPINLOCK( this->newplaylock );
549
- if( nullptr != this->newplaydef ) {
550
- this->doecho = false;
550
+ {
551
+ SpinLockGuard guard( this->newplaylock );
552
+ if( nullptr != this->newplaydef ) {
553
+ this->doecho = false;
551
554
 
552
- if( nullptr != this->player ) {
553
- playerreplaced = true;
554
- }
555
+ if( nullptr != this->player ) {
556
+ playerreplaced = true;
557
+ }
555
558
 
556
- this->player = this->newplaydef;
557
- this->newplaydef = nullptr;
558
- playernew = true;
559
+ this->player = this->newplaydef;
560
+ this->newplaydef = nullptr;
561
+ playernew = true;
562
+ }
559
563
  }
560
- RELEASESPINLOCK( this->newplaylock );
561
564
 
562
565
  if( playerreplaced ) {
563
566
  postdatabacktojsfromthread( shared_from_this(), "play", "end", "replaced" );
@@ -625,9 +628,8 @@ void projectrtpchannel::setnexttick( void ) {
625
628
  }
626
629
 
627
630
  void projectrtpchannel::requestplay( soundsoup::pointer newdef ) {
628
- AQUIRESPINLOCK( this->newplaylock );
631
+ SpinLockGuard guard( this->newplaylock );
629
632
  this->newplaydef = newdef;
630
- RELEASESPINLOCK( this->newplaylock );
631
633
  }
632
634
 
633
635
  /*
@@ -635,9 +637,8 @@ Post a request to record (or modify a param of a record). This function is typic
635
637
  called from a control thread (i.e. node).
636
638
  */
637
639
  void projectrtpchannel::requestrecord( channelrecorder::pointer rec ) {
638
- AQUIRESPINLOCK( this->newrecorderslock );
640
+ SpinLockGuard guard( this->newrecorderslock );
639
641
  this->newrecorders.push_back( rec );
640
- RELEASESPINLOCK( this->newrecorderslock );
641
642
  }
642
643
 
643
644
  /*
@@ -646,10 +647,9 @@ to requestrecord.
646
647
  */
647
648
  void projectrtpchannel::checkfornewrecorders( void ) {
648
649
  channelrecorder::pointer rec;
649
- AQUIRESPINLOCK( this->newrecorderslock );
650
+ SpinLockGuard guard( this->newrecorderslock );
650
651
 
651
652
  for ( auto const& newrec : this->newrecorders ) {
652
-
653
653
  for( auto& currentrec: this->recorders ) {
654
654
  if( currentrec->file == newrec->file ) {
655
655
  currentrec->pause = newrec->pause;
@@ -669,8 +669,6 @@ endofwhileloop:;
669
669
  }
670
670
 
671
671
  this->newrecorders.clear();
672
-
673
- RELEASESPINLOCK( this->newrecorderslock );
674
672
  }
675
673
 
676
674
  void projectrtpchannel::removeoldrecorders( void ) {
@@ -832,17 +830,14 @@ void projectrtpchannel::writerecordings( void ) {
832
830
  }
833
831
 
834
832
  bool projectrtpchannel::dtlsnegotiate( void ) {
833
+ SpinLockGuard guard( this->rtpdtlslock );
835
834
 
836
- AQUIRESPINLOCK( this->rtpdtlslock );
837
835
  dtlssession::pointer oursession = this->rtpdtls;
838
- RELEASESPINLOCK( this->rtpdtlslock );
839
836
 
840
837
  if( nullptr == oursession ) return false;
841
838
  if( !oursession->rtpdtlshandshakeing ) return false;
842
839
 
843
- AQUIRESPINLOCK( this->rtpdtlslock );
844
840
  auto dtlsstate = oursession->handshake();
845
- RELEASESPINLOCK( this->rtpdtlslock );
846
841
 
847
842
  if( GNUTLS_E_SUCCESS != dtlsstate && 0 != gnutls_error_is_fatal( dtlsstate ) ) {
848
843
  oursession->bye();
@@ -929,9 +924,12 @@ void projectrtpchannel::readsomertp( void ) {
929
924
  if( !this->active || this->_requestclose ) return;
930
925
 
931
926
  /* Grab a buffer */
932
- AQUIRESPINLOCK( this->rtpbufferlock );
933
- rtppacket* buf = this->inbuff->reserve();
934
- RELEASESPINLOCK( this->rtpbufferlock );
927
+ rtppacket* buf;
928
+ {
929
+ SpinLockGuard guard( this->rtpbufferlock );
930
+ buf = this->inbuff->reserve();
931
+ }
932
+
935
933
 
936
934
  if( nullptr == buf ) {
937
935
  fprintf( stderr, "Error no buffer\n" );
@@ -954,15 +952,19 @@ void projectrtpchannel::readsomertp( void ) {
954
952
  if( this->handlestun( buf->pk, bytesrecvd ) )
955
953
  goto readsomemore;
956
954
 
957
- AQUIRESPINLOCK( this->rtpdtlslock );
958
- dtlssession::pointer currentdtlssession = this->rtpdtls;
959
- RELEASESPINLOCK( this->rtpdtlslock );
955
+ dtlssession::pointer currentdtlssession;
956
+ {
957
+ SpinLockGuard guard( this->rtpdtlslock );
958
+ currentdtlssession = this->rtpdtls;
959
+ }
960
960
 
961
961
  if( nullptr != currentdtlssession &&
962
962
  currentdtlssession->rtpdtlshandshakeing ) {
963
- AQUIRESPINLOCK( this->rtpdtlslock );
964
- currentdtlssession->write( buf->pk, bytesrecvd );
965
- RELEASESPINLOCK( this->rtpdtlslock );
963
+ {
964
+ SpinLockGuard guard( this->rtpdtlslock );
965
+ currentdtlssession->write( buf->pk, bytesrecvd );
966
+ }
967
+
966
968
  this->dtlsnegotiate();
967
969
  goto readsomemore;
968
970
  }
@@ -1010,9 +1012,10 @@ void projectrtpchannel::readsomertp( void ) {
1010
1012
  buf->setpayloadtype( RFC2833PAYLOADTYPE );
1011
1013
  }
1012
1014
 
1013
- AQUIRESPINLOCK( this->rtpbufferlock );
1014
- this->inbuff->push();
1015
- RELEASESPINLOCK( this->rtpbufferlock );
1015
+ {
1016
+ SpinLockGuard guard( this->rtpbufferlock );
1017
+ this->inbuff->push();
1018
+ }
1016
1019
  }
1017
1020
 
1018
1021
  readsomemore:
@@ -1079,9 +1082,11 @@ void projectrtpchannel::writepacket( rtppacket *pk ) {
1079
1082
 
1080
1083
  if( !this->active ) return;
1081
1084
 
1082
- AQUIRESPINLOCK( this->rtpdtlslock );
1083
- dtlssession::pointer currentdtlssession = this->rtpdtls;
1084
- RELEASESPINLOCK( this->rtpdtlslock );
1085
+ dtlssession::pointer currentdtlssession;
1086
+ {
1087
+ SpinLockGuard guard( this->rtpdtlslock );
1088
+ currentdtlssession = this->rtpdtls;
1089
+ }
1085
1090
 
1086
1091
  if( nullptr != currentdtlssession &&
1087
1092
  currentdtlssession->rtpdtlshandshakeing ) {
@@ -1143,7 +1148,7 @@ bool projectrtpchannel::mix( projectrtpchannel::pointer other ) {
1143
1148
  return true;
1144
1149
  }
1145
1150
 
1146
- AQUIRESPINLOCK( this->mixerlock );
1151
+ SpinLockGuard guard( this->mixerlock );
1147
1152
 
1148
1153
  if( nullptr == this->mixer && nullptr != other->mixer ) {
1149
1154
  this->mixer = other->mixer;
@@ -1162,13 +1167,10 @@ bool projectrtpchannel::mix( projectrtpchannel::pointer other ) {
1162
1167
  this->mixer->go();
1163
1168
  } else {
1164
1169
  /* If we get here this and other are already mixing and should be cleaned up first */
1165
- RELEASESPINLOCK( this->mixerlock );
1166
1170
  postdatabacktojsfromthread( shared_from_this(), "mix", "busy" );
1167
1171
  return false;
1168
1172
  }
1169
1173
 
1170
- RELEASESPINLOCK( this->mixerlock );
1171
-
1172
1174
  postdatabacktojsfromthread( shared_from_this(), "mix", "start" );
1173
1175
  postdatabacktojsfromthread( other, "mix", "start" );
1174
1176
 
@@ -1181,11 +1183,9 @@ Add the other to a mixer - both channels have access to the same mixer.
1181
1183
  n way relationship. Adds to queue for when our main thread calls into us.
1182
1184
  */
1183
1185
  bool projectrtpchannel::unmix( void ) {
1186
+ SpinLockGuard guard( this->mixerlock );
1184
1187
 
1185
- AQUIRESPINLOCK( this->mixerlock );
1186
1188
  if( nullptr != this->mixer ) this->removemixer = true;
1187
- RELEASESPINLOCK( this->mixerlock );
1188
-
1189
1189
  return true;
1190
1190
  }
1191
1191
 
@@ -1196,9 +1196,10 @@ bool projectrtpchannel::unmix( void ) {
1196
1196
  void projectrtpchannel::dounmix( void ) {
1197
1197
  this->mixing = false;
1198
1198
  this->removemixer = false;
1199
- AQUIRESPINLOCK( this->mixerlock );
1199
+
1200
+ SpinLockGuard guard( this->mixerlock );
1201
+
1200
1202
  this->mixer = nullptr;
1201
- RELEASESPINLOCK( this->mixerlock );
1202
1203
 
1203
1204
  postdatabacktojsfromthread( shared_from_this(), "mix", "finished" );
1204
1205
 
@@ -1212,9 +1213,8 @@ void projectrtpchannel::dounmix( void ) {
1212
1213
  Queue digits to send as RFC 2833.
1213
1214
  */
1214
1215
  void projectrtpchannel::dtmf( std::string digits ) {
1215
- AQUIRESPINLOCK( this->queuddigitslock );
1216
+ SpinLockGuard guard( this->queuddigitslock );
1216
1217
  this->queueddigits += digits;
1217
- RELEASESPINLOCK( this->queuddigitslock );
1218
1218
  }
1219
1219
 
1220
1220
  /*
@@ -1227,12 +1227,13 @@ void projectrtpchannel::senddtmf( void ) {
1227
1227
  }
1228
1228
 
1229
1229
  uint8_t tosend = 0;
1230
- AQUIRESPINLOCK( this->queuddigitslock );
1231
- if( this->queueddigits.size() > 0 ) {
1232
- tosend = this->queueddigits[ 0 ];
1233
- this->queueddigits.erase( this->queueddigits.begin() );
1230
+ {
1231
+ SpinLockGuard guard( this->queuddigitslock );
1232
+ if( this->queueddigits.size() > 0 ) {
1233
+ tosend = this->queueddigits[ 0 ];
1234
+ this->queueddigits.erase( this->queueddigits.begin() );
1235
+ }
1234
1236
  }
1235
- RELEASESPINLOCK( this->queuddigitslock );
1236
1237
 
1237
1238
  if( 0 == tosend ) {
1238
1239
  return;
@@ -1264,7 +1265,7 @@ void projectrtpchannel::senddtmf( void ) {
1264
1265
  return;
1265
1266
  }
1266
1267
 
1267
- const char volume = 15;
1268
+ const char volume = 10;
1268
1269
  const char endofevent = 0x80;
1269
1270
 
1270
1271
  rtppacket *dst = this->gettempoutbuf();
@@ -2368,12 +2369,14 @@ void getchannelstats( napi_env env, napi_value &result ) {
2368
2369
  void initrtpchannel( napi_env env, napi_value &result, int32_t startport, int32_t endport ) {
2369
2370
  napi_value ccreate;
2370
2371
 
2371
- AQUIRESPINLOCK( availableportslock );
2372
- while(!availableports.empty()) availableports.pop();
2373
- for( int i = (int) startport; i < (int) endport; i = i + 2 ) {
2374
- availableports.push( i );
2372
+ {
2373
+ SpinLockGuard guard( availableportslock );
2374
+
2375
+ while(!availableports.empty()) availableports.pop();
2376
+ for( int i = (int) startport; i < (int) endport; i = i + 2 ) {
2377
+ availableports.push( i );
2378
+ }
2375
2379
  }
2376
- RELEASESPINLOCK( availableportslock );
2377
2380
 
2378
2381
  if( napi_ok != napi_create_function( env, "exports", NAPI_AUTO_LENGTH, channelcreate, nullptr, &ccreate ) ) return;
2379
2382
  if( napi_ok != napi_set_named_property( env, result, "openchannel", ccreate ) ) return;
@@ -56,24 +56,30 @@ void projectchannelmux::mixall( void ) {
56
56
 
57
57
  rtppacket *src;
58
58
  while( true ) {
59
- AQUIRESPINLOCK( chan->rtpbufferlock );
60
- src = chan->inbuff->peek();
61
- RELEASESPINLOCK( chan->rtpbufferlock );
59
+ {
60
+ SpinLockGuard guard( chan->rtpbufferlock );
61
+ src = chan->inbuff->peek();
62
+ }
62
63
 
63
64
  if( nullptr == src ) break;
64
65
 
65
- AQUIRESPINLOCK( chan->rtpdtlslock );
66
- dtlssession::pointer currentdtlssession = chan->rtpdtls;
67
- RELEASESPINLOCK( chan->rtpdtlslock );
66
+ dtlssession::pointer currentdtlssession;
67
+ {
68
+ SpinLockGuard guard( chan->rtpdtlslock );
69
+ currentdtlssession = chan->rtpdtls;
70
+ }
71
+
68
72
  if( nullptr != currentdtlssession &&
69
73
  !currentdtlssession->rtpdtlshandshakeing ) {
70
74
  if( !currentdtlssession->unprotect( src ) ) {
71
75
  chan->receivedpkskip++;
72
76
  src = nullptr;
73
-
74
- AQUIRESPINLOCK( chan->rtpbufferlock );
75
- chan->inbuff->poppeeked();
76
- RELEASESPINLOCK( chan->rtpbufferlock );
77
+
78
+ {
79
+ SpinLockGuard guard( chan->rtpbufferlock );
80
+ chan->inbuff->poppeeked();
81
+ }
82
+
77
83
  break;
78
84
  }
79
85
  }
@@ -86,9 +92,10 @@ void projectchannelmux::mixall( void ) {
86
92
  }
87
93
  }
88
94
  /* remove the DTMF packet */
89
- AQUIRESPINLOCK( chan->rtpbufferlock );
90
- chan->inbuff->poppeeked();
91
- RELEASESPINLOCK( chan->rtpbufferlock );
95
+ {
96
+ SpinLockGuard guard( chan->rtpbufferlock );
97
+ chan->inbuff->poppeeked();
98
+ }
92
99
  }
93
100
 
94
101
  if( nullptr != src ) {
@@ -101,9 +108,8 @@ void projectchannelmux::mixall( void ) {
101
108
  /* Now we subtract this channel to send to this channel. */
102
109
  for( auto& chan: this->channels ) {
103
110
  if( !chan->send ) {
104
- AQUIRESPINLOCK( chan->rtpbufferlock );
111
+ SpinLockGuard guard( chan->rtpbufferlock );
105
112
  chan->inbuff->poppeeked();
106
- RELEASESPINLOCK( chan->rtpbufferlock );
107
113
  continue;
108
114
  }
109
115
 
@@ -113,15 +119,20 @@ void projectchannelmux::mixall( void ) {
113
119
  this->subtracted.copy( this->added );
114
120
 
115
121
  if( chan->recv ) {
116
- AQUIRESPINLOCK( chan->rtpbufferlock );
117
- rtppacket *src = chan->inbuff->peeked();
118
- RELEASESPINLOCK( chan->rtpbufferlock );
122
+ rtppacket *src;
123
+ {
124
+ SpinLockGuard guard( chan->rtpbufferlock );
125
+ src = chan->inbuff->peeked();
126
+ }
127
+
119
128
  if( nullptr != src ) {
120
129
  this->subtracted -= chan->incodec;
121
130
  }
122
- AQUIRESPINLOCK( chan->rtpbufferlock );
123
- chan->inbuff->poppeeked();
124
- RELEASESPINLOCK( chan->rtpbufferlock );
131
+
132
+ {
133
+ SpinLockGuard guard( chan->rtpbufferlock );
134
+ chan->inbuff->poppeeked();
135
+ }
125
136
  }
126
137
 
127
138
  chan->outcodec << codecx::next;
@@ -144,15 +155,20 @@ void projectchannelmux::mix2( void ) {
144
155
  rtppacket *src;
145
156
 
146
157
  while( true ) {
147
- AQUIRESPINLOCK( chan1->rtpbufferlock );
148
- src = chan1->inbuff->pop();
149
- RELEASESPINLOCK( chan1->rtpbufferlock );
158
+ {
159
+ SpinLockGuard guard( chan1->rtpbufferlock );
160
+ src = chan1->inbuff->pop();
161
+ }
150
162
 
151
163
  if( nullptr == src ) break;
152
164
 
153
- AQUIRESPINLOCK( chan1->rtpdtlslock );
154
- dtlssession::pointer currentdtlssession = chan1->rtpdtls;
155
- RELEASESPINLOCK( chan1->rtpdtlslock );
165
+ dtlssession::pointer currentdtlssession;
166
+ {
167
+ SpinLockGuard guard( chan1->rtpdtlslock );
168
+ currentdtlssession = chan1->rtpdtls;
169
+ }
170
+
171
+
156
172
  if( nullptr != currentdtlssession &&
157
173
  !currentdtlssession->rtpdtlshandshakeing ) {
158
174
  if( !currentdtlssession->unprotect( src ) ) {
@@ -168,15 +184,20 @@ void projectchannelmux::mix2( void ) {
168
184
  this->postrtpdata( chan1, chan2, src );
169
185
 
170
186
  while( true ) {
171
- AQUIRESPINLOCK( chan2->rtpbufferlock );
172
- src = chan2->inbuff->pop();
173
- RELEASESPINLOCK( chan2->rtpbufferlock );
187
+ {
188
+ SpinLockGuard guard( chan2->rtpbufferlock );
189
+ src = chan2->inbuff->pop();
190
+ }
174
191
 
175
192
  if( nullptr == src ) break;
176
193
 
177
- AQUIRESPINLOCK( chan2->rtpdtlslock );
178
- dtlssession::pointer currentdtlssession = chan2->rtpdtls;
179
- RELEASESPINLOCK( chan2->rtpdtlslock );
194
+
195
+ dtlssession::pointer currentdtlssession;
196
+ {
197
+ SpinLockGuard guard( chan2->rtpdtlslock );
198
+ currentdtlssession = chan2->rtpdtls;
199
+ }
200
+
180
201
  if( nullptr != currentdtlssession &&
181
202
  !currentdtlssession->rtpdtlshandshakeing ) {
182
203
  if( !currentdtlssession->unprotect( src ) ) {
@@ -299,8 +320,7 @@ static bool underlyingpointercmp( projectrtpchannelptr l, projectrtpchannelptr r
299
320
  Check for new channels to add to the mix in our own thread.
300
321
  */
301
322
  void projectchannelmux::checkfornewmixes( void ) {
302
-
303
- AQUIRESPINLOCK( this->newchannelslock );
323
+ SpinLockGuard guard( this->newchannelslock );
304
324
 
305
325
  for ( auto const& newchan : this->newchannels ) {
306
326
  this->channels.push_back( newchan );
@@ -309,24 +329,22 @@ void projectchannelmux::checkfornewmixes( void ) {
309
329
 
310
330
  this->channels.sort( underlyingpointercmp );
311
331
  this->channels.unique( underlyingpointerequal );
312
-
313
- RELEASESPINLOCK( this->newchannelslock );
314
332
  }
315
333
 
316
334
  void projectchannelmux::addchannel( projectrtpchannelptr chan ) {
317
- AQUIRESPINLOCK( this->newchannelslock );
335
+ SpinLockGuard guard( this->newchannelslock );
336
+
318
337
  chan->mixing = true;
319
338
  this->newchannels.push_back( chan );
320
- RELEASESPINLOCK( this->newchannelslock );
321
339
  }
322
340
 
323
341
  void projectchannelmux::addchannels( projectrtpchannelptr chana, projectrtpchannelptr chanb ) {
324
- AQUIRESPINLOCK( this->newchannelslock );
342
+ SpinLockGuard guard( this->newchannelslock );
343
+
325
344
  chana->mixing = true;
326
345
  chanb->mixing = true;
327
346
  this->newchannels.push_back( chana );
328
347
  this->newchannels.push_back( chanb );
329
- RELEASESPINLOCK( this->newchannelslock );
330
348
  }
331
349
 
332
350
  /*
@@ -28,12 +28,6 @@ static std::atomic_bool warningissued( false );
28
28
  int32_t startport = 10000;
29
29
  int32_t endport = 20000;
30
30
 
31
- void boost::throw_exception( std::exception const & e ) {
32
- std::string err = boost::diagnostic_information( e );
33
- fprintf( stderr, "%s", err.c_str() );
34
- exit( EXIT_FAILURE );
35
- }
36
-
37
31
  /* our work queue requires some work to not exit */
38
32
  static ourhighrestimer periodictimer( workercontext );
39
33
 
@@ -203,33 +197,35 @@ void initserver( napi_env env, napi_value &result ) {
203
197
  if( napi_ok != napi_set_named_property( env, result, "stats", cstats ) ) return;
204
198
  }
205
199
 
206
- NAPI_MODULE_INIT() {
207
- napi_value result;
208
-
209
- std::atomic_bool test;
210
- if( !test.is_lock_free() ) {
211
- fprintf( stderr, "Warning - performance will be poor as atomic variables are not available\n" );
212
- }
213
-
214
- srand( time( NULL ) );
200
+ /* Initialize the module */
201
+ napi_value initprtp(napi_env env, napi_value exports) {
202
+ std::atomic_bool test;
203
+ if (!test.is_lock_free()) {
204
+ fprintf(stderr, "Warning - performance will be poor as atomic variables are not available\n");
205
+ }
215
206
 
216
- dtlsinit();
207
+ srand(time(NULL));
217
208
 
218
- if( napi_ok != napi_create_object( env, &result ) ) return NULL;
209
+ /* Initialize DTLS or other dependencies */
210
+ dtlsinit();
219
211
 
220
- /* Init our modules */
221
- initserver( env, result );
222
- initrtpbuffer( env, result );
223
- initrtpchannel( env, result, startport, endport );
224
- initrtpsoundfile( env, result );
225
- initrtpcodecx( env, result );
226
- initfilter( env, result );
227
- inittonegen( env, result );
228
- initsrtp( env, result );
212
+ /* Initialize the exported module object */
213
+ initserver(env, exports);
214
+ initrtpbuffer(env, exports);
215
+ initrtpchannel(env, exports, startport, endport);
216
+ initrtpsoundfile(env, exports);
217
+ initrtpcodecx(env, exports);
218
+ initfilter(env, exports);
219
+ inittonegen(env, exports);
220
+ initsrtp(env, exports);
229
221
 
230
- gen711convertdata();
222
+ /* Generate G.711 conversion data */
223
+ gen711convertdata();
231
224
 
232
- return result;
225
+ return exports;
233
226
  }
234
227
 
228
+ /* Register the module */
229
+ NAPI_MODULE(NODE_GYP_MODULE_NAME, initprtp)
230
+
235
231
  #endif /* NODE_MODULE */
package/stress/index.js CHANGED
@@ -46,6 +46,18 @@ const run = async () => {
46
46
  await node.listen( projectrtp, "127.0.0.1", 9002 )
47
47
  } else console.log( "Mode: server as listener" )
48
48
 
49
+ let currentstatsquery = 0
50
+ const intervaletimers = [
51
+ setInterval( () => {
52
+ currentstatsquery++
53
+ const prtpstats = projectrtp.stats()
54
+ currentstatsquery--
55
+ }, 100 ),
56
+ setInterval( () => {
57
+ if( currentstatsquery > 3 ) utils.log( "Problem with stats not completing" )
58
+ }, 100 )
59
+ ]
60
+
49
61
  while ( rununtil > Math.floor( Date.now() / 1000 ) ) {
50
62
  if( utils.currentchannelcount() < maxnumberofsessions ) {
51
63
  scenarios[ utils.between( 0, scenarios.length ) ]( utils.between( minmscalllength, maxmscalllength ) )
@@ -56,6 +68,9 @@ const run = async () => {
56
68
 
57
69
  /* It is safe to call shutdown before we are complete - it will just shutdown after all the work is done */
58
70
  projectrtp.shutdown()
71
+
72
+ clearInterval( intervaletimers[ 0 ] )
73
+ clearInterval( intervaletimers[ 1 ] )
59
74
  }
60
75
 
61
76
  run()
@@ -680,7 +680,6 @@ describe( "rtpproxy server", function() {
680
680
  const p = await prtp.proxy.listen( undefined, "127.0.0.1", ourport )
681
681
  const ournode = await prtp.node.connect( ourport, "127.0.0.1" )
682
682
 
683
-
684
683
  const chnl = await prtp.openchannel()
685
684
  await new Promise( ( resolve ) => { setTimeout( () => resolve(), 100 ) } )
686
685
  await chnl.close()
package/src/binding.gyp DELETED
@@ -1,40 +0,0 @@
1
- {
2
- "targets": [
3
- {
4
- "target_name": "projectrtp",
5
- "defines": [ "NODE_MODULE", "BOOST_NO_EXCEPTIONS", "BOOST_EXCEPTION_DISABLE" ],
6
- "cflags_cc!": [ "-fno-rtti" ],
7
- "cflags_cc": [
8
- "-O3",
9
- "-g",
10
- "-Wall",
11
- "-fstack-protector-all",
12
- "-std=c++17",
13
- "-fconcepts-ts",
14
- "-Weffc++" ],
15
- "libraries": [
16
- "-lrt",
17
- "-lspandsp",
18
- "-lilbc",
19
- "-lgnutls",
20
- "-lsrtp2",
21
- "-fstack-protector-all"
22
- ],
23
- "sources": [
24
- "projectrtpfirfilter.cpp",
25
- "projectrtpnodemain.cpp",
26
- "projectrtpbuffer.cpp",
27
- "projectrtppacket.cpp",
28
- "projectrtprawsound.cpp",
29
- "projectrtpcodecx.cpp",
30
- "projectrtpchannelrecorder.cpp",
31
- "projectrtpsoundfile.cpp",
32
- "projectrtpsoundsoup.cpp",
33
- "projectrtptonegen.cpp",
34
- "projectrtpchannel.cpp",
35
- "projectrtpchannelmux.cpp",
36
- "projectrtpsrtp.cpp",
37
- "projectrtpstun.cpp" ]
38
- }
39
- ]
40
- }