UNPKG

kad-webrtc

Version:
139 lines (124 loc) 3.51 kB
/** * @module kad-webrtc/transport */ 'use strict'; var assert = require('assert'); var hat = require('hat'); var inherits = require('util').inherits; var WebRTCContact = require('./contact'); var RPC = require('kad').RPC; var SimplePeer = require('simple-peer'); inherits(WebRTCTransport, RPC); /** * Represents an RPC interface over WebRTC * @constructor * @param {object} contact * @param {object} options */ function WebRTCTransport(contact, options) { if (!(this instanceof WebRTCTransport)) { return new WebRTCTransport(contact, options); } assert(contact instanceof WebRTCContact, 'Invalid contact supplied'); assert(typeof options === 'object', 'Invalid options were supplied'); assert( typeof options.signaller === 'object', 'Invalid signaller was supplied' ); this._signaller = options.signaller; this._wrtc = options.wrtc; RPC.call(this, contact, options); } /** * Setup WebRTC transport * #_open * @param {function} ready */ WebRTCTransport.prototype._open = function(ready) { this._peers = {}; this._signalHandler = this._onSignal.bind(this); this._signaller.addListener(this._contact.nick, this._signalHandler); setTimeout(function() { ready(); }); }; /** * Handle a message sent through `_signaller` from another peer * #_onSignal * @param {object} signallerMessage */ WebRTCTransport.prototype._onSignal = function(signallerMessage) { var self = this; var signal = signallerMessage.signal; var sender = signallerMessage.sender; var handshakeID = signallerMessage.handshakeID; var peer = this._peers[signallerMessage.handshakeID]; if(!peer) { peer = this._createPeer(sender, handshakeID, false); peer.once('data', function(data) { var buffer = new Buffer(data); self.receive(buffer, { nick: signallerMessage.sender }); peer.destroy(); }); } peer.signal(signal); }; /** * Send a RPC to the given contact * #_send * @param {buffer} data * @param {Contact} contact */ WebRTCTransport.prototype._send = function(data, contact) { var self = this; var handshakeID = hat(); var newPeer = this._createPeer(contact.nick, handshakeID, true); newPeer.once('connect', function() { newPeer.send(data.toString()); setTimeout(function() { newPeer.destroy(); }, 1000); }); }; /** * Initialize a WebRTC peer and store it in `_peers` * #_createPeer * @param {string} nick * @param {string} handshakeID * @param {boolean} initiator */ WebRTCTransport.prototype._createPeer = function(nick, handshakeID, initiator) { var self = this; var peer = new SimplePeer({ wrtc: this._wrtc, initiator: initiator }); peer.on('signal', function(signal) { self._signaller.emit(nick, { sender: self._contact.nick, handshakeID: handshakeID, signal: signal }); }); peer.on('error', function(err) { self._log.error('peer encountered an error %s', err.message); }); peer.once('close', function() { peer.removeAllListeners('data'); peer.removeAllListeners('signal'); peer.removeAllListeners('error'); delete self._peers[handshakeID]; }); this._peers[handshakeID] = peer; return peer; }; /** * Close the underlying socket * #_close */ WebRTCTransport.prototype._close = function() { var self = this; Object.keys(this._peers).forEach(function(handshakeID) { self._peers[handshakeID].destroy(); }); this._peers = {}; this._signaller.removeListener(this._contact.nick, this._signalHandler); }; module.exports = WebRTCTransport;