Socket
Socket
Sign inDemoInstall

faye-websocket

Package Overview
Dependencies
0
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.2 to 0.2.0

CHANGELOG.txt

3

examples/autobahn_client.js

@@ -6,4 +6,3 @@ var WebSocket = require('../lib/faye/websocket');

cases = 0,
skip = [247,248,249,250,251,252,253,254,255,
256,257,258,259,260,261,262,263,264];
skip = [];

@@ -10,0 +9,0 @@ var socket = new WebSocket.Client(host + '/getCaseCount');

@@ -28,4 +28,4 @@ var WebSocket = require('../lib/faye/websocket'),

server.addListener('upgrade', function(request, socket, head) {
var ws = new WebSocket(request, socket, head);
console.log('open', ws.url, ws.version);
var ws = new WebSocket(request, socket, head, ['irc', 'xmpp']);
console.log('open', ws.url, ws.version, ws.protocol);

@@ -32,0 +32,0 @@ ws.onmessage = function(event) {

@@ -10,6 +10,6 @@ // API and protocol references:

var Draft75Parser = require('./websocket/draft75_parser'),
Draft76Parser = require('./websocket/draft76_parser'),
Protocol8Parser = require('./websocket/protocol8_parser'),
API = require('./websocket/api');
var Draft75Parser = require('./websocket/draft75_parser'),
Draft76Parser = require('./websocket/draft76_parser'),
HybiParser = require('./websocket/hybi_parser'),
API = require('./websocket/api');

@@ -19,3 +19,3 @@ var getParser = function(request) {

return headers['sec-websocket-version']
? Protocol8Parser
? HybiParser
: (headers['sec-websocket-key1'] && headers['sec-websocket-key2'])

@@ -35,3 +35,3 @@ ? Draft76Parser

var WebSocket = function(request, socket, head) {
var WebSocket = function(request, socket, head, supportedProtos) {
this.request = request;

@@ -46,5 +46,8 @@ this._stream = request.socket;

var Parser = getParser(request);
this._parser = new Parser(this, this._stream);
this._parser.handshakeResponse(head);
this._parser = new Parser(this, {protocols: supportedProtos});
var handshake = this._parser.handshakeResponse(head);
try { this._stream.write(handshake, 'binary') } catch (e) {}
this.protocol = this._parser.protocol || '';
this.readyState = API.OPEN;

@@ -60,3 +63,5 @@ this.version = this._parser.getVersion();

this._stream.addListener('data', function(data) {
self._parser.parse(data);
var response = self._parser.parse(data);
if (!response) return;
try { self._stream.write(response, 'binary') } catch (e) {}
});

@@ -63,0 +68,0 @@ ['close', 'end', 'error'].forEach(function(event) {

@@ -11,2 +11,3 @@ var API = {

onclose: null,
protocol: null,

@@ -23,3 +24,9 @@ receive: function(data) {

if (this.readyState === API.CLOSED) return false;
return this._parser.frame(data, type, errorType);
var frame = this._parser.frame(data, type, errorType);
try {
this._stream.write(frame, 'binary');
return true;
} catch (e) {
return false;
}
},

@@ -26,0 +33,0 @@

@@ -5,12 +5,13 @@ var API = require('./api'),

var Protocol8Parser = require('./protocol8_parser');
var HybiParser = require('./hybi_parser');
var Client = function(url) {
this.url = url;
this.uri = require('url').parse(url);
var Client = function(url, protocols) {
this.url = url;
this._uri = require('url').parse(url);
this.protocol = '';
this.readyState = API.CONNECTING;
this.bufferedAmount = 0;
var secure = (this.uri.protocol === 'wss:'),
var secure = (this._uri.protocol === 'wss:'),
self = this,

@@ -20,6 +21,6 @@ onConnect = function() { self._onConnect() },

connection = secure
? tls.connect(this.uri.port || 443, this.uri.hostname, onConnect)
: net.createConnection(this.uri.port || 80, this.uri.hostname);
? tls.connect(this._uri.port || 443, this._uri.hostname, onConnect)
: net.createConnection(this._uri.port || 80, this._uri.hostname);
this._parser = new Protocol8Parser(this, connection, {masking: true});
this._parser = new HybiParser(this, {masking: true, protocols: protocols});
this._stream = connection;

@@ -39,5 +40,7 @@

Client.prototype._onConnect = function() {
this._handshake = this._parser.createHandshake(this.uri);
this._handshake = this._parser.createHandshake(this._uri, this._stream);
this._message = [];
this._handshake.requestData();
try {
this._stream.write(this._handshake.requestData(), 'binary');
} catch (e) {}
};

@@ -55,2 +58,3 @@

if (this._handshake.isValid()) {
this.protocol = this._handshake.protocol || '';
this.readyState = API.OPEN;

@@ -65,3 +69,3 @@ var event = new API.Event('open');

this.readyState = API.CLOSED;
var event = new API.Event('close');
var event = new API.Event('close', {code: 1006, reason: ''});
event.initEvent('close', false, false);

@@ -68,0 +72,0 @@ this.dispatchEvent(event);

@@ -1,60 +0,87 @@

var Draft75Parser = function(webSocket, stream) {
this._socket = webSocket;
this._stream = stream;
this._buffer = [];
this._buffering = false;
var Draft75Parser = function(webSocket) {
this._socket = webSocket;
this._stage = 0;
};
var instance = {
FRAME_START : new Buffer([0x00]),
FRAME_END : new Buffer([0xFF]),
getVersion: function() {
return 'draft-75';
return 'hixie-75';
},
handshakeResponse: function() {
var stream = this._stream;
try {
stream.write( 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'WebSocket-Origin: ' + this._socket.request.headers.origin + '\r\n' +
'WebSocket-Location: ' + this._socket.url + '\r\n\r\n');
} catch (e) {}
return new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'WebSocket-Origin: ' + this._socket.request.headers.origin + '\r\n' +
'WebSocket-Location: ' + this._socket.url + '\r\n\r\n',
'utf8');
},
parse: function(data) {
for (var i = 0, n = data.length; i < n; i++)
this._handleChar(data[i]);
parse: function(buffer) {
var data, message, value;
for (var i = 0, n = buffer.length; i < n; i++) {
data = buffer[i];
switch (this._stage) {
case 0:
this._parseLeadingByte(data);
break;
case 1:
value = (data & 0x7F);
this._length = value + 128 * this._length;
if (this._closing && this._length === 0) {
this._socket.close(null, null, false);
}
else if ((0x80 & data) !== 0x80) {
if (this._length === 0) {
this._socket.receive('');
this._stage = 0;
}
else {
this._buffer = [];
this._stage = 2;
}
}
break;
case 2:
if (data === 0xFF) {
message = new Buffer(this._buffer);
this._socket.receive(message.toString('utf8', 0, this._buffer.length));
this._stage = 0;
}
else {
this._buffer.push(data);
if (this._length && this._buffer.length === this._length)
this._stage = 0;
}
break;
}
}
},
frame: function(data) {
var stream = this._stream;
try {
stream.write(this.FRAME_START, 'binary');
stream.write(new Buffer(data), 'utf8');
stream.write(this.FRAME_END, 'binary');
return true;
} catch (e) {
return false;
_parseLeadingByte: function(data) {
if ((0x80 & data) === 0x80) {
this._length = 0;
this._stage = 1;
} else {
delete this._length;
this._buffer = [];
this._stage = 2;
}
},
_handleChar: function(data) {
switch (data) {
case 0x00:
this._buffering = true;
break;
case 0xFF:
this._buffer = new Buffer(this._buffer);
this._socket.receive(this._buffer.toString('utf8', 0, this._buffer.length));
this._buffer = [];
this._buffering = false;
break;
default:
if (this._buffering) this._buffer.push(data);
}
frame: function(data) {
if (Buffer.isBuffer(data)) return data;
var buffer = new Buffer(data, 'utf8'),
frame = new Buffer(buffer.length + 2);
frame[0] = 0x00;
frame[buffer.length + 1] = 0xFF;
buffer.copy(frame, 1);
return frame;
}

@@ -61,0 +88,0 @@ };

@@ -26,27 +26,31 @@ var crypto = require('crypto'),

Draft76Parser.prototype.getVersion = function() {
return 'draft-76';
return 'hixie-76';
};
Draft76Parser.prototype.handshakeResponse = function(head) {
var request = this._socket.request,
stream = this._stream;
var request = this._socket.request, tmp;
try {
stream.write( 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'Sec-WebSocket-Origin: ' + request.headers.origin + '\r\n' +
'Sec-WebSocket-Location: ' + this._socket.url + '\r\n\r\n',
'binary');
} catch (e) {}
var response = new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'Sec-WebSocket-Origin: ' + request.headers.origin + '\r\n' +
'Sec-WebSocket-Location: ' + this._socket.url + '\r\n\r\n',
'binary');
this.handshakeSignature(head);
var signature = this.handshakeSignature(head);
if (signature) {
tmp = new Buffer(response.length + signature.length);
response.copy(tmp, 0);
signature.copy(tmp, response.length);
response = tmp;
}
return response;
};
Draft76Parser.prototype.handshakeSignature = function(head) {
if (head.length === 0) return;
if (head.length === 0) return null;
this._handshakeComplete = true;
var request = this._socket.request,
stream = this._stream,

@@ -65,5 +69,3 @@ key1 = request.headers['sec-websocket-key1'],

try {
stream.write(MD5.digest('binary'), 'binary');
} catch (e) {};
return new Buffer(MD5.digest('binary'), 'binary');
};

@@ -75,6 +77,22 @@

this.handshakeSignature(data);
return this.handshakeSignature(data);
};
Draft76Parser.prototype._parseLeadingByte = function(data) {
if (data !== 0xFF)
return Draft75Parser.prototype._parseLeadingByte.call(this, data);
this._closing = true;
this._length = 0;
this._stage = 1;
};
Draft76Parser.prototype.close = function(code, reason, callback, context) {
if (this._closed) return;
if (this._closing) this._socket.send(new Buffer([0xFF, 0x00]));
this._closed = true;
if (callback) callback.call(context);
};
module.exports = Draft76Parser;
{ "name" : "faye-websocket"
, "description" : "Robust general-purpose WebSocket server and client"
, "description" : "Standards-compliant WebSocket server and client"
, "homepage" : "http://github.com/jcoglan/faye-websocket-node"

@@ -7,6 +7,6 @@ , "author" : "James Coglan <jcoglan@gmail.com> (http://jcoglan.com/)"

, "version" : "0.1.2"
, "version" : "0.2.0"
, "engines" : {"node": ">=0.4.0"}
, "main" : "./lib/faye/websocket"
, "devDependencies" : {"jsclass": ">=3.0.4"}
, "devDependencies" : {"jsclass": ""}

@@ -13,0 +13,0 @@ , "bugs" : "http://github.com/jcoglan/faye-websocket-node/issues"

@@ -16,3 +16,3 @@ var Client = require('../../../lib/faye/websocket/client')

open_socket: function(url, callback) {
open_socket: function(url, protocols, callback) {
var done = false,

@@ -28,3 +28,3 @@ self = this,

this._ws = new Client(url)
this._ws = new Client(url, protocols)

@@ -54,2 +54,7 @@ this._ws.onopen = function() { resume(true) }

check_protocol: function(protocol, callback) {
this.assertEqual( protocol, this._ws.protocol )
callback()
},
listen_for_message: function(callback) {

@@ -82,2 +87,3 @@ var self = this

before(function() {
this.protocols = ["foo", "echo"]
this.plain_text_url = "ws://localhost:8000/bayeux"

@@ -89,13 +95,19 @@ this.secure_url = "wss://localhost:8000/bayeux"

it("can open a connection", function() { with(this) {
open_socket(socket_url)
open_socket(socket_url, protocols)
check_open()
check_protocol("echo")
}})
it("cannot open a connection to the wrong host", function() { with(this) {
open_socket(blocked_url)
open_socket(blocked_url, protocols)
check_closed()
}})
it("cannot open a connection with unacceptable protocols", function() { with(this) {
open_socket(socket_url, ["foo"])
check_closed()
}})
it("can close the connection", function() { with(this) {
open_socket(socket_url)
open_socket(socket_url, protocols)
close_socket()

@@ -107,3 +119,3 @@ check_closed()

before(function() { with(this) {
open_socket(socket_url)
open_socket(socket_url, protocols)
}})

@@ -120,3 +132,3 @@

before(function() { with(this) {
open_socket(socket_url)
open_socket(socket_url, protocols)
close_socket()

@@ -123,0 +135,0 @@ }})

@@ -6,21 +6,56 @@ var Draft75Parser = require('../../../lib/faye/websocket/draft75_parser')

this.webSocket = {dispatchEvent: function() {}}
this.socket = new FakeSocket
this.parser = new Draft75Parser(webSocket, socket)
this.parser = new Draft75Parser(webSocket)
}})
describe("parse", function() { with(this) {
it("parses text frames", function() { with(this) {
expect(webSocket, "receive").given("Hello")
parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
sharedBehavior("draft-75 parser", function() { with(this) {
it("parses text frames", function() { with(this) {
expect(webSocket, "receive").given("Hello")
parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
}})
it("parses multiple frames from the same packet", function() { with(this) {
expect(webSocket, "receive").given("Hello").exactly(2)
parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
}})
it("parses text frames beginning 0x00-0x7F", function() { with(this) {
expect(webSocket, "receive").given("Hello")
parser.parse([0x66, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
}})
it("ignores frames with a length header", function() { with(this) {
expect(webSocket, "receive").exactly(0)
parser.parse([0x80, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f])
}})
it("parses text following an ignored block", function() { with(this) {
expect(webSocket, "receive").given("Hello")
parser.parse([0x80, 0x02, 0x48, 0x65, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff])
}})
it("parses multibyte text frames", function() { with(this) {
expect(webSocket, "receive").given("Apple = ")
parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff])
}})
it("parses frames received in several packets", function() { with(this) {
expect(webSocket, "receive").given("Apple = ")
parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65])
parser.parse([0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff])
}})
it("parses fragmented frames", function() { with(this) {
expect(webSocket, "receive").given("Hello")
parser.parse([0x00, 0x48, 0x65, 0x6c])
parser.parse([0x6c, 0x6f, 0xff])
}})
}})
it("parses multibyte text frames", function() { with(this) {
expect(webSocket, "receive").given("Apple = ")
parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff])
}})
behavesLike("draft-75 parser")
it("parses fragmented frames", function() { with(this) {
expect(webSocket, "receive").given("Hello")
parser.parse([0x00, 0x48, 0x65, 0x6c])
parser.parse([0x6c, 0x6f, 0xff])
it("does not close the socket if a 76 close frame is received", function() { with(this) {
expect(webSocket, "close").exactly(0)
expect(webSocket, "receive").given("")
parser.parse([0xFF, 0x00])
}})

@@ -31,11 +66,9 @@ }})

it("returns the given string formatted as a WebSocket frame", function() { with(this) {
parser.frame("Hello")
assertEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], socket.read() )
assertBufferEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], parser.frame("Hello") )
}})
it("encodes multibyte characters correctly", function() { with(this) {
parser.frame("Apple = ")
assertEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], socket.read() )
assertBufferEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], parser.frame("Apple = ") )
}})
}})
}})

@@ -9,19 +9,2 @@ require('jsclass')

JS.ENV.FakeSocket = function() {
this._fragments = []
}
FakeSocket.prototype.write = function(buffer, encoding) {
this._fragments.push([buffer, encoding])
}
FakeSocket.prototype.read = function() {
var output = []
this._fragments.forEach(function(buffer, i) {
for (var j = 0, n = buffer[0].length; j < n; j++)
output.push(buffer[0][j])
})
return output
}
FakeSocket.prototype.addListener = function() {}
JS.ENV.EchoServer = function() {}

@@ -37,3 +20,3 @@ EchoServer.prototype.listen = function(port, ssl) {

server.addListener('upgrade', function(request, socket, head) {
var ws = new WebSocket(request, socket, head)
var ws = new WebSocket(request, socket, head, ["echo"])
ws.onmessage = function(event) {

@@ -60,7 +43,15 @@ ws.send(event.data)

JS.require('JS.Test', function() {
JS.Test.Unit.Assertions.define("assertBufferEqual", function(array, buffer) {
this.assertEqual(array.length, buffer.length);
var ary = [], n = buffer.length;
while (n--) ary[n] = buffer[n];
this.assertEqual(array, ary);
})
JS.require( 'ClientSpec',
'Draft75ParserSpec',
'Protocol8ParserSpec',
'Draft76ParserSpec',
'HybiParserSpec',
JS.Test.method('autorun'))
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc