@babblevoice/projectrtp 2.4.17 → 2.5.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/README.md CHANGED
@@ -54,82 +54,15 @@ The folder is separated out into interface, unit and mock. The mock folder conta
54
54
 
55
55
  These are designed to create real world scenarios - opening and closing multiple channels and random times and at load. This is designed to test for unexpected behaviour. These test do not provide a pass/fail - but might crash or produce unexpected output on bad behaviour. These have concurrency/race condition tests in mind.
56
56
 
57
- ### `npm run check`
58
-
59
- Use tsc for type checking and eslint.
60
-
61
- NB: tsc should be installed as a global module:
62
-
63
- ```bash
64
- npm install -G typescript
65
- ```
66
-
67
- Eslint should be installed as a module
68
-
69
- ```bash
70
- npm install eslint
71
- ```
57
+ ### Local build
72
58
 
73
- Other types modules need installing:
59
+ If you wish to build outsode of a Docker image, there are npm target scripts for build and rebuild. For beta releases the following can be done.
74
60
 
75
61
  ```bash
76
- npm i --save-dev @types/node @types/mocha @types/chai @types/uuid
77
- ```
78
-
79
- ## Dependencies
80
-
81
- * spandsp-devel
82
- * libilbc
83
- * boost
84
- * gnutls
85
- * libsrtp
86
- * openssl (for now the NodeJS scripts use openssl to generate a self signed cert for DTLS)
87
-
88
- libilbc is included as a git submodule and requires building. This needs pulling which also
89
- has a submodule so (although this is handled inteh Dockerfile if you are building an image):
90
-
91
- ```
92
- git submodule update --init --recursive
93
- ```
94
-
95
- ## Docker/Podman
96
-
97
- Podman has some shortfalls. Remove and install docker.
98
-
99
- ```
100
- docker build .
101
- ```
102
-
103
- ### Multi arch targets
104
-
105
- Qemu emulators are needed
106
-
107
- ```
108
- docker run -it --rm --privileged tonistiigi/binfmt --install all
109
- ```
110
-
111
- Or in one shot and build it. This create a docker image and container buildkit.
112
- ```
113
- docker buildx create --name rtpbuilder --use --bootstrap --platform linux/amd64,linux/arm64
114
- ```
115
-
116
- To clean up if you want to remove this buildx env:
117
- ```
118
- docker buildx rm rtpbuilder
119
- ```
120
-
121
- Then to build, and push to Docker hub (REMEMBER to update all references to version number including in Dockerfile)
122
- ```
123
62
  docker buildx prune
124
- docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:<version> . --push
63
+ docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:2.4.20_beta1 . --push
125
64
  ```
126
65
 
127
- NB: updating version, Docker file, this readme and package.json all need updating - is there a way of automating this?
128
-
129
- ### Local build
130
-
131
- If you wish to build outsode of a Docker image, there are npm target scripts for build and rebuild.
132
-
133
66
  ## Example scripts
134
67
 
135
68
  The examples folder contains two scripts which use this library. The simplenode can be used where no special functionality is required. The standard projectrtp docker image points to this - so starting a docker instance will run up as a node and attempt to connect to a central control server.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/projectrtp",
3
- "version": "2.4.17",
3
+ "version": "2.5.22",
4
4
  "description": "A scalable Node addon RTP server",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -43,13 +43,15 @@
43
43
  "WebRTC"
44
44
  ],
45
45
  "devDependencies": {
46
- "@types/node": "^12.20.55",
47
46
  "@types/chai": "^4.3.4",
48
47
  "@types/mocha": "^10.0.1",
48
+ "@types/node": "^12.20.55",
49
49
  "@types/uuid": "^9.0.0",
50
50
  "chai": "^4.3.7",
51
- "mocha": "^10.2.0",
52
51
  "eslint": "^8.29.0",
53
- "jsdoc": "^4.0.0"
52
+ "fft-js": "^0.0.12",
53
+ "jsdoc": "^4.0.0",
54
+ "mocha": "^10.2.0",
55
+ "nodeplotlib": "^0.7.7"
54
56
  }
