Skip to content

Commit

Permalink
peer-bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddias committed Jun 18, 2016
1 parent 9e87695 commit 2119f8f
Show file tree
Hide file tree
Showing 13 changed files with 455 additions and 70 deletions.
6 changes: 6 additions & 0 deletions examples/peer-bridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
How to use Peer Bridge
======================

> Peer Bridge is used by Remote Performer to connect the peers together through WebRTC DataChannels, exposing a primitive to broadcast the MIDI controls.

16 changes: 16 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict'

var gulp = require('gulp')

var sigServer = require('./src/sig-server')
var sigS

gulp.task('test:browser:before', (done) => {
sigS = sigServer.start(15555, done)
})

gulp.task('test:browser:after', (done) => {
sigS.stop(done)
})

require('aegir/gulp')(gulp)
17 changes: 13 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
"description": "Real-time music collaboration for the web",
"main": "src/index.js",
"scripts": {
"build": "browserify -t brfs src/public/js/app.js > src/public/js/bundle.js",
"start": "npm run build && node src/index.js",
"build": "browserify -t brfs src/app/index.js > src/public/js/bundle.js",
"start": "npm run build && node src/sig-server/index.js",
"lint": "standard",
"test": "exit 0"
"test": "gulp test",
"test:node": "gulp test:node",
"test:browser": "gulp test:browser"
},
"repository": {
"type": "git",
"url": "https://github.com/websound/RemotePerformer.git"
},
"author": "Nathan Ward",
"license": "MIT",
"bugs": {
"url": "https://github.com/websound/RemotePerformer/issues"
Expand All @@ -32,14 +33,22 @@
"inert": "^4.0.0",
"insert-css": "^0.2.0",
"jquery": "^2.1.0",
"length-prefixed-stream": "^1.5.0",
"process-nextick-args": "^1.0.7",
"simple-peer": "^6.0.4",
"socket.io": "^1.4.6",
"socket.io-client": "^1.4.6",
"watchify": "^3.7.0",
"ws": "^1.1.0"
},
"devDependencies": {
"aegir": "^3.2.0",
"chai": "^3.5.0",
"eslint-config-standard": "^5.1.0",
"eslint-plugin-standard": "^1.3.2",
"mocha": "^2.5.3",
"pre-commit": "^1.1.3",
"run-parallel": "^1.1.6",
"standard": "^7.1.2"
}
}
File renamed without changes.
91 changes: 91 additions & 0 deletions src/app/peer-bridge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
var SimplePeer = require('simple-peer')
var EE = require('events').EventEmitter
var util = require('util')
var lpstream = require('length-prefixed-stream')
var io = require('socket.io-client')

exports = module.exports = PeerBridge

util.inherits(PeerBridge, EE)

function PeerBridge () {
this.conns = {}
this.id = (~~(Math.random() * 1e9)).toString(36) + Date.now()

this.setUp = (sigUrl, callback) => {
var sioClient = io.connect(sigUrl, {
transports: ['websocket'],
'force new connection': true
})
sioClient.once('connect_error', callback)
sioClient.on('connect', () => {
sioClient.emit('ss-join', this.id)
sioClient.on('ws-handshake', incommingDial)
sioClient.on('ws-peer', peerDiscovered.bind(this))
callback()
})

function incommingDial (offer) {
if (offer.answer) {
return
}

const channel = new SimplePeer({ trickle: false })

channel.on('connect', () => {
this.emit('peer', offer.srcId)
// this.conns[offer.srcId] = {
// channel: channel,
// lps: ''
// }
// attach LPS
// TODO decode the messages received
})

channel.on('signal', function (signal) {
offer.signal = signal
offer.answer = true
sioClient.emit('ss-handshake', offer)
})

channel.signal(offer.signal)
}

function peerDiscovered (_id) {
var intentId = (~~(Math.random() * 1e9)).toString(36) + Date.now()
var channel = new SimplePeer({ initiator: true, trickle: false })

channel.on('signal', function (signal) {
sioClient.emit('ss-handshake', {
intentId: intentId,
srcId: this.id,
dstId: _id,
signal: signal
})
})

sioClient.on('ws-handshake', (offer) => {
if (offer.intentId !== intentId || !offer.answer) {
return
}

channel.on('connect', () => {
// TODO add to the conns map with lps attached
this.emit('peer', _id)
})
channel.signal(offer.signal)
})
}
}

this.broadcast = (buf) => {
Object.keys(this.conns).forEach((key) => {
this.conns[key].lps.encode.write(buf)
})
}

this.send = (id, buf) => {
this.conns[id].lps.encode.write(buf)
}
}

