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

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
}