UNPKG

simple-peer-wrapper

Version:

A wrapper for simple-peer that includes a socket.io signaling server client. To be used in the browser with simple-peer-server.

213 lines (179 loc) 5.48 kB
const Peer = require('simple-peer'); class SimplePeerClientWrapper { constructor(socket, debug, simplePeerOptions) { this.initPeerRequest = false; this.socket = socket; this.localStream; this.debug = debug; this.connections = []; this.onConnectCallback; this.onDataCallback; this.onStreamCallback; // this.onTrackCallback; this.onCloseCallback; this.onErrorCallback; this.simplePeerOptions; if (typeof simplePeerOptions !== 'undefined') { this.simplePeerOptions = simplePeerOptions; } } setlocalStream(stream) { this.localStream = stream; } init() { this.debug && console.log( 'running init Peer Client. # of ' + this.connections.length, ); this.initPeerRequest = true; for (let i = 0; i < this.connections.length; i++) { this.socket.emit('initiate peer', this.connections[i].room); if (this.connections[i].initiator) { this.attemptPeerStart(this.connections[i]); } } } attemptPeerStart(connection) { this.debug && console.log( 'Attempting peer start', connection.peerStarted, connection.roomReady, ); if (!connection.peerStarted && connection.roomReady) { this.debug && console.log('Creating peer connection'); this.createPeerConnection(connection); } else { this.debug && console.log('Not creating peer connection'); } } createPeerConnection(connection) { this.debug && console.log('creating simple peer'); const options = this._getPeerOptions(connection.initiator); const peer = new Peer(options); // If initiator,peer.on'signal' will fire right away, if not it waits for signal // https://github.com/feross/simple-peer#peeronsignal-data-- peer.on('signal', (data) => this._sendSignal(data, connection)); peer.on('connect', () => this._handleConnection()); peer.on('error', (err) => this._handleError(err)); peer.on('stream', (stream) => this._handleStream(stream)); peer.on('data', (data) => this._handleData(data)); // peer.on('track', (track, stream) => // this._handleTrack(track, stream), // ); peer.on('close', () => this._handleClose()); connection.peerStarted = true; connection.peer = peer; } isPeerStarted() { let peerStarted = false; // if any peer connection is not started then it returns false for (let i = 0; i < this.connections.length; i++) { peerStarted = this.connections[i].peerStarted; } return peerStarted; } setEventCallback(event, callback) { switch (event) { case 'connect': this.onConnectCallback = callback; break; case 'data': this.onDataCallback = callback; break; case 'stream': this.onStreamCallback = callback; break; // case 'track': // this.onTrackCallback = callback; // break; case 'close': this.onCloseCallback = callback; break; case 'error': this.onErrorCallback = callback; } } sendData(data) { let msg = JSON.stringify({ data: data, userId: this.socket.id }); for (let i = 0; i < this.connections.length; i++) { const peer = this.connections[i]; if (peer.peerStarted) { const peerConn = peer.peer; if (peerConn.connected) { peerConn.write(msg); } } } } terminateSession() { for (let i = 0; i < this.connections.length; i++) { const peer = this.connections[i].peer; peer.destroy(); // simple-peer method to close and cleanup peer connection this.connections[i].peer = null; this.connections[i].peerStarted = false; } this.socket.emit('hangup'); this.socket.close(); } _getPeerOptions(initiator) { const options = { initiator: initiator, }; if (typeof this.localStream !== 'undefined') { options.stream = this.localStream; } if (typeof this.simplePeerOptions !== 'undefined') { const spOptions = Object.entries(this.simplePeerOptions); if (spOptions.length > 0) { for (const [key, value] of spOptions) { options[key] = value; } } } return options; } _sendSignal(data, connection) { this.debug && console.log('sending signal'); const message = { room: connection.room, data: JSON.stringify(data), }; this.socket.emit('sending signal', message); } _handleConnection() { this.debug && console.log('SIMPLE PEER IS CONNECTED'); if (this.onConnectCallback) this.onConnectCallback(); } _handleStream(stream) { this.onStreamCallback(stream); } _handleError(err) { if (typeof this.onErrorCallback !== 'undefined') { this.onErrorCallback(err); } else { console.log(err); } } _handleData(data) { const decodedString = new TextDecoder('utf-8').decode(data); const decodedJSON = JSON.parse(decodedString); this.onDataCallback(decodedJSON); } _handleClose() { if (typeof this.onCloseCallback !== 'undefined') { this.onCloseCallback(); } this.debug && console.log('Closing Connection'); } _handleRemoteHangup() { this.debug && console.log('Handling remote hangup'); this.terminateSession(true); } _closePeerConnection() { // peerStarted = false; // peer.destroy(); // peer = null; } } module.exports = SimplePeerClientWrapper;