@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 +3 -70
- package/package.json +6 -4
- package/src/globals.h +5 -0
- package/src/projectrtpbuffer.cpp +30 -6
- package/src/projectrtpbuffer.h +14 -3
- package/src/projectrtpchannel.cpp +110 -56
- package/src/projectrtpchannel.h +6 -0
- package/src/projectrtpchannelmux.cpp +23 -15
- package/src/projectrtpchannelmux.h +4 -2
- package/src/projectrtpcodecx.cpp +72 -96
- package/src/projectrtpcodecx.h +18 -5
- package/src/projectrtppacket.cpp +16 -41
- package/src/projectrtppacket.h +0 -2
- package/src/projectrtprawsound.cpp +56 -75
- package/src/projectrtprawsound.h +3 -2
- package/src/projectrtpsoundfile.cpp +4 -1
- package/src/projectrtptonegen.cpp +26 -43
- package/test/interface/pcap.js +2 -2
- package/test/interface/pcaps/440hzinbackgroundg722.pcap +0 -0
- package/test/interface/projectrtpchannel.js +10 -10
- package/test/interface/projectrtpdtmf.js +88 -4
- package/test/interface/projectrtpmix.js +1 -2
- package/test/interface/transcode.js +821 -0
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
|
-
###
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
-
"
|
|
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
|
package/src/projectrtpbuffer.cpp
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
84
|
-
|
|
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
|
-
|
|
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 )
|
|
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;
|
package/src/projectrtpbuffer.h
CHANGED
|
@@ -10,13 +10,17 @@
|
|
|
10
10
|
#include "projectrtppacket.h"
|
|
11
11
|
|
|
12
12
|
/* Defaults */
|
|
13
|
-
/*
|
|
14
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
882
|
-
return;
|
|
887
|
+
goto readsomemore;
|
|
883
888
|
}
|
|
884
889
|
|
|
885
890
|
if( buf->getssrc() != this->ssrcin ) {
|
|
886
891
|
this->receivedpkskip++;
|
|
887
|
-
|
|
888
|
-
return;
|
|
892
|
+
goto readsomemore;
|
|
889
893
|
}
|
|
890
894
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
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
|
-
|
|
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
|
-
|
|
988
|
+
goto completewrite;
|
|
974
989
|
}
|
|
975
990
|
|
|
976
|
-
|
|
977
|
-
|
|
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
|
-
|
|
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 */
|
package/src/projectrtpchannel.h
CHANGED
|
@@ -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
|
|