55
57
  }
package/src/globals.h CHANGED
@@ -9,6 +9,9 @@
9
9
  #define G711PAYLOADBYTES 160
10
10
  #define G722PAYLOADBYTES 160
11
11
  #define L16PAYLOADSAMPLES 160
12
+ #define G711PAYLOADSAMPLES 160
13
+ #define G722PAYLOADSAMPLES 160
14
+ #define L1616PAYLOADSAMPLES 320
12
15
  #define L16NARROWBANDBYTES 320
13
16
  #define L16WIDEBANDBYTES 640
14
17
  #define ILBC20PAYLOADBYTES 38
@@ -17,6 +20,8 @@
17
20
  #define PCMUPAYLOADTYPE 0
18
21
  #define PCMAPAYLOADTYPE 8
19
22
  #define G722PAYLOADTYPE 9
23
+ /* defaults for our supported dynamic payload types */
24
+ #define RFC2833PAYLOADTYPE 101
20
25
  #define ILBCPAYLOADTYPE 97
21
26
  /* Only use this value for internal use and must not clash with the types above */
22
27
  #define L168KPAYLOADTYPE 11
@@ -1,4 +1,7 @@
1
1
 
2
+ #include <iostream>
3
+ #include <cstdlib>
4
+
2
5
  #include "projectrtpbuffer.h"
3
6
  #include "globals.h"
4
7
 
@@ -23,7 +26,10 @@ rtpbuffer::rtpbuffer( int buffercount, int waterlevel ) :
23
26
  buffercount( buffercount ),
24
27
  waterlevel( waterlevel ),
25
28
  outsn( 0 ),
