@babblevoice/projectrtp 2.3.7 → 2.4.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.
@@ -0,0 +1,65 @@
1
+ name: Build
2
+
3
+ # Controls when the workflow will run
4
+ on:
5
+ workflow_dispatch:
6
+ push:
7
+ branches:
8
+ - 'main'
9
+ - 'dev'
10
+ tags:
11
+ - 'v*.*.*'
12
+ pull_request:
13
+ branches:
14
+ - 'main'
15
+ - 'dev'
16
+
17
+ #GH
18
+ permissions:
19
+ contents: read
20
+
21
+ jobs:
22
+ build:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ # Get the repository's code
26
+ - name: Checkout
27
+ uses: actions/checkout@v3
28
+ # https://github.com/docker/setup-qemu-action
29
+ - name: Set up QEMU
30
+ uses: docker/setup-qemu-action@v1
31
+ # https://github.com/docker/setup-buildx-action
32
+ - name: Set up Docker Buildx
33
+ id: buildx
34
+ uses: docker/setup-buildx-action@v2
35
+ - name: Login to Docker Hub
36
+ if: github.event_name != 'pull_request'
37
+ uses: docker/login-action@v2
38
+ with:
39
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
40
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
41
+ - name: Docker meta
42
+ id: ourdockertags
43
+ uses: docker/metadata-action@v3
44
+ with:
45
+ # list of Docker images to use as base name for tags
46
+ images: |
47
+ docker.io/tinpotnick/projectrtp
48
+ # Docker tags based on the following events/attributes
49
+ tags: |
50
+ type=schedule
51
+ type=ref,event=branch
52
+ type=ref,event=pr
53
+ type=semver,pattern={{version}}
54
+ type=semver,pattern={{major}}.{{minor}}
55
+ type=semver,pattern={{major}}
56
+ type=sha
57
+
58
+ - name: Build and push
59
+ uses: docker/build-push-action@v2
60
+ with:
61
+ context: .
62
+ platforms: linux/amd64,linux/arm64
63
+ push: ${{ github.event_name != 'pull_request' }}
64
+ tags: ${{ steps.ourdockertags.outputs.tags }}
65
+ labels: ${{ steps.ourdockertags.outputs.labels }}
package/lib/node.js CHANGED
@@ -78,7 +78,8 @@ class rtpnode {
78
78
  const con = {
79
79
  connectionid: uuidv4(),
80
80
  connection,
81
- "connectionlength": 0
81
+ "connectionlength": 0,
82
+ "mode": "connect"
82
83
  }
83
84
  this.connections[ con.connectionid ] = con
84
85
  this.connection.on( "data", this._onsocketdata.bind( this, con ) )
@@ -97,7 +98,8 @@ class rtpnode {
97
98
  const con = {
98
99
  connectionid: uuidv4(),
99
100
  connection,
100
- "connectionlength": 0
101
+ "connectionlength": 0,
102
+ "mode": "listen"
101
103
  }
102
104
  this.connections[ con.connectionid ] = con
103
105
  connection.setKeepAlive( true )
@@ -163,12 +165,13 @@ class rtpnode {
163
165
  * @param { object } connection
164
166
  * @returns { void }
165
167
  */
166
- send( msg, connection ) {
168
+ send( msg, connection, cb = undefined ) {
167
169
  this._post( msg, ( modifiedmsg ) => {
168
170
  if( this._destroying ) return
169
171
  msg.status = this.prtp.stats()
170
172
  msg.status.instance = instance
171
173
  connection.write( message.createmessage( modifiedmsg ) )
174
+ if (cb !== undefined) cb(msg)
172
175
  } )
173
176
  }
174
177
 
@@ -195,7 +198,9 @@ class rtpnode {
195
198
  * @returns { Promise< Boolean > }
196
199
  */
197
200
  async _processmessage( msg, con ) {
198
- return ( await this._openchannel( msg, con ) || this._updatechannel( msg, con ) )
201
+ if( "open" == msg.channel ) return await this._openchannel( msg, con )
202
+
203
+ return this._updatechannel( msg, con )
199
204
  }
200
205
 
201
206
  /**
@@ -285,21 +290,25 @@ class rtpnode {
285
290
  * @returns { Promise< Boolean > }
286
291
  */
287
292
  async _openchannel( msg, con ) {
288
- if( "open" !== msg.channel ) return false
289
293
  con.connectionlength += 1
290
294
  msg.forcelocal = true
291
295
 
292
- const chan = await this.prtp.openchannel( msg, ( x ) => {
293
- this.send( { ...{ "id": chan.id, "uuid": chan.uuid }, ...x }, con.connection )
294
- if( "close" === x.action ) {
295
- con.connectionlength -= 1
296
- channels.delete( chan.uuid )
297
-
298
- if( 0 == con.connectionlength ) {
299
- this.connections.delete( con.instance )
300
- con.connection.destroy()
301
- }
302
- }
296
+ const chan = await this.prtp.openchannel( msg, ( cookie ) => {
297
+ // TODO: we might want to ensure the actual event has been written
298
+ // to the server before cleaning up the channel on our side?
299
+ this.send( { ...{ "id": chan.id, "uuid": chan.uuid }, ...cookie },
300
+ con.connection,
301
+ ( cookie ) => {
302
+ if ( "close" === cookie.action ) {
303
+ con.connectionlength -= 1
304
+ channels.delete( chan.uuid )
305
+
306
+ if( 0 == con.connectionlength && "listen" == con.mode ) {
307
+ this.connections.delete( con.instance )
308
+ con.connection.destroy()
309
+ }
310
+ }
311
+ } )
303
312
  } )
304
313
  channels.set( chan.uuid, chan )
305
314
  this.send( { ...chan, ...{ "action": "open" } }, con.connection )
package/lib/server.js CHANGED
@@ -260,20 +260,27 @@ class channel {
260
260
  /**
261
261
  * This method forces an open channel on the same remote node.
262
262
  * @param { object } options
263
+ * @param { channelcallback } cb
263
264
  * @returns { Promise< channel > }
264
265
  */
265
- openchannel( options = {} ) {
266
+ openchannel( options = undefined, cb = undefined ) {
267
+ if( "function" == typeof options ) {
268
+ cb = options
269
+ options = {}
270
+ }
266
271
 
267
272
  options.channel = "open"
268
273
 
269
274
  const resolvepromise = new Promise( ( res ) => {
270
275
 
271
276
  const newchannel = new channel()
277
+ if( cb ) newchannel.em.on( "all", cb )
278
+
272
279
  newchannel.connection = this.connection
273
280
  newchannel.channels = this.channels
274
281
  newchannel.channels.push( newchannel )
282
+ newchannel.openresolve = res
275
283
  newchannel._write( options )
276
- res( newchannel )
277
284
  } )
278
285
 
279
286
  return resolvepromise
@@ -597,8 +604,6 @@ class channel {
597
604
  * @private
598
605
  */
599
606
  _runclose( msg ) {
600
- if( "close" !== msg.action ) return
601
-
602
607
  if( undefined !== this.openresolve ) {
603
608
  this.openresolve()
604
609
  delete this.openresolve
@@ -612,10 +617,6 @@ class channel {
612
617
  if( 0 === this.channels.length && this.connection.sock ) this.connection.sock.destroy()
613
618
  }
614
619
 
615
- if( this.connection && this.connection.sock && !this.channels ) {
616
- this.connection.sock.destroy()
617
- delete this.connection.sock
618
- }
619
620
 
620
621
  channels.delete( this.id )
621
622
  }
@@ -633,7 +634,7 @@ class channel {
633
634
  this.em.emit( "all", msg )
634
635
  this.em.emit( msg.action, msg )
635
636
 
636
- this._runclose( msg )
637
+ if( "close" == msg.action ) this._runclose( msg )
637
638
  }
638
639
 
639
640
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/projectrtp",
3
- "version": "2.3.7",
3
+ "version": "2.4.0",
4
4
  "description": "A scalable Node addon RTP server",
5
5
  "main": "index.js",
6
6
  "directories": {
package/stress/utils.js CHANGED
@@ -20,9 +20,18 @@ module.exports.logclosechannel = ( message, d, mstimeout ) => {
20
20
  channelcount--
21
21
  totalcount++
22
22
  module.exports.log( message )
23
- module.exports.log( ` Expected number of packets: ${Math.round(mstimeout / 20)}, Received: ${d.stats.in["count"]},` +
24
- ` Score: ${(d.stats.in["count"] / mstimeout * 20).toFixed(2)}` )
25
- module.exports.log( `Channel closed - current count now ${channelcount} total channels this session ${totalcount}` )
23
+
24
+ const score = ( d.stats.in["count"] / mstimeout * 20 ).toFixed( 2 )
25
+ let scoremsg = ` Score: ${ score }`
26
+
27
+ // Colour based on score: red, yellow, green
28
+ if( 0.25 >= score ) scoremsg = "\x1B[31m" + scoremsg
29
+ else if( 0.7 >= score ) scoremsg = "\x1B[33m" + scoremsg
30
+ else scoremsg = "\x1B[32m" + scoremsg
31
+ scoremsg += "\x1B[37m"
32
+
33
+ module.exports.log( `Expected number of packets: ${ Math.round( mstimeout / 20 ) }, Received: ${ d.stats.in[ "count" ] },` + scoremsg )
34
+ module.exports.log( `Channel closed - current count now ${ channelcount } total channels this session ${ totalcount }` )
26
35
  }
27
36
 
28
37
  module.exports.totalchannelcount = () => {
@@ -673,4 +673,21 @@ describe( "rtpproxy server", function() {
673
673
 
674
674
 
675
675
  } )
676
+ it( "Ensure connection stays open with 0 channel in listen mode", async () => {
677
+
678
+ const ourport = getnextport()
679
+ prtp.server.clearnodes()
680
+ const p = await prtp.proxy.listen( undefined, "127.0.0.1", ourport )
681
+ const ournode = await prtp.node.connect( ourport, "127.0.0.1" )
682
+
683
+
684
+ const chnl = await prtp.openchannel()
685
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 100 ) } )
686
+ await chnl.close()
687
+ const chnl2 = await prtp.openchannel()
688
+ await chnl2.close()
689
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 100 ) } )
690
+ ournode.destroy()
691
+ p.destroy()
692
+ } )
676
693
  } )