Compare commits

..

14 Commits

Author SHA1 Message Date
James Coglan 1c33c0ce56 Bump version to 0.3.6. 2014-10-04 08:30:43 +01:00
James Coglan f693b02743 Merge pull request #8 from meteor/close-before-start
driver.close() before driver.start() should close
2014-09-07 21:29:25 +01:00
James Coglan 91f19cb69b Use the SVG build status icon from Travis. 2014-09-07 21:06:45 +01:00
David Glasser dcd7c278b6 driver.close() before driver.start() should close 2014-08-15 10:48:30 -07:00
James Coglan dbedb370b7 Bump version to 0.3.5. 2014-07-06 10:18:19 +01:00
James Coglan 28858d9fb3 Delegate the protocol and version methods correctly in the TCP driver. 2014-07-04 17:49:11 +01:00
James Coglan ae52cf995e Stop the Hybi parser hanging onto data it doesn't need after emitFrame(). 2014-06-16 20:30:44 +01:00
James Coglan dfe7b2b000 Trailing blank lines are bad. 2014-05-17 00:35:31 +01:00
James Coglan d40de878b2 Bump version to 0.3.4. 2014-05-08 02:19:58 +01:00
James Coglan ed3907d5fd Clean up the state management code in StreamReader. 2014-05-07 20:49:49 +01:00
James Coglan 84b6f50f1a Merge pull request #6 from meteor/forget-finished-buffers
StreamReader: Don't hang on to fully read buffers
2014-05-07 20:41:15 +01:00
David Glasser 8d19ee823e StreamReader: Don't hang on to fully read buffers 2014-05-06 11:52:59 -07:00
James Coglan 3bee0366c5 Bump version to 0.3.3. 2014-04-24 23:31:43 +01:00
James Coglan 9f2782da14 Correct the draft-76 status line reason phrase. 2014-04-17 02:23:58 +01:00
22 changed files with 80 additions and 81 deletions
-1
View File
@@ -8,4 +8,3 @@ node_js:
before_install:
- '[ "${TRAVIS_NODE_VERSION}" = "0.6" ] && npm conf set strict-ssl false || true'
+17 -1
View File
@@ -1,3 +1,20 @@
### 0.3.6 / 2014-10-04
* It is now possible to call `close()` before `start()` and close the driver
### 0.3.5 / 2014-07-06
* Don't hold references to frame buffers after a message has been emitted
* Make sure that `protocol` and `version` are exposed properly by the TCP driver
### 0.3.4 / 2014-05-08
* Don't hold memory-leaking references to I/O buffers after they have been parsed
### 0.3.3 / 2014-04-24
* Correct the draft-76 status line reason phrase
### 0.3.2 / 2013-12-29
* Expand `maxLength` to cover sequences of continuation frames and `draft-{75,76}`
@@ -31,4 +48,3 @@
### 0.1.0 / 2013-05-04
* First stable release
+2 -3
View File
@@ -1,4 +1,4 @@
# websocket-driver [![Build Status](https://travis-ci.org/faye/websocket-driver-node.png)](https://travis-ci.org/faye/websocket-driver-node)
# websocket-driver [![Build Status](https://travis-ci.org/faye/websocket-driver-node.svg)](https://travis-ci.org/faye/websocket-driver-node)
This module provides a complete implementation of the WebSocket protocols that
can be hooked up to any I/O stream. It aims to simplify things by decoupling
@@ -285,7 +285,7 @@ after `emit('open')` has fired.
(The MIT License)
Copyright (c) 2010-2013 James Coglan
Copyright (c) 2010-2014 James Coglan
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the 'Software'), to deal in
@@ -304,4 +304,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-1
View File
@@ -18,4 +18,3 @@ var server = net.createServer(function(connection) {
});
server.listen(process.argv[2]);
-1
View File
@@ -41,4 +41,3 @@ var Driver = {
};
module.exports = Driver;
-1
View File
@@ -123,4 +123,3 @@ Base.MessageEvent = function(data) {
};
module.exports = Base;
-1
View File
@@ -109,4 +109,3 @@ for (var key in instance)
Client.prototype[key] = instance[key];
module.exports = Client;
-1
View File
@@ -115,4 +115,3 @@ for (var key in instance)
Draft75.prototype[key] = instance[key];
module.exports = Draft75;
+1 -2
View File
@@ -48,7 +48,7 @@ var instance = {
},
_handshakeResponse: function() {
return new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
return new Buffer('HTTP/1.1 101 WebSocket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'Sec-WebSocket-Origin: ' + this._request.headers.origin + '\r\n' +
@@ -106,4 +106,3 @@ for (var key in instance)
Draft76.prototype[key] = instance[key];
module.exports = Draft76;
-1
View File
@@ -27,4 +27,3 @@ Headers.prototype._strip = function(string) {
};
module.exports = Headers;
-1
View File
@@ -78,4 +78,3 @@ HttpParser.prototype.parse = function(data) {
};
module.exports = HttpParser;
+35 -40
View File
@@ -7,26 +7,33 @@ var Hybi = function(request, url, options) {
Base.apply(this, arguments);
this._reset();
this._reader = new Reader();
this._stage = 0;
this._masking = this._options.masking;
this._protocols = this._options.protocols || [];
this._reader = new Reader();
this._stage = 0;
this._masking = this._options.masking;
this._protocols = this._options.protocols || [];
this._requireMasking = this._options.requireMasking;
this._pingCallbacks = {};
if (typeof this._protocols === 'string')
this._protocols = this._protocols.split(/\s*,\s*/);
this._requireMasking = this._options.requireMasking;
this._pingCallbacks = {};
if (!this._request) return;
if (!this.version) {
var version = this._request.headers['sec-websocket-version'];
this.version = 'hybi-' + version;
var protos = this._request.headers['sec-websocket-protocol'],
supported = this._protocols;
if (protos !== undefined) {
if (typeof protos === 'string') protos = protos.split(/\s*,\s*/);
this.protocol = protos.filter(function(p) { return supported.indexOf(p) >= 0 })[0];
}
var version = this._request.headers['sec-websocket-version'];
this.version = 'hybi-' + version;
};
util.inherits(Hybi, Base);
Hybi.mask = function(payload, mask, offset) {
if (mask.length === 0) return payload;
if (!mask || mask.length === 0) return payload;
offset = offset || 0;
for (var i = 0, n = payload.length - offset; i < n; i++) {
@@ -118,8 +125,7 @@ var instance = {
case 4:
buffer = this._reader.read(this._length);
if (buffer) {
this._payload = buffer;
this._emitFrame();
this._emitFrame(buffer);
this._stage = 0;
}
break;
@@ -203,7 +209,7 @@ var instance = {
reason = reason || '';
code = code || this.ERRORS.normal_closure;
if (this.readyState === 0) {
if (this.readyState <= 0) {
this.readyState = 3;
this.emit('close', new Base.CloseEvent(code, reason));
return true;
@@ -220,26 +226,15 @@ var instance = {
var secKey = this._request.headers['sec-websocket-key'];
if (!secKey) return '';
var accept = Hybi.generateAccept(secKey),
protos = this._request.headers['sec-websocket-protocol'],
supported = this._protocols,
proto,
var headers = [
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: ' + Hybi.generateAccept(secKey)
];
headers = [
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: ' + accept
];
if (protos !== undefined) {
if (typeof protos === 'string') protos = protos.split(/\s*,\s*/);
proto = protos.filter(function(p) { return supported.indexOf(p) >= 0 })[0];
if (proto) {
this.protocol = proto;
headers.push('Sec-WebSocket-Protocol: ' + proto);
}
}
if (this.protocol)
headers.push('Sec-WebSocket-Protocol: ' + this.protocol);
return new Buffer(headers.concat(this.__headers.toString(), '').join('\r\n'), 'utf8');
},
@@ -269,8 +264,6 @@ var instance = {
this._final = (data & this.FIN) === this.FIN;
this._opcode = (data & this.OPCODE);
this._mask = [];
this._payload = [];
if (this.OPCODE_CODES.indexOf(this._opcode) < 0)
return this._fail('protocol_error', 'Unrecognized frame opcode: ' + this._opcode);
@@ -320,14 +313,17 @@ var instance = {
}
},
_emitFrame: function() {
var payload = Hybi.mask(this._payload, this._mask),
_emitFrame: function(buffer) {
var payload = Hybi.mask(buffer, this._mask),
isFinal = this._final,
opcode = this._opcode;
this._final = this._opcode = this._length = this._lengthSize = this._masked = this._mask = null;
if (opcode === this.OPCODES.continuation) {
if (!this._mode) return this._fail('protocol_error', 'Received unexpected continuation frame');
this._buffer(payload);
if (this._final) {
if (isFinal) {
var message = this._concatBuffer();
if (this._mode === 'text') message = this._encode(message);
this._reset();
@@ -338,7 +334,7 @@ var instance = {
}
}
else if (opcode === this.OPCODES.text) {
if (this._final) {
if (isFinal) {
var message = this._encode(payload);
if (message === null)
this._fail('encoding_error', 'Could not decode a text frame as UTF-8');
@@ -350,7 +346,7 @@ var instance = {
}
}
else if (opcode === this.OPCODES.binary) {
if (this._final) {
if (isFinal) {
this.emit('message', new Base.MessageEvent(payload));
} else {
this._mode = 'binary';
@@ -426,4 +422,3 @@ for (var key in instance)
Hybi.prototype[key] = instance[key];
module.exports = Hybi;
+10 -14
View File
@@ -4,10 +4,6 @@ var StreamReader = function() {
this._cursor = 0;
};
StreamReader.prototype.read = function(bytes) {
return this._readBuffer(bytes);
};
StreamReader.prototype.put = function(buffer) {
if (!buffer || buffer.length === 0) return;
if (!buffer.copy) buffer = new Buffer(buffer);
@@ -15,7 +11,7 @@ StreamReader.prototype.put = function(buffer) {
this._queueSize += buffer.length;
};
StreamReader.prototype._readBuffer = function(length) {
StreamReader.prototype.read = function(length) {
if (length > this._queueSize) return null;
var buffer = new Buffer(length),
@@ -23,22 +19,22 @@ StreamReader.prototype._readBuffer = function(length) {
remain = length,
n = queue.length,
i = 0,
chunk, offset, size;
if (remain === 0) return buffer;
chunk, size;
while (remain > 0 && i < n) {
chunk = queue[i];
offset = (i === 0) ? this._cursor : 0;
size = Math.min(remain, chunk.length - offset);
chunk.copy(buffer, length - remain, offset, offset + size);
remain -= size;
size = Math.min(remain, chunk.length - this._cursor);
chunk.copy(buffer, length - remain, this._cursor, this._cursor + size);
remain -= size;
this._queueSize -= size;
this._cursor = (this._cursor + size) % chunk.length;
i += 1;
}
queue.splice(0, i-1);
this._cursor = (i === 1 ? this._cursor : 0) + size;
queue.splice(0, this._cursor === 0 ? i : i - 1);
return buffer;
};
+3 -1
View File
@@ -40,6 +40,9 @@ var instance = {
this._delegate.on(event, function(e) { self.emit(event, e) });
}, this);
this.protocol = this._delegate.protocol;
this.version = this._delegate.version;
this.parse(this._http.body);
this.emit('connect', new Base.ConnectEvent());
},
@@ -101,4 +104,3 @@ Server.http = function(request, options) {
};
module.exports = Server;
-1
View File
@@ -141,4 +141,3 @@ Messages.prototype.destroy = function() {};
exports.IO = IO;
exports.Messages = Messages;
+1 -2
View File
@@ -5,7 +5,7 @@
, "keywords" : ["websocket"]
, "license" : "MIT"
, "version" : "0.3.2"
, "version" : "0.3.6"
, "engines" : {"node": ">=0.4.0"}
, "main" : "./lib/websocket/driver"
, "devDependencies" : {"jstest": ""}
@@ -18,4 +18,3 @@
, "bugs" : "http://github.com/faye/websocket-driver-node/issues"
}
-1
View File
@@ -42,4 +42,3 @@ require('./websocket/driver/draft75_spec')
require('./websocket/driver/draft76_spec')
require('./websocket/driver/hybi_spec')
require('./websocket/driver/client_spec')
+8 -1
View File
@@ -50,6 +50,14 @@ test.describe("Client", function() { with(this) {
assertEqual( null, driver().getState() )
}})
describe("close", function() { with(this) {
it("changes the state to closed", function() { with(this) {
driver().close()
assertEqual( "closed", driver().getState() )
assertEqual( [1000, ''], close )
}})
}})
describe("start", function() { with(this) {
it("writes the handshake request to the socket", function() { with(this) {
expect(driver().io, "emit").given("data", buffer(
@@ -249,4 +257,3 @@ test.describe("Client", function() { with(this) {
}})
}})
}})
@@ -112,4 +112,3 @@ test.describe("draft-75", function() { with(this) {
}})
}})
}})
-1
View File
@@ -97,4 +97,3 @@ test.describe("Draft75", function() { with(this) {
itShouldBehaveLike("draft-75 protocol")
}})
+3 -4
View File
@@ -53,7 +53,7 @@ test.describe("Draft76", function() { with(this) {
describe("start", function() { with(this) {
it("writes the handshake response to the socket", function() { with(this) {
expect(driver().io, "emit").given("data", buffer(
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +
"HTTP/1.1 101 WebSocket Protocol Handshake\r\n" +
"Upgrade: WebSocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Origin: http://www.example.com\r\n" +
@@ -95,7 +95,7 @@ test.describe("Draft76", function() { with(this) {
it("queues the frames until the handshake has been sent", function() { with(this) {
expect(driver().io, "emit").given("data", buffer(
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +
"HTTP/1.1 101 WebSocket Protocol Handshake\r\n" +
"Upgrade: WebSocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Origin: http://www.example.com\r\n" +
@@ -116,7 +116,7 @@ test.describe("Draft76", function() { with(this) {
it("writes the handshake response with no body", function() { with(this) {
expect(driver().io, "emit").given("data", buffer(
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +
"HTTP/1.1 101 WebSocket Protocol Handshake\r\n" +
"Upgrade: WebSocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Origin: http://www.example.com\r\n" +
@@ -184,4 +184,3 @@ test.describe("Draft76", function() { with(this) {
}})
}})
}})
-1
View File
@@ -539,4 +539,3 @@ test.describe("Hybi", function() { with(this) {
}})
}})
}})