26
- dropped( 0 ) {
29
+ dropped( 0 ),
30
+ pushed( 0 ),
31
+ popped( 0 ),
32
+ badsn( 0 ) {
27
33
 
28
34
  this->buffer.resize( buffercount );
29
35
  this->orderedrtpdata.resize( buffercount );
@@ -46,7 +52,8 @@ Returns the next packet in order - does not modify our structure.
46
52
  */
47
53
  rtppacket* rtpbuffer::peek( void ) {
48
54
  if( nullptr != this->peekedpopped ) return this->peekedpopped;
49
- this->peekedpopped = this->orderedrtpdata.at( this->outsn % this->buffercount );
55
+ uint16_t bufindex = this->outsn % this->buffercount;
56
+ this->peekedpopped = this->orderedrtpdata.at( bufindex );
50
57
  return this->peekedpopped;
51
58
  }
52
59
 
@@ -80,12 +87,19 @@ rtppacket* rtpbuffer::pop( void ) {
80
87
  this->peekedpopped = nullptr;
81
88
  if( nullptr == out ) return nullptr;
82
89
 
83
- if( nullptr != this->orderedrtpdata.at( oldsn % this->buffercount ) ) {
84
- this->orderedrtpdata.at( oldsn % this->buffercount ) = nullptr;
90
+ uint16_t bufindex = oldsn % this->buffercount;
91
+ if( nullptr != this->orderedrtpdata.at( bufindex ) ) {
92
+ this->orderedrtpdata.at( bufindex ) = nullptr;
85
93
  this->availablertpdata.push( out );
86
94
  }
87
95
 
88
- if( out->getsequencenumber() != oldsn ) return nullptr;
96
+ auto outsn = out->getsequencenumber();
97
+ if( outsn != oldsn ) {
98
+ this->badsn++;
99
+ return nullptr;
100
+ }
101
+
102
+ this->popped++;
89
103
  return out;
90
104
  }
91
105
 
@@ -94,7 +108,12 @@ Stores the last reserved packet.
94
108
  */
95
109
  void rtpbuffer::push( void ) {
96
110
 
97
- if( nullptr == this->reserved ) return;
111
+ if( nullptr == this->reserved ) {
112
+ fprintf( stderr, "Push on buffer - but no buffer reserved to push\n" );
113
+ this->dropped++;
114
+ return;
115
+ }
116
+
98
117
  uint16_t sn = this->reserved->getsequencenumber();
99
118
 
100
119
  /*
@@ -117,6 +136,11 @@ void rtpbuffer::push( void ) {
117
136
 
118
137
  if( nullptr == this->orderedrtpdata.at( sn % this->buffercount ) ) {
119
138
  this->orderedrtpdata.at( sn % this->buffercount ) = this->reserved;
139
+ this->pushed++;
140
+ } else {
141
+ /* this shouldn't happen as it means a duplicate sn or we have got our index incorrect */
142
+ this->availablertpdata.push( this->reserved );
143
+ this->dropped++;
120
144
  }
121
145
 
122
146
  this->reserved = nullptr;
@@ -10,13 +10,17 @@
10
10
  #include "projectrtppacket.h"
11
11
 
12
12
  /* Defaults */
13
- /* The number of packets we will keep in a buffer */
14
- #define BUFFERPACKETCOUNT 40
13
+ /*
14
+ The number of packets we will keep in a buffer
15
+ MUST BE POWER OF 2 or the mod won't work on the
16
+ circular buffer when wrapping around the uint16.
17
+ */
18
+ #define BUFFERPACKETCOUNT 32
15
19
  /*
16
20
  How many packets we receive before we start taking packets out of the buffer
17
21
  If we fill, Delay = ( BUFFERPACKETCOUNT - BUFFERPACKETCAP ) * 20mS
18
22
  */
19
- #define BUFFERPACKETCAP 15 /* 200mS @ a ptime of 20mS */
23
+ #define BUFFERPACKETCAP 10 /* 200mS @ a ptime of 20mS */
20
24
 
21
25
  /*
22
26
  My thoughts on buffers. We reorder as we might want to use the data
@@ -49,6 +53,10 @@ public:
49
53
  void push( void );
50
54
  rtppacket* reserve( void );
51
55
  uint64_t getdropped( void ) { return this->dropped; }
56
+ uint64_t getpushed( void ) { return this->pushed; }
57
+ uint64_t getpopped( void ) { return this->popped; }
58
+ uint64_t getbadsn( void ) { return this->badsn; }
59
+ uint16_t getoutsn( void ) { return this->outsn; }
52
60
 
53
61
  int size( void ) { return this->buffercount; }
54
62
 
@@ -76,6 +84,9 @@ private:
76
84
  int waterlevel;
77
85
  uint16_t outsn;
78
86
  uint64_t dropped;
87
+ uint64_t pushed;
88
+ uint64_t popped;
89
+ uint64_t badsn;
79
90
  };
80
91
 
81
92
  #ifdef TESTSUITE
@@ -53,8 +53,10 @@ projectrtpchannel::projectrtpchannel( unsigned short port ):
53
53
  totalticktime( 0 ),
54
54
  totaltickcount( 0 ),
55
55
  tickswithnortpcount( 0 ),
56
+ outpkwritecount( 0 ),
56
57
  outpkcount( 0 ),
57
58
  outpkskipcount( 0 ),
59
+ outpkdropcount( 0 ),
58
60
  inbuff( rtpbuffer::create() ),
59
61
  rtpbufferlock( false ),
60
62
  rtpoutindex( 0 ),
@@ -66,7 +68,8 @@ projectrtpchannel::projectrtpchannel( unsigned short port ):
66
68
  /* private */
67
69
  active( false ),
68
70
  port( port ),
69
- rfc2833pt( 101 ),
71
+ rfc2833pt( RFC2833PAYLOADTYPE ),
72
+ ilbcpt( ILBCPAYLOADTYPE ),
70
73
  lasttelephoneeventsn( 0 ),
71
74
  lasttelephoneevent( 0 ),
72
75
  resolver( workercontext ),
@@ -133,6 +136,8 @@ void projectrtpchannel::requestclose( std::string reason ) {
133
136
  void projectrtpchannel::remote( std::string address,
134
137
  unsigned short port,
135
138
  uint32_t codec,
139
+ unsigned short ilbcpt,
140
+ unsigned short rfc2833pt,
136
141
  dtlssession::mode m,
137
142
  std::string fingerprint ) {
138
143
 
@@ -162,6 +167,8 @@ void projectrtpchannel::remote( std::string address,
162
167
  }
163
168
 
164
169
  this->codec = codec;
170
+ this->rfc2833pt = rfc2833pt;
171
+ this->ilbcpt = ilbcpt;
165
172
 
166
173
  if( changed ) {
167
174
  if( dtlssession::none != m ) {
@@ -410,13 +417,17 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
410
417
  this->startticktimer();
411
418
 
412
419
  this->incrtsout();
413
- if( this->checkidlerecv() ) return;
420
+
421
+ if( this->checkidlerecv() ) {
422
+ this->endticktimer();
423
+ return;
424
+ }
425
+
414
426
  this->checkfornewrecorders();
415
427
 
416
428
  this->incodec << codecx::next;
417
429
  this->outcodec << codecx::next;
418
430
 
419
-
420
431
  rtppacket *src;
421
432
  do {
422
433
  AQUIRESPINLOCK( this->rtpbufferlock );
@@ -827,6 +838,7 @@ void projectrtpchannel::readsomertp( void ) {
827
838
  RELEASESPINLOCK( this->rtpbufferlock );
828
839
 
829
840
  if( nullptr == buf ) {
841
+ fprintf( stderr, "Error no buffer\n" );
830
842
  this->requestclose( "error.nobuffer" );
831
843
  return;
832
844
  }
@@ -835,15 +847,16 @@ void projectrtpchannel::readsomertp( void ) {
835
847
  boost::asio::buffer( buf->pk, RTPMAXLENGTH ), this->rtpsenderendpoint,
836
848
  [ this, buf ]( boost::system::error_code ec, std::size_t bytesrecvd ) {
837
849
 
838
- if( ec ) return;
850
+ if ( ec && ec != boost::asio::error::message_size ) return;
851
+ this->receivedpkcount++;
852
+
839
853
  if( !this->active || this->_requestclose ) return;
840
854
 
841
855
  if ( bytesrecvd > 0 && bytesrecvd <= RTPMAXLENGTH ) {
856
+ buf->length = bytesrecvd;
842
857
 
843
- if( this->handlestun( buf->pk, bytesrecvd ) ) {
844
- this->readsomertp();
845
- return;
846
- }
858
+ if( this->handlestun( buf->pk, bytesrecvd ) )
859
+ goto readsomemore;
847
860
 
848
861
  AQUIRESPINLOCK( this->rtpdtlslock );
849
862
  dtlssession::pointer currentdtlssession = this->rtpdtls;
@@ -854,20 +867,13 @@ void projectrtpchannel::readsomertp( void ) {
854
867
  AQUIRESPINLOCK( this->rtpdtlslock );
855
868
  currentdtlssession->write( buf->pk, bytesrecvd );
856
869
  RELEASESPINLOCK( this->rtpdtlslock );
857
-
858
870
  this->dtlsnegotiate();
859
- this->readsomertp();
860
- return;
871
+ goto readsomemore;
861
872
  }
862
873
 
863
- /* RTP - TODO check for MUXED RTCP */
864
- /* We should still count packets we are instructed to drop */
865
- this->receivedpkcount++;
866
-
867
874
  if( !this->recv ) {
868
875
  this->receivedpkskip++;
869
- this->readsomertp();
870
- return;
876
+ goto readsomemore;
871
877
  }
872
878
 
873
879
  this->tickswithnortpcount = 0;
@@ -878,26 +884,28 @@ void projectrtpchannel::readsomertp( void ) {
878
884
  if( this->confirmedrtpsenderendpoint != this->rtpsenderendpoint ) {
879
885
  /* After the first packet - we only accept data from the verified source */
880
886
  this->receivedpkskip++;
881
- this->readsomertp();
882
- return;
887
+ goto readsomemore;
883
888
  }
884
889
 
885
890
  if( buf->getssrc() != this->ssrcin ) {
886
891
  this->receivedpkskip++;
887
- this->readsomertp();
888
- return;
892
+ goto readsomemore;
889
893
  }
890
894
 
891
-
892
-
893
- buf->length = bytesrecvd;
895
+ /* dynamic payload types */
896
+ auto pt = buf->getpayloadtype();
897
+ if( pt == this->ilbcpt ) {
898
+ buf->setpayloadtype( ILBCPAYLOADTYPE );
899
+ } else if ( pt == this->rfc2833pt ) {
900
+ buf->setpayloadtype( RFC2833PAYLOADTYPE );
901
+ }
894
902
 
895
903
  AQUIRESPINLOCK( this->rtpbufferlock );
896
904
  this->inbuff->push();
897
905
  RELEASESPINLOCK( this->rtpbufferlock );
898
-
899
906
  }
900
907
 
908
+ readsomemore:
901
909
  this->readsomertp();
902
910
 
903
911
  } );
@@ -961,44 +969,46 @@ void projectrtpchannel::writepacket( rtppacket *pk ) {
961
969
 
962
970
  if( !this->active ) return;
963
971
 
972
+ AQUIRESPINLOCK( this->rtpdtlslock );
973
+ dtlssession::pointer currentdtlssession = this->rtpdtls;
974
+ RELEASESPINLOCK( this->rtpdtlslock );
975
+
976
+ if( nullptr != currentdtlssession &&
977
+ currentdtlssession->rtpdtlshandshakeing ) {
978
+ goto completewrite;
979
+ }
980
+
964
981
  if( nullptr == pk ) {
965
- this->outpkskipcount++;
966
982
  fprintf( stderr, "We have been given an nullptr RTP packet??\n" );
967
- return;
983
+ goto completewrite;
968
984
  }
969
985
 
970
986
  if( 0 == pk->length ) {
971
- this->outpkskipcount++;
972
987
  fprintf( stderr, "We have been given an RTP packet of zero length??\n" );
973
- return;
988
+ goto completewrite;
974
989
  }
975
990
 
976
- if( !this->send ) {
977
- this->outpkskipcount++;
978
- /* silently drop - could we do this sooner to use less CPU? */
979
- return;
980
- }
981
-
982
- AQUIRESPINLOCK( this->rtpdtlslock );
983
- dtlssession::pointer currentdtlssession = this->rtpdtls;
984
- RELEASESPINLOCK( this->rtpdtlslock );
985
-
986
- if( nullptr != currentdtlssession &&
987
- currentdtlssession->rtpdtlshandshakeing ) {
988
- this->outpkskipcount++;
989
- return;
990
- }
991
+ /* silently drop - could we do this sooner to use less CPU? */
992
+ if( !this->send ) goto completewrite;
991
993
 
992
994
  if( nullptr != currentdtlssession &&
993
995
  !currentdtlssession->rtpdtlshandshakeing ) {
994
996
  if( !currentdtlssession->protect( pk ) ) {
995
- this->outpkskipcount++;
996
- return;
997
+ goto completewrite;
997
998
  }
998
999
  }
999
1000
 
1000
1001
  if( this->remoteconfirmed ) {
1001
1002
  this->snout++;
1003
+ this->outpkwritecount++;
1004
+
1005
+ /* dynamic payload types */
1006
+ auto pt = pk->getpayloadtype();
1007
+ if( pt == ILBCPAYLOADTYPE ) {
1008
+ pk->setpayloadtype( this->ilbcpt );
1009
+ } else if ( pt == RFC2833PAYLOADTYPE ) {
1010
+ pk->setpayloadtype( this->rfc2833pt );
1011
+ }
1002
1012
 
1003
1013
  this->rtpsocket.async_send_to(
1004
1014
  boost::asio::buffer( pk->pk, pk->length ),
@@ -1009,6 +1019,7 @@ void projectrtpchannel::writepacket( rtppacket *pk ) {
1009
1019
  boost::asio::placeholders::bytes_transferred ) );
1010
1020
  return;
1011
1021
  }
1022
+ completewrite:
1012
1023
  this->outpkskipcount++;
1013
1024
  }
1014
1025
 
@@ -1037,6 +1048,8 @@ bool projectrtpchannel::mix( projectrtpchannel::pointer other ) {
1037
1048
  other->mixer = this->mixer;
1038
1049
 
1039
1050
  this->mixer->addchannels( shared_from_this(), other );
1051
+
1052
+ this->mixer->go();
1040
1053
  } else {
1041
1054
  /* If we get here this and other are already mixing and should be cleaned up first */
1042
1055
  RELEASESPINLOCK( this->mixerlock );
@@ -1044,11 +1057,6 @@ bool projectrtpchannel::mix( projectrtpchannel::pointer other ) {
1044
1057
  return false;
1045
1058
  }
1046
1059
 
1047
- this->mixing = true;
1048
- other->mixing = true;
1049
-
1050
- this->mixer->go();
1051
-
1052
1060
  RELEASESPINLOCK( this->mixerlock );
1053
1061
 
1054
1062
  postdatabacktojsfromthread( shared_from_this(), "mix", "start" );
@@ -1190,6 +1198,9 @@ void projectrtpchannel::handlesend(
1190
1198
 
1191
1199
  if( !error && bytes_transferred > 0 ) {
1192
1200
  this->outpkcount++;
1201
+ } else {
1202
+ fprintf( stderr, "Problem sending packet\n" );
1203
+ this->outpkdropcount++;
1193
1204
  }
1194
1205
  }
1195
1206
 
@@ -1561,6 +1572,23 @@ static napi_value channelremote( napi_env env, napi_callback_info info ) {
1561
1572
  uint32_t codecval = 0;
1562
1573
  napi_get_value_uint32( env, ncodec, &codecval );
1563
1574
 
1575
+ uint32_t ilbcpt = ILBCPAYLOADTYPE;
1576
+ uint32_t rfc2833pt = RFC2833PAYLOADTYPE;
1577
+
1578
+ bool hasit;
1579
+ napi_value nptval;
1580
+ if( napi_ok == napi_has_named_property( env, argv[ 0 ], "ilbcpt", &hasit ) &&
1581
+ hasit &&
1582
+ napi_ok == napi_get_named_property( env, argv[ 0 ], "ilbcpt", &nptval ) ) {
1583
+ napi_get_value_uint32( env, nptval, &ilbcpt );
1584
+ }
1585
+
1586
+ if( napi_ok == napi_has_named_property( env, argv[ 0 ], "rfc2833pt", &hasit ) &&
1587
+ hasit &&
1588
+ napi_ok == napi_get_named_property( env, argv[ 0 ], "rfc2833pt", &nptval ) ) {
1589
+ napi_get_value_uint32( env, nptval, &rfc2833pt );
1590
+ }
1591
+
1564
1592
  size_t bytescopied;
1565
1593
  char remoteaddress[ 128 ];
1566
1594
 
@@ -1571,7 +1599,6 @@ static napi_value channelremote( napi_env env, napi_callback_info info ) {
1571
1599
 
1572
1600
  /* optional - DTLS */
1573
1601
  napi_value dtls;
1574
- bool hasit;
1575
1602
  dtlssession::mode dtlsmode = dtlssession::none;
1576
1603
  char vfingerprint[ 128 ];
1577
1604
  vfingerprint[ 0 ] = 0;
@@ -1621,7 +1648,7 @@ static napi_value channelremote( napi_env env, napi_callback_info info ) {
1621
1648
  }
1622
1649
  }
1623
1650
 
1624
- chan->remote( remoteaddress, remoteport, codecval, dtlsmode, vfingerprint );
1651
+ chan->remote( remoteaddress, remoteport, codecval, ilbcpt, rfc2833pt, dtlsmode, vfingerprint );
1625
1652
 
1626
1653
  return createnapibool( env, true );
1627
1654
  }
@@ -1714,23 +1741,35 @@ napi_value createcloseobject( napi_env env, projectrtpchannel::pointer p ) {
1714
1741
  if( napi_ok != napi_create_double( env, 0.0, &mos ) ) return NULL;
1715
1742
  }
1716
1743
 
1717
- napi_value receivedpkcount, receivedpkskip, receiveddropped;
1744
+ napi_value receivedpkcount, receivedpkskip, receiveddropped, resceivedpushed, resceivedpopped, bufferbadsn;
1718
1745
  if( napi_ok != napi_create_double( env, p->receivedpkcount, &receivedpkcount ) ) return NULL;
1719
1746
  if( napi_ok != napi_create_double( env, p->receivedpkskip, &receivedpkskip ) ) return NULL;
1720
1747
  if( napi_ok != napi_create_double( env, p->inbuff->getdropped(), &receiveddropped ) ) return NULL;
1748
+ if( napi_ok != napi_create_double( env, p->inbuff->getpopped(), &resceivedpopped ) ) return NULL;
1749
+ if( napi_ok != napi_create_double( env, p->inbuff->getpushed(), &resceivedpushed ) ) return NULL;
1750
+ if( napi_ok != napi_create_double( env, p->inbuff->getbadsn(), &bufferbadsn ) ) return NULL;
1721
1751
 
1722
1752
  if( napi_ok != napi_set_named_property( env, in, "mos", mos ) ) return NULL;
1723
1753
  if( napi_ok != napi_set_named_property( env, in, "count", receivedpkcount ) ) return NULL;
1724
1754
  if( napi_ok != napi_set_named_property( env, in, "dropped", receiveddropped ) ) return NULL;
1755
+ if( napi_ok != napi_set_named_property( env, in, "popped", resceivedpopped ) ) return NULL;
1756
+ if( napi_ok != napi_set_named_property( env, in, "pushed", resceivedpushed ) ) return NULL;
1725
1757
  if( napi_ok != napi_set_named_property( env, in, "skip", receivedpkskip ) ) return NULL;
1758
+ if( napi_ok != napi_set_named_property( env, in, "badsn", bufferbadsn ) ) return NULL;
1726
1759
 
1727
- napi_value sentpkcount, outpkskipcount;
1760
+ napi_value sentpkcount, outpkskipcount, outdropcount, outwritecount;
1728
1761
  if( napi_ok != napi_create_double( env, p->outpkcount, &sentpkcount ) ) return NULL;
1729
1762
  if( napi_ok != napi_set_named_property( env, out, "count", sentpkcount ) ) return NULL;
1730
1763
 
1731
1764
  if( napi_ok != napi_create_double( env, p->outpkskipcount, &outpkskipcount ) ) return NULL;
1732
1765
  if( napi_ok != napi_set_named_property( env, out, "skip", outpkskipcount ) ) return NULL;
1733
1766
 
1767
+ if( napi_ok != napi_create_double( env, p->outpkdropcount, &outdropcount ) ) return NULL;
1768
+ if( napi_ok != napi_set_named_property( env, out, "drop", outdropcount ) ) return NULL;
1769
+
1770
+ if( napi_ok != napi_create_double( env, p->outpkwritecount, &outwritecount ) ) return NULL;
1771
+ if( napi_ok != napi_set_named_property( env, out, "write", outwritecount ) ) return NULL;
1772
+
1734
1773
  napi_value meanticktimeus, maxticktimeus, totaltickcount;
1735
1774
  if( p->totaltickcount > 0 ) {
1736
1775
  if( napi_ok != napi_create_double( env, ( p->totalticktime / p->totaltickcount ), &meanticktimeus ) ) return NULL;
@@ -1903,6 +1942,8 @@ static napi_value channelcreate( napi_env env, napi_callback_info info ) {
1903
1942
  char vfingerprint[ 128 ];
1904
1943
  vfingerprint[ 0 ] = 0;
1905
1944
  uint32_t codecval = 0;
1945
+ uint32_t ilbcpt = ILBCPAYLOADTYPE;
1946
+ uint32_t rfc2833pt = RFC2833PAYLOADTYPE;
1906
1947
 
1907
1948
  if( napi_ok == napi_has_named_property( env, argv[ 0 ], "remote", &hasit ) &&
1908
1949
  hasit &&
@@ -1975,6 +2016,19 @@ nodtls:
1975
2016
  return NULL;
1976
2017
  }
1977
2018
 
2019
+ napi_value nptval;
2020
+ if( napi_ok == napi_has_named_property( env, nremote, "ilbcpt", &hasit ) &&
2021
+ hasit &&
2022
+ napi_ok == napi_get_named_property( env, nremote, "ilbcpt", &nptval ) ) {
2023
+ napi_get_value_uint32( env, nptval, &ilbcpt );
2024
+ }
2025
+
2026
+ if( napi_ok == napi_has_named_property( env, nremote, "rfc2833pt", &hasit ) &&
2027
+ hasit &&
2028
+ napi_ok == napi_get_named_property( env, nremote, "rfc2833pt", &nptval ) ) {
2029
+ napi_get_value_uint32( env, nptval, &rfc2833pt );
2030
+ }
2031
+
1978
2032
  napi_get_value_uint32( env, ncodec, &codecval );
1979
2033
 
1980
2034
  if( napi_ok != napi_get_named_property( env, nremote, "address", &naddress ) ) {
@@ -2087,7 +2141,7 @@ nodtls:
2087
2141
  return NULL;
2088
2142
  }
2089
2143
 
2090
- p->remote( remoteaddress, remoteport, codecval, dtlsmode, vfingerprint );
2144
+ p->remote( remoteaddress, remoteport, codecval, ilbcpt, rfc2833pt, dtlsmode, vfingerprint );
2091
2145
  uint32_t ssrc = p->requestopen();
2092
2146
 
2093
2147
  /* methods */
@@ -82,6 +82,8 @@ public:
82
82
  void remote( std::string address,
83
83
  unsigned short port,
84
84
  uint32_t codec,
85
+ unsigned short ilbcpt,
86
+ unsigned short rfc2833pt,
85
87
  dtlssession::mode,
86
88
  std::string fingerprint );
87
89
 
@@ -132,8 +134,10 @@ public:
132
134
  std::atomic_uint64_t totaltickcount;
133
135
  std::atomic_uint16_t tickswithnortpcount;
134
136
 
137
+ std::atomic_uint64_t outpkwritecount;
135
138
  std::atomic_uint64_t outpkcount;
136
139
  std::atomic_uint64_t outpkskipcount;
140
+ std::atomic_uint64_t outpkdropcount;
137
141
 
138
142
  /* buffer and spin lock for in traffic */
139
143
  rtpbuffer::pointer inbuff;
@@ -159,6 +163,8 @@ private:
159
163
  std::atomic_bool active;
160
164
  unsigned short port;
161
165
  unsigned short rfc2833pt;
166
+ unsigned short ilbcpt;
167
+
162
168
  uint32_t lasttelephoneeventsn;
163
169
  uint8_t lasttelephoneevent;
164
170