35 changes: 3 additions & 32 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,5 @@
var attachWSS = require('./ws-server.js')
var Hapi = require('hapi')
var path = require('path')
'use strict'

var server = new Hapi.Server({})
exports = module.exports

server.connection({
port: Number(process.env.PORT) || 9090
})

server.register(require('inert'), function (err) {
if (err) {
throw err
}

server.route({
method: 'GET',
path: '/{param*}',
handler: {
directory: {
path: path.join(__dirname, '/public')
}
}
})

server.start(function (err) {
if (err) {
throw err
}

console.log('Server running at:', server.info.uri)
attachWSS(server)
})
})
exports.PeerBridge = require('./app/peer-bridge.js')
54 changes: 54 additions & 0 deletions src/sig-server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
var attachWSS = require('./ws-server.js')
var Hapi = require('hapi')
var path = require('path')

exports = module.exports

exports.start = (port, callback) => {
if (typeof port === 'function') {
callback = port
port = undefined
}
var options = {
connections: {
routes: {
cors: true
}
}
}

var httpListener = new Hapi.Server(options)

httpListener.connection({
port: port || Number(process.env.PORT) || 9090
})

httpListener.register(require('inert'), function (err) {
if (err) {
throw err
}

httpListener.route({
method: 'GET',
path: '/{param*}',
handler: {
directory: {
path: path.join(__dirname, '../public')
}
}
})

httpListener.start(function (err) {
if (err) {
throw err
}

console.log('Server running at:', httpListener.info.uri)
httpListener.peers = attachWSS(httpListener).peers
callback(null, httpListener.info)
})
})

return httpListener
}

75 changes: 75 additions & 0 deletions src/sig-server/ws-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
'use strict'

const log = console.log
const SocketIO = require('socket.io')

module.exports = (http) => {
const io = new SocketIO(http.listener)

io.on('connection', handle)

const peers = {}

this.peers = () => {
return peers
}

function safeEmit (addr, event, arg) {
const peer = peers[addr]
if (!peer) {
log('trying to emit %s but peer is gone', event)
return
}

peer.emit(event, arg)
}

function handle (socket) {
socket.on('ss-join', join.bind(socket))
socket.on('ss-leave', leave.bind(socket))
socket.on('disconnect', disconnect.bind(socket)) // socket.io own event
socket.on('ss-handshake', forwardHandshake)
}

// join this signaling server network
function join (id) {
peers[id] = this // socket
Object.keys(peers).forEach((_id) => {
if (_id === id) {
return
}
// broadcast the new peer
safeEmit(_id, 'ws-peer', id)
})
}

function leave (multiaddr) {
if (peers[multiaddr]) {
delete peers[multiaddr]
}
}

function disconnect () {
Object.keys(peers).forEach((mh) => {
if (peers[mh].id === this.id) {
delete peers[mh]
}
})
}

// forward an WebRTC offer to another peer
function forwardHandshake (offer) {
if (offer.answer) {
safeEmit(offer.srcId, 'ws-handshake', offer)
} else {
if (peers[offer.dstId]) {
safeEmit(offer.dstId, 'ws-handshake', offer)
} else {
offer.err = 'peer is not available'
safeEmit(offer.srcId, 'ws-handshake', offer)
}
}
}

return this
}
34 changes: 0 additions & 34 deletions src/ws-server.js

This file was deleted.

3 changes: 3 additions & 0 deletions test/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'

require('./peer-bridge/test-peer-bridge.js')
3 changes: 3 additions & 0 deletions test/node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'

require('./sig-server/test-sig-server.js')
13 changes: 13 additions & 0 deletions test/peer-bridge/test-peer-bridge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* eslint-env mocha */
'use strict'

var expect = require('chai').expect
// var parallel = require('run-parallel')

var PeerBridge = require('../../src').PeerBridge

describe('peer bridge', () => {
it('a test', (done) => {
done()
})
})
Loading

0 comments on commit 2119f8f

Please sign in to comment.