diff --git a/server/node.ws.js/run.sh b/server/node.ws.js/run.sh new file mode 100644 index 0000000..2cf7563 --- /dev/null +++ b/server/node.ws.js/run.sh @@ -0,0 +1,6 @@ +#!/bin/sh +while true +do + echo "Running node" + node server.js $1 +done diff --git a/server/node.ws.js/server.js b/server/node.ws.js/server.js new file mode 100644 index 0000000..a6a64fb --- /dev/null +++ b/server/node.ws.js/server.js @@ -0,0 +1,41 @@ +var sys = require("sys"), + ws = require("./ws"); + +function broadcast(data, from) { + clients.forEach(function (client) { + if (client != from) { + try { + client.write(data); + } catch (e) { + clients.remove(client); + } + } + }); +} + +Array.prototype.remove = function(e) { + for (var i = 0; i < this.length; i++) + if (e == this[i]) return this.splice(i, 1); +} + +var clients = []; + +ws.createServer(function (websocket) { + clients.push(websocket); + + websocket.addListener("connect", function (resource) { + // emitted after handshake + sys.debug("connect: " + resource); + broadcast(clients.length+''); + }).addListener("data", function (data) { + // send data to attached clients + sys.puts('sending data...'); + broadcast(data, websocket); + }).addListener("close", function () { + // emitted when server or client closes connection + sys.debug("close"); + clients.remove(websocket); + broadcast(clients.length+''); + }); +}).listen(parseInt(process.ARGV[2]) || 8000); + diff --git a/server/node.ws.js/ws.js b/server/node.ws.js/ws.js new file mode 100644 index 0000000..622d693 --- /dev/null +++ b/server/node.ws.js/ws.js @@ -0,0 +1,131 @@ +// Github: http://github.com/ncr/node.ws.js +// Compatible with node v0.1.91 +// Author: Jacek Becela +// License: MIT +// Based on: http://github.com/Guille/node.websocket.js + +function nano(template, data) { + return template.replace(/\{([\w\.]*)}/g, function (str, key) { + var keys = key.split("."), value = data[keys.shift()]; + keys.forEach(function (key) { value = value[key] }); + return value; + }); +} + +var sys = require("sys"), + net = require("net"), + headerExpressions = [ + /^GET (\/[^\s]*) HTTP\/1\.1$/, + /^Upgrade: WebSocket$/, + /^Connection: Upgrade$/, + /^Host: (.+)$/, + /^Origin: (.+)$/ + ], + handshakeTemplate = [ + 'HTTP/1.1 101 Web Socket Protocol Handshake', + 'Upgrade: WebSocket', + 'Connection: Upgrade', + 'WebSocket-Origin: {origin}', + 'WebSocket-Location: ws://{host}{resource}', + '', + '' + ].join("\r\n"), + policy_file = ''; + +exports.createServer = function (websocketListener) { + return net.createServer(function (socket) { + socket.setTimeout(0); + socket.setNoDelay(true); + socket.setEncoding("utf8"); + + var emitter = new process.EventEmitter(), + handshaked = false, + buffer = ""; + + function handle(data) { + buffer += data; + + var chunks = buffer.split("\ufffd"), + count = chunks.length - 1; // last is "" or a partial packet + + for(var i = 0; i < count; i++) { + var chunk = chunks[i]; + if(chunk[0] == "\u0000") { + emitter.emit("data", chunk.slice(1)); + } else { + socket.end(); + return; + } + } + + buffer = chunks[count]; + } + + function handshake(data) { + var headers = data.split("\r\n"); + + if(//.exec(headers[0])) { + socket.write(policy_file); + socket.end(); + return; + } + + var matches = [], match; + for (var i = 0, l = headerExpressions.length; i < l; i++) { + match = headerExpressions[i].exec(headers[i]); + + if (match) { + if(match.length > 1) { + matches.push(match[1]); + } + } else { + socket.end(); + return; + } + } + + socket.write(nano(handshakeTemplate, { + resource: matches[0], + host: matches[1], + origin: matches[2], + })); + + handshaked = true; + emitter.emit("connect", matches[0]); + } + + socket.addListener("data", function (data) { + if(handshaked) { + handle(data); + } else { + handshake(data); + } + }).addListener("end", function () { + socket.end(); + }).addListener("close", function () { + if (handshaked) { // don't emit close from policy-requests + emitter.emit("close"); + } + }); + + emitter.remoteAddress = socket.remoteAddress; + + emitter.write = function (data) { + try { + socket.write('\u0000', 'binary'); + socket.write(data, 'utf8'); + socket.write('\uffff', 'binary'); + } catch(e) { + // Socket not open for writing, + // should get "close" event just before. + socket.end(); + } + } + + emitter.end = function () { + socket.end(); + } + + websocketListener(emitter); // emits: "connect", "data", "close", provides: write(data), end() + }); +}