var through = require('through2') var duplexify = require('duplexify') var WS = require('ws') module.exports = WebSocketStream function WebSocketStream(target, protocols, options) { var stream, socket var isBrowser = process.title === 'browser' var isNative = !!global.WebSocket var socketWrite = isBrowser ? socketWriteBrowser : socketWriteNode var proxy = through.obj(socketWrite, socketEnd) if (protocols && !Array.isArray(protocols) && 'object' === typeof protocols) { // accept the "options" Object as the 2nd argument options = protocols protocols = null } if (!options) options = {} // browser only: sets the maximum socket buffer size before throttling var bufferSize = options.browserBufferSize || 1024 * 512 // browser only: how long to wait when throttling var bufferTimeout = options.browserBufferTimeout || 1000 // use existing WebSocket object that was passed in if (typeof target === 'object') { socket = target // otherwise make a new one } else { // special constructor treatment for native websockets in browsers, see // https://github.com/maxogden/websocket-stream/issues/82 if (isNative && isBrowser) { socket = new WS(target, protocols) } else { socket = new WS(target, protocols, options) } socket.binaryType = 'arraybuffer' } // was already open when passed in if (socket.readyState === 1) { stream = proxy } else { stream = duplexify.obj() socket.addEventListener("open", onready) } stream.socket = socket socket.addEventListener("close", onclose) socket.addEventListener("error", onerror) socket.addEventListener("message", onmessage) proxy.on('close', destroy) function socketWriteNode(chunk, enc, next) { socket.send(chunk, next) } function socketWriteBrowser(chunk, enc, next) { if (socket.bufferedAmount > bufferSize) { setTimeout(socketWriteBrowser, bufferTimeout, chunk, enc, next) return } try { socket.send(chunk) } catch(err) { return next(err) } next() } function socketEnd(done) { socket.close() done() } function onready() { stream.setReadable(proxy) stream.setWritable(proxy) stream.emit('connect') } function onclose() { stream.end(); stream.destroy() } function onerror(err) { stream.destroy(err) } function onmessage(event) { var data = event.data if (data instanceof ArrayBuffer) data = new Buffer(new Uint8Array(data)) else data = new Buffer(data) proxy.push(data) } function destroy() { socket.close() } return stream }