Comparing version
@@ -0,1 +1,11 @@ | ||
v0.3.0 - Dec 8th 2011 | ||
====================== | ||
* Node.js v0.4.x compatibility. | ||
* Code cleanups and efficiency improvements. | ||
* WebSocket server added, although this will still mainly be a client library. | ||
* WebSocket server certified to pass the Autobahn test suite. | ||
* Protocol improvements and corrections - such as handling (redundant) masks for empty fragments. | ||
* 'wscat' command line utility added, which can act as either client or server. | ||
v0.2.6 - Dec 3rd 2011 | ||
@@ -2,0 +12,0 @@ ====================== |
module.exports = require('./lib/WebSocket'); | ||
module.exports.Server = require('./lib/WebSocketServer'); | ||
module.exports.Sender = require('./lib/Sender'); | ||
module.exports.Receiver = require('./lib/Receiver'); |
@@ -66,6 +66,3 @@ /*! | ||
var firstLength = data[1] & 0x7f; | ||
if (firstLength == 0) { | ||
opcodes['1'].finish(null, null); | ||
} | ||
else if (firstLength < 126) { | ||
if (firstLength < 126) { | ||
opcodes['1'].getData(firstLength); | ||
@@ -123,6 +120,3 @@ } | ||
var firstLength = data[1] & 0x7f; | ||
if (firstLength == 0) { | ||
opcodes['2'].finish(null, null); | ||
} | ||
else if (firstLength < 126) { | ||
if (firstLength < 126) { | ||
opcodes['2'].getData(firstLength); | ||
@@ -181,6 +175,3 @@ } | ||
var firstLength = data[1] & 0x7f; | ||
if (firstLength == 0) { | ||
opcodes['8'].finish(null, null); | ||
} | ||
else if (firstLength < 126) { | ||
if (firstLength < 126) { | ||
opcodes['8'].getData(firstLength); | ||
@@ -241,6 +232,3 @@ } | ||
var firstLength = data[1] & 0x7f; | ||
if (firstLength == 0) { | ||
opcodes['9'].finish(null, null); | ||
} | ||
else if (firstLength < 126) { | ||
if (firstLength < 126) { | ||
opcodes['9'].getData(firstLength); | ||
@@ -282,6 +270,3 @@ } | ||
var firstLength = data[1] & 0x7f; | ||
if (firstLength == 0) { | ||
opcodes['10'].finish(null, null); | ||
} | ||
else if (firstLength < 126) { | ||
if (firstLength < 126) { | ||
opcodes['10'].getData(firstLength); | ||
@@ -371,2 +356,6 @@ } | ||
Receiver.prototype.expect = function(length, handler) { | ||
if (length == 0) { | ||
handler(null); | ||
return; | ||
} | ||
this.expectBuffer = this.allocateFromPool(length); | ||
@@ -481,3 +470,3 @@ this.expectOffset = 0; | ||
Receiver.prototype.unmask = function (mask, buf, binary) { | ||
if (mask != null) { | ||
if (mask != null && buf != null) { | ||
for (var i = 0, ll = buf.length; i < ll; i++) { | ||
@@ -484,0 +473,0 @@ buf[i] ^= mask[i % 4]; |
@@ -52,3 +52,3 @@ /*! | ||
Sender.prototype.close = function(code, data, options) { | ||
Sender.prototype.close = function(code, data, mask) { | ||
if (typeof code !== 'undefined') { | ||
@@ -62,4 +62,9 @@ if (typeof code !== 'number' || | ||
if (dataBuffer.length > 2) dataBuffer.write(data, 2); | ||
var buf = this.frameData(0x8, dataBuffer, true, true); // always masked | ||
this._socket.write(buf, 'binary'); | ||
var buf = this.frameData(0x8, dataBuffer, true, mask); | ||
try { | ||
this._socket.write(buf, 'binary'); | ||
} | ||
catch (e) { | ||
this.emit('error', e); | ||
} | ||
} | ||
@@ -76,3 +81,8 @@ | ||
var buf = this.frameData(0x9, data || '', true, mask); | ||
this._socket.write(buf, 'binary'); | ||
try { | ||
this._socket.write(buf, 'binary'); | ||
} | ||
catch (e) { | ||
this.emit('error', e); | ||
} | ||
} | ||
@@ -89,3 +99,8 @@ | ||
var buf = this.frameData(0xa, data || '', true, mask); | ||
this._socket.write(buf, 'binary'); | ||
try { | ||
this._socket.write(buf, 'binary'); | ||
} | ||
catch (e) { | ||
this.emit('error', e); | ||
} | ||
} | ||
@@ -108,3 +123,9 @@ | ||
if (finalFragment) this.firstFragment = true | ||
this._socket.write(buf, 'binary', cb); | ||
try { | ||
this._socket.write(buf, 'binary', cb); | ||
} | ||
catch (e) { | ||
if (typeof cb == 'function') cb(e); | ||
else this.emit('error', e); | ||
} | ||
} | ||
@@ -111,0 +132,0 @@ |
@@ -28,110 +28,94 @@ /*! | ||
function WebSocket(address, options) { | ||
var serverUrl = url.parse(address); | ||
if (!serverUrl.host) throw new Error('invalid url'); | ||
if (Object.prototype.toString.call(address) == '[object Array]') { | ||
/** | ||
* Act as server client | ||
*/ | ||
options = options || {}; | ||
options.origin = options.origin || null; | ||
options.protocolVersion = options.protocolVersion || protocolVersion; | ||
if (options.protocolVersion != 8 && options.protocolVersion != 13) { | ||
throw new Error('unsupported protocol version'); | ||
this._state = 'connecting'; | ||
this._isServer = true; | ||
var self = this; | ||
process.nextTick(function() { | ||
upgrade.apply(self, address); | ||
}); | ||
} | ||
else { | ||
/** | ||
* Act as regular client | ||
*/ | ||
this._isServer = false; | ||
var key = new Buffer(options.protocolVersion + '-' + Date.now()).toString('base64'); | ||
var shasum = crypto.createHash('sha1'); | ||
shasum.update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'); | ||
var expectedServerKey = shasum.digest('base64'); | ||
var serverUrl = url.parse(address); | ||
if (!serverUrl.host) throw new Error('invalid url'); | ||
// node<=v0.4.x compatibility | ||
var isNodeV4 = false; | ||
var agent; | ||
if (/^v0\.4/.test(process.version)) { | ||
isNodeV4 = true; | ||
agent = new http.Agent({ | ||
host: serverUrl.hostname, | ||
port: serverUrl.port || 80 | ||
}); | ||
} | ||
options = options || {}; | ||
options.origin = options.origin || null; | ||
options.protocolVersion = options.protocolVersion || protocolVersion; | ||
if (options.protocolVersion != 8 && options.protocolVersion != 13) { | ||
throw new Error('unsupported protocol version'); | ||
} | ||
var requestOptions = { | ||
port: serverUrl.port || 80, | ||
host: serverUrl.hostname, | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Version': options.protocolVersion, | ||
'Sec-WebSocket-Key': key | ||
var key = new Buffer(options.protocolVersion + '-' + Date.now()).toString('base64'); | ||
var shasum = crypto.createHash('sha1'); | ||
shasum.update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'); | ||
var expectedServerKey = shasum.digest('base64'); | ||
// node<=v0.4.x compatibility | ||
var isNodeV4 = false; | ||
var agent; | ||
if (/^v0\.4/.test(process.version)) { | ||
isNodeV4 = true; | ||
agent = new http.Agent({ | ||
host: serverUrl.hostname, | ||
port: serverUrl.port || 80 | ||
}); | ||
} | ||
}; | ||
if (isNodeV4) { | ||
requestOptions.path = (serverUrl.pathname || '/') + (serverUrl.search || ''); | ||
requestOptions.agent = agent; | ||
} | ||
else requestOptions.path = serverUrl.path || '/'; | ||
if (options.origin) { | ||
if (options.protocolVersion < 13) requestOptions.headers['Sec-WebSocket-Origin'] = options.origin; | ||
else requestOptions.headers['Origin'] = options.origin; | ||
} | ||
var req = http.request(requestOptions); | ||
var self = this; | ||
(isNodeV4 ? agent : req).on('upgrade', function(res, socket, upgradeHead) { | ||
if (self._state == 'disconnected') { | ||
// client disconnected before server accepted connection | ||
self.emit('close'); | ||
socket.end(); | ||
return; | ||
var requestOptions = { | ||
port: serverUrl.port || 80, | ||
host: serverUrl.hostname, | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Version': options.protocolVersion, | ||
'Sec-WebSocket-Key': key | ||
} | ||
}; | ||
if (isNodeV4) { | ||
requestOptions.path = (serverUrl.pathname || '/') + (serverUrl.search || ''); | ||
requestOptions.agent = agent; | ||
} | ||
var serverKey = res.headers['sec-websocket-accept']; | ||
if (typeof serverKey == 'undefined' || serverKey !== expectedServerKey) { | ||
self.emit('error', 'invalid server key'); | ||
socket.end(); | ||
return; | ||
else requestOptions.path = serverUrl.path || '/'; | ||
if (options.origin) { | ||
if (options.protocolVersion < 13) requestOptions.headers['Sec-WebSocket-Origin'] = options.origin; | ||
else requestOptions.headers['Origin'] = options.origin; | ||
} | ||
self._socket = socket; | ||
socket.setTimeout(0); | ||
socket.setNoDelay(true); | ||
socket.on('close', function() { | ||
if (self._state == 'disconnected') return; | ||
self._state = 'disconnected'; | ||
self.emit('close', self._closeCode || 1000, self._closeMessage || ''); | ||
var req = http.request(requestOptions); | ||
var self = this; | ||
(isNodeV4 ? agent : req).on('error', function(error) { | ||
self.emit('error', error); | ||
}); | ||
(isNodeV4 ? agent : req).on('upgrade', function(res, socket, upgradeHead) { | ||
if (self._state == 'disconnected') { | ||
// client disconnected before server accepted connection | ||
self.emit('close'); | ||
socket.end(); | ||
return; | ||
} | ||
var serverKey = res.headers['sec-websocket-accept']; | ||
if (typeof serverKey == 'undefined' || serverKey !== expectedServerKey) { | ||
self.emit('error', 'invalid server key'); | ||
socket.end(); | ||
return; | ||
} | ||
var receiver = new Receiver(); | ||
socket.on('data', function (data) { | ||
receiver.add(data); | ||
upgrade.call(self, res, socket, upgradeHead); | ||
}); | ||
receiver.on('text', function (data, flags) { | ||
flags = flags || {}; | ||
self.emit('message', data, flags); | ||
}); | ||
receiver.on('binary', function (data, flags) { | ||
flags = flags || {}; | ||
flags.binary = true; | ||
self.emit('message', data, flags); | ||
}); | ||
receiver.on('ping', function(data, flags) { | ||
flags = flags || {}; | ||
self.pong(data, {mask: true, binary: flags.binary === true}); | ||
self.emit('ping', data, flags); | ||
}); | ||
receiver.on('close', function(code, data, flags) { | ||
flags = flags || {}; | ||
self.close(code, data, {mask: true}); | ||
}); | ||
receiver.on('error', function(reason, errorCode) { | ||
// close the connection when the receiver reports a HyBi error code | ||
if (typeof errorCode !== 'undefined') { | ||
self.close(errorCode, '', {mask: true}); | ||
} | ||
self.emit('error', reason, errorCode); | ||
}); | ||
self._sender = new Sender(socket); | ||
self._state = 'connected'; | ||
self.emit('open'); | ||
req.end(); | ||
this._state = 'connecting'; | ||
} | ||
if (upgradeHead && upgradeHead.length > 0) receiver.add(upgradeHead); | ||
}); | ||
this._socket = null; | ||
var realEmit = this.emit; | ||
@@ -142,6 +126,2 @@ this.emit = function(event) { | ||
} | ||
req.end(); | ||
this._socket = null; | ||
this._state = 'connecting'; | ||
} | ||
@@ -159,7 +139,11 @@ | ||
* @param {Object} data to be sent to the server | ||
* @param {Object} Members - mask: boolean, binary: boolean | ||
* @api public | ||
*/ | ||
WebSocket.prototype.close = function(code, data, options) { | ||
WebSocket.prototype.close = function(code, data) { | ||
if (this._state == 'closing') return; | ||
if (this._state == 'connecting') { | ||
this._state = 'disconnected'; | ||
return; | ||
} | ||
if (this._state != 'connected') throw new Error('not connected'); | ||
@@ -170,3 +154,4 @@ try { | ||
this._closeMessage = data; | ||
this._sender.close(code, data, options); | ||
var mask = !this._isServer; | ||
this._sender.close(code, data, mask); | ||
this.terminate(); | ||
@@ -189,8 +174,5 @@ } | ||
if (this._state != 'connected') throw new Error('not connected'); | ||
try { | ||
this._sender.ping(data, options); | ||
} | ||
catch (e) { | ||
this.emit('error', e); | ||
} | ||
options = options || {}; | ||
if (typeof options.mask == 'undefined') options.mask = !this._isServer; | ||
this._sender.ping(data, options); | ||
} | ||
@@ -208,8 +190,5 @@ | ||
if (this._state != 'connected') throw new Error('not connected'); | ||
try { | ||
this._sender.pong(data, options); | ||
} | ||
catch (e) { | ||
this.emit('error', e); | ||
} | ||
options = options || {}; | ||
if (typeof options.mask == 'undefined') options.mask = !this._isServer; | ||
this._sender.pong(data, options); | ||
} | ||
@@ -239,2 +218,3 @@ | ||
options.fin = true; | ||
if (typeof options.mask == 'undefined') options.mask = !this._isServer; | ||
if (data instanceof fs.ReadStream) { | ||
@@ -252,8 +232,3 @@ startQueue(this); | ||
else { | ||
try { | ||
this._sender.send(data, options, cb); | ||
} | ||
catch (e) { | ||
this.emit('error', e); | ||
} | ||
this._sender.send(data, options, cb); | ||
} | ||
@@ -282,2 +257,4 @@ } | ||
if (typeof cb != 'function') throw new Error('callback must be provided'); | ||
options = options || {}; | ||
if (typeof options.mask == 'undefined') options.mask = !this._isServer; | ||
startQueue(this); | ||
@@ -324,2 +301,53 @@ var self = this; | ||
function upgrade(res, socket, upgradeHead) { | ||
this._socket = socket; | ||
socket.setTimeout(0); | ||
socket.setNoDelay(true); | ||
var self = this; | ||
socket.on('close', function() { | ||
if (self._state == 'disconnected') return; | ||
self._state = 'disconnected'; | ||
self.emit('close', self._closeCode || 1000, self._closeMessage || ''); | ||
}); | ||
var receiver = new Receiver(); | ||
socket.on('data', function (data) { | ||
receiver.add(data); | ||
}); | ||
receiver.on('text', function (data, flags) { | ||
flags = flags || {}; | ||
self.emit('message', data, flags); | ||
}); | ||
receiver.on('binary', function (data, flags) { | ||
flags = flags || {}; | ||
flags.binary = true; | ||
self.emit('message', data, flags); | ||
}); | ||
receiver.on('ping', function(data, flags) { | ||
flags = flags || {}; | ||
self.pong(data, {mask: !self._isServer, binary: flags.binary === true}); | ||
self.emit('ping', data, flags); | ||
}); | ||
receiver.on('close', function(code, data, flags) { | ||
flags = flags || {}; | ||
self.close(code, data, {mask: !self._isServer}); | ||
}); | ||
receiver.on('error', function(reason, errorCode) { | ||
// close the connection when the receiver reports a HyBi error code | ||
if (typeof errorCode !== 'undefined') { | ||
self.close(errorCode, '', {mask: !self._isServer}); | ||
} | ||
self.emit('error', reason, errorCode); | ||
}); | ||
this._sender = new Sender(socket); | ||
this._sender.on('error', function(error) { | ||
self.emit('error', e); | ||
}); | ||
this._state = 'connected'; | ||
this.emit('open'); | ||
if (upgradeHead && upgradeHead.length > 0) receiver.add(upgradeHead); | ||
} | ||
function startQueue(instance) { | ||
@@ -326,0 +354,0 @@ instance._queue = instance._queue || []; |
@@ -5,3 +5,3 @@ { | ||
"description": "simple and very fast websocket protocol client for node.js", | ||
"version": "0.2.9", | ||
"version": "0.3.0", | ||
"repository": { | ||
@@ -19,3 +19,3 @@ "type": "git", | ||
"engines": { | ||
"node": ">0.4.0" | ||
"node": ">=0.4.0" | ||
}, | ||
@@ -22,0 +22,0 @@ "dependencies": { |
@@ -24,3 +24,6 @@ var http = require('http') | ||
var srv = new Server(webServer); | ||
webServer.on('upgrade', (handler || validServer).bind(null, srv)); | ||
webServer.on('upgrade', function(req, socket) { | ||
webServer._socket = socket; | ||
(handler || validServer)(srv, req, socket); | ||
}); | ||
webServer.listen(port, '127.0.0.1', function() { cb(srv); }); | ||
@@ -165,2 +168,3 @@ } | ||
this.webServer.close(); | ||
if (this._socket) this._socket.end(); | ||
} |
@@ -26,57 +26,13 @@ var assert = require('assert') | ||
describe('WebSocket', function() { | ||
it('throws exception for invalid url', function(done) { | ||
try { | ||
var ws = new WebSocket('echo.websocket.org'); | ||
} | ||
catch (e) { | ||
done(); | ||
} | ||
}) | ||
it('text data can be sent and received', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi'); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.equal('hi', message); | ||
ws.terminate(); | ||
srv.close(); | ||
describe('#ctor', function() { | ||
it('throws exception for invalid url', function(done) { | ||
try { | ||
var ws = new WebSocket('echo.websocket.org'); | ||
} | ||
catch (e) { | ||
done(); | ||
}); | ||
}); | ||
} | ||
}) | ||
}) | ||
it('binary data can be sent and received as array', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 2; | ||
ws.on('open', function() { | ||
ws.send(array, {binary: true}); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('binary data can be sent and received as buffer', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var buf = new Buffer('foobar'); | ||
ws.on('open', function() { | ||
ws.send(buf, {binary: true}); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(buf, message)); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('can disconnect before connection is established', function(done) { | ||
@@ -90,2 +46,3 @@ server.createServer(++port, function(srv) { | ||
ws.on('close', function() { | ||
srv.close(); | ||
done(); | ||
@@ -95,25 +52,11 @@ }); | ||
}) | ||
it('send before connect should fail', function(done) { | ||
it('can close before connection is established', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
try { | ||
ws.send('hi'); | ||
} | ||
catch (e) { | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}) | ||
it('send without data should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.close(1001); | ||
ws.on('open', function() { | ||
ws.send(); | ||
assert.fail('connect shouldnt be raised here'); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.equal(false, flags.masked); | ||
assert.equal('', message); | ||
ws.on('close', function() { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
@@ -123,14 +66,2 @@ }); | ||
}) | ||
it('ping before connect should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
try { | ||
ws.ping(); | ||
} | ||
catch (e) { | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}) | ||
it('invalid server key is denied', function(done) { | ||
@@ -149,3 +80,2 @@ server.createServer(++port, server.handlers.invalidKey, function(srv) { | ||
ws.on('close', function() { | ||
srv.close(); | ||
done(); | ||
@@ -155,744 +85,847 @@ }); | ||
}) | ||
it('send calls optional callback when flushed', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi', function() { | ||
describe('#ping', function() { | ||
it('before connect should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('error', function() {}); | ||
try { | ||
ws.ping(); | ||
} | ||
catch (e) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}) | ||
it('without message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.ping(); | ||
}); | ||
srv.on('ping', function(message) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('send with unencoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi'); | ||
}) | ||
it('with message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.ping('hi'); | ||
}); | ||
srv.on('ping', function(message) { | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.equal(false, flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.ping('hi', {mask: true}); | ||
}); | ||
srv.on('ping', function(message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
}) | ||
it('send with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi', {mask: true}); | ||
describe('#pong', function() { | ||
it('without message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.pong(); | ||
}); | ||
srv.on('pong', function(message) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('with message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.pong('hi'); | ||
}); | ||
srv.on('pong', function(message) { | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('send with unencoded binary message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 2; | ||
ws.on('open', function() { | ||
ws.send(array, {binary: true}); | ||
}) | ||
it('with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.pong('hi', {mask: true}); | ||
}); | ||
srv.on('pong', function(message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.equal(false, flags.masked); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
}) | ||
it('send with encoded binary message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 2; | ||
ws.on('open', function() { | ||
ws.send(array, {mask: true, binary: true}); | ||
describe('#send', function() { | ||
it('very long binary data can be sent and received (with echoing server)', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5 * 1024 * 1024); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 5; | ||
ws.on('open', function() { | ||
ws.send(array, {binary: true}); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(flags.masked); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('can send and receive text data', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi'); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.equal('hi', message); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('send with binary stream will send fragmented data', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var callbackFired = false; | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream, {binary: true}, function(error) { | ||
assert.equal(null, error); | ||
callbackFired = true; | ||
}) | ||
it('send and receive binary data as an array', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 2; | ||
ws.on('open', function() { | ||
ws.send(array, {binary: true}); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile'), data)); | ||
ws.terminate(); | ||
}); | ||
ws.on('close', function() { | ||
assert.ok(callbackFired); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('send with text stream will send fragmented data', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var callbackFired = false; | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream, {binary: false}, function(error) { | ||
assert.equal(null, error); | ||
callbackFired = true; | ||
}) | ||
it('binary data can be sent and received as buffer', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var buf = new Buffer('foobar'); | ||
ws.on('open', function() { | ||
ws.send(buf, {binary: true}); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(buf, message)); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
ws.terminate(); | ||
}); | ||
ws.on('close', function() { | ||
assert.ok(callbackFired); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('stream before connect should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
try { | ||
ws.stream(function() {}); | ||
} | ||
catch (e) { | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}) | ||
it('stream without callback should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
}) | ||
it('before connect should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('error', function() {}); | ||
try { | ||
ws.stream(); | ||
ws.send('hi'); | ||
} | ||
catch (e) { | ||
ws.terminate(); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}) | ||
it('ping without message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.ping(); | ||
}) | ||
it('without data should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send(); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.equal(false, flags.masked); | ||
assert.equal('', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('ping', function(message) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('calls optional callback when flushed', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi', function() { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('ping with message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.ping('hi'); | ||
}) | ||
it('with unencoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi'); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.equal(false, flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('ping', function(message) { | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.send('hi', {mask: true}); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('ping with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.ping('hi', {mask: true}); | ||
}) | ||
it('with unencoded binary message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 2; | ||
ws.on('open', function() { | ||
ws.send(array, {binary: true}); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.equal(false, flags.masked); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('ping', function(message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('with encoded binary message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 2; | ||
ws.on('open', function() { | ||
ws.send(array, {mask: true, binary: true}); | ||
}); | ||
srv.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(flags.masked); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('pong without message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.pong(); | ||
}) | ||
it('with binary stream will send fragmented data', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var callbackFired = false; | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream, {binary: true}, function(error) { | ||
assert.equal(null, error); | ||
callbackFired = true; | ||
}); | ||
}); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile'), data)); | ||
ws.terminate(); | ||
}); | ||
ws.on('close', function() { | ||
assert.ok(callbackFired); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
srv.on('pong', function(message) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('with text stream will send fragmented data', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var callbackFired = false; | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream, {binary: false}, function(error) { | ||
assert.equal(null, error); | ||
callbackFired = true; | ||
}); | ||
}); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
ws.terminate(); | ||
}); | ||
ws.on('close', function() { | ||
assert.ok(callbackFired); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('pong with message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.pong('hi'); | ||
}) | ||
it('will cause intermittent send to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.send('foobar'); | ||
ws.send('baz'); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
assert.equal('foobar', data); | ||
} | ||
else { | ||
assert.ok(!flags.binary); | ||
assert.equal('baz', data); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
srv.on('pong', function(message) { | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('will cause intermittent stream to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) send('foo'); | ||
else send('bar', true); | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
assert.equal('foobar', data); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('pong with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.pong('hi', {mask: true}); | ||
}) | ||
it('will cause intermittent ping to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.ping('foobar'); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
srv.on('ping', function(data) { | ||
assert.equal('foobar', data); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
srv.on('pong', function(message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('hi', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}) | ||
it('will cause intermittent pong to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.pong('foobar'); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
srv.on('pong', function(data) { | ||
assert.equal('foobar', data); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('close without invalid first argument throws exception', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
try { | ||
ws.close('error'); | ||
} | ||
catch (e) { | ||
}) | ||
it('will cause intermittent close to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.close(1000, 'foobar'); | ||
}); | ||
ws.on('close', function() { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
ws.on('error', function() { /* That's quite alright -- a send was attempted after close */ }); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
}); | ||
srv.on('close', function(code, data) { | ||
assert.equal(1000, code); | ||
assert.equal('foobar', data); | ||
}); | ||
}); | ||
}); | ||
}) | ||
}) | ||
it('close without reserved error code 1004 throws exception', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
describe('#stream', function() { | ||
it('very long binary data can be streamed', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var buffer = new Buffer(10 * 1024); | ||
for (var i = 0; i < buffer.length; ++i) buffer[i] = i % 0xff; | ||
ws.on('open', function() { | ||
var i = 0; | ||
var blockSize = 800; | ||
var bufLen = buffer.length; | ||
ws.stream({binary: true}, function(error, send) { | ||
assert.ok(!error); | ||
var start = i * blockSize; | ||
var toSend = Math.min(blockSize, bufLen - (i * blockSize)); | ||
var end = start + toSend; | ||
var isFinal = toSend < blockSize; | ||
send(buffer.slice(start, end), isFinal); | ||
i += 1; | ||
}); | ||
}); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(buffer, data)); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('stream before connect should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('error', function() {}); | ||
try { | ||
ws.close(1004); | ||
ws.stream(function() {}); | ||
} | ||
catch (e) { | ||
ws.terminate(); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}) | ||
it('close without message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.close(1000); | ||
}) | ||
it('stream without callback should fail', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
try { | ||
ws.stream(); | ||
} | ||
catch (e) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
srv.on('close', function(code, message, flags) { | ||
assert.equal('', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('close with message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.close(1000, 'some reason'); | ||
}); | ||
srv.on('close', function(code, message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('some reason', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('close with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.close(1000, 'some reason', {mask: true}); | ||
}); | ||
srv.on('close', function(code, message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('some reason', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('close ends connection to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var connectedOnce = false; | ||
ws.on('open', function() { | ||
connectedOnce = true; | ||
ws.close(1000, 'some reason', {mask: true}); | ||
}); | ||
ws.on('close', function() { | ||
assert.ok(connectedOnce); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('very long binary data can be sent and received (with echoing server)', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var array = new Float32Array(5 * 1024 * 1024); | ||
for (var i = 0; i < array.length; ++i) array[i] = i / 5; | ||
ws.on('open', function() { | ||
ws.send(array, {binary: true}); | ||
}); | ||
ws.on('message', function(message, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('very long binary data can be streamed', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var buffer = new Buffer(10 * 1024); | ||
for (var i = 0; i < buffer.length; ++i) buffer[i] = i % 0xff; | ||
ws.on('open', function() { | ||
var i = 0; | ||
var blockSize = 800; | ||
var bufLen = buffer.length; | ||
ws.stream({binary: true}, function(error, send) { | ||
assert.ok(!error); | ||
var start = i * blockSize; | ||
var toSend = Math.min(blockSize, bufLen - (i * blockSize)); | ||
var end = start + toSend; | ||
var isFinal = toSend < blockSize; | ||
send(buffer.slice(start, end), isFinal); | ||
i += 1; | ||
}) | ||
it('will cause intermittent send to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.send('foobar'); | ||
ws.send('baz'); | ||
} | ||
else { | ||
send(payload.substr(5, 5), true); | ||
} | ||
}); | ||
}); | ||
}); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(flags.binary); | ||
assert.ok(areArraysEqual(buffer, data)); | ||
ws.terminate(); | ||
srv.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
it('streaming data will cause intermittent send to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.send('foobar'); | ||
ws.send('baz'); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
assert.equal('foobar', data); | ||
} | ||
else { | ||
send(payload.substr(5, 5), true); | ||
assert.ok(!flags.binary); | ||
assert.equal('baz', data); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
}) | ||
it('will cause intermittent stream to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
var i2 = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i2 == 1) send('foo'); | ||
else send('bar', true); | ||
}); | ||
ws.send('baz'); | ||
} | ||
else send(payload.substr(5, 5), true); | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
assert.equal('foobar', data); | ||
} | ||
else if (receivedIndex == 3){ | ||
assert.ok(!flags.binary); | ||
assert.equal('baz', data); | ||
setTimeout(function() { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}, 1000); | ||
} | ||
else throw new Error('more messages than we actually sent just arrived'); | ||
}); | ||
}); | ||
}) | ||
it('will cause intermittent ping to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.ping('foobar'); | ||
} | ||
else { | ||
send(payload.substr(5, 5), true); | ||
} | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
srv.on('ping', function(data) { | ||
assert.equal('foobar', data); | ||
} | ||
else { | ||
assert.ok(!flags.binary); | ||
assert.equal('baz', data); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}) | ||
it('streaming data will cause intermittent stream to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
var i2 = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i2 == 1) send('foo'); | ||
else send('bar', true); | ||
}); | ||
ws.send('baz'); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
else send(payload.substr(5, 5), true); | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
}) | ||
it('will cause intermittent pong to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.pong('foobar'); | ||
} | ||
else { | ||
send(payload.substr(5, 5), true); | ||
} | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
srv.on('pong', function(data) { | ||
assert.equal('foobar', data); | ||
} | ||
else if (receivedIndex == 3){ | ||
assert.ok(!flags.binary); | ||
assert.equal('baz', data); | ||
setTimeout(function() { | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}, 1000); | ||
} | ||
else throw new Error('more messages than we actually sent just arrived'); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('sending stream will cause intermittent send to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.send('foobar'); | ||
ws.send('baz'); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
assert.equal('foobar', data); | ||
} | ||
else { | ||
assert.ok(!flags.binary); | ||
assert.equal('baz', data); | ||
}) | ||
it('will cause intermittent close to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
var errorGiven = false; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.close(1000, 'foobar'); | ||
} | ||
else if(i == 2) { | ||
send(payload.substr(5, 5), true); | ||
} | ||
else if (i == 3) { | ||
assert.ok(error); | ||
errorGiven = true; | ||
} | ||
}); | ||
}); | ||
ws.on('close', function() { | ||
assert.ok(errorGiven); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}) | ||
it('sending stream will cause intermittent stream to be delayed in order', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) send('foo'); | ||
else send('bar', true); | ||
done(); | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
++receivedIndex; | ||
if (receivedIndex == 1) { | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
} | ||
else if (receivedIndex == 2) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
}); | ||
srv.on('close', function(code, data) { | ||
assert.equal(1000, code); | ||
assert.equal('foobar', data); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}); | ||
}) | ||
}) | ||
it('streaming data will cause intermittent ping to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.ping('foobar'); | ||
describe('#close', function() { | ||
it('will raise error callback, if any, if called during send stream', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var errorGiven = false; | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream, function(error) { | ||
errorGiven = error != null; | ||
}); | ||
ws.close(1000, 'foobar'); | ||
}); | ||
ws.on('close', function() { | ||
setTimeout(function() { | ||
assert.ok(errorGiven); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}, 1000); | ||
}); | ||
}); | ||
}) | ||
it('without invalid first argument throws exception', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
try { | ||
ws.close('error'); | ||
} | ||
else { | ||
send(payload.substr(5, 5), true); | ||
catch (e) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
srv.on('ping', function(data) { | ||
assert.equal('foobar', data); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}) | ||
it('sending stream will cause intermittent ping to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.ping('foobar'); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
srv.on('ping', function(data) { | ||
assert.equal('foobar', data); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}) | ||
it('streaming data will cause intermittent pong to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
assert.ok(!error); | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.pong('foobar'); | ||
}) | ||
it('without reserved error code 1004 throws exception', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
try { | ||
ws.close(1004); | ||
} | ||
else { | ||
send(payload.substr(5, 5), true); | ||
catch (e) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
if (++receivedIndex == 2) { | ||
}) | ||
it('without message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.close(1000); | ||
}); | ||
srv.on('close', function(code, message, flags) { | ||
assert.equal('', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
done(); | ||
}); | ||
}); | ||
srv.on('pong', function(data) { | ||
assert.equal('foobar', data); | ||
if (++receivedIndex == 2) { | ||
}) | ||
it('with message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.close(1000, 'some reason'); | ||
}); | ||
srv.on('close', function(code, message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('some reason', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
it('sending stream will cause intermittent pong to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.pong('foobar'); | ||
}); | ||
var receivedIndex = 0; | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
if (++receivedIndex == 2) { | ||
}) | ||
it('with encoded message is successfully transmitted to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
ws.close(1000, 'some reason', {mask: true}); | ||
}); | ||
srv.on('close', function(code, message, flags) { | ||
assert.ok(flags.masked); | ||
assert.equal('some reason', message); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
srv.on('pong', function(data) { | ||
assert.equal('foobar', data); | ||
if (++receivedIndex == 2) { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}) | ||
it('streaming data will cause intermittent close to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var payload = 'HelloWorld'; | ||
var errorGiven = false; | ||
ws.on('open', function() { | ||
var i = 0; | ||
ws.stream(function(error, send) { | ||
if (++i == 1) { | ||
send(payload.substr(0, 5)); | ||
ws.close(1000, 'foobar'); | ||
} | ||
else if(i == 2) { | ||
send(payload.substr(5, 5), true); | ||
} | ||
else if (i == 3) { | ||
assert.ok(error); | ||
errorGiven = true; | ||
} | ||
done(); | ||
}); | ||
}); | ||
ws.on('close', function() { | ||
assert.ok(errorGiven); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.equal(payload, data); | ||
}); | ||
srv.on('close', function(code, data) { | ||
assert.equal(1000, code); | ||
assert.equal('foobar', data); | ||
}); | ||
}); | ||
}) | ||
it('sending stream will cause intermittent close to be delivered', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream); | ||
ws.close(1000, 'foobar'); | ||
}); | ||
ws.on('close', function() { | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}); | ||
ws.on('error', function() { /* That's quite alright -- a send was attempted after close */ }); | ||
srv.on('message', function(data, flags) { | ||
assert.ok(!flags.binary); | ||
assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); | ||
}); | ||
srv.on('close', function(code, data) { | ||
assert.equal(1000, code); | ||
assert.equal('foobar', data); | ||
}); | ||
}); | ||
}) | ||
it('close during send stream causes error callback if given', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var errorGiven = false; | ||
ws.on('open', function() { | ||
var fileStream = fs.createReadStream('test/fixtures/textfile'); | ||
fileStream.setEncoding('utf8'); | ||
fileStream.bufferSize = 100; | ||
ws.send(fileStream, function(error) { | ||
errorGiven = error != null; | ||
}) | ||
it('ends connection to the server', function(done) { | ||
server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
var connectedOnce = false; | ||
ws.on('open', function() { | ||
connectedOnce = true; | ||
ws.close(1000, 'some reason', {mask: true}); | ||
}); | ||
ws.close(1000, 'foobar'); | ||
}); | ||
ws.on('close', function() { | ||
setTimeout(function() { | ||
assert.ok(errorGiven); | ||
ws.on('close', function() { | ||
assert.ok(connectedOnce); | ||
srv.close(); | ||
ws.terminate(); | ||
done(); | ||
}, 1000); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
108194
11.83%27
12.5%2830
11.33%4
33.33%3
50%