diff options
| author | Jules Laplace <jules@okfoc.us> | 2012-09-24 16:22:07 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2012-09-24 16:22:07 -0400 |
| commit | 686106d544ecc3b6ffd4db2b665d3bc879a58d8c (patch) | |
| tree | a5b5e50237cef70e12f0745371896e96f5f6d578 /node_modules/socket.io/support | |
ok
Diffstat (limited to 'node_modules/socket.io/support')
15 files changed, 1094 insertions, 0 deletions
diff --git a/node_modules/socket.io/support/node-websocket-client/LICENSE b/node_modules/socket.io/support/node-websocket-client/LICENSE new file mode 100644 index 0000000..f3c2eae --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2010, Peter Griess <pg@std.in> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of node-websocket-client nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/socket.io/support/node-websocket-client/Makefile b/node_modules/socket.io/support/node-websocket-client/Makefile new file mode 100644 index 0000000..e7c849a --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/Makefile @@ -0,0 +1,22 @@ +# This makefile exists to help run tests. +# +# If TEST_UNIX is a non-empty value, runs tests for UNIX sockets. This +# functionality is not in node-websocket-server at the moment. + +.PHONY: test + +all: test test-unix + +test: + for f in `ls -1 test/test-*.js | grep -v unix` ; do \ + echo $$f ; \ + node $$f ; \ + done + +test-unix: + if [[ -n "$$TEST_UNIX" ]] ; then \ + for f in `ls -1 test/test-*.js | grep unix` ; do \ + echo $$f ; \ + node $$f ; \ + done \ + fi diff --git a/node_modules/socket.io/support/node-websocket-client/README.md b/node_modules/socket.io/support/node-websocket-client/README.md new file mode 100644 index 0000000..8823a5c --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/README.md @@ -0,0 +1,41 @@ +A prototype [Web Socket](http://www.whatwg.org/specs/web-socket-protocol/) +client implementation for [node.js](http://nodejs.org). + +Tested with +[miksago/node-websocket-server](http://github.com/miksago/node-websocket-server) +v1.2.00. + +Requires [nodejs](http://nodejs.org) 0.1.98 or later. + +## Installation + +Install this using `npm` as follows + + npm install websocket-client + +... or just dump `lib/websocket.js` in your `$NODE_PATH`. + +## Usage + + var sys = require('sys'); + var WebSocket = require('websocket').WebSocket; + + var ws = new WebSocket('ws://localhost:8000/biff', 'borf'); + ws.addListener('data', function(buf) { + sys.debug('Got data: ' + sys.inspect(buf)); + }); + ws.onmessage = function(m) { + sys.debug('Got message: ' + m); + } + +## API + +This supports the `send()` and `onmessage()` APIs. The `WebSocket` object will +also emit `data` events that are node `Buffer` objects, in case you want to +work with something lower-level than strings. + +## Transports + +Multiple transports are supported, indicated by the scheme provided to the +`WebSocket` constructor. `ws://` is a standard TCP-based Web Socket; +`ws+unix://` allows connection to a UNIX socket at the given path. diff --git a/node_modules/socket.io/support/node-websocket-client/examples/client-unix.js b/node_modules/socket.io/support/node-websocket-client/examples/client-unix.js new file mode 100644 index 0000000..3bb23ba --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/examples/client-unix.js @@ -0,0 +1,12 @@ +var sys = require('sys'); +var WebSocket = require('../lib/websocket').WebSocket; + +var ws = new WebSocket('ws+unix://' + process.argv[2], 'boffo'); + +ws.addListener('message', function(d) { + sys.debug('Received message: ' + d.toString('utf8')); +}); + +ws.addListener('open', function() { + ws.send('This is a message', 1); +}); diff --git a/node_modules/socket.io/support/node-websocket-client/examples/client.js b/node_modules/socket.io/support/node-websocket-client/examples/client.js new file mode 100644 index 0000000..259bf6e --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/examples/client.js @@ -0,0 +1,10 @@ +var sys = require('sys'); +var WebSocket = require('../lib/websocket').WebSocket; + +var ws = new WebSocket('ws://localhost:8000/biff', 'borf'); +ws.addListener('data', function(buf) { + sys.debug('Got data: ' + sys.inspect(buf)); +}); +ws.onmessage = function(m) { + sys.debug('Got message: ' + m); +} diff --git a/node_modules/socket.io/support/node-websocket-client/examples/server-unix.js b/node_modules/socket.io/support/node-websocket-client/examples/server-unix.js new file mode 100644 index 0000000..912be0e --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/examples/server-unix.js @@ -0,0 +1,13 @@ +var sys = require('sys'); +var ws = require('websocket-server/ws'); + +var srv = ws.createServer({ debug : true}); +srv.addListener('connection', function(s) { + sys.debug('Got a connection!'); + + s._req.socket.addListener('fd', function(fd) { + sys.debug('Got an fd: ' + fd); + }); +}); + +srv.listen(process.argv[2]); diff --git a/node_modules/socket.io/support/node-websocket-client/lib/websocket.js b/node_modules/socket.io/support/node-websocket-client/lib/websocket.js new file mode 100644 index 0000000..4f7f734 --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/lib/websocket.js @@ -0,0 +1,617 @@ +var assert = require('assert'); +var buffer = require('buffer'); +var crypto = require('crypto'); +var events = require('events'); +var http = require('http'); +var net = require('net'); +var urllib = require('url'); +var sys = require('util'); + +var FRAME_NO = 0; +var FRAME_LO = 1; +var FRAME_HI = 2; + +// Values for readyState as per the W3C spec +var CONNECTING = 0; +var OPEN = 1; +var CLOSING = 2; +var CLOSED = 3; + +var debugLevel = parseInt(process.env.NODE_DEBUG, 16); +var debug = (debugLevel & 0x4) ? + function() { sys.error.apply(this, arguments); } : + function() { }; + +// Generate a Sec-WebSocket-* value +var createSecretKey = function() { + // How many spaces will we be inserting? + var numSpaces = 1 + Math.floor(Math.random() * 12); + assert.ok(1 <= numSpaces && numSpaces <= 12); + + // What is the numerical value of our key? + var keyVal = (Math.floor( + Math.random() * (4294967295 / numSpaces) + ) * numSpaces); + + // Our string starts with a string representation of our key + var s = keyVal.toString(); + + // Insert 'numChars' worth of noise in the character ranges + // [0x21, 0x2f] (14 characters) and [0x3a, 0x7e] (68 characters) + var numChars = 1 + Math.floor(Math.random() * 12); + assert.ok(1 <= numChars && numChars <= 12); + + for (var i = 0; i < numChars; i++) { + var pos = Math.floor(Math.random() * s.length + 1); + + var c = Math.floor(Math.random() * (14 + 68)); + c = (c <= 14) ? + String.fromCharCode(c + 0x21) : + String.fromCharCode((c - 14) + 0x3a); + + s = s.substring(0, pos) + c + s.substring(pos, s.length); + } + + // We shoudln't have any spaces in our value until we insert them + assert.equal(s.indexOf(' '), -1); + + // Insert 'numSpaces' worth of spaces + for (var i = 0; i < numSpaces; i++) { + var pos = Math.floor(Math.random() * (s.length - 1)) + 1; + s = s.substring(0, pos) + ' ' + s.substring(pos, s.length); + } + + assert.notEqual(s.charAt(0), ' '); + assert.notEqual(s.charAt(s.length), ' '); + + return s; +}; + +// Generate a challenge sequence +var createChallenge = function() { + var c = ''; + for (var i = 0; i < 8; i++) { + c += String.fromCharCode(Math.floor(Math.random() * 255)); + } + + return c; +}; + +// Get the value of a secret key string +// +// This strips non-digit values and divides the result by the number of +// spaces found. +var secretKeyValue = function(sk) { + var ns = 0; + var v = 0; + + for (var i = 0; i < sk.length; i++) { + var cc = sk.charCodeAt(i); + + if (cc == 0x20) { + ns++; + } else if (0x30 <= cc && cc <= 0x39) { + v = v * 10 + cc - 0x30; + } + } + + return Math.floor(v / ns); +} + +// Get the to-be-hashed value of a secret key string +// +// This takes the result of secretKeyValue() and encodes it in a big-endian +// byte string +var secretKeyHashValue = function(sk) { + var skv = secretKeyValue(sk); + + var hv = ''; + hv += String.fromCharCode((skv >> 24) & 0xff); + hv += String.fromCharCode((skv >> 16) & 0xff); + hv += String.fromCharCode((skv >> 8) & 0xff); + hv += String.fromCharCode((skv >> 0) & 0xff); + + return hv; +}; + +// Compute the secret key signature based on two secret key strings and some +// handshaking data. +var computeSecretKeySignature = function(s1, s2, hs) { + assert.equal(hs.length, 8); + + var hash = crypto.createHash('md5'); + + hash.update(secretKeyHashValue(s1)); + hash.update(secretKeyHashValue(s2)); + hash.update(hs); + + return hash.digest('binary'); +}; + +// Return a hex representation of the given binary string; used for debugging +var str2hex = function(str) { + var hexChars = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' + ]; + + var out = ''; + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i); + out += hexChars[(c & 0xf0) >>> 4]; + out += hexChars[c & 0x0f]; + out += ' '; + } + + return out.trim(); +}; + +// Get the scheme for a URL, undefined if none is found +var getUrlScheme = function(url) { + var i = url.indexOf(':'); + if (i == -1) { + return undefined; + } + + return url.substring(0, i); +}; + +// Set a constant on the given object +var setConstant = function(obj, name, value) { + Object.defineProperty(obj, name, { + get : function() { + return value; + } + }); +}; + +// WebSocket object +// +// This is intended to conform (mostly) to http://dev.w3.org/html5/websockets/ +// +// N.B. Arguments are parsed in the anonymous function at the bottom of the +// constructor. +var WebSocket = function(url, proto, opts) { + events.EventEmitter.call(this); + + // Retain a reference to our object + var self = this; + + // State of our end of the connection + var readyState = CONNECTING; + + // Whether or not the server has sent a close handshake + var serverClosed = false; + + // Our underlying net.Stream instance + var stream = undefined; + + opts = opts || { + origin : 'http://www.example.com' + }; + + // Frame parsing functions + // + // These read data from the given buffer starting at the given offset, + // looking for the end of the current frame. If found, the current frame is + // emitted and the function returns. Only a single frame is processed at a + // time. + // + // The number of bytes read to complete a frame is returned, which the + // caller is to use to advance along its buffer. If 0 is returned, no + // completed frame bytes were found, and the caller should probably enqueue + // the buffer as a continuation of the current message. If a complete frame + // is read, the function is responsible for resting 'frameType'. + + // Framing data + var frameType = FRAME_NO; + var bufs = []; + var bufsBytes = 0; + + // Frame-parsing functions + var frameFuncs = [ + // FRAME_NO + function(buf, off) { + if (buf[off] & 0x80) { + frameType = FRAME_HI; + } else { + frameType = FRAME_LO; + } + + return 1; + }, + + // FRAME_LO + function(buf, off) { + debug('frame_lo(' + sys.inspect(buf) + ', ' + off + ')'); + + // Find the first instance of 0xff, our terminating byte + for (var i = off; i < buf.length && buf[i] != 0xff; i++) + ; + + // We didn't find a terminating byte + if (i >= buf.length) { + return 0; + } + + // We found a terminating byte; collect all bytes into a single buffer + // and emit it + var mb = null; + if (bufs.length == 0) { + mb = buf.slice(off, i); + } else { + mb = new buffer.Buffer(bufsBytes + i); + + var mbOff = 0; + bufs.forEach(function(b) { + b.copy(mb, mbOff, 0, b.length); + mbOff += b.length; + }); + + assert.equal(mbOff, bufsBytes); + + // Don't call Buffer.copy() if we're coping 0 bytes. Rather + // than being a no-op, this will trigger a range violation on + // the destination. + if (i > 0) { + buf.copy(mb, mbOff, off, i); + } + + // We consumed all of the buffers that we'd been saving; clear + // things out + bufs = []; + bufsBytes = 0; + } + + process.nextTick(function() { + var b = mb; + return function() { + var m = b.toString('utf8'); + + self.emit('data', b); + self.emit('message', m); // wss compat + + if (self.onmessage) { + self.onmessage({data: m}); + } + }; + }()); + + frameType = FRAME_NO; + return i - off + 1; + }, + + // FRAME_HI + function(buf, off) { + debug('frame_hi(' + sys.inspect(buf) + ', ' + off + ')'); + + if (buf[off] !== 0) { + throw new Error('High-byte framing not supported.'); + } + + serverClosed = true; + return 1; + } + ]; + + // Handle data coming from our socket + var dataListener = function(buf) { + if (buf.length <= 0 || serverClosed) { + return; + } + + debug('dataListener(' + sys.inspect(buf) + ')'); + + var off = 0; + var consumed = 0; + + do { + if (frameType < 0 || frameFuncs.length <= frameType) { + throw new Error('Unexpected frame type: ' + frameType); + } + + assert.equal(bufs.length === 0, bufsBytes === 0); + assert.ok(off < buf.length); + + consumed = frameFuncs[frameType](buf, off); + off += consumed; + } while (!serverClosed && consumed > 0 && off < buf.length); + + if (serverClosed) { + serverCloseHandler(); + } + + if (consumed == 0) { + bufs.push(buf.slice(off, buf.length)); + bufsBytes += buf.length - off; + } + }; + + // Handle incoming file descriptors + var fdListener = function(fd) { + self.emit('fd', fd); + }; + + // Handle errors from any source (HTTP client, stream, etc) + var errorListener = function(e) { + process.nextTick(function() { + self.emit('wserror', e); + + if (self.onerror) { + self.onerror(e); + } + }); + }; + + // Finish the closing process; destroy the socket and tell the application + // that we've closed. + var finishClose = self.finishClose = function() { + readyState = CLOSED; + if (stream) { + stream.end(); + stream.destroy(); + stream = undefined; + } + + process.nextTick(function() { + self.emit('close'); + if (self.onclose) { + self.onclose(); + } + }); + }; + + // Send a close frame to the server + var sendClose = function() { + assert.equal(OPEN, readyState); + + readyState = CLOSING; + stream.write('\xff\x00', 'binary'); + }; + + // Handle a close packet sent from the server + var serverCloseHandler = function() { + assert.ok(serverClosed); + assert.ok(readyState === OPEN || readyState === CLOSING); + + bufs = []; + bufsBytes = 0; + + // Handle state transitions asynchronously so that we don't change + // readyState before the application has had a chance to process data + // events which are already in the delivery pipeline. For example, a + // 'data' event could be delivered with a readyState of CLOSING if we + // received both frames in the same packet. + process.nextTick(function() { + if (readyState === OPEN) { + sendClose(); + } + + finishClose(); + }); + }; + + // External API + self.close = function(timeout) { + if (readyState === CONNECTING) { + // If we're still in the process of connecting, the server is not + // in a position to understand our close frame. Just nuke the + // connection and call it a day. + finishClose(); + } else if (readyState === OPEN) { + sendClose(); + + if (timeout) { + setTimeout(finishClose, timeout * 1000); + } + } + }; + + self.send = function(str, fd) { + if (readyState != OPEN) { + return; + } + + stream.write('\x00', 'binary'); + stream.write(str, 'utf8', fd); + stream.write('\xff', 'binary'); + }; + + // wss compat + self.write = self.send; + + setConstant(self, 'url', url); + + Object.defineProperty(self, 'readyState', { + get : function() { + return readyState; + } + }); + + // Connect and perform handshaking with the server + (function() { + // Parse constructor arguments + if (!url) { + throw new Error('Url and must be specified.'); + } + + // Secrets used for handshaking + var key1 = createSecretKey(); + var key2 = createSecretKey(); + var challenge = createChallenge(); + + debug( + 'key1=\'' + str2hex(key1) + '\'; ' + + 'key2=\'' + str2hex(key2) + '\'; ' + + 'challenge=\'' + str2hex(challenge) + '\'' + ); + + var httpHeaders = { + 'Connection' : 'Upgrade', + 'Upgrade' : 'WebSocket', + 'Sec-WebSocket-Key1' : key1, + 'Sec-WebSocket-Key2' : key2 + }; + if (opts.origin) { + httpHeaders['Origin'] = opts.origin; + } + if (proto) { + httpHeaders['Sec-WebSocket-Protocol'] = proto; + } + + var httpPath = '/'; + + // Create the HTTP client that we'll use for handshaking. We'll cannabalize + // its socket via the 'upgrade' event and leave it to rot. + // + // N.B. The ws+unix:// scheme makes use of the implementation detail + // that http.Client passes its constructor arguments through, + // un-inspected to net.Stream.connect(). The latter accepts a + // string as its first argument to connect to a UNIX socket. + var opt = {}; + var agent = null; + switch (getUrlScheme(url)) { + case 'ws': + var u = urllib.parse(url); + agent = new http.Agent({ + host: u.hostname, + port: u.port || 80 + }); + opt.agent = agent; + opt.host = u.hostname; + opt.port = u.port || 80; + opt.path = (u.pathname || '/') + (u.search || ''); + opt.headers = httpHeaders; + break; + + case 'ws+unix': + var sockPath = url.substring('ws+unix://'.length, url.length); + var u = urllib.parse(url); + agent = new http.Agent({ + host: 'localhost', + port: sockPath + }); + opt.agent = agent; + opt.host = 'localhost'; + opt.path = sockPath; + opt.headers = httpHeaders; + break; + + default: + throw new Error('Invalid URL scheme \'' + urlScheme + '\' specified.'); + } + + var httpReq = http.request(opt, function() { }); + var upgradeHandler = (function() { + var data = undefined; + + return function(req, s, head) { + req.socket.setNoDelay(true); + stream = s; + + if (readyState == CLOSED) { + stream.end(); + stream.destroy(); + stream = undefined; + return; + } + + stream.on('data', function(d) { + if (d.length <= 0) { + return; + } + + if (!data) { + data = d; + } else { + var data2 = new buffer.Buffer(data.length + d.length); + + data.copy(data2, 0, 0, data.length); + d.copy(data2, data.length, 0, d.length); + + data = data2; + } + + if (data.length >= 16) { + var expected = computeSecretKeySignature(key1, key2, challenge); + var actual = data.slice(0, 16).toString('binary'); + + // Handshaking fails; we're donezo + if (actual != expected) { + debug( + 'expected=\'' + str2hex(expected) + '\'; ' + + 'actual=\'' + str2hex(actual) + '\'' + ); + + process.nextTick(function() { + // N.B. Emit 'wserror' here, as 'error' is a reserved word in the + // EventEmitter world, and gets thrown. + self.emit( + 'wserror', + new Error('Invalid handshake from server:' + + 'expected \'' + str2hex(expected) + '\', ' + + 'actual \'' + str2hex(actual) + '\'' + ) + ); + + if (self.onerror) { + self.onerror(); + } + + finishClose(); + }); + } + + // Un-register our data handler and add the one to be used + // for the normal, non-handshaking case. If we have extra + // data left over, manually fire off the handler on + // whatever remains. + // + // XXX: This is lame. We should only remove the listeners + // that we added. + httpReq.removeAllListeners('upgrade'); + stream.removeAllListeners('data'); + stream.on('data', dataListener); + + readyState = OPEN; + + process.nextTick(function() { + self.emit('open'); + + if (self.onopen) { + self.onopen(); + } + }); + + // Consume any leftover data + if (data.length > 16) { + stream.emit('data', data.slice(16, data.length)); + } + } + }); + stream.on('fd', fdListener); + stream.on('error', errorListener); + stream.on('close', function() { + errorListener(new Error('Stream closed unexpectedly.')); + }); + + stream.emit('data', head); + }; + })(); + agent.on('upgrade', upgradeHandler); // node v0.4 + httpReq.on('upgrade', upgradeHandler); // node v0.5+ + + httpReq.write(challenge, 'binary'); + httpReq.end(); + })(); +}; +sys.inherits(WebSocket, events.EventEmitter); +exports.WebSocket = WebSocket; + +// Add some constants to the WebSocket object +setConstant(WebSocket.prototype, 'CONNECTING', CONNECTING); +setConstant(WebSocket.prototype, 'OPEN', OPEN); +setConstant(WebSocket.prototype, 'CLOSING', CLOSING); +setConstant(WebSocket.prototype, 'CLOSED', CLOSED); + +// vim:ts=4 sw=4 et diff --git a/node_modules/socket.io/support/node-websocket-client/package.json b/node_modules/socket.io/support/node-websocket-client/package.json new file mode 100644 index 0000000..c6e221f --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/package.json @@ -0,0 +1,22 @@ +{ + "name" : "websocket-client", + "version" : "1.0.0", + "description" : "An HTML5 Web Sockets client", + "author" : "Peter Griess <pg@std.in>", + "engines" : { + "node" : ">=0.1.98" + }, + "repositories" : [ + { + "type" : "git", + "url" : "http://github.com/pgriess/node-websocket-client.git" + } + ], + "licenses" : [ + { + "type" : "BSD", + "url" : "http://github.com/pgriess/node-websocket-client/blob/master/LICENSE" + } + ], + "main" : "./lib/websocket" +} diff --git a/node_modules/socket.io/support/node-websocket-client/test/test-basic.js b/node_modules/socket.io/support/node-websocket-client/test/test-basic.js new file mode 100644 index 0000000..f010424 --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/test/test-basic.js @@ -0,0 +1,68 @@ +// Verify that we can connect to a WebSocket server, exchange messages, and +// shut down cleanly. + +var assert = require('assert'); +var WebSocket = require('../lib/websocket').WebSocket; +var WebSocketServer = require('websocket-server/ws/server').Server; + +var PORT = 1024 + Math.floor(Math.random() * 4096); +var C_MSG = 'Client test: ' + (Math.random() * 100); +var S_MSG = 'Server test: ' + (Math.random() * 100); + +var serverGotConnection = false; +var clientGotOpen = false; +var clientGotData = false; +var clientGotMessage = false; +var serverGotMessage = false; +var serverGotClose = false; +var clientGotClose = false; + +var wss = new WebSocketServer(); +wss.listen(PORT, 'localhost'); +wss.on('connection', function(c) { + serverGotConnection = true; + + c.on('message', function(m) { + assert.equal(m, C_MSG); + serverGotMessage = true; + + c.close(); + }); + + c.on('close', function() { + serverGotClose = true; + wss.close(); + }); + + c.write(S_MSG); +}); + +var ws = new WebSocket('ws://localhost:' + PORT + '/', 'biff'); +ws.on('open', function() { + clientGotOpen = true; +}); +ws.on('data', function(buf) { + assert.equal(typeof buf, 'object'); + assert.equal(buf.toString('utf8'), S_MSG); + + clientGotData = true; + + ws.send(C_MSG); +}); +ws.onmessage = function(m) { + assert.deepEqual(m, {data : S_MSG}); + clientGotMessage = true; +}; +ws.onclose = function() { + clientGotClose = true; +}; + +process.on('exit', function() { + assert.ok(serverGotConnection); + assert.ok(clientGotOpen); + assert.ok(clientGotData); + assert.ok(clientGotMessage); + assert.ok(serverGotMessage); + assert.ok(serverGotClose); + assert.ok(clientGotClose); +}); diff --git a/node_modules/socket.io/support/node-websocket-client/test/test-client-close.js b/node_modules/socket.io/support/node-websocket-client/test/test-client-close.js new file mode 100644 index 0000000..76fb81f --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/test/test-client-close.js @@ -0,0 +1,43 @@ +// Verify that a connection can be closed gracefully from the client. + +var assert = require('assert'); +var WebSocket = require('../lib/websocket').WebSocket; +var WebSocketServer = require('websocket-server/ws/server').Server; + +var PORT = 1024 + Math.floor(Math.random() * 4096); +var C_MSG = 'Client test: ' + (Math.random() * 100); + +var serverGotClientMessage = false; +var clientGotServerClose = false; +var serverGotClientClose = false; + +var wss = new WebSocketServer(); +wss.listen(PORT, 'localhost'); +wss.on('connection', function(c) { + c.on('message', function(m) { + assert.equal(m, C_MSG); + serverGotClientMessage = true; + }); + c.on('close', function() { + serverGotClientClose = true; + wss.close(); + }); +}); + +var ws = new WebSocket('ws://localhost:' + PORT); +ws.onopen = function() { + ws.send(C_MSG); + + // XXX: Add a timeout here + ws.close(5); +}; +ws.onclose = function() { + assert.equal(ws.CLOSED, ws.readyState); + clientGotServerClose = true; +}; + +process.on('exit', function() { + assert.ok(serverGotClientMessage); + assert.ok(clientGotServerClose); + assert.ok(serverGotClientClose); +}); diff --git a/node_modules/socket.io/support/node-websocket-client/test/test-readonly-attrs.js b/node_modules/socket.io/support/node-websocket-client/test/test-readonly-attrs.js new file mode 100644 index 0000000..de896b3 --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/test/test-readonly-attrs.js @@ -0,0 +1,43 @@ +// Verify that some attributes of a WebSocket object are read-only. + +var assert = require('assert'); +var sys = require('sys'); +var WebSocket = require('../lib/websocket').WebSocket; +var WebSocketServer = require('websocket-server/ws/server').Server; + +var PORT = 1024 + Math.floor(Math.random() * 4096); + +var wss = new WebSocketServer(); +wss.listen(PORT, 'localhost'); +wss.on('connection', function(c) { + c.close(); + wss.close(); +}); +var ws = new WebSocket('ws://localhost:' + PORT + '/', 'biff'); +ws.on('open', function() { + assert.equal(ws.CONNECTING, 0); + try { + ws.CONNECTING = 13; + assert.equal( + ws.CONNECTING, 0, + 'Should not have been able to set read-only CONNECTING attribute' + ); + } catch (e) { + assert.equal(e.type, 'no_setter_in_callback'); + } + + assert.equal(ws.OPEN, 1); + assert.equal(ws.CLOSING, 2); + assert.equal(ws.CLOSED, 3); + + assert.equal(ws.url, 'ws://localhost:' + PORT + '/'); + try { + ws.url = 'foobar'; + assert.equal( + ws.url, 'ws://localhost:' + PORT + '/', + 'Should not have been able to set read-only url attribute' + ); + } catch (e) { + assert.equal(e.type, 'no_setter_in_callback'); + } +}); diff --git a/node_modules/socket.io/support/node-websocket-client/test/test-ready-state.js b/node_modules/socket.io/support/node-websocket-client/test/test-ready-state.js new file mode 100644 index 0000000..8fcbd4c --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/test/test-ready-state.js @@ -0,0 +1,26 @@ +// Verify that readyState transitions are implemented correctly + +var assert = require('assert'); +var WebSocket = require('../lib/websocket').WebSocket; +var WebSocketServer = require('websocket-server/ws/server').Server; + +var PORT = 1024 + Math.floor(Math.random() * 4096); + +var wss = new WebSocketServer(); +wss.listen(PORT, 'localhost'); +wss.on('connection', function(c) { + c.close(); +}); + +var ws = new WebSocket('ws://localhost:' + PORT); +assert.equal(ws.readyState, ws.CONNECTING); +ws.onopen = function() { + assert.equal(ws.readyState, ws.OPEN); + + ws.close(); + assert.ok(ws.readyState == ws.CLOSING); +}; +ws.onclose = function() { + assert.equal(ws.readyState, ws.CLOSED); + wss.close(); +}; diff --git a/node_modules/socket.io/support/node-websocket-client/test/test-server-close.js b/node_modules/socket.io/support/node-websocket-client/test/test-server-close.js new file mode 100644 index 0000000..a286429 --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/test/test-server-close.js @@ -0,0 +1,41 @@ +// Verify that a connection can be closed gracefully from the server. + +var assert = require('assert'); +var WebSocket = require('../lib/websocket').WebSocket; +var WebSocketServer = require('websocket-server/ws/server').Server; + +var PORT = 1024 + Math.floor(Math.random() * 4096); +var S_MSG = 'Server test: ' + (Math.random() * 100); + +var clientGotServerMessage = false; +var clientGotServerClose = false; +var serverGotClientClose = false; + +var wss = new WebSocketServer(); +wss.listen(PORT, 'localhost'); +wss.on('connection', function(c) { + c.on('close', function() { + serverGotClientClose = true; + wss.close(); + }); + + c.write(S_MSG); + c.close(); +}); + +var ws = new WebSocket('ws://localhost:' + PORT); +ws.onmessage = function(m) { + assert.deepEqual(m, {data: S_MSG}); + + clientGotServerMessage = true; +}; +ws.onclose = function() { + assert.equal(ws.CLOSED, ws.readyState); + clientGotServerClose = true; +}; + +process.on('exit', function() { + assert.ok(clientGotServerMessage); + assert.ok(clientGotServerClose); + assert.ok(serverGotClientClose); +}); diff --git a/node_modules/socket.io/support/node-websocket-client/test/test-unix-send-fd.js b/node_modules/socket.io/support/node-websocket-client/test/test-unix-send-fd.js new file mode 100644 index 0000000..8f1c28d --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/test/test-unix-send-fd.js @@ -0,0 +1,63 @@ +// Verify that both sides of the WS connection can both send and receive file +// descriptors. + +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var sys = require('sys'); +var WebSocket = require('../lib/websocket').WebSocket; +var WebSocketServer = require('websocket-server/ws/server').Server; + +var PATH = path.join(__dirname, 'sock.' + process.pid); +var C_MSG = 'Client test: ' + (Math.random() * 100); +var S_MSG = 'Server test: ' + (Math.random() * 100); + +var clientReceivedData = false; +var clientReceivedFD = false; +var serverReceivedData = false; +var serverReceivedFD = false; + +var wss = new WebSocketServer(); +wss.on('listening', function() { + var ws = new WebSocket('ws+unix://' + PATH); + ws.on('data', function(d) { + assert.equal(d.toString('utf8'), S_MSG); + + clientReceivedData = true; + + ws.send(C_MSG, 1); + ws.close(); + }); + ws.on('fd', function(fd) { + assert.ok(fd >= 0); + + clientReceivedFD = true; + }); +}); +wss.on('connection', function(c) { + c.write(S_MSG, 0); + c._req.socket.on('fd', function(fd) { + assert.ok(fd >= 0); + + serverReceivedFD = true; + }); + c.on('message', function(d) { + assert.equal(d, C_MSG); + + serverReceivedData = true; + + wss.close(); + }); +}); +wss.listen(PATH); + +process.on('exit', function() { + assert.ok(clientReceivedFD); + assert.ok(clientReceivedData); + assert.ok(serverReceivedFD); + assert.ok(serverReceivedData); + + try { + fs.unlinkSync(PATH); + } catch (e) { } +}); diff --git a/node_modules/socket.io/support/node-websocket-client/test/test-unix-sockets.js b/node_modules/socket.io/support/node-websocket-client/test/test-unix-sockets.js new file mode 100644 index 0000000..5cbf094 --- /dev/null +++ b/node_modules/socket.io/support/node-websocket-client/test/test-unix-sockets.js @@ -0,0 +1,46 @@ +// Verify that we can connect to a server over UNIX domain sockets. + +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var sys = require('sys'); +var WebSocket = require('../lib/websocket').WebSocket; +var WebSocketServer = require('websocket-server/ws/server').Server; + +var PATH = path.join(__dirname, 'sock.' + process.pid); +var S_MSG = 'Server test: ' + (Math.random() * 100); + +var serverGotConnection = false; +var clientGotOpen = false; +var clientGotData = false; + +var wss = new WebSocketServer(); +wss.on('listening', function() { + var ws = new WebSocket('ws+unix://' + PATH); + ws.on('open', function() { + clientGotOpen = true; + + ws.close(); + }); + ws.on('data', function(d) { + assert.equal(d.toString('utf8'), S_MSG); + clientGotData = true; + }); +}); +wss.on('connection', function(c) { + serverGotConnection = true; + + c.write(S_MSG); + wss.close(); +}); +wss.listen(PATH); + +process.on('exit', function() { + assert.ok(serverGotConnection); + assert.ok(clientGotOpen); + assert.ok(clientGotData); + + try { + fs.unlinkSync(PATH); + } catch(e) { } +}); |
