Skip to content
Browse files

Fixing a few issues, starting to work on draft76 upgrade. note to sel…

…f: commit more regularly.
  • Loading branch information...
1 parent e91ec9e commit 0354f08319802fe322c09ace2119faecd376c0ec @miksago miksago committed Jun 9, 2010
Showing with 92 additions and 63 deletions.
  1. +12 −3 Rakefile
  2. +12 −9 examples/echo-server.js
  3. +1 −1 lib/ws.js
  4. +57 −50 lib/ws/connection.js
  5. +5 −0 package.json
  6. +5 −0 samples/handshake-packets
View
15 Rakefile
@@ -5,6 +5,8 @@ require 'json'
puts "---"
+@version = `git describe`.match("v([0-9]+\.[0-9]+.\[0-9]+).*")[1]
+
def to_node_json(obj)
obj = obj.to_json
# reformat it a bit
@@ -35,15 +37,21 @@ end
namespace :write do
desc "Write the package.json file"
task :pkgspec do
- version = `git describe`.match("v([0-9]+\.[0-9]+.\[0-9]+).*")[1]
package = {
:name => "websocket-server",
- :version => version,
+ :version => @version,
:author => "Micheil Smith <micheil@brandedcode.com>",
:description => "A WebSocket server written in low-level node.js, 90-100% spec compatible.",
:main => "./lib/ws",
:engines => { :node => ">=0.1.94-0" },
- :licenses => [{ :type => "MIT", :url => "./LICENSE.md" }]
+ :licenses => [{ :type => "MIT", :url => "./LICENSE.md" }],
+ :repository => {
+ :type => "git",
+ :url => "http://github.com/miksago/node-websocket-server.git"
+ },
+ :bugs => {
+ :web => "http://github.com/miksago/node-websocket-server/issues"
+ }
}
puts "Making package.json"
@@ -59,6 +67,7 @@ namespace :npm do
task :publish do
puts "Publishing to NPM"
system("npm publish #{`pwd`}")
+ system("npm tag websocket-server #{@version} stable")
puts "-> Done"
end
end
View
21 examples/echo-server.js
@@ -3,31 +3,32 @@ var ws = require('../lib/ws');
// We're using a custom logged method here:
var logger = require("../utils/logger");
-function log(data){
- sys.log("\033[0;32m"+data.toString()+"\033[0m");
-};
var server = ws.createServer({
- debug: true
+ debug: true,
+ version: "draft75"
});
-server.listen(8000);
server.addListener("listening", function(){
- log("Listening for connections.");
+ sys.log("Listening for connections.");
});
// Handle WebSocket Requests
server.addListener("connection", function(conn){
- log("<"+conn._id+"> connected");
+ function log(data){
+ sys.log("\033[0;32m<"+conn._id+"> "+data.toString()+"\033[0m");
+ };
+
+ log("connected");
server.broadcast("<"+conn._id+"> connected");
conn.addListener("close", function(){
- log("<"+conn._id+"> onClose");
+ log("onClose");
server.broadcast("<"+conn._id+"> disconnected");
});
conn.addListener("message", function(message){
- log("<"+conn._id + "> "+message);
+ log(message);
server.broadcast("<"+conn._id+"> "+message);
});
});
@@ -37,3 +38,5 @@ server.addListener("request", function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('This is, infact a websocket server, but we can do http!\n');
});
+
+server.listen(8000, "localhost");
View
2 lib/ws.js
@@ -45,7 +45,7 @@ function Server(options){
this.server = new http.Server();
this.options = mixin({
- version: "draft75",//"draft75", // string, [spec, draft75]
+ version: "auto",// string, either: draft75, draft76, auto
origin: "*", // string | array, any valid domain
subprotocol: null, // string | array
debug: false
View
107 lib/ws/connection.js
@@ -3,10 +3,10 @@ var sys = require("sys")
, events = require("events");
// Debugger:
-var LOG = true;
+var LOG = false;
-function log(msg){
- if(LOG) sys.log(msg);
+function debug(msg){
+ if(LOG) sys.log("<"+this._id+"> "+msg);
};
/*-----------------------------------------------
@@ -20,19 +20,23 @@ function Connection(server, req, socket, upgradeHead){
this._req = req;
this._server = server;
this._upgradeHead = upgradeHead;
+ this._id = this._req.socket.remotePort;
- setup.call(this);
- auto_version.call(this);
+ this.version = this.getVersion();
- log("new connection: using "+server.options.version);
-
- if(this._upgradeHead && this._upgradeHead.length == 8 && server.options.version == "draft76"){
- handshake.call(this);
- } else if (server.options.version == "draft75"){
- handshake.call(this);
+ if(! checkVersion.call(this)){
+ this.reject("Invalid version.");
} else {
- this.readyState = 2;
- log("waiting.");
+ debug.call(this, this.version+" connection");
+
+ setup.call(this);
+
+ if((this.version == "draft75") || (this.version == "draft76" && this._upgradeHead && this._upgradeHead.length == 8)){
+ handshake.call(this);
+ } else {
+ this.readyState = 2;
+ debug.call(this, "waiting.");
+ }
}
};
@@ -46,16 +50,6 @@ sys.inherits(Connection, events.EventEmitter);
4, connected
5. closed
-----------------------------------------------*/
-
-// var states = [
-// "unknown",
-// "opening",
-// "waiting",
-// "handshaking",
-// "connected",
-// "closed"
-// ];
-
Connection.prototype.__state__ = 0;
Object.defineProperty(Connection.prototype, "readyState", {
@@ -78,31 +72,39 @@ Object.defineProperty(Connection.prototype, "readyState", {
-----------------------------------------------*/
Connection.prototype.write = function(data){
var socket = this._req.socket;
- if(this.readyState == 4){
- log("write: "+this._id+" <"+data+">");
+
+ if(this.readyState == 4 && socket.writable){
+ debug.call(this, "write: "+data);
+
socket.write("\u0000", "binary");
socket.write(data, "utf8");
socket.write("\uffff", "binary");
-
return true;
} else {
+ debug.call(this, "ERROR: write: "+data)
return false;
}
};
Connection.prototype.close = function(){
- log(this._id + ": closed");
this._req.socket.end();
this._req.socket.destroy();
this.readyState = 5;
+ debug.call(this, "closed");
+};
+
+Connection.prototype.reject = function(reason){
+ debug.call(this, "rejected. Reason: "+reason);
+ this.emit("rejected");
+ this.close();
};
-function auto_version(){
+Connection.prototype.getVersion = function(){
if(this._req.headers["sec-websocket-key1"] && this._req.headers["sec-websocket-key2"]){
- log(">> Should be draft76+");
+ return "draft76";
} else {
- log(">> Should be draft75");
+ return "draft75";
}
};
@@ -128,7 +130,7 @@ function setup(){
ondata.call(conn, data, start, end);
};
- this.addListener("readyStateChange", function(state){
+ conn.addListener("readyStateChange", function(state){
if(state == 4){
attachClient.call(conn);
} else if( state == 5 ){
@@ -142,11 +144,26 @@ function setup(){
});
};
+
+function checkVersion(){
+ var server_version = this._server.options.version
+ , client_version = this.version = this.version || this.getVersion();
+
+ if(server_version == "auto" || server_version == client_version){
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*-----------------------------------------------
+ Attach & Detach the client from the server
+-----------------------------------------------*/
function attachClient(){
var server = this._server;
// Set the connection ID:
- var client_id = this._id = this._req.socket.remotePort+""+(+new Date);;
+ var client_id = this._id;
var resource = this._req.url.replace(/^\//, '');
// A simple hash of all currently connected clients.
if(!server.connections) server.connections = {};
@@ -181,7 +198,7 @@ function detachClient(){
-----------------------------------------------*/
function ondata(data, start, end){
// The readyState will only be 2 if using draft76:
- if(this.readyState == 2 && this._server.options.version == "draft76"){
+ if(this.readyState == 2 && this.version == "draft76"){
// TODO: I need to figure out an alternative here.
// data.copy(this._req.upgradeHead, 0, start, end);
handshake.call(this);
@@ -191,13 +208,13 @@ function ondata(data, start, end){
var flag_end = data.toString("ascii", end-1, end);
if(flag_begin == "\u0000" && flag_end == "\ufffd"){
- if((end-1)-(start+1) > 0){
+ if(data.length > 2){
this.emit("message", data.toString("utf8", start+1, end-1));
} else {
this.close();
}
} else {
- this.close();
+ this.reject("invalid message");
}
}
};
@@ -249,21 +266,13 @@ function websocket_location(){
Do the handshake.
-----------------------------------------------*/
function handshake(){
- var version = this._server.options.version;
this.readyState = 3;
- log("handshake");
-
- if(version == "draft75"){
- handshakeWithDraft75.call(this);
- } else if(version == "draft76"){
- handshakeWithDraft76.call(this);
- }
+ debug.call(this, this.version+" handshake");
+ handshake[this.version].call(this);
}
/* Using draft75, work out and send the handshake. */
-function handshakeWithDraft75(){
- log("handshakeWithDraft75");
-
+handshake.draft75 = function(){
var req = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
@@ -274,13 +283,11 @@ function handshakeWithDraft75(){
req += "\r\nWebSocket-Protocol: "+this._server.options.subprotocol;
}
- this._req.socket.write(req, "ascii");
- this._req.socket.write("\r\n\r\n", "ascii");
+ this._req.socket.write(req+"\r\n\r\n", "ascii");
this._req.socket.flush();
this.readyState = 4;
};
/* Using draft76 (security model), work out and send the handshake. */
-function handshakeWithDraft76(){
-
+handshake.draft76 = function(){
};
View
5 package.json
@@ -1,6 +1,11 @@
{ "version": "1.0.53"
, "description": "A WebSocket server written in low-level node.js, 90-100% spec compatible."
+, "repository": { "type": "git"
+, "url": "http://github.com/miksago/node-websocket-server.git"
+}
, "main": "./lib/ws"
+, "bugs": { "web": "http://github.com/miksago/node-websocket-server/issues"
+}
, "author": "Micheil Smith <micheil@brandedcode.com>"
, "licenses": [{ "type": "MIT", "url": "./LICENSE.md" }]
, "name": "websocket-server"
View
5 samples/handshake-packets
@@ -76,5 +76,10 @@ Connection: Upgrade
Host: example.com
Origin: http://example.com
+GET / HTTP/1.1
+Upgrade: WebSocket
+Connection: Upgrade
+Host: example.com
+Origin: http://example.com

0 comments on commit 0354f08

Please sign in to comment.
Something went wrong with that request. Please try again.