@babblevoice/projectrtp 2.5.35 → 2.6.0
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/.dockerignore +2 -0
- package/Dockerfile +5 -7
- package/Dockerfile.debian +42 -0
- package/README.md +18 -1
- package/asan.options +2 -0
- package/binding.gyp +30 -3
- package/index.js +21 -1
- package/jsconfig.json +1 -1
- package/lib/server.js +26 -10
- package/package.json +6 -6
- package/src/globals.h +3 -0
- package/src/projectrtpbuffer.cpp +3 -0
- package/src/projectrtpchannel.cpp +176 -181
- package/src/projectrtpchannel.h +5 -6
- package/src/projectrtpchannelmux.cpp +45 -46
- package/src/projectrtpchannelmux.h +2 -4
- package/src/projectrtpchannelrecorder.h +4 -4
- package/src/projectrtpcodecx.cpp +36 -56
- package/src/projectrtpnodemain.cpp +3 -0
- package/src/projectrtppacket.cpp +3 -0
- package/src/projectrtprawsound.cpp +30 -11
- package/src/projectrtprawsound.h +3 -1
- package/src/projectrtpsoundfile.cpp +260 -182
- package/src/projectrtpsoundfile.h +14 -3
- package/src/projectrtpsoundsoup.cpp +2 -0
- package/src/projectrtpstun.cpp +3 -0
- package/stress/echorecord.scenario.js +4 -1
- package/stress/index.js +4 -1
- package/stress/playbackrecordtoofast.scenario.js +106 -0
- package/stress/playbackthenmix.scenario.js +70 -0
- package/stress/utils.js +27 -3
- package/test/interface/projectrtpdtmf.js +41 -12
- package/test/interface/projectrtpmix.js +78 -0
- package/test/interface/projectrtprecord.js +1 -1
- package/test/interface/projectrtpsound.js +121 -0
package/.dockerignore
CHANGED
package/Dockerfile
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
# I have tied this to version alpine 3.16 as 3.17 has an exception symbol dynamic linking issue.
|
|
4
|
-
FROM alpine:3.20 AS builder
|
|
5
|
-
|
|
2
|
+
FROM alpine:3.21 AS builder
|
|
6
3
|
|
|
7
4
|
WORKDIR /usr/src/
|
|
8
5
|
|
|
@@ -17,10 +14,11 @@ RUN apk add --no-cache \
|
|
|
17
14
|
WORKDIR /usr/local/lib/node_modules/@babblevoice/projectrtp/
|
|
18
15
|
COPY . .
|
|
19
16
|
|
|
20
|
-
RUN npm ci --no-optional --production
|
|
21
|
-
rm -fr src/build/Release/obj.target
|
|
17
|
+
RUN npm ci --no-optional --production && \
|
|
18
|
+
rm -fr src/build/Release/obj.target && \
|
|
19
|
+
rm -fr build/Release/obj.target/projectrtp
|
|
22
20
|
|
|
23
|
-
FROM alpine:3.
|
|
21
|
+
FROM alpine:3.21 AS app
|
|
24
22
|
|
|
25
23
|
RUN apk add --no-cache \
|
|
26
24
|
spandsp tiff gnutls libsrtp libc6-compat openssl ca-certificates nodejs npm
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
FROM node:22-bookworm-slim AS builder
|
|
3
|
+
|
|
4
|
+
WORKDIR /usr/src/
|
|
5
|
+
|
|
6
|
+
RUN apt-get update && apt-get install -y \
|
|
7
|
+
build-essential cmake python3 wget libspandsp-dev libtiff-dev libgnutls28-dev libsrtp2-dev libboost-all-dev && \
|
|
8
|
+
npm install -g node-gyp && \
|
|
9
|
+
wget https://github.com/TimothyGu/libilbc/releases/download/v3.0.4/libilbc-3.0.4.tar.gz && \
|
|
10
|
+
tar xvzf libilbc-3.0.4.tar.gz && \
|
|
11
|
+
cd libilbc-3.0.4 && \
|
|
12
|
+
cmake . -DCMAKE_INSTALL_LIBDIR=/usr/lib -DCMAKE_INSTALL_INCLUDEDIR=/usr/include && \
|
|
13
|
+
cmake --build . && \
|
|
14
|
+
cmake --install . && \
|
|
15
|
+
cd .. && rm -rf libilbc-3.0.4 libilbc-3.0.4.tar.gz && \
|
|
16
|
+
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
17
|
+
|
|
18
|
+
WORKDIR /usr/local/lib/node_modules/@babblevoice/projectrtp/
|
|
19
|
+
COPY . .
|
|
20
|
+
|
|
21
|
+
# Install production dependencies
|
|
22
|
+
RUN npm ci --no-optional --production && \
|
|
23
|
+
rm -fr src/build/Release/obj.target && \
|
|
24
|
+
rm -fr build/Release/obj.target/projectrtp
|
|
25
|
+
|
|
26
|
+
FROM node:22-bookworm-slim AS app
|
|
27
|
+
|
|
28
|
+
RUN apt-get update && apt-get install -y \
|
|
29
|
+
libspandsp2 libtiff6 libgnutls30 libc6 openssl ca-certificates && \
|
|
30
|
+
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
31
|
+
|
|
32
|
+
COPY --from=builder /usr/local/lib/node_modules/@babblevoice/projectrtp/ /usr/local/lib/node_modules/@babblevoice/projectrtp/
|
|
33
|
+
COPY --from=builder /usr/lib/libilbc* /usr/lib/
|
|
34
|
+
|
|
35
|
+
ENV NODE_PATH=/usr/local/lib/node_modules
|
|
36
|
+
|
|
37
|
+
# Expose UDP ports
|
|
38
|
+
EXPOSE 10000-50000/udp
|
|
39
|
+
|
|
40
|
+
# Set working directory and run the app
|
|
41
|
+
WORKDIR /usr/local/lib/node_modules/@babblevoice/projectrtp/
|
|
42
|
+
CMD ["node", "examples/simplenode.js"]
|
package/README.md
CHANGED
|
@@ -46,6 +46,12 @@ We now have 3 different sets of tests.
|
|
|
46
46
|
|
|
47
47
|
### `npm test`
|
|
48
48
|
|
|
49
|
+
If you are using an image - that doesn't have dev deps installed then theses might need to be added:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
npm install --omit=prod --ignore-scripts
|
|
53
|
+
```
|
|
54
|
+
|
|
49
55
|
All tests are run from NodeJS. From the root directory, run the `npm test`. These test all our interfaces and should test expected outputs. These tests use mocha.
|
|
50
56
|
|
|
51
57
|
The folder is separated out into interface, unit and mock. The mock folder contains mock objects/functions required for testing. Unit tests are to help test internal functions. Interface tests are used to guarantee a stable interface for a specific version number. If these tests require changing (other than bug fixing i.e. a material API change), then a major version update will happen.
|
|
@@ -60,7 +66,18 @@ If you wish to build outsode of a Docker image, there are npm target scripts for
|
|
|
60
66
|
|
|
61
67
|
```bash
|
|
62
68
|
docker buildx prune
|
|
63
|
-
docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:2.5.
|
|
69
|
+
docker buildx build --platform linux/amd64,linux/arm64 -t tinpotnick/projectrtp:2.5.37_beta22 . --push
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Dev build
|
|
73
|
+
|
|
74
|
+
Some items might need installing.
|
|
75
|
+
```sh
|
|
76
|
+
sudo dnf install libasan libubsan
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
npm run build:dev
|
|
64
81
|
```
|
|
65
82
|
|
|
66
83
|
## Example scripts
|
package/asan.options
ADDED
package/binding.gyp
CHANGED
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
{
|
|
2
|
+
"variables": {
|
|
3
|
+
"build_type%": "prod"
|
|
4
|
+
},
|
|
2
5
|
"targets": [
|
|
3
6
|
{
|
|
4
7
|
"target_name": "projectrtp",
|
|
5
8
|
"defines": [ "NODE_MODULE", "BOOST_NO_EXCEPTIONS", "BOOST_EXCEPTION_DISABLE", "NAPI_DISABLE_CPP_EXCEPTIONS" ],
|
|
6
9
|
"cflags_cc!": [ "-fno-rtti" ],
|
|
7
10
|
"cflags_cc": [
|
|
8
|
-
"-O3",
|
|
9
11
|
"-g",
|
|
10
|
-
"-Wall",
|
|
11
|
-
"-fstack-protector-strong",
|
|
12
12
|
"-std=c++20",
|
|
13
13
|
"-Weffc++" ],
|
|
14
|
+
"conditions": [
|
|
15
|
+
[
|
|
16
|
+
"build_type=='dev'", {
|
|
17
|
+
"cflags": [
|
|
18
|
+
"-O1",
|
|
19
|
+
"-fsanitize=address,undefined,bounds",
|
|
20
|
+
"-fno-omit-frame-pointer",
|
|
21
|
+
"-D_FORTIFY_SOURCE=2",
|
|
22
|
+
"-fstack-protector-strong",
|
|
23
|
+
"-fstack-protector-all",
|
|
24
|
+
"-Wformat-security",
|
|
25
|
+
"-Wall",
|
|
26
|
+
"-Wextra"
|
|
27
|
+
],
|
|
28
|
+
"ldflags": [
|
|
29
|
+
"-fsanitize=address,undefined,bounds"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
"build_type=='prod'", {
|
|
35
|
+
"cflags": [
|
|
36
|
+
"-O3"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
],
|
|
14
41
|
"ldflags": [
|
|
15
42
|
"-Wl,-z,relro",
|
|
16
43
|
"-Wl,-z,now",
|
package/index.js
CHANGED
|
@@ -10,7 +10,12 @@ const { spawnSync } = require( "child_process" )
|
|
|
10
10
|
|
|
11
11
|
let localaddress = "127.0.0.1"
|
|
12
12
|
let privateaddress = "127.0.0.1"
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
let bin = "./build/Release/projectrtp"
|
|
15
|
+
if ( fs.existsSync( "./build/Debug/projectrtp.node" ) ) {
|
|
16
|
+
console.log( "Dev build exists - using dev build..." )
|
|
17
|
+
bin = "./build/Debug/projectrtp"
|
|
18
|
+
}
|
|
14
19
|
|
|
15
20
|
|
|
16
21
|
/**
|
|
@@ -135,6 +140,21 @@ class proxy {
|
|
|
135
140
|
this._server.clearnodes()
|
|
136
141
|
}
|
|
137
142
|
|
|
143
|
+
/**
|
|
144
|
+
*
|
|
145
|
+
* @param {*} nodes
|
|
146
|
+
*/
|
|
147
|
+
setnodes( nodes ) {
|
|
148
|
+
this._server.setnodes( nodes )
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
*
|
|
153
|
+
*/
|
|
154
|
+
getnodes() {
|
|
155
|
+
return this._server.getnodes()
|
|
156
|
+
}
|
|
157
|
+
|
|
138
158
|
get () {
|
|
139
159
|
return server.interface.get()
|
|
140
160
|
}
|
package/jsconfig.json
CHANGED
package/lib/server.js
CHANGED
|
@@ -34,26 +34,22 @@ const nodeconnectiontype = { "listen": 1, "connect": 2 }
|
|
|
34
34
|
* @property { channel } left
|
|
35
35
|
* @property { channel } right
|
|
36
36
|
* @property { Set< channel > } channels
|
|
37
|
-
* @ignore
|
|
38
37
|
*/
|
|
39
38
|
/**
|
|
40
39
|
* @typedef { object } nodebridge
|
|
41
40
|
* @property { Array< channelbridge > } bridges
|
|
42
41
|
* @property { string } main
|
|
43
|
-
* @ignore
|
|
44
42
|
*/
|
|
45
43
|
|
|
46
44
|
/**
|
|
47
45
|
* The remote (listening) nodes
|
|
48
46
|
* @type { Array< nodehost > }
|
|
49
|
-
* @ignore
|
|
50
47
|
*/
|
|
51
48
|
let listeningnodes = []
|
|
52
49
|
|
|
53
50
|
/**
|
|
54
51
|
* Our nodes which have connected to our listening server.
|
|
55
52
|
* @type { Map< string, nodeconnection > }
|
|
56
|
-
* @ignore
|
|
57
53
|
*/
|
|
58
54
|
let nodes = new Map()
|
|
59
55
|
|
|
@@ -429,8 +425,8 @@ class channel {
|
|
|
429
425
|
* @returns { Promise< Boolean > }
|
|
430
426
|
*/
|
|
431
427
|
async mix( other ) {
|
|
432
|
-
|
|
433
|
-
|
|
428
|
+
if( !other ) return false
|
|
429
|
+
if( !other.uuid ) return false
|
|
434
430
|
|
|
435
431
|
this._write( {
|
|
436
432
|
"channel": "mix",
|
|
@@ -627,7 +623,8 @@ class channel {
|
|
|
627
623
|
* @param { object } msg
|
|
628
624
|
*/
|
|
629
625
|
_on( msg ) {
|
|
630
|
-
msg.
|
|
626
|
+
msg.now = new Date()
|
|
627
|
+
msg.timestamp = msg.now.getTime()
|
|
631
628
|
this.history.push( msg )
|
|
632
629
|
if( this._runopen( msg ) ) return
|
|
633
630
|
if( this.#haserror( msg ) ) return
|
|
@@ -653,7 +650,8 @@ class channel {
|
|
|
653
650
|
|
|
654
651
|
this.connection.sock.write( message.createmessage( msg ) )
|
|
655
652
|
|
|
656
|
-
msg.
|
|
653
|
+
msg.now = new Date()
|
|
654
|
+
msg.timestamp = msg.now.getTime()
|
|
657
655
|
this.history.push( msg )
|
|
658
656
|
|
|
659
657
|
if( this._sockerr && nodeconnectiontype.connect == this.connection.type ) {
|
|
@@ -667,7 +665,9 @@ class channel {
|
|
|
667
665
|
}
|
|
668
666
|
|
|
669
667
|
/**
|
|
670
|
-
* @
|
|
668
|
+
* @param { number } min
|
|
669
|
+
* @param { number } max
|
|
670
|
+
* @returns { number }
|
|
671
671
|
*/
|
|
672
672
|
function between( min, max ) {
|
|
673
673
|
return Math.floor(
|
|
@@ -991,11 +991,27 @@ class serverinterface {
|
|
|
991
991
|
* Clean up after using remote nodes for us to connect to, switch back to local mode.
|
|
992
992
|
* @returns { void }
|
|
993
993
|
*/
|
|
994
|
-
clearnodes
|
|
994
|
+
clearnodes() {
|
|
995
995
|
delete serverinterface._s
|
|
996
996
|
listeningnodes = []
|
|
997
997
|
}
|
|
998
998
|
|
|
999
|
+
/**
|
|
1000
|
+
*
|
|
1001
|
+
* @param { Array< nodehost > } nodes
|
|
1002
|
+
*/
|
|
1003
|
+
setnodes( nodes ) {
|
|
1004
|
+
listeningnodes = nodes
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
*
|
|
1009
|
+
* @returns { Array< nodehost > }
|
|
1010
|
+
*/
|
|
1011
|
+
getnodes() {
|
|
1012
|
+
return listeningnodes
|
|
1013
|
+
}
|
|
1014
|
+
|
|
999
1015
|
/**
|
|
1000
1016
|
* Remove our reference to server interface
|
|
1001
1017
|
* @ignore
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@babblevoice/projectrtp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "A scalable Node addon RTP server",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -9,18 +9,18 @@
|
|
|
9
9
|
"test": "test"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
|
-
"test": "./node_modules/mocha/bin/_mocha test/**/*.js --check-leaks",
|
|
12
|
+
"test": "ASAN_OPTIONS=$(cat asan.options) LD_PRELOAD=/usr/lib64/libasan.so.8 ./node_modules/mocha/bin/_mocha test/**/*.js --check-leaks",
|
|
13
13
|
"github:check": "node test/basictests.js; npm update; ./node_modules/mocha/bin/_mocha test/**/*.js --check-leaks --exit",
|
|
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
|
-
"stress": "node stress/index.js",
|
|
17
|
-
"configure:dev": "node-gyp configure --
|
|
16
|
+
"stress": "ASAN_OPTIONS=$(cat asan.options) LD_PRELOAD=/usr/lib64/libasan.so.8 node stress/index.js",
|
|
17
|
+
"configure:dev": "node-gyp configure --build_type=dev",
|
|
18
18
|
"configure": "node-gyp configure",
|
|
19
|
-
"rebuild:dev": "node-gyp configure --debug; node-gyp rebuild --debug",
|
|
20
19
|
"clean": "node-gyp clean",
|
|
21
|
-
"build:dev": "node-gyp configure build --
|
|
20
|
+
"build:dev": "node-gyp configure build --build_type=dev",
|
|
22
21
|
"build": "node-gyp configure build",
|
|
23
22
|
"rebuild": "node-gyp rebuild",
|
|
23
|
+
"rebuild:dev": "node-gyp configure --build_type=dev; node-gyp rebuild --build_type=dev",
|
|
24
24
|
"install": "node-gyp rebuild"
|
|
25
25
|
},
|
|
26
26
|
"repository": {
|
package/src/globals.h
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#define L16NARROWBANDBYTES 320
|
|
16
16
|
#define L16WIDEBANDBYTES 640
|
|
17
17
|
#define ILBC20PAYLOADBYTES 38
|
|
18
|
+
#define ILBC20PAYLOADSAMPLES 38 /* correct ? */
|
|
18
19
|
#define ILBC30PAYLOADBYTES 50 /* not needed but for completness */
|
|
19
20
|
|
|
20
21
|
#define PCMUPAYLOADTYPE 0
|
|
@@ -65,4 +66,6 @@ struct SpinLockGuard {
|
|
|
65
66
|
}
|
|
66
67
|
};
|
|
67
68
|
|
|
69
|
+
#define releasespinlock( x ) x.store( false, std::memory_order_release );
|
|
70
|
+
|
|
68
71
|
#endif /* PROJECTRTPGLOBALS_H */
|