You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
2.6 KiB
112 lines
2.6 KiB
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 |
|
}
|
|
|