mirror of
https://github.com/logsol/chuck.js.git
synced 2026-05-11 10:37:34 +00:00
removed node_modules added gitignore
This commit is contained in:
parent
2e864f5293
commit
1d24d98297
526 changed files with 1 additions and 224610 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
||||||
1
node_modules/.bin/r.js
generated
vendored
1
node_modules/.bin/r.js
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
../requirejs/bin/r.js
|
|
||||||
20
node_modules/node-static/LICENSE
generated
vendored
20
node_modules/node-static/LICENSE
generated
vendored
|
|
@ -1,20 +0,0 @@
|
||||||
Copyright (c) 2010 Alexis Sellier
|
|
||||||
|
|
||||||
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 the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE 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.
|
|
||||||
141
node_modules/node-static/README.md
generated
vendored
141
node_modules/node-static/README.md
generated
vendored
|
|
@ -1,141 +0,0 @@
|
||||||
node-static
|
|
||||||
===========
|
|
||||||
|
|
||||||
> a simple, *rfc 2616 compliant* file streaming module for [node](http://nodejs.org)
|
|
||||||
|
|
||||||
node-static has an in-memory file cache, making it highly efficient.
|
|
||||||
node-static understands and supports *conditional GET* and *HEAD* requests.
|
|
||||||
node-static was inspired by some of the other static-file serving modules out there,
|
|
||||||
such as node-paperboy and antinode.
|
|
||||||
|
|
||||||
synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
var static = require('node-static');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create a node-static server instance to serve the './public' folder
|
|
||||||
//
|
|
||||||
var file = new(static.Server)('./public');
|
|
||||||
|
|
||||||
require('http').createServer(function (request, response) {
|
|
||||||
request.addListener('end', function () {
|
|
||||||
//
|
|
||||||
// Serve files!
|
|
||||||
//
|
|
||||||
file.serve(request, response);
|
|
||||||
});
|
|
||||||
}).listen(8080);
|
|
||||||
|
|
||||||
API
|
|
||||||
---
|
|
||||||
|
|
||||||
### Creating a node-static Server #
|
|
||||||
|
|
||||||
Creating a file server instance is as simple as:
|
|
||||||
|
|
||||||
new static.Server();
|
|
||||||
|
|
||||||
This will serve files in the current directory. If you want to serve files in a specific
|
|
||||||
directory, pass it as the first argument:
|
|
||||||
|
|
||||||
new static.Server('./public');
|
|
||||||
|
|
||||||
You can also specify how long the client is supposed to cache the files node-static serves:
|
|
||||||
|
|
||||||
new static.Server('./public', { cache: 3600 });
|
|
||||||
|
|
||||||
This will set the `Cache-Control` header, telling clients to cache the file for an hour.
|
|
||||||
This is the default setting.
|
|
||||||
|
|
||||||
### Serving files under a directory #
|
|
||||||
|
|
||||||
To serve files under a directory, simply call the `serve` method on a `Server` instance, passing it
|
|
||||||
the HTTP request and response object:
|
|
||||||
|
|
||||||
var fileServer = new static.Server('./public');
|
|
||||||
|
|
||||||
require('http').createServer(function (request, response) {
|
|
||||||
request.addListener('end', function () {
|
|
||||||
fileServer.serve(request, response);
|
|
||||||
});
|
|
||||||
}).listen(8080);
|
|
||||||
|
|
||||||
### Serving specific files #
|
|
||||||
|
|
||||||
If you want to serve a specific file, like an error page for example, use the `serveFile` method:
|
|
||||||
|
|
||||||
fileServer.serveFile('/error.html', 500, {}, request, response);
|
|
||||||
|
|
||||||
This will serve the `error.html` file, from under the file root directory, with a `500` status code.
|
|
||||||
For example, you could serve an error page, when the initial request wasn't found:
|
|
||||||
|
|
||||||
require('http').createServer(function (request, response) {
|
|
||||||
request.addListener('end', function () {
|
|
||||||
fileServer.serve(request, response, function (e, res) {
|
|
||||||
if (e && (e.status === 404)) { // If the file wasn't found
|
|
||||||
fileServer.serveFile('/not-found.html', 404, {}, request, response);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).listen(8080);
|
|
||||||
|
|
||||||
More on intercepting errors bellow.
|
|
||||||
|
|
||||||
### Intercepting errors & Listening #
|
|
||||||
|
|
||||||
An optional callback can be passed as last argument, it will be called every time a file
|
|
||||||
has been served successfully, or if there was an error serving the file:
|
|
||||||
|
|
||||||
var fileServer = new static.Server('./public');
|
|
||||||
|
|
||||||
require('http').createServer(function (request, response) {
|
|
||||||
request.addListener('end', function () {
|
|
||||||
fileServer.serve(request, response, function (err, result) {
|
|
||||||
if (err) { // There was an error serving the file
|
|
||||||
sys.error("Error serving " + request.url + " - " + err.message);
|
|
||||||
|
|
||||||
// Respond to the client
|
|
||||||
response.writeHead(err.status, err.headers);
|
|
||||||
response.end();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).listen(8080);
|
|
||||||
|
|
||||||
Note that if you pass a callback, and there is an error serving the file, node-static
|
|
||||||
*will not* respond to the client. This gives you the opportunity to re-route the request,
|
|
||||||
or handle it differently.
|
|
||||||
|
|
||||||
For example, you may want to interpret a request as a static request, but if the file isn't found,
|
|
||||||
send it to an application.
|
|
||||||
|
|
||||||
If you only want to *listen* for errors, you can use *event listeners*:
|
|
||||||
|
|
||||||
fileServer.serve(request, response).addListener('error', function (err) {
|
|
||||||
sys.error("Error serving " + request.url + " - " + err.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
With this method, you don't have to explicitly send the response back, in case of an error.
|
|
||||||
|
|
||||||
### Options when creating an instance of `Server` #
|
|
||||||
|
|
||||||
#### `cache` #
|
|
||||||
|
|
||||||
Sets the `Cache-Control` header.
|
|
||||||
|
|
||||||
example: `{ cache: 7200 }`
|
|
||||||
|
|
||||||
Passing a number will set the cache duration to that number of seconds.
|
|
||||||
Passing `false` will disable the `Cache-Control` header.
|
|
||||||
|
|
||||||
> Defaults to `3600`
|
|
||||||
|
|
||||||
#### `headers` #
|
|
||||||
|
|
||||||
Sets response headers.
|
|
||||||
|
|
||||||
example: `{ 'X-Hello': 'World!' }`
|
|
||||||
|
|
||||||
> defaults to `{}`
|
|
||||||
|
|
||||||
43
node_modules/node-static/benchmark/node-static-0.3.0.txt
generated
vendored
43
node_modules/node-static/benchmark/node-static-0.3.0.txt
generated
vendored
|
|
@ -1,43 +0,0 @@
|
||||||
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
|
|
||||||
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
|
|
||||||
Licensed to The Apache Software Foundation, http://www.apache.org/
|
|
||||||
|
|
||||||
Benchmarking 127.0.0.1 (be patient)
|
|
||||||
|
|
||||||
|
|
||||||
Server Software: node-static/0.3.0
|
|
||||||
Server Hostname: 127.0.0.1
|
|
||||||
Server Port: 8080
|
|
||||||
|
|
||||||
Document Path: /lib/node-static.js
|
|
||||||
Document Length: 6038 bytes
|
|
||||||
|
|
||||||
Concurrency Level: 20
|
|
||||||
Time taken for tests: 2.323 seconds
|
|
||||||
Complete requests: 10000
|
|
||||||
Failed requests: 0
|
|
||||||
Write errors: 0
|
|
||||||
Total transferred: 63190000 bytes
|
|
||||||
HTML transferred: 60380000 bytes
|
|
||||||
Requests per second: 4304.67 [#/sec] (mean)
|
|
||||||
Time per request: 4.646 [ms] (mean)
|
|
||||||
Time per request: 0.232 [ms] (mean, across all concurrent requests)
|
|
||||||
Transfer rate: 26563.66 [Kbytes/sec] received
|
|
||||||
|
|
||||||
Connection Times (ms)
|
|
||||||
min mean[+/-sd] median max
|
|
||||||
Connect: 0 0 0.2 0 3
|
|
||||||
Processing: 1 4 1.4 4 28
|
|
||||||
Waiting: 1 4 1.3 4 18
|
|
||||||
Total: 2 5 1.5 4 28
|
|
||||||
|
|
||||||
Percentage of the requests served within a certain time (ms)
|
|
||||||
50% 4
|
|
||||||
66% 5
|
|
||||||
75% 5
|
|
||||||
80% 5
|
|
||||||
90% 5
|
|
||||||
95% 6
|
|
||||||
98% 8
|
|
||||||
99% 9
|
|
||||||
100% 28 (longest request)
|
|
||||||
25
node_modules/node-static/examples/file-server.js
generated
vendored
25
node_modules/node-static/examples/file-server.js
generated
vendored
|
|
@ -1,25 +0,0 @@
|
||||||
var static = require('../lib/node-static');
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create a node-static server to serve the current directory
|
|
||||||
//
|
|
||||||
var file = new(static.Server)('.', { cache: 7200, headers: {'X-Hello':'World!'} });
|
|
||||||
|
|
||||||
require('http').createServer(function (request, response) {
|
|
||||||
request.addListener('end', function () {
|
|
||||||
//
|
|
||||||
// Serve files!
|
|
||||||
//
|
|
||||||
file.serve(request, response, function (err, res) {
|
|
||||||
if (err) { // An error as occured
|
|
||||||
console.error("> Error serving " + request.url + " - " + err.message);
|
|
||||||
response.writeHead(err.status, err.headers);
|
|
||||||
response.end();
|
|
||||||
} else { // The file was served successfully
|
|
||||||
console.log("> " + request.url + " - " + res.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).listen(8080);
|
|
||||||
|
|
||||||
console.log("> node-static is listening on http://127.0.0.1:8080");
|
|
||||||
252
node_modules/node-static/lib/node-static.js
generated
vendored
252
node_modules/node-static/lib/node-static.js
generated
vendored
|
|
@ -1,252 +0,0 @@
|
||||||
var fs = require('fs'),
|
|
||||||
events = require('events'),
|
|
||||||
buffer = require('buffer'),
|
|
||||||
http = require('http'),
|
|
||||||
url = require('url'),
|
|
||||||
path = require('path');
|
|
||||||
|
|
||||||
this.version = [0, 6, 0];
|
|
||||||
|
|
||||||
var mime = require('./node-static/mime');
|
|
||||||
var util = require('./node-static/util');
|
|
||||||
|
|
||||||
var serverInfo = 'node-static/' + this.version.join('.');
|
|
||||||
|
|
||||||
// In-memory file store
|
|
||||||
this.store = {};
|
|
||||||
this.indexStore = {};
|
|
||||||
|
|
||||||
this.Server = function (root, options) {
|
|
||||||
if (root && (typeof(root) === 'object')) { options = root, root = null }
|
|
||||||
|
|
||||||
this.root = path.resolve(root || '.');
|
|
||||||
this.options = options || {};
|
|
||||||
this.cache = 3600;
|
|
||||||
|
|
||||||
this.defaultHeaders = {};
|
|
||||||
this.options.headers = this.options.headers || {};
|
|
||||||
|
|
||||||
if ('cache' in this.options) {
|
|
||||||
if (typeof(this.options.cache) === 'number') {
|
|
||||||
this.cache = this.options.cache;
|
|
||||||
} else if (! this.options.cache) {
|
|
||||||
this.cache = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.cache !== false) {
|
|
||||||
this.defaultHeaders['Cache-Control'] = 'max-age=' + this.cache;
|
|
||||||
}
|
|
||||||
this.defaultHeaders['Server'] = serverInfo;
|
|
||||||
|
|
||||||
for (var k in this.defaultHeaders) {
|
|
||||||
this.options.headers[k] = this.options.headers[k] ||
|
|
||||||
this.defaultHeaders[k];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Server.prototype.serveDir = function (pathname, req, res, finish) {
|
|
||||||
var htmlIndex = path.join(pathname, 'index.html'),
|
|
||||||
that = this;
|
|
||||||
|
|
||||||
fs.stat(htmlIndex, function (e, stat) {
|
|
||||||
if (!e) {
|
|
||||||
that.respond(null, 200, {}, [htmlIndex], stat, req, res, finish);
|
|
||||||
} else {
|
|
||||||
if (pathname in exports.store) {
|
|
||||||
streamFiles(exports.indexStore[pathname].files);
|
|
||||||
} else {
|
|
||||||
// Stream a directory of files as a single file.
|
|
||||||
fs.readFile(path.join(pathname, 'index.json'), function (e, contents) {
|
|
||||||
if (e) { return finish(404, {}) }
|
|
||||||
var index = JSON.parse(contents);
|
|
||||||
exports.indexStore[pathname] = index;
|
|
||||||
streamFiles(index.files);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function streamFiles(files) {
|
|
||||||
util.mstat(pathname, files, function (e, stat) {
|
|
||||||
that.respond(pathname, 200, {}, files, stat, req, res, finish);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.Server.prototype.serveFile = function (pathname, status, headers, req, res) {
|
|
||||||
var that = this;
|
|
||||||
var promise = new(events.EventEmitter);
|
|
||||||
|
|
||||||
pathname = this.resolve(pathname);
|
|
||||||
|
|
||||||
fs.stat(pathname, function (e, stat) {
|
|
||||||
if (e) {
|
|
||||||
return promise.emit('error', e);
|
|
||||||
}
|
|
||||||
that.respond(null, status, headers, [pathname], stat, req, res, function (status, headers) {
|
|
||||||
that.finish(status, headers, req, res, promise);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return promise;
|
|
||||||
};
|
|
||||||
this.Server.prototype.finish = function (status, headers, req, res, promise, callback) {
|
|
||||||
var result = {
|
|
||||||
status: status,
|
|
||||||
headers: headers,
|
|
||||||
message: http.STATUS_CODES[status]
|
|
||||||
};
|
|
||||||
|
|
||||||
headers['Server'] = serverInfo;
|
|
||||||
|
|
||||||
if (!status || status >= 400) {
|
|
||||||
if (callback) {
|
|
||||||
callback(result);
|
|
||||||
} else {
|
|
||||||
if (promise.listeners('error').length > 0) {
|
|
||||||
promise.emit('error', result);
|
|
||||||
}
|
|
||||||
res.writeHead(status, headers);
|
|
||||||
res.end();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Don't end the request here, if we're streaming;
|
|
||||||
// it's taken care of in `prototype.stream`.
|
|
||||||
if (status !== 200 || req.method !== 'GET') {
|
|
||||||
res.writeHead(status, headers);
|
|
||||||
res.end();
|
|
||||||
}
|
|
||||||
callback && callback(null, result);
|
|
||||||
promise.emit('success', result);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Server.prototype.servePath = function (pathname, status, headers, req, res, finish) {
|
|
||||||
var that = this,
|
|
||||||
promise = new(events.EventEmitter);
|
|
||||||
|
|
||||||
pathname = this.resolve(pathname);
|
|
||||||
|
|
||||||
// Only allow GET and HEAD requests
|
|
||||||
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
||||||
finish(405, { 'Allow': 'GET, HEAD' });
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we're not trying to access a
|
|
||||||
// file outside of the root.
|
|
||||||
if (pathname.indexOf(that.root) === 0) {
|
|
||||||
fs.stat(pathname, function (e, stat) {
|
|
||||||
if (e) {
|
|
||||||
finish(404, {});
|
|
||||||
} else if (stat.isFile()) { // Stream a single file.
|
|
||||||
that.respond(null, status, headers, [pathname], stat, req, res, finish);
|
|
||||||
} else if (stat.isDirectory()) { // Stream a directory of files.
|
|
||||||
that.serveDir(pathname, req, res, finish);
|
|
||||||
} else {
|
|
||||||
finish(400, {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Forbidden
|
|
||||||
finish(403, {});
|
|
||||||
}
|
|
||||||
return promise;
|
|
||||||
};
|
|
||||||
this.Server.prototype.resolve = function (pathname) {
|
|
||||||
return path.resolve(path.join(this.root, pathname));
|
|
||||||
};
|
|
||||||
this.Server.prototype.serve = function (req, res, callback) {
|
|
||||||
var that = this,
|
|
||||||
promise = new(events.EventEmitter);
|
|
||||||
|
|
||||||
var pathname = decodeURI(url.parse(req.url).pathname);
|
|
||||||
|
|
||||||
var finish = function (status, headers) {
|
|
||||||
that.finish(status, headers, req, res, promise, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
process.nextTick(function () {
|
|
||||||
that.servePath(pathname, 200, {}, req, res, finish).on('success', function (result) {
|
|
||||||
promise.emit('success', result);
|
|
||||||
}).on('error', function (err) {
|
|
||||||
promise.emit('error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (! callback) { return promise }
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Server.prototype.respond = function (pathname, status, _headers, files, stat, req, res, finish) {
|
|
||||||
var mtime = Date.parse(stat.mtime),
|
|
||||||
key = pathname || files[0],
|
|
||||||
headers = {};
|
|
||||||
|
|
||||||
// Copy default headers
|
|
||||||
for (var k in this.options.headers) { headers[k] = this.options.headers[k] }
|
|
||||||
|
|
||||||
headers['Etag'] = JSON.stringify([stat.ino, stat.size, mtime].join('-'));
|
|
||||||
headers['Date'] = new(Date)().toUTCString();
|
|
||||||
headers['Last-Modified'] = new(Date)(stat.mtime).toUTCString();
|
|
||||||
|
|
||||||
// Conditional GET
|
|
||||||
// If the "If-Modified-Since" or "If-None-Match" headers
|
|
||||||
// match the conditions, send a 304 Not Modified.
|
|
||||||
if (req.headers['if-none-match'] === headers['Etag'] ||
|
|
||||||
Date.parse(req.headers['if-modified-since']) >= mtime) {
|
|
||||||
finish(304, headers);
|
|
||||||
} else if (req.method === 'HEAD') {
|
|
||||||
finish(200, headers);
|
|
||||||
} else {
|
|
||||||
var fileExtension = path.extname(files[0]).slice(1).toLowerCase();
|
|
||||||
headers['Content-Length'] = stat.size;
|
|
||||||
headers['Content-Type'] = mime.contentTypes[fileExtension] ||
|
|
||||||
'application/octet-stream';
|
|
||||||
|
|
||||||
for (var k in _headers) { headers[k] = _headers[k] }
|
|
||||||
|
|
||||||
res.writeHead(status, headers);
|
|
||||||
|
|
||||||
// If the file was cached and it's not older
|
|
||||||
// than what's on disk, serve the cached version.
|
|
||||||
if (this.cache && (key in exports.store) &&
|
|
||||||
exports.store[key].stat.mtime >= stat.mtime) {
|
|
||||||
res.end(exports.store[key].buffer);
|
|
||||||
finish(status, headers);
|
|
||||||
} else {
|
|
||||||
this.stream(pathname, files, new(buffer.Buffer)(stat.size), res, function (e, buffer) {
|
|
||||||
if (e) { return finish(500, {}) }
|
|
||||||
exports.store[key] = {
|
|
||||||
stat: stat,
|
|
||||||
buffer: buffer,
|
|
||||||
timestamp: Date.now()
|
|
||||||
};
|
|
||||||
finish(status, headers);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Server.prototype.stream = function (pathname, files, buffer, res, callback) {
|
|
||||||
(function streamFile(files, offset) {
|
|
||||||
var file = files.shift();
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
file = file[0] === '/' ? file : path.join(pathname || '.', file);
|
|
||||||
|
|
||||||
// Stream the file to the client
|
|
||||||
fs.createReadStream(file, {
|
|
||||||
flags: 'r',
|
|
||||||
mode: 0666
|
|
||||||
}).on('data', function (chunk) {
|
|
||||||
chunk.copy(buffer, offset);
|
|
||||||
offset += chunk.length;
|
|
||||||
}).on('close', function () {
|
|
||||||
streamFile(files, offset);
|
|
||||||
}).on('error', function (err) {
|
|
||||||
callback(err);
|
|
||||||
console.error(err);
|
|
||||||
}).pipe(res, { end: false });
|
|
||||||
} else {
|
|
||||||
res.end();
|
|
||||||
callback(null, buffer, offset);
|
|
||||||
}
|
|
||||||
})(files.slice(0), 0);
|
|
||||||
};
|
|
||||||
140
node_modules/node-static/lib/node-static/mime.js
generated
vendored
140
node_modules/node-static/lib/node-static/mime.js
generated
vendored
|
|
@ -1,140 +0,0 @@
|
||||||
this.contentTypes = {
|
|
||||||
"aiff": "audio/x-aiff",
|
|
||||||
"arj": "application/x-arj-compressed",
|
|
||||||
"asf": "video/x-ms-asf",
|
|
||||||
"asx": "video/x-ms-asx",
|
|
||||||
"au": "audio/ulaw",
|
|
||||||
"avi": "video/x-msvideo",
|
|
||||||
"bcpio": "application/x-bcpio",
|
|
||||||
"ccad": "application/clariscad",
|
|
||||||
"cod": "application/vnd.rim.cod",
|
|
||||||
"com": "application/x-msdos-program",
|
|
||||||
"cpio": "application/x-cpio",
|
|
||||||
"cpt": "application/mac-compactpro",
|
|
||||||
"csh": "application/x-csh",
|
|
||||||
"css": "text/css",
|
|
||||||
"deb": "application/x-debian-package",
|
|
||||||
"dl": "video/dl",
|
|
||||||
"doc": "application/msword",
|
|
||||||
"drw": "application/drafting",
|
|
||||||
"dvi": "application/x-dvi",
|
|
||||||
"dwg": "application/acad",
|
|
||||||
"dxf": "application/dxf",
|
|
||||||
"dxr": "application/x-director",
|
|
||||||
"etx": "text/x-setext",
|
|
||||||
"ez": "application/andrew-inset",
|
|
||||||
"fli": "video/x-fli",
|
|
||||||
"flv": "video/x-flv",
|
|
||||||
"gif": "image/gif",
|
|
||||||
"gl": "video/gl",
|
|
||||||
"gtar": "application/x-gtar",
|
|
||||||
"gz": "application/x-gzip",
|
|
||||||
"hdf": "application/x-hdf",
|
|
||||||
"hqx": "application/mac-binhex40",
|
|
||||||
"htm": "text/html",
|
|
||||||
"html": "text/html",
|
|
||||||
"ice": "x-conference/x-cooltalk",
|
|
||||||
"ico": "image/x-icon",
|
|
||||||
"ief": "image/ief",
|
|
||||||
"igs": "model/iges",
|
|
||||||
"ips": "application/x-ipscript",
|
|
||||||
"ipx": "application/x-ipix",
|
|
||||||
"jad": "text/vnd.sun.j2me.app-descriptor",
|
|
||||||
"jar": "application/java-archive",
|
|
||||||
"jpeg": "image/jpeg",
|
|
||||||
"jpg": "image/jpeg",
|
|
||||||
"js": "text/javascript",
|
|
||||||
"json": "application/json",
|
|
||||||
"latex": "application/x-latex",
|
|
||||||
"less": "text/css",
|
|
||||||
"lsp": "application/x-lisp",
|
|
||||||
"lzh": "application/octet-stream",
|
|
||||||
"m": "text/plain",
|
|
||||||
"m3u": "audio/x-mpegurl",
|
|
||||||
"man": "application/x-troff-man",
|
|
||||||
"manifest": "text/cache-manifest",
|
|
||||||
"me": "application/x-troff-me",
|
|
||||||
"midi": "audio/midi",
|
|
||||||
"mif": "application/x-mif",
|
|
||||||
"mime": "www/mime",
|
|
||||||
"movie": "video/x-sgi-movie",
|
|
||||||
"mp4": "video/mp4",
|
|
||||||
"mpg": "video/mpeg",
|
|
||||||
"mpga": "audio/mpeg",
|
|
||||||
"ms": "application/x-troff-ms",
|
|
||||||
"nc": "application/x-netcdf",
|
|
||||||
"oda": "application/oda",
|
|
||||||
"ogm": "application/ogg",
|
|
||||||
"pbm": "image/x-portable-bitmap",
|
|
||||||
"pdf": "application/pdf",
|
|
||||||
"pgm": "image/x-portable-graymap",
|
|
||||||
"pgn": "application/x-chess-pgn",
|
|
||||||
"pgp": "application/pgp",
|
|
||||||
"pm": "application/x-perl",
|
|
||||||
"png": "image/png",
|
|
||||||
"pnm": "image/x-portable-anymap",
|
|
||||||
"ppm": "image/x-portable-pixmap",
|
|
||||||
"ppz": "application/vnd.ms-powerpoint",
|
|
||||||
"pre": "application/x-freelance",
|
|
||||||
"prt": "application/pro_eng",
|
|
||||||
"ps": "application/postscript",
|
|
||||||
"qt": "video/quicktime",
|
|
||||||
"ra": "audio/x-realaudio",
|
|
||||||
"rar": "application/x-rar-compressed",
|
|
||||||
"ras": "image/x-cmu-raster",
|
|
||||||
"rgb": "image/x-rgb",
|
|
||||||
"rm": "audio/x-pn-realaudio",
|
|
||||||
"rpm": "audio/x-pn-realaudio-plugin",
|
|
||||||
"rtf": "text/rtf",
|
|
||||||
"rtx": "text/richtext",
|
|
||||||
"scm": "application/x-lotusscreencam",
|
|
||||||
"set": "application/set",
|
|
||||||
"sgml": "text/sgml",
|
|
||||||
"sh": "application/x-sh",
|
|
||||||
"shar": "application/x-shar",
|
|
||||||
"silo": "model/mesh",
|
|
||||||
"sit": "application/x-stuffit",
|
|
||||||
"skt": "application/x-koan",
|
|
||||||
"smil": "application/smil",
|
|
||||||
"snd": "audio/basic",
|
|
||||||
"sol": "application/solids",
|
|
||||||
"spl": "application/x-futuresplash",
|
|
||||||
"src": "application/x-wais-source",
|
|
||||||
"stl": "application/SLA",
|
|
||||||
"stp": "application/STEP",
|
|
||||||
"sv4cpio": "application/x-sv4cpio",
|
|
||||||
"sv4crc": "application/x-sv4crc",
|
|
||||||
"svg": "image/svg+xml",
|
|
||||||
"swf": "application/x-shockwave-flash",
|
|
||||||
"tar": "application/x-tar",
|
|
||||||
"tcl": "application/x-tcl",
|
|
||||||
"tex": "application/x-tex",
|
|
||||||
"texinfo": "application/x-texinfo",
|
|
||||||
"tgz": "application/x-tar-gz",
|
|
||||||
"tiff": "image/tiff",
|
|
||||||
"tr": "application/x-troff",
|
|
||||||
"tsi": "audio/TSP-audio",
|
|
||||||
"tsp": "application/dsptype",
|
|
||||||
"tsv": "text/tab-separated-values",
|
|
||||||
"txt": "text/plain",
|
|
||||||
"unv": "application/i-deas",
|
|
||||||
"ustar": "application/x-ustar",
|
|
||||||
"vcd": "application/x-cdlink",
|
|
||||||
"vda": "application/vda",
|
|
||||||
"vivo": "video/vnd.vivo",
|
|
||||||
"vrm": "x-world/x-vrml",
|
|
||||||
"wav": "audio/x-wav",
|
|
||||||
"wax": "audio/x-ms-wax",
|
|
||||||
"wma": "audio/x-ms-wma",
|
|
||||||
"wmv": "video/x-ms-wmv",
|
|
||||||
"wmx": "video/x-ms-wmx",
|
|
||||||
"wrl": "model/vrml",
|
|
||||||
"wvx": "video/x-ms-wvx",
|
|
||||||
"xbm": "image/x-xbitmap",
|
|
||||||
"xlw": "application/vnd.ms-excel",
|
|
||||||
"xml": "text/xml",
|
|
||||||
"xpm": "image/x-xpixmap",
|
|
||||||
"xwd": "image/x-xwindowdump",
|
|
||||||
"xyz": "chemical/x-pdb",
|
|
||||||
"zip": "application/zip"
|
|
||||||
};
|
|
||||||
30
node_modules/node-static/lib/node-static/util.js
generated
vendored
30
node_modules/node-static/lib/node-static/util.js
generated
vendored
|
|
@ -1,30 +0,0 @@
|
||||||
var fs = require('fs'),
|
|
||||||
path = require('path');
|
|
||||||
|
|
||||||
this.mstat = function (dir, files, callback) {
|
|
||||||
(function mstat(files, stats) {
|
|
||||||
var file = files.shift();
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
fs.stat(path.join(dir, file), function (e, stat) {
|
|
||||||
if (e) {
|
|
||||||
callback(e);
|
|
||||||
} else {
|
|
||||||
mstat(files, stats.concat([stat]));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback(null, {
|
|
||||||
size: stats.reduce(function (total, stat) {
|
|
||||||
return total + stat.size;
|
|
||||||
}, 0),
|
|
||||||
mtime: stats.reduce(function (latest, stat) {
|
|
||||||
return latest > stat.mtime ? latest : stat.mtime;
|
|
||||||
}, 0),
|
|
||||||
ino: stats.reduce(function (total, stat) {
|
|
||||||
return total + stat.ino;
|
|
||||||
}, 0)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})(files.slice(0), []);
|
|
||||||
};
|
|
||||||
43
node_modules/node-static/package.json
generated
vendored
43
node_modules/node-static/package.json
generated
vendored
|
|
@ -1,43 +0,0 @@
|
||||||
{
|
|
||||||
"name": "node-static",
|
|
||||||
"description": "simple, compliant file streaming module for node",
|
|
||||||
"url": "http://github.com/cloudhead/node-static",
|
|
||||||
"keywords": [
|
|
||||||
"http",
|
|
||||||
"static",
|
|
||||||
"file",
|
|
||||||
"server"
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "Alexis Sellier",
|
|
||||||
"email": "self@cloudhead.net"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Pablo Cantero",
|
|
||||||
"email": "pablo@pablocantero.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/cloudhead/node-static.git"
|
|
||||||
},
|
|
||||||
"main": "./lib/node-static",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {},
|
|
||||||
"version": "0.6.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.1"
|
|
||||||
},
|
|
||||||
"_id": "node-static@0.6.0",
|
|
||||||
"devDependencies": {},
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"_engineSupported": true,
|
|
||||||
"_npmVersion": "1.1.9",
|
|
||||||
"_nodeVersion": "v0.6.13",
|
|
||||||
"_defaultsLoaded": true,
|
|
||||||
"dist": {
|
|
||||||
"shasum": "25024f29b5177b69afdbde315fcebdf9563ce072"
|
|
||||||
},
|
|
||||||
"_from": "node-static@>= 0.6.0"
|
|
||||||
}
|
|
||||||
1
node_modules/requirejs/.npmignore
generated
vendored
1
node_modules/requirejs/.npmignore
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
README.md
|
|
||||||
15472
node_modules/requirejs/bin/r.js
generated
vendored
15472
node_modules/requirejs/bin/r.js
generated
vendored
File diff suppressed because one or more lines are too long
37
node_modules/requirejs/package.json
generated
vendored
37
node_modules/requirejs/package.json
generated
vendored
|
|
@ -1,37 +0,0 @@
|
||||||
{
|
|
||||||
"name": "requirejs",
|
|
||||||
"description": "Node adapter for RequireJS, for loading AMD modules. Includes RequireJS optimizer",
|
|
||||||
"version": "2.0.2",
|
|
||||||
"homepage": "http://github.com/jrburke/r.js",
|
|
||||||
"author": {
|
|
||||||
"name": "James Burke",
|
|
||||||
"email": "jrburke@gmail.com",
|
|
||||||
"url": "http://github.com/jrburke"
|
|
||||||
},
|
|
||||||
"licenses": [
|
|
||||||
{
|
|
||||||
"type": "BSD",
|
|
||||||
"url": "https://github.com/jrburke/r.js/blob/master/LICENSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "https://github.com/jrburke/r.js/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"main": "./bin/r.js",
|
|
||||||
"bin": {
|
|
||||||
"r.js": "./bin/r.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
},
|
|
||||||
"_id": "requirejs@2.0.2",
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {},
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"_engineSupported": true,
|
|
||||||
"_npmVersion": "1.1.9",
|
|
||||||
"_nodeVersion": "v0.6.13",
|
|
||||||
"_defaultsLoaded": true,
|
|
||||||
"_from": "requirejs@>= 2.0.2"
|
|
||||||
}
|
|
||||||
2037
node_modules/requirejs/require.js
generated
vendored
2037
node_modules/requirejs/require.js
generated
vendored
File diff suppressed because it is too large
Load diff
3
node_modules/socket.io/.npmignore
generated
vendored
3
node_modules/socket.io/.npmignore
generated
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
support
|
|
||||||
test
|
|
||||||
examples
|
|
||||||
6
node_modules/socket.io/.travis.yml
generated
vendored
6
node_modules/socket.io/.travis.yml
generated
vendored
|
|
@ -1,6 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.6
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
irc: "irc.freenode.org#socket.io"
|
|
||||||
260
node_modules/socket.io/History.md
generated
vendored
260
node_modules/socket.io/History.md
generated
vendored
|
|
@ -1,260 +0,0 @@
|
||||||
|
|
||||||
0.9.6 / 2012-04-17
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed XSS in jsonp-polling.
|
|
||||||
|
|
||||||
0.9.5 / 2012-04-05
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added test for polling and socket close.
|
|
||||||
* Ensure close upon request close.
|
|
||||||
* Fix disconnection reason being lost for polling transports.
|
|
||||||
* Ensure that polling transports work with Connection: close.
|
|
||||||
* Log disconnection reason.
|
|
||||||
|
|
||||||
0.9.4 / 2012-04-01
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Disconnecting from namespace improvement (#795) [DanielBaulig]
|
|
||||||
* Bumped client with polling reconnection loop (#438)
|
|
||||||
|
|
||||||
0.9.3 / 2012-03-28
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fix "Syntax error" on FF Web Console with XHR Polling [mikito]
|
|
||||||
|
|
||||||
0.9.2 / 2012-03-13
|
|
||||||
==================
|
|
||||||
|
|
||||||
* More sensible close `timeout default` (fixes disconnect issue)
|
|
||||||
|
|
||||||
0.9.1-1 / 2012-03-02
|
|
||||||
====================
|
|
||||||
|
|
||||||
* Bumped client with NPM dependency fix.
|
|
||||||
|
|
||||||
0.9.1 / 2012-03-02
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Changed heartbeat timeout and interval defaults (60 and 25 seconds)
|
|
||||||
* Make tests work both on 0.4 and 0.6
|
|
||||||
* Updated client (improvements + bug fixes).
|
|
||||||
|
|
||||||
0.9.0 / 2012-02-26
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Make it possible to use a regexp to match the socket.io resource URL.
|
|
||||||
We need this because we have to prefix the socket.io URL with a variable ID.
|
|
||||||
* Supplemental fix to gavinuhma/authfix, it looks like the same Access-Control-Origin logic is needed in the http and xhr-polling transports
|
|
||||||
* Updated express dep for windows compatibility.
|
|
||||||
* Combine two substr calls into one in decodePayload to improve performance
|
|
||||||
* Minor documentation fix
|
|
||||||
* Minor. Conform to style of other files.
|
|
||||||
* Switching setting to 'match origin protocol'
|
|
||||||
* Revert "Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect()."
|
|
||||||
* Revert "Handle leaked dispatch:[id] subscription."
|
|
||||||
* Merge pull request #667 from dshaw/patch/redis-disconnect
|
|
||||||
* Handle leaked dispatch:[id] subscription.
|
|
||||||
* Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect().
|
|
||||||
* Prevent memory leaking on uncompleted requests & add max post size limitation
|
|
||||||
* Fix for testcase
|
|
||||||
* Set Access-Control-Allow-Credentials true, regardless of cookie
|
|
||||||
* Remove assertvarnish from package as it breaks on 0.6
|
|
||||||
* Correct irc channel
|
|
||||||
* Added proper return after reserved field error
|
|
||||||
* Fixes manager.js failure to close connection after transport error has happened
|
|
||||||
* Added implicit port 80 for origin checks. fixes #638
|
|
||||||
* Fixed bug #432 in 0.8.7
|
|
||||||
* Set Access-Control-Allow-Origin header to origin to enable withCredentials
|
|
||||||
* Adding configuration variable matchOriginProtocol
|
|
||||||
* Fixes location mismatch error in Safari.
|
|
||||||
* Use tty to detect if we should add colors or not by default.
|
|
||||||
* Updated the package location.
|
|
||||||
|
|
||||||
0.8.7 / 2011-11-05
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed memory leaks in closed clients.
|
|
||||||
* Fixed memory leaks in namespaces.
|
|
||||||
* Fixed websocket handling for malformed requests from proxies. [einaros]
|
|
||||||
* Node 0.6 compatibility. [einaros] [3rd-Eden]
|
|
||||||
* Adapted tests and examples.
|
|
||||||
|
|
||||||
0.8.6 / 2011-10-27
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added JSON decoding on jsonp-polling transport.
|
|
||||||
* Fixed README example.
|
|
||||||
* Major speed optimizations [3rd-Eden] [einaros] [visionmedia]
|
|
||||||
* Added decode/encode benchmarks [visionmedia]
|
|
||||||
* Added support for black-listing client sent events.
|
|
||||||
* Fixed logging options, closes #540 [3rd-Eden]
|
|
||||||
* Added vary header for gzip [3rd-Eden]
|
|
||||||
* Properly cleaned up async websocket / flashsocket tests, after patching node-websocket-client
|
|
||||||
* Patched to properly shut down when a finishClose call is made during connection establishment
|
|
||||||
* Added support for socket.io version on url and far-future Expires [3rd-Eden] [getify]
|
|
||||||
* Began IE10 compatibility [einaros] [tbranyen]
|
|
||||||
* Misc WebSocket fixes [einaros]
|
|
||||||
* Added UTF8 to respone headers for htmlfile [3rd-Eden]
|
|
||||||
|
|
||||||
0.8.5 / 2011-10-07
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added websocket draft HyBi-16 support. [einaros]
|
|
||||||
* Fixed websocket continuation bugs. [einaros]
|
|
||||||
* Fixed flashsocket transport name.
|
|
||||||
* Fixed websocket tests.
|
|
||||||
* Ensured `parser#decodePayload` doesn't choke.
|
|
||||||
* Added http referrer verification to manager verifyOrigin.
|
|
||||||
* Added access control for cross domain xhr handshakes [3rd-Eden]
|
|
||||||
* Added support for automatic generation of socket.io files [3rd-Eden]
|
|
||||||
* Added websocket binary support [einaros]
|
|
||||||
* Added gzip support for socket.io.js [3rd-Eden]
|
|
||||||
* Expose socket.transport [3rd-Eden]
|
|
||||||
* Updated client.
|
|
||||||
|
|
||||||
0.8.4 / 2011-09-06
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Client build
|
|
||||||
|
|
||||||
0.8.3 / 2011-09-03
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed `\n` parsing for non-JSON packets (fixes #479).
|
|
||||||
* Fixed parsing of certain unicode characters (fixes #451).
|
|
||||||
* Fixed transport message packet logging.
|
|
||||||
* Fixed emission of `error` event resulting in an uncaught exception if unhandled (fixes #476).
|
|
||||||
* Fixed; allow for falsy values as the configuration value of `log level` (fixes #491).
|
|
||||||
* Fixed repository URI in `package.json`. Fixes #504.
|
|
||||||
* Added text/plain content-type to handshake responses [einaros]
|
|
||||||
* Improved single byte writes [einaros]
|
|
||||||
* Updated socket.io-flashsocket default port from 843 to 10843 [3rd-Eden]
|
|
||||||
* Updated client.
|
|
||||||
|
|
||||||
0.8.2 / 2011-08-29
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Updated client.
|
|
||||||
|
|
||||||
0.8.1 / 2011-08-29
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed utf8 bug in send framing in websocket [einaros]
|
|
||||||
* Fixed typo in docs [Znarkus]
|
|
||||||
* Fixed bug in send framing for over 64kB of data in websocket [einaros]
|
|
||||||
* Corrected ping handling in websocket transport [einaros]
|
|
||||||
|
|
||||||
0.8.0 / 2011-08-28
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Updated to work with two-level websocket versioning. [einaros]
|
|
||||||
* Added hybi07 support. [einaros]
|
|
||||||
* Added hybi10 support. [einaros]
|
|
||||||
* Added http referrer verification to manager.js verifyOrigin. [einaors]
|
|
||||||
|
|
||||||
0.7.11 / 2011-08-27
|
|
||||||
===================
|
|
||||||
|
|
||||||
* Updated socket.io-client.
|
|
||||||
|
|
||||||
0.7.10 / 2011-08-27
|
|
||||||
===================
|
|
||||||
|
|
||||||
* Updated socket.io-client.
|
|
||||||
|
|
||||||
0.7.9 / 2011-08-12
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Updated socket.io-client.
|
|
||||||
* Make sure we only do garbage collection when the server we receive is actually run.
|
|
||||||
|
|
||||||
0.7.8 / 2011-08-08
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Changed; make sure sio#listen passes options to both HTTP server and socket.io manager.
|
|
||||||
* Added docs for sio#listen.
|
|
||||||
* Added options parameter support for Manager constructor.
|
|
||||||
* Added memory leaks tests and test-leaks Makefile task.
|
|
||||||
* Removed auto npm-linking from make test.
|
|
||||||
* Make sure that you can disable heartbeats. [3rd-Eden]
|
|
||||||
* Fixed rooms memory leak [3rd-Eden]
|
|
||||||
* Send response once we got all POST data, not immediately [Pita]
|
|
||||||
* Fixed onLeave behavior with missing clientsk [3rd-Eden]
|
|
||||||
* Prevent duplicate references in rooms.
|
|
||||||
* Added alias for `to` to `in` and `in` to `to`.
|
|
||||||
* Fixed roomClients definition.
|
|
||||||
* Removed dependency on redis for installation without npm [3rd-Eden]
|
|
||||||
* Expose path and querystring in handshakeData [3rd-Eden]
|
|
||||||
|
|
||||||
0.7.7 / 2011-07-12
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed double dispatch handling with emit to closed clients.
|
|
||||||
* Added test for emitting to closed clients to prevent regression.
|
|
||||||
* Fixed race condition in redis test.
|
|
||||||
* Changed Transport#end instrumentation.
|
|
||||||
* Leveraged $emit instead of emit internally.
|
|
||||||
* Made tests faster.
|
|
||||||
* Fixed double disconnect events.
|
|
||||||
* Fixed disconnect logic
|
|
||||||
* Simplified remote events handling in Socket.
|
|
||||||
* Increased testcase timeout.
|
|
||||||
* Fixed unknown room emitting (GH-291). [3rd-Eden]
|
|
||||||
* Fixed `address` in handshakeData. [3rd-Eden]
|
|
||||||
* Removed transports definition in chat example.
|
|
||||||
* Fixed room cleanup
|
|
||||||
* Fixed; make sure the client is cleaned up after booting.
|
|
||||||
* Make sure to mark the client as non-open if the connection is closed.
|
|
||||||
* Removed unneeded `buffer` declarations.
|
|
||||||
* Fixed; make sure to clear socket handlers and subscriptions upon transport close.
|
|
||||||
|
|
||||||
0.7.6 / 2011-06-30
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed general dispatching when a client has closed.
|
|
||||||
|
|
||||||
0.7.5 / 2011-06-30
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed dispatching to clients that are disconnected.
|
|
||||||
|
|
||||||
0.7.4 / 2011-06-30
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed; only clear handlers if they were set. [level09]
|
|
||||||
|
|
||||||
0.7.3 / 2011-06-30
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Exposed handshake data to clients.
|
|
||||||
* Refactored dispatcher interface.
|
|
||||||
* Changed; Moved id generation method into the manager.
|
|
||||||
* Added sub-namespace authorization. [3rd-Eden]
|
|
||||||
* Changed; normalized SocketNamespace local eventing [dvv]
|
|
||||||
* Changed; Use packet.reason or default to 'packet' [3rd-Eden]
|
|
||||||
* Changed console.error to console.log.
|
|
||||||
* Fixed; bind both servers at the same time do that the test never times out.
|
|
||||||
* Added 304 support.
|
|
||||||
* Removed `Transport#name` for abstract interface.
|
|
||||||
* Changed; lazily require http and https module only when needed. [3rd-Eden]
|
|
||||||
|
|
||||||
0.7.2 / 2011-06-22
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Make sure to write a packet (of type `noop`) when closing a poll.
|
|
||||||
This solves a problem with cross-domain requests being flagged as aborted and
|
|
||||||
reconnection being triggered.
|
|
||||||
* Added `noop` message type.
|
|
||||||
|
|
||||||
0.7.1 / 2011-06-21
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed cross-domain XHR.
|
|
||||||
* Added CORS test to xhr-polling suite.
|
|
||||||
|
|
||||||
0.7.0 / 2010-06-21
|
|
||||||
==================
|
|
||||||
|
|
||||||
* http://socket.io/announcement.html
|
|
||||||
31
node_modules/socket.io/Makefile
generated
vendored
31
node_modules/socket.io/Makefile
generated
vendored
|
|
@ -1,31 +0,0 @@
|
||||||
|
|
||||||
ALL_TESTS = $(shell find test/ -name '*.test.js')
|
|
||||||
ALL_BENCH = $(shell find benchmarks -name '*.bench.js')
|
|
||||||
|
|
||||||
run-tests:
|
|
||||||
@./node_modules/.bin/expresso \
|
|
||||||
-t 3000 \
|
|
||||||
-I support \
|
|
||||||
--serial \
|
|
||||||
$(TESTFLAGS) \
|
|
||||||
$(TESTS)
|
|
||||||
|
|
||||||
test:
|
|
||||||
@$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests
|
|
||||||
|
|
||||||
test-cov:
|
|
||||||
@TESTFLAGS=--cov $(MAKE) test
|
|
||||||
|
|
||||||
test-leaks:
|
|
||||||
@ls test/leaks/* | xargs node --expose_debug_as=debug --expose_gc
|
|
||||||
|
|
||||||
run-bench:
|
|
||||||
@node $(PROFILEFLAGS) benchmarks/runner.js
|
|
||||||
|
|
||||||
bench:
|
|
||||||
@$(MAKE) BENCHMARKS="$(ALL_BENCH)" run-bench
|
|
||||||
|
|
||||||
profile:
|
|
||||||
@PROFILEFLAGS='--prof --trace-opt --trace-bailout --trace-deopt' $(MAKE) bench
|
|
||||||
|
|
||||||
.PHONY: test bench profile
|
|
||||||
345
node_modules/socket.io/Readme.md
generated
vendored
345
node_modules/socket.io/Readme.md
generated
vendored
|
|
@ -1,345 +0,0 @@
|
||||||
# Socket.IO
|
|
||||||
|
|
||||||
Socket.IO is a Node.JS project that makes WebSockets and realtime possible in
|
|
||||||
all browsers. It also enhances WebSockets by providing built-in multiplexing,
|
|
||||||
horizontal scalability, automatic JSON encoding/decoding, and more.
|
|
||||||
|
|
||||||
## How to Install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install socket.io
|
|
||||||
```
|
|
||||||
|
|
||||||
## How to use
|
|
||||||
|
|
||||||
First, require `socket.io`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io');
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, attach it to a HTTP/HTTPS server. If you're using the fantastic `express`
|
|
||||||
web framework:
|
|
||||||
|
|
||||||
```js
|
|
||||||
var app = express.createServer()
|
|
||||||
, io = io.listen(app);
|
|
||||||
|
|
||||||
app.listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.emit('news', { hello: 'world' });
|
|
||||||
socket.on('my other event', function (data) {
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, load it from the client side code:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script src="/socket.io/socket.io.js"></script>
|
|
||||||
<script>
|
|
||||||
var socket = io.connect('http://localhost');
|
|
||||||
socket.on('news', function (data) {
|
|
||||||
console.log(data);
|
|
||||||
socket.emit('my other event', { my: 'data' });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
For more thorough examples, look at the `examples/` directory.
|
|
||||||
|
|
||||||
## Short recipes
|
|
||||||
|
|
||||||
### Sending and receiving events.
|
|
||||||
|
|
||||||
Socket.IO allows you to emit and receive custom events.
|
|
||||||
Besides `connect`, `message` and `disconnect`, you can emit custom events:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// note, io.listen(<port>) will create a http server for you
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
io.sockets.emit('this', { will: 'be received by everyone' });
|
|
||||||
|
|
||||||
socket.on('private message', function (from, msg) {
|
|
||||||
console.log('I received a private message by ', from, ' saying ', msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('disconnect', function () {
|
|
||||||
io.sockets.emit('user disconnected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Storing data associated to a client
|
|
||||||
|
|
||||||
Sometimes it's necessary to store data associated with a client that's
|
|
||||||
necessary for the duration of the session.
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.on('set nickname', function (name) {
|
|
||||||
socket.set('nickname', name, function () { socket.emit('ready'); });
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('msg', function () {
|
|
||||||
socket.get('nickname', function (err, name) {
|
|
||||||
console.log('Chat message by ', name);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Client side
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script>
|
|
||||||
var socket = io.connect('http://localhost');
|
|
||||||
|
|
||||||
socket.on('connect', function () {
|
|
||||||
socket.emit('set nickname', confirm('What is your nickname?'));
|
|
||||||
socket.on('ready', function () {
|
|
||||||
console.log('Connected !');
|
|
||||||
socket.emit('msg', confirm('What is your message?'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Restricting yourself to a namespace
|
|
||||||
|
|
||||||
If you have control over all the messages and events emitted for a particular
|
|
||||||
application, using the default `/` namespace works.
|
|
||||||
|
|
||||||
If you want to leverage 3rd-party code, or produce code to share with others,
|
|
||||||
socket.io provides a way of namespacing a `socket`.
|
|
||||||
|
|
||||||
This has the benefit of `multiplexing` a single connection. Instead of
|
|
||||||
socket.io using two `WebSocket` connections, it'll use one.
|
|
||||||
|
|
||||||
The following example defines a socket that listens on '/chat' and one for
|
|
||||||
'/news':
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
var chat = io
|
|
||||||
.of('/chat')
|
|
||||||
.on('connection', function (socket) {
|
|
||||||
socket.emit('a message', { that: 'only', '/chat': 'will get' });
|
|
||||||
chat.emit('a message', { everyone: 'in', '/chat': 'will get' });
|
|
||||||
});
|
|
||||||
|
|
||||||
var news = io
|
|
||||||
.of('/news');
|
|
||||||
.on('connection', function (socket) {
|
|
||||||
socket.emit('item', { news: 'item' });
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Client side:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script>
|
|
||||||
var chat = io.connect('http://localhost/chat')
|
|
||||||
, news = io.connect('http://localhost/news');
|
|
||||||
|
|
||||||
chat.on('connect', function () {
|
|
||||||
chat.emit('hi!');
|
|
||||||
});
|
|
||||||
|
|
||||||
news.on('news', function () {
|
|
||||||
news.emit('woot');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sending volatile messages.
|
|
||||||
|
|
||||||
Sometimes certain messages can be dropped. Let's say you have an app that
|
|
||||||
shows realtime tweets for the keyword `bieber`.
|
|
||||||
|
|
||||||
If a certain client is not ready to receive messages (because of network slowness
|
|
||||||
or other issues, or because he's connected through long polling and is in the
|
|
||||||
middle of a request-response cycle), if he doesn't receive ALL the tweets related
|
|
||||||
to bieber your application won't suffer.
|
|
||||||
|
|
||||||
In that case, you might want to send those messages as volatile messages.
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
var tweets = setInterval(function () {
|
|
||||||
getBieberTweet(function (tweet) {
|
|
||||||
socket.volatile.emit('bieber tweet', tweet);
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
socket.on('disconnect', function () {
|
|
||||||
clearInterval(tweets);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Client side
|
|
||||||
|
|
||||||
In the client side, messages are received the same way whether they're volatile
|
|
||||||
or not.
|
|
||||||
|
|
||||||
### Getting acknowledgements
|
|
||||||
|
|
||||||
Sometimes, you might want to get a callback when the client confirmed the message
|
|
||||||
reception.
|
|
||||||
|
|
||||||
To do this, simply pass a function as the last parameter of `.send` or `.emit`.
|
|
||||||
What's more, when you use `.emit`, the acknowledgement is done by you, which
|
|
||||||
means you can also pass data along:
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.on('ferret', function (name, fn) {
|
|
||||||
fn('woot');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Client side
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script>
|
|
||||||
var socket = io.connect(); // TIP: .connect with no args does auto-discovery
|
|
||||||
socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
|
|
||||||
socket.emit('ferret', 'tobi', function (data) {
|
|
||||||
console.log(data); // data will be 'woot'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Broadcasting messages
|
|
||||||
|
|
||||||
To broadcast, simply add a `broadcast` flag to `emit` and `send` method calls.
|
|
||||||
Broadcasting means sending a message to everyone else except for the socket
|
|
||||||
that starts it.
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.broadcast.emit('user connected');
|
|
||||||
socket.broadcast.json.send({ a: 'message' });
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rooms
|
|
||||||
|
|
||||||
Sometimes you want to put certain sockets in the same room, so that it's easy
|
|
||||||
to broadcast to all of them together.
|
|
||||||
|
|
||||||
Think of this as built-in channels for sockets. Sockets `join` and `leave`
|
|
||||||
rooms in each socket.
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.join('justin bieber fans');
|
|
||||||
socket.broadcast.to('justin bieber fans').emit('new fan');
|
|
||||||
io.sockets.in('rammstein fans').emit('new non-fan');
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using it just as a cross-browser WebSocket
|
|
||||||
|
|
||||||
If you just want the WebSocket semantics, you can do that too.
|
|
||||||
Simply leverage `send` and listen on the `message` event:
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.on('message', function () { });
|
|
||||||
socket.on('disconnect', function () { });
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Client side
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script>
|
|
||||||
var socket = io.connect('http://localhost/');
|
|
||||||
socket.on('connect', function () {
|
|
||||||
socket.send('hi');
|
|
||||||
|
|
||||||
socket.on('message', function (msg) {
|
|
||||||
// my msg
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changing configuration
|
|
||||||
|
|
||||||
Configuration in socket.io is TJ-style:
|
|
||||||
|
|
||||||
#### Server side
|
|
||||||
|
|
||||||
```js
|
|
||||||
var io = require('socket.io').listen(80);
|
|
||||||
|
|
||||||
io.configure(function () {
|
|
||||||
io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']);
|
|
||||||
});
|
|
||||||
|
|
||||||
io.configure('development', function () {
|
|
||||||
io.set('transports', ['websocket', 'xhr-polling']);
|
|
||||||
io.enable('log');
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
(The MIT License)
|
|
||||||
|
|
||||||
Copyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com>
|
|
||||||
|
|
||||||
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 the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE 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.
|
|
||||||
64
node_modules/socket.io/benchmarks/decode.bench.js
generated
vendored
64
node_modules/socket.io/benchmarks/decode.bench.js
generated
vendored
|
|
@ -1,64 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var benchmark = require('benchmark')
|
|
||||||
, colors = require('colors')
|
|
||||||
, io = require('../')
|
|
||||||
, parser = io.parser
|
|
||||||
, suite = new benchmark.Suite('Decode packet');
|
|
||||||
|
|
||||||
suite.add('string', function () {
|
|
||||||
parser.decodePacket('4:::"2"');
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('event', function () {
|
|
||||||
parser.decodePacket('5:::{"name":"woot"}');
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('event+ack', function () {
|
|
||||||
parser.decodePacket('5:1+::{"name":"tobi"}');
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('event+data', function () {
|
|
||||||
parser.decodePacket('5:::{"name":"edwald","args":[{"a": "b"},2,"3"]}');
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('heartbeat', function () {
|
|
||||||
parser.decodePacket('2:::');
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('error', function () {
|
|
||||||
parser.decodePacket('7:::2+0');
|
|
||||||
});
|
|
||||||
|
|
||||||
var payload = parser.encodePayload([
|
|
||||||
parser.encodePacket({ type: 'message', data: '5', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: '53d', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
|
||||||
]);
|
|
||||||
|
|
||||||
suite.add('payload', function () {
|
|
||||||
parser.decodePayload(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.on('cycle', function (bench, details) {
|
|
||||||
console.log('\n' + suite.name.grey, details.name.white.bold);
|
|
||||||
console.log([
|
|
||||||
details.hz.toFixed(2).cyan + ' ops/sec'.grey
|
|
||||||
, details.count.toString().white + ' times executed'.grey
|
|
||||||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey
|
|
||||||
,
|
|
||||||
].join(', '.grey));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!module.parent) {
|
|
||||||
suite.run();
|
|
||||||
} else {
|
|
||||||
module.exports = suite;
|
|
||||||
}
|
|
||||||
90
node_modules/socket.io/benchmarks/encode.bench.js
generated
vendored
90
node_modules/socket.io/benchmarks/encode.bench.js
generated
vendored
|
|
@ -1,90 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var benchmark = require('benchmark')
|
|
||||||
, colors = require('colors')
|
|
||||||
, io = require('../')
|
|
||||||
, parser = io.parser
|
|
||||||
, suite = new benchmark.Suite('Encode packet');
|
|
||||||
|
|
||||||
suite.add('string', function () {
|
|
||||||
parser.encodePacket({
|
|
||||||
type: 'json'
|
|
||||||
, endpoint: ''
|
|
||||||
, data: '2'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('event', function () {
|
|
||||||
parser.encodePacket({
|
|
||||||
type: 'event'
|
|
||||||
, name: 'woot'
|
|
||||||
, endpoint: ''
|
|
||||||
, args: []
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('event+ack', function () {
|
|
||||||
parser.encodePacket({
|
|
||||||
type: 'json'
|
|
||||||
, id: 1
|
|
||||||
, ack: 'data'
|
|
||||||
, endpoint: ''
|
|
||||||
, data: { a: 'b' }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('event+data', function () {
|
|
||||||
parser.encodePacket({
|
|
||||||
type: 'event'
|
|
||||||
, name: 'edwald'
|
|
||||||
, endpoint: ''
|
|
||||||
, args: [{a: 'b'}, 2, '3']
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('heartbeat', function () {
|
|
||||||
parser.encodePacket({
|
|
||||||
type: 'heartbeat'
|
|
||||||
, endpoint: ''
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.add('error', function () {
|
|
||||||
parser.encodePacket({
|
|
||||||
type: 'error'
|
|
||||||
, reason: 'unauthorized'
|
|
||||||
, advice: 'reconnect'
|
|
||||||
, endpoint: ''
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
suite.add('payload', function () {
|
|
||||||
parser.encodePayload([
|
|
||||||
parser.encodePacket({ type: 'message', data: '5', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: '53d', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' })
|
|
||||||
, parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' })
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.on('cycle', function (bench, details) {
|
|
||||||
console.log('\n' + suite.name.grey, details.name.white.bold);
|
|
||||||
console.log([
|
|
||||||
details.hz.toFixed(2).cyan + ' ops/sec'.grey
|
|
||||||
, details.count.toString().white + ' times executed'.grey
|
|
||||||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey
|
|
||||||
,
|
|
||||||
].join(', '.grey));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!module.parent) {
|
|
||||||
suite.run();
|
|
||||||
} else {
|
|
||||||
module.exports = suite;
|
|
||||||
}
|
|
||||||
55
node_modules/socket.io/benchmarks/runner.js
generated
vendored
55
node_modules/socket.io/benchmarks/runner.js
generated
vendored
|
|
@ -1,55 +0,0 @@
|
||||||
/**
|
|
||||||
* Benchmark runner dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var colors = require('colors')
|
|
||||||
, path = require('path');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all the benchmarks
|
|
||||||
*/
|
|
||||||
|
|
||||||
var benchmarks_files = process.env.BENCHMARKS.split(' ')
|
|
||||||
, all = [].concat(benchmarks_files)
|
|
||||||
, first = all.shift()
|
|
||||||
, benchmarks = {};
|
|
||||||
|
|
||||||
// find the benchmarks and load them all in our obj
|
|
||||||
benchmarks_files.forEach(function (file) {
|
|
||||||
benchmarks[file] = require(path.join(__dirname, '..', file));
|
|
||||||
});
|
|
||||||
|
|
||||||
// setup the complete listeners
|
|
||||||
benchmarks_files.forEach(function (file) {
|
|
||||||
var benchmark = benchmarks[file]
|
|
||||||
, next_file = all.shift()
|
|
||||||
, next = benchmarks[next_file];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a oncomplete function for the tests, either we are done or we
|
|
||||||
* have more benchmarks to process.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function complete () {
|
|
||||||
if (!next) {
|
|
||||||
console.log(
|
|
||||||
'\n\nBenchmark completed in'.grey
|
|
||||||
, (Date.now() - start).toString().green + ' ms'.grey
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.log('\nStarting benchmark '.grey + next_file.yellow);
|
|
||||||
next.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// attach the listener
|
|
||||||
benchmark.on('complete', complete);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the benchmark
|
|
||||||
*/
|
|
||||||
|
|
||||||
var start = Date.now();
|
|
||||||
console.log('Starting benchmark '.grey + first.yellow);
|
|
||||||
benchmarks[first].run();
|
|
||||||
80
node_modules/socket.io/examples/chat/app.js
generated
vendored
80
node_modules/socket.io/examples/chat/app.js
generated
vendored
|
|
@ -1,80 +0,0 @@
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var express = require('express')
|
|
||||||
, stylus = require('stylus')
|
|
||||||
, nib = require('nib')
|
|
||||||
, sio = require('../../lib/socket.io');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var app = express.createServer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.configure(function () {
|
|
||||||
app.use(stylus.middleware({ src: __dirname + '/public', compile: compile }));
|
|
||||||
app.use(express.static(__dirname + '/public'));
|
|
||||||
app.set('views', __dirname);
|
|
||||||
app.set('view engine', 'jade');
|
|
||||||
|
|
||||||
function compile (str, path) {
|
|
||||||
return stylus(str)
|
|
||||||
.set('filename', path)
|
|
||||||
.use(nib());
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App routes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.get('/', function (req, res) {
|
|
||||||
res.render('index', { layout: false });
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App listen.
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.listen(3000, function () {
|
|
||||||
var addr = app.address();
|
|
||||||
console.log(' app listening on http://' + addr.address + ':' + addr.port);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket.IO server (single process only)
|
|
||||||
*/
|
|
||||||
|
|
||||||
var io = sio.listen(app)
|
|
||||||
, nicknames = {};
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.on('user message', function (msg) {
|
|
||||||
socket.broadcast.emit('user message', socket.nickname, msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('nickname', function (nick, fn) {
|
|
||||||
if (nicknames[nick]) {
|
|
||||||
fn(true);
|
|
||||||
} else {
|
|
||||||
fn(false);
|
|
||||||
nicknames[nick] = socket.nickname = nick;
|
|
||||||
socket.broadcast.emit('announcement', nick + ' connected');
|
|
||||||
io.sockets.emit('nicknames', nicknames);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('disconnect', function () {
|
|
||||||
if (!socket.nickname) return;
|
|
||||||
|
|
||||||
delete nicknames[socket.nickname];
|
|
||||||
socket.broadcast.emit('announcement', socket.nickname + ' disconnected');
|
|
||||||
socket.broadcast.emit('nicknames', nicknames);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
83
node_modules/socket.io/examples/chat/index.jade
generated
vendored
83
node_modules/socket.io/examples/chat/index.jade
generated
vendored
|
|
@ -1,83 +0,0 @@
|
||||||
doctype 5
|
|
||||||
html
|
|
||||||
head
|
|
||||||
link(href='/stylesheets/style.css', rel='stylesheet')
|
|
||||||
script(src='http://code.jquery.com/jquery-1.6.1.min.js')
|
|
||||||
script(src='/socket.io/socket.io.js')
|
|
||||||
script
|
|
||||||
// socket.io specific code
|
|
||||||
var socket = io.connect();
|
|
||||||
|
|
||||||
socket.on('connect', function () {
|
|
||||||
$('#chat').addClass('connected');
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('announcement', function (msg) {
|
|
||||||
$('#lines').append($('<p>').append($('<em>').text(msg)));
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('nicknames', function (nicknames) {
|
|
||||||
$('#nicknames').empty().append($('<span>Online: </span>'));
|
|
||||||
for (var i in nicknames) {
|
|
||||||
$('#nicknames').append($('<b>').text(nicknames[i]));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('user message', message);
|
|
||||||
socket.on('reconnect', function () {
|
|
||||||
$('#lines').remove();
|
|
||||||
message('System', 'Reconnected to the server');
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('reconnecting', function () {
|
|
||||||
message('System', 'Attempting to re-connect to the server');
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('error', function (e) {
|
|
||||||
message('System', e ? e : 'A unknown error occurred');
|
|
||||||
});
|
|
||||||
|
|
||||||
function message (from, msg) {
|
|
||||||
$('#lines').append($('<p>').append($('<b>').text(from), msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
// dom manipulation
|
|
||||||
$(function () {
|
|
||||||
$('#set-nickname').submit(function (ev) {
|
|
||||||
socket.emit('nickname', $('#nick').val(), function (set) {
|
|
||||||
if (!set) {
|
|
||||||
clear();
|
|
||||||
return $('#chat').addClass('nickname-set');
|
|
||||||
}
|
|
||||||
$('#nickname-err').css('visibility', 'visible');
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#send-message').submit(function () {
|
|
||||||
message('me', $('#message').val());
|
|
||||||
socket.emit('user message', $('#message').val());
|
|
||||||
clear();
|
|
||||||
$('#lines').get(0).scrollTop = 10000000;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
function clear () {
|
|
||||||
$('#message').val('').focus();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
body
|
|
||||||
#chat
|
|
||||||
#nickname
|
|
||||||
form.wrap#set-nickname
|
|
||||||
p Please type in your nickname and press enter.
|
|
||||||
input#nick
|
|
||||||
p#nickname-err Nickname already in use
|
|
||||||
#connecting
|
|
||||||
.wrap Connecting to socket.io server
|
|
||||||
#messages
|
|
||||||
#nicknames
|
|
||||||
#lines
|
|
||||||
form#send-message
|
|
||||||
input#message
|
|
||||||
button Send
|
|
||||||
11
node_modules/socket.io/examples/chat/package.json
generated
vendored
11
node_modules/socket.io/examples/chat/package.json
generated
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"name": "chat.io"
|
|
||||||
, "description": "example chat application with socket.io"
|
|
||||||
, "version": "0.0.1"
|
|
||||||
, "dependencies": {
|
|
||||||
"express": "2.5.5"
|
|
||||||
, "jade": "0.16.4"
|
|
||||||
, "stylus": "0.19.0"
|
|
||||||
, "nib": "0.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
96
node_modules/socket.io/examples/chat/public/stylesheets/mixins.styl
generated
vendored
96
node_modules/socket.io/examples/chat/public/stylesheets/mixins.styl
generated
vendored
|
|
@ -1,96 +0,0 @@
|
||||||
border-radius(n)
|
|
||||||
-webkit-border-radius n
|
|
||||||
-moz-border-radius n
|
|
||||||
border-radius n
|
|
||||||
|
|
||||||
// replace str with val
|
|
||||||
|
|
||||||
replace(expr, str, val)
|
|
||||||
expr = clone(expr)
|
|
||||||
for e, i in expr
|
|
||||||
if str == e
|
|
||||||
expr[i] = val
|
|
||||||
expr
|
|
||||||
|
|
||||||
// normalize gradient point (webkit)
|
|
||||||
|
|
||||||
grad-point(pos)
|
|
||||||
if length(pos) == 1
|
|
||||||
return left pos if pos in (top bottom)
|
|
||||||
return pos top if pos in (left right)
|
|
||||||
else if pos[0] in (top bottom)
|
|
||||||
pos[1] pos[0]
|
|
||||||
else
|
|
||||||
pos
|
|
||||||
|
|
||||||
// implicit color stop position
|
|
||||||
|
|
||||||
pos-in-stops(i, stops)
|
|
||||||
len = length(stops)
|
|
||||||
if len - 1 == i
|
|
||||||
100%
|
|
||||||
else if i
|
|
||||||
unit(i / len * 100, '%')
|
|
||||||
else
|
|
||||||
0%
|
|
||||||
|
|
||||||
// normalize color stops
|
|
||||||
// - (color pos) -> (pos color)
|
|
||||||
// - (color) -> (implied-pos color)
|
|
||||||
|
|
||||||
normalize-stops(stops)
|
|
||||||
stops = clone(stops)
|
|
||||||
for stop, i in stops
|
|
||||||
if length(stop) == 1
|
|
||||||
color = stop[0]
|
|
||||||
stop[0] = pos-in-stops(i, stops)
|
|
||||||
stop[1] = color
|
|
||||||
else if typeof(stop[1]) == 'unit'
|
|
||||||
pos = stop[1]
|
|
||||||
stop[1] = stop[0]
|
|
||||||
stop[0] = pos
|
|
||||||
stops
|
|
||||||
|
|
||||||
// join color stops with the given translation function
|
|
||||||
|
|
||||||
join-stops(stops, translate)
|
|
||||||
str = ''
|
|
||||||
len = length(stops)
|
|
||||||
for stop, i in stops
|
|
||||||
str += ', ' if i
|
|
||||||
pos = stop[0]
|
|
||||||
color = stop[1]
|
|
||||||
str += translate(color, pos)
|
|
||||||
unquote(str)
|
|
||||||
|
|
||||||
// webkit translation function
|
|
||||||
|
|
||||||
webkit-stop(color, pos)
|
|
||||||
s('color-stop(%d, %s)', pos / 100, color)
|
|
||||||
|
|
||||||
// mozilla translation function
|
|
||||||
|
|
||||||
moz-stop(color, pos)
|
|
||||||
s('%s %s', color, pos)
|
|
||||||
|
|
||||||
// create a linear gradient with the given start
|
|
||||||
// position, followed by color stops
|
|
||||||
|
|
||||||
linear-gradient(start, stops...)
|
|
||||||
error('color stops required') unless length(stops)
|
|
||||||
prop = current-property[0]
|
|
||||||
val = current-property[1]
|
|
||||||
stops = normalize-stops(stops)
|
|
||||||
|
|
||||||
// webkit
|
|
||||||
end = grad-point(opposite-position(start))
|
|
||||||
webkit = s('-webkit-gradient(linear, %s, %s, %s)', grad-point(start), end, join-stops(stops, webkit-stop))
|
|
||||||
add-property(prop, replace(val, '__CALL__', webkit))
|
|
||||||
|
|
||||||
// moz
|
|
||||||
stops = join-stops(stops, moz-stop)
|
|
||||||
moz = s('-moz-linear-gradient(%s, %s)', start, stops)
|
|
||||||
add-property(prop, replace(val, '__CALL__', moz))
|
|
||||||
|
|
||||||
// literal
|
|
||||||
s('linear-gradient(%s, %s)', start, stops)
|
|
||||||
188
node_modules/socket.io/examples/chat/public/stylesheets/style.css
generated
vendored
188
node_modules/socket.io/examples/chat/public/stylesheets/style.css
generated
vendored
|
|
@ -1,188 +0,0 @@
|
||||||
#chat,
|
|
||||||
#nickname,
|
|
||||||
#messages {
|
|
||||||
width: 600px;
|
|
||||||
}
|
|
||||||
#chat {
|
|
||||||
position: relative;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
#nickname,
|
|
||||||
#connecting {
|
|
||||||
position: absolute;
|
|
||||||
height: 410px;
|
|
||||||
z-index: 100;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
background: #fff;
|
|
||||||
text-align: center;
|
|
||||||
width: 600px;
|
|
||||||
font: 15px Georgia;
|
|
||||||
color: #666;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#nickname .wrap,
|
|
||||||
#connecting .wrap {
|
|
||||||
padding-top: 150px;
|
|
||||||
}
|
|
||||||
#nickname input {
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
#nickname input:focus {
|
|
||||||
border-color: #999;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
#nickname #nickname-err {
|
|
||||||
color: #8b0000;
|
|
||||||
font-size: 12px;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
.connected #connecting {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.nickname-set #nickname {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#messages {
|
|
||||||
height: 380px;
|
|
||||||
background: #eee;
|
|
||||||
}
|
|
||||||
#messages em {
|
|
||||||
text-shadow: 0 1px 0 #fff;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
#messages p {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
font: 12px Helvetica, Arial;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
#messages p b {
|
|
||||||
display: inline-block;
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
#messages p:nth-child(even) {
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
#messages #nicknames {
|
|
||||||
background: #ccc;
|
|
||||||
padding: 2px 4px 4px;
|
|
||||||
font: 11px Helvetica;
|
|
||||||
}
|
|
||||||
#messages #nicknames span {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
#messages #nicknames b {
|
|
||||||
display: inline-block;
|
|
||||||
color: #fff;
|
|
||||||
background: #999;
|
|
||||||
padding: 3px 6px;
|
|
||||||
margin-right: 5px;
|
|
||||||
-webkit-border-radius: 10px;
|
|
||||||
-moz-border-radius: 10px;
|
|
||||||
border-radius: 10px;
|
|
||||||
text-shadow: 0 1px 0 #666;
|
|
||||||
}
|
|
||||||
#messages #lines {
|
|
||||||
height: 355px;
|
|
||||||
overflow: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
#messages #lines::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
}
|
|
||||||
#messages #lines::-webkit-scrollbar-button:start:decrement,
|
|
||||||
#messages #lines ::-webkit-scrollbar-button:end:increment {
|
|
||||||
display: block;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
#messages #lines::-webkit-scrollbar-button:vertical:increment {
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
#messages #lines::-webkit-scrollbar-track-piece {
|
|
||||||
background-color: #fff;
|
|
||||||
-webkit-border-radius: 3px;
|
|
||||||
}
|
|
||||||
#messages #lines::-webkit-scrollbar-thumb:vertical {
|
|
||||||
height: 50px;
|
|
||||||
background-color: #ccc;
|
|
||||||
-webkit-border-radius: 3px;
|
|
||||||
}
|
|
||||||
#messages #lines::-webkit-scrollbar-thumb:horizontal {
|
|
||||||
width: 50px;
|
|
||||||
background-color: #fff;
|
|
||||||
-webkit-border-radius: 3px;
|
|
||||||
}
|
|
||||||
#send-message {
|
|
||||||
background: #fff;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
#send-message input {
|
|
||||||
border: none;
|
|
||||||
height: 30px;
|
|
||||||
padding: 0 10px;
|
|
||||||
line-height: 30px;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 580px;
|
|
||||||
}
|
|
||||||
#send-message input:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
#send-message button {
|
|
||||||
position: absolute;
|
|
||||||
top: 5px;
|
|
||||||
right: 5px;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
margin: 0;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
display: inline-block;
|
|
||||||
text-decoration: none;
|
|
||||||
background: #43a1f7;
|
|
||||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #43a1f7), color-stop(1, #377ad0));
|
|
||||||
background: -webkit-linear-gradient(top, #43a1f7 0%, #377ad0 100%);
|
|
||||||
background: -moz-linear-gradient(top, #43a1f7 0%, #377ad0 100%);
|
|
||||||
background: linear-gradient(top, #43a1f7 0%, #377ad0 100%);
|
|
||||||
border: 1px solid #2e70c4;
|
|
||||||
-webkit-border-radius: 16px;
|
|
||||||
-moz-border-radius: 16px;
|
|
||||||
border-radius: 16px;
|
|
||||||
color: #fff;
|
|
||||||
font-family: "lucida grande", sans-serif;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: normal;
|
|
||||||
line-height: 1;
|
|
||||||
padding: 3px 10px 5px 10px;
|
|
||||||
text-align: center;
|
|
||||||
text-shadow: 0 -1px 1px #2d6dc0;
|
|
||||||
}
|
|
||||||
button:hover,
|
|
||||||
button.hover {
|
|
||||||
background: darker;
|
|
||||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #43a1f7), color-stop(1, #2e70c4));
|
|
||||||
background: -webkit-linear-gradient(top, #43a1f7 0%, #2e70c4 100%);
|
|
||||||
background: -moz-linear-gradient(top, #43a1f7 0%, #2e70c4 100%);
|
|
||||||
background: linear-gradient(top, #43a1f7 0%, #2e70c4 100%);
|
|
||||||
border: 1px solid #2e70c4;
|
|
||||||
cursor: pointer;
|
|
||||||
text-shadow: 0 -1px 1px #2c6bbb;
|
|
||||||
}
|
|
||||||
button:active,
|
|
||||||
button.active {
|
|
||||||
background: #2e70c4;
|
|
||||||
border: 1px solid #2e70c4;
|
|
||||||
border-bottom: 1px solid #2861aa;
|
|
||||||
text-shadow: 0 -1px 1px #2b67b5;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button.focus {
|
|
||||||
outline: none;
|
|
||||||
-webkit-box-shadow: 0 1px 0 0 rgba(255,255,255,0.4), 0 0 4px 0 #377ad0;
|
|
||||||
-moz-box-shadow: 0 1px 0 0 rgba(255,255,255,0.4), 0 0 4px 0 #377ad0;
|
|
||||||
box-shadow: 0 1px 0 0 rgba(255,255,255,0.4), 0 0 4px 0 #377ad0;
|
|
||||||
}
|
|
||||||
118
node_modules/socket.io/examples/chat/public/stylesheets/style.styl
generated
vendored
118
node_modules/socket.io/examples/chat/public/stylesheets/style.styl
generated
vendored
|
|
@ -1,118 +0,0 @@
|
||||||
@import 'nib'
|
|
||||||
|
|
||||||
#chat, #nickname, #messages
|
|
||||||
width 600px
|
|
||||||
|
|
||||||
#chat
|
|
||||||
position relative
|
|
||||||
border 1px solid #ccc
|
|
||||||
|
|
||||||
#nickname, #connecting
|
|
||||||
position absolute
|
|
||||||
height 410px
|
|
||||||
z-index 100
|
|
||||||
left 0
|
|
||||||
top 0
|
|
||||||
background #fff
|
|
||||||
text-align center
|
|
||||||
width 600px
|
|
||||||
font 15px Georgia
|
|
||||||
color #666
|
|
||||||
display block
|
|
||||||
.wrap
|
|
||||||
padding-top 150px
|
|
||||||
|
|
||||||
#nickname
|
|
||||||
input
|
|
||||||
border 1px solid #ccc
|
|
||||||
padding 10px
|
|
||||||
&:focus
|
|
||||||
border-color #999
|
|
||||||
outline 0
|
|
||||||
#nickname-err
|
|
||||||
color darkred
|
|
||||||
font-size 12px
|
|
||||||
visibility hidden
|
|
||||||
|
|
||||||
.connected
|
|
||||||
#connecting
|
|
||||||
display none
|
|
||||||
|
|
||||||
.nickname-set
|
|
||||||
#nickname
|
|
||||||
display none
|
|
||||||
|
|
||||||
#messages
|
|
||||||
height 380px
|
|
||||||
background #eee
|
|
||||||
em
|
|
||||||
text-shadow 0 1px 0 #fff
|
|
||||||
color #999
|
|
||||||
p
|
|
||||||
padding 0
|
|
||||||
margin 0
|
|
||||||
font 12px Helvetica, Arial
|
|
||||||
padding 5px 10px
|
|
||||||
b
|
|
||||||
display inline-block
|
|
||||||
padding-right 10px
|
|
||||||
p:nth-child(even)
|
|
||||||
background #fafafa
|
|
||||||
#nicknames
|
|
||||||
background #ccc
|
|
||||||
padding 2px 4px 4px
|
|
||||||
font 11px Helvetica
|
|
||||||
span
|
|
||||||
color black
|
|
||||||
b
|
|
||||||
display inline-block
|
|
||||||
color #fff
|
|
||||||
background #999
|
|
||||||
padding 3px 6px
|
|
||||||
margin-right 5px
|
|
||||||
border-radius 10px
|
|
||||||
text-shadow 0 1px 0 #666
|
|
||||||
#lines
|
|
||||||
height 355px
|
|
||||||
overflow auto
|
|
||||||
overflow-x hidden
|
|
||||||
overflow-y auto
|
|
||||||
&::-webkit-scrollbar
|
|
||||||
width 6px
|
|
||||||
height 6px
|
|
||||||
&::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:end:increment
|
|
||||||
display block
|
|
||||||
height 10px
|
|
||||||
&::-webkit-scrollbar-button:vertical:increment
|
|
||||||
background-color #fff
|
|
||||||
&::-webkit-scrollbar-track-piece
|
|
||||||
background-color #fff
|
|
||||||
-webkit-border-radius 3px
|
|
||||||
&::-webkit-scrollbar-thumb:vertical
|
|
||||||
height 50px
|
|
||||||
background-color #ccc
|
|
||||||
-webkit-border-radius 3px
|
|
||||||
&::-webkit-scrollbar-thumb:horizontal
|
|
||||||
width 50px
|
|
||||||
background-color #fff
|
|
||||||
-webkit-border-radius 3px
|
|
||||||
|
|
||||||
#send-message
|
|
||||||
background #fff
|
|
||||||
position relative
|
|
||||||
input
|
|
||||||
border none
|
|
||||||
height 30px
|
|
||||||
padding 0 10px
|
|
||||||
line-height 30px
|
|
||||||
vertical-align middle
|
|
||||||
width 580px
|
|
||||||
&:focus
|
|
||||||
outline 0
|
|
||||||
button
|
|
||||||
position absolute
|
|
||||||
top 5px
|
|
||||||
right 5px
|
|
||||||
|
|
||||||
button
|
|
||||||
download-button()
|
|
||||||
74
node_modules/socket.io/examples/irc-output/app.js
generated
vendored
74
node_modules/socket.io/examples/irc-output/app.js
generated
vendored
|
|
@ -1,74 +0,0 @@
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var express = require('express')
|
|
||||||
, stylus = require('stylus')
|
|
||||||
, nib = require('nib')
|
|
||||||
, sio = require('../../lib/socket.io')
|
|
||||||
, irc = require('./irc');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var app = express.createServer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.configure(function () {
|
|
||||||
app.use(stylus.middleware({ src: __dirname + '/public', compile: compile }))
|
|
||||||
app.use(express.static(__dirname + '/public'));
|
|
||||||
app.set('views', __dirname);
|
|
||||||
app.set('view engine', 'jade');
|
|
||||||
|
|
||||||
function compile (str, path) {
|
|
||||||
return stylus(str)
|
|
||||||
.set('filename', path)
|
|
||||||
.use(nib());
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App routes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.get('/', function (req, res) {
|
|
||||||
res.render('index', { layout: false });
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App listen.
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.listen(3000, function () {
|
|
||||||
var addr = app.address();
|
|
||||||
console.log(' app listening on http://' + addr.address + ':' + addr.port);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket.IO server
|
|
||||||
*/
|
|
||||||
|
|
||||||
var io = sio.listen(app)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to IRC.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var client = new irc.Client('irc.freenode.net', 6667);
|
|
||||||
client.connect('socketio\\test\\' + String(Math.random()).substr(-3));
|
|
||||||
client.on('001', function () {
|
|
||||||
this.send('JOIN', '#node.js');
|
|
||||||
});
|
|
||||||
client.on('PART', function (prefix) {
|
|
||||||
io.sockets.emit('announcement', irc.user(prefix) + ' left the channel');
|
|
||||||
});
|
|
||||||
client.on('JOIN', function (prefix) {
|
|
||||||
io.sockets.emit('announcement', irc.user(prefix) + ' joined the channel');
|
|
||||||
});
|
|
||||||
client.on('PRIVMSG', function (prefix, channel, text) {
|
|
||||||
io.sockets.emit('irc message', irc.user(prefix), text);
|
|
||||||
});
|
|
||||||
28
node_modules/socket.io/examples/irc-output/index.jade
generated
vendored
28
node_modules/socket.io/examples/irc-output/index.jade
generated
vendored
|
|
@ -1,28 +0,0 @@
|
||||||
doctype 5
|
|
||||||
html
|
|
||||||
head
|
|
||||||
link(href='/stylesheets/style.css', rel='stylesheet')
|
|
||||||
script(src='http://code.jquery.com/jquery-1.6.1.min.js')
|
|
||||||
script(src='/socket.io/socket.io.js')
|
|
||||||
script
|
|
||||||
var socket = io.connect();
|
|
||||||
|
|
||||||
socket.on('connect', function () {
|
|
||||||
$('#irc').addClass('connected');
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('announcement', function (msg) {
|
|
||||||
$('#messages').append($('<p>').append($('<em>').text(msg)));
|
|
||||||
$('#messages').get(0).scrollTop = 10000000;
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('irc message', function (user, msg) {
|
|
||||||
$('#messages').append($('<p>').append($('<b>').text(user), msg));
|
|
||||||
$('#messages').get(0).scrollTop = 10000000;
|
|
||||||
});
|
|
||||||
body
|
|
||||||
h2 Node.JS IRC
|
|
||||||
#irc
|
|
||||||
#connecting
|
|
||||||
.wrap Connecting to socket.io server
|
|
||||||
#messages
|
|
||||||
164
node_modules/socket.io/examples/irc-output/irc.js
generated
vendored
164
node_modules/socket.io/examples/irc-output/irc.js
generated
vendored
|
|
@ -1,164 +0,0 @@
|
||||||
/**
|
|
||||||
* From https://github.com/felixge/nodelog/
|
|
||||||
*/
|
|
||||||
|
|
||||||
var sys = require('util');
|
|
||||||
var tcp = require('net');
|
|
||||||
var irc = exports;
|
|
||||||
|
|
||||||
function bind(fn, scope) {
|
|
||||||
var bindArgs = Array.prototype.slice.call(arguments);
|
|
||||||
bindArgs.shift();
|
|
||||||
bindArgs.shift();
|
|
||||||
|
|
||||||
return function() {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
fn.apply(scope, bindArgs.concat(args));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function each(set, iterator) {
|
|
||||||
for (var i = 0; i < set.length; i++) {
|
|
||||||
var r = iterator(set[i], i);
|
|
||||||
if (r === false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var Client = irc.Client = function(host, port) {
|
|
||||||
this.host = host || 'localhost';
|
|
||||||
this.port = port || 6667;
|
|
||||||
|
|
||||||
this.connection = null;
|
|
||||||
this.buffer = '';
|
|
||||||
this.encoding = 'utf8';
|
|
||||||
this.timeout = 10 * 60 * 60 * 1000;
|
|
||||||
|
|
||||||
this.nick = null;
|
|
||||||
this.user = null;
|
|
||||||
this.real = null;
|
|
||||||
}
|
|
||||||
sys.inherits(Client, process.EventEmitter);
|
|
||||||
|
|
||||||
Client.prototype.connect = function(nick, user, real) {
|
|
||||||
var connection = tcp.createConnection(this.port, this.host);
|
|
||||||
connection.setEncoding(this.encoding);
|
|
||||||
connection.setTimeout(this.timeout);
|
|
||||||
connection.addListener('connect', bind(this.onConnect, this));
|
|
||||||
connection.addListener('data', bind(this.onReceive, this));
|
|
||||||
connection.addListener('end', bind(this.onEof, this));
|
|
||||||
connection.addListener('timeout', bind(this.onTimeout, this));
|
|
||||||
connection.addListener('close', bind(this.onClose, this));
|
|
||||||
|
|
||||||
this.nick = nick;
|
|
||||||
this.user = user || 'guest';
|
|
||||||
this.real = real || 'Guest';
|
|
||||||
|
|
||||||
this.connection = connection;
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.disconnect = function(why) {
|
|
||||||
if (this.connection.readyState !== 'closed') {
|
|
||||||
this.connection.close();
|
|
||||||
sys.puts('disconnected (reason: '+why+')');
|
|
||||||
this.emit('DISCONNECT', why);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.send = function(arg1) {
|
|
||||||
if (this.connection.readyState !== 'open') {
|
|
||||||
return this.disconnect('cannot send with readyState: '+this.connection.readyState);
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = [];
|
|
||||||
for (var i = 0; i< arguments.length; i++) {
|
|
||||||
if (arguments[i]) {
|
|
||||||
message.push(arguments[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
message = message.join(' ');
|
|
||||||
|
|
||||||
sys.puts('> '+message);
|
|
||||||
message = message + "\r\n";
|
|
||||||
this.connection.write(message, this.encoding);
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.parse = function(message) {
|
|
||||||
var match = message.match(/(?:(:[^\s]+) )?([^\s]+) (.+)/);
|
|
||||||
var parsed = {
|
|
||||||
prefix: match[1],
|
|
||||||
command: match[2]
|
|
||||||
};
|
|
||||||
|
|
||||||
var params = match[3].match(/(.*?) ?:(.*)/);
|
|
||||||
if (params) {
|
|
||||||
// Params before :
|
|
||||||
params[1] = (params[1])
|
|
||||||
? params[1].split(' ')
|
|
||||||
: [];
|
|
||||||
// Rest after :
|
|
||||||
params[2] = params[2]
|
|
||||||
? [params[2]]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
params = params[1].concat(params[2]);
|
|
||||||
} else {
|
|
||||||
params = match[3].split(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed.params = params;
|
|
||||||
return parsed;
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.onConnect = function() {
|
|
||||||
this.send('NICK', this.nick);
|
|
||||||
this.send('USER', this.user, '0', '*', ':'+this.real);
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.onReceive = function(chunk) {
|
|
||||||
this.buffer = this.buffer + chunk;
|
|
||||||
|
|
||||||
while (this.buffer) {
|
|
||||||
var offset = this.buffer.indexOf("\r\n");
|
|
||||||
if (offset < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = this.buffer.substr(0, offset);
|
|
||||||
this.buffer = this.buffer.substr(offset + 2);
|
|
||||||
sys.puts('< '+message);
|
|
||||||
|
|
||||||
message = this.parse(message);
|
|
||||||
|
|
||||||
this.emit.apply(this, [message.command, message.prefix].concat(message.params));
|
|
||||||
|
|
||||||
if (message !== false) {
|
|
||||||
this.onMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.onMessage = function(message) {
|
|
||||||
switch (message.command) {
|
|
||||||
case 'PING':
|
|
||||||
this.send('PONG', ':'+message.params[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.onEof = function() {
|
|
||||||
this.disconnect('eof');
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.onTimeout = function() {
|
|
||||||
this.disconnect('timeout');
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.onClose = function() {
|
|
||||||
this.disconnect('close');
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.user = function(prefix) {
|
|
||||||
return prefix.match(/:([^!]+)!/)[1]
|
|
||||||
};
|
|
||||||
10
node_modules/socket.io/examples/irc-output/package.json
generated
vendored
10
node_modules/socket.io/examples/irc-output/package.json
generated
vendored
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"name": "socket.io-irc"
|
|
||||||
, "version": "0.0.1"
|
|
||||||
, "dependencies": {
|
|
||||||
"express": "2.5.5"
|
|
||||||
, "jade": "0.16.4"
|
|
||||||
, "stylus": "0.19.0"
|
|
||||||
, "nib": "0.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
69
node_modules/socket.io/examples/irc-output/public/stylesheets/style.styl
generated
vendored
69
node_modules/socket.io/examples/irc-output/public/stylesheets/style.styl
generated
vendored
|
|
@ -1,69 +0,0 @@
|
||||||
@import 'nib'
|
|
||||||
|
|
||||||
h2
|
|
||||||
font bold 18px Helvetica Neue, Arial
|
|
||||||
|
|
||||||
#irc, #messages
|
|
||||||
width 600px
|
|
||||||
|
|
||||||
#irc
|
|
||||||
position relative
|
|
||||||
border 1px solid #ccc
|
|
||||||
|
|
||||||
#connecting
|
|
||||||
position absolute
|
|
||||||
height 410px
|
|
||||||
z-index 100
|
|
||||||
left 0
|
|
||||||
top 0
|
|
||||||
background #fff
|
|
||||||
text-align center
|
|
||||||
width 600px
|
|
||||||
font 15px Georgia
|
|
||||||
color #666
|
|
||||||
display block
|
|
||||||
.wrap
|
|
||||||
padding-top 150px
|
|
||||||
|
|
||||||
.connected
|
|
||||||
#connecting
|
|
||||||
display none
|
|
||||||
|
|
||||||
#messages
|
|
||||||
height 380px
|
|
||||||
background #eee
|
|
||||||
overflow auto
|
|
||||||
overflow-x hidden
|
|
||||||
overflow-y auto
|
|
||||||
&::-webkit-scrollbar
|
|
||||||
width 6px
|
|
||||||
height 6px
|
|
||||||
&::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:end:increment
|
|
||||||
display block
|
|
||||||
height 10px
|
|
||||||
&::-webkit-scrollbar-button:vertical:increment
|
|
||||||
background-color #fff
|
|
||||||
&::-webkit-scrollbar-track-piece
|
|
||||||
background-color #fff
|
|
||||||
-webkit-border-radius 3px
|
|
||||||
&::-webkit-scrollbar-thumb:vertical
|
|
||||||
height 50px
|
|
||||||
background-color #ccc
|
|
||||||
-webkit-border-radius 3px
|
|
||||||
&::-webkit-scrollbar-thumb:horizontal
|
|
||||||
width 50px
|
|
||||||
background-color #fff
|
|
||||||
-webkit-border-radius 3px
|
|
||||||
em
|
|
||||||
text-shadow 0 1px 0 #fff
|
|
||||||
color #999
|
|
||||||
p
|
|
||||||
padding 0
|
|
||||||
margin 0
|
|
||||||
font 12px Helvetica, Arial
|
|
||||||
padding 5px 10px
|
|
||||||
b
|
|
||||||
display inline-block
|
|
||||||
padding-right 10px
|
|
||||||
p:nth-child(even)
|
|
||||||
background #fafafa
|
|
||||||
8
node_modules/socket.io/index.js
generated
vendored
8
node_modules/socket.io/index.js
generated
vendored
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = require('./lib/socket.io');
|
|
||||||
167
node_modules/socket.io/lib/client.js
generated
vendored
167
node_modules/socket.io/lib/client.js
generated
vendored
|
|
@ -1,167 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var parser = require('socket.io-client').parser
|
|
||||||
, EventEmitter = require('events').EventEmitter
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Client (id, server) {
|
|
||||||
this.id = id;
|
|
||||||
this.acks = {};
|
|
||||||
this.store = server.store;
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
store.subscribe(id, function (packet) {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
store.subscribe(id + '.disconect', function () {
|
|
||||||
self.onDisconnect();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from EventEmitter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save reference to original `emit`.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype._emit = Client.prototype.emit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Broadcast flag.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.__defineGetter__('broadcast', function () {
|
|
||||||
this.flags.broadcast = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON flag (deprecated)
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.__defineGetter__('json', function () {
|
|
||||||
this.flags.broadcast = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Joins a group.
|
|
||||||
*
|
|
||||||
* @param {String} group
|
|
||||||
* @return {Client} for chaining
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.join = function (group, fn) {
|
|
||||||
if (!~this.subscriptions.indexOf(group)) {
|
|
||||||
var self = this;
|
|
||||||
this.subscriptions.push(group);
|
|
||||||
this.store.addToGroup(group, this.sid, function (ev, args) {
|
|
||||||
self.onGroupEvent(ev, args);
|
|
||||||
}, fn);
|
|
||||||
} else {
|
|
||||||
fn && fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leaves a group.
|
|
||||||
*
|
|
||||||
* @return {Client} for chaining
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.leave = function (group) {
|
|
||||||
var index = this.subscriptions.indexOf(group);
|
|
||||||
if (~index) {
|
|
||||||
this.subscriptions.splice(index, 1);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Client.prototype.disconnect = function () {
|
|
||||||
if (this.socket) {
|
|
||||||
this.socket.disconnect();
|
|
||||||
} else {
|
|
||||||
this.publish('disconnect');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called upon disconnect.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.onDisconnect = function () {
|
|
||||||
for (var i = 0, l = this.subscriptions; i < l; i++) {
|
|
||||||
this.store.removeFromGroup(id, group, fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers ACK.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.ack = function (fn, callback) {
|
|
||||||
this.subscribe('ack');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emits an event.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.emit = function () {
|
|
||||||
var args = toArray(arguments), fn;
|
|
||||||
|
|
||||||
if ('function' == typeof args[args.length - 1]) {
|
|
||||||
fn = args.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = args.shift();
|
|
||||||
if (args.length) {
|
|
||||||
data += '\n' + JSON.stringify(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fn) {
|
|
||||||
this.ack(fn, function (id) {
|
|
||||||
self.sendPacket('event', data, id);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.sendPacket('event', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.sendPacket = function (type, data, id) {
|
|
||||||
var data = parser.encode({ type: type, data: data, id: id });
|
|
||||||
|
|
||||||
if (this.server.sockets[id]) {
|
|
||||||
this.server.sockets[id].write(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
97
node_modules/socket.io/lib/logger.js
generated
vendored
97
node_modules/socket.io/lib/logger.js
generated
vendored
|
|
@ -1,97 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var util = require('./util')
|
|
||||||
, toArray = util.toArray;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log levels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var levels = [
|
|
||||||
'error'
|
|
||||||
, 'warn'
|
|
||||||
, 'info'
|
|
||||||
, 'debug'
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Colors for log levels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var colors = [
|
|
||||||
31
|
|
||||||
, 33
|
|
||||||
, 36
|
|
||||||
, 90
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pads the nice output to the longest log level.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function pad (str) {
|
|
||||||
var max = 0;
|
|
||||||
|
|
||||||
for (var i = 0, l = levels.length; i < l; i++)
|
|
||||||
max = Math.max(max, levels[i].length);
|
|
||||||
|
|
||||||
if (str.length < max)
|
|
||||||
return str + new Array(max - str.length + 1).join(' ');
|
|
||||||
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger (console).
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Logger = module.exports = function (opts) {
|
|
||||||
opts = opts || {}
|
|
||||||
this.colors = false !== opts.colors;
|
|
||||||
this.level = 3;
|
|
||||||
this.enabled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log method.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Logger.prototype.log = function (type) {
|
|
||||||
var index = levels.indexOf(type);
|
|
||||||
|
|
||||||
if (index > this.level || !this.enabled)
|
|
||||||
return this;
|
|
||||||
|
|
||||||
console.log.apply(
|
|
||||||
console
|
|
||||||
, [this.colors
|
|
||||||
? ' \033[' + colors[index] + 'm' + pad(type) + ' -\033[39m'
|
|
||||||
: type + ':'
|
|
||||||
].concat(toArray(arguments).slice(1))
|
|
||||||
);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate methods.
|
|
||||||
*/
|
|
||||||
|
|
||||||
levels.forEach(function (name) {
|
|
||||||
Logger.prototype[name] = function () {
|
|
||||||
this.log.apply(this, [name].concat(toArray(arguments)));
|
|
||||||
};
|
|
||||||
});
|
|
||||||
984
node_modules/socket.io/lib/manager.js
generated
vendored
984
node_modules/socket.io/lib/manager.js
generated
vendored
|
|
@ -1,984 +0,0 @@
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var fs = require('fs')
|
|
||||||
, url = require('url')
|
|
||||||
, tty = require('tty')
|
|
||||||
, util = require('./util')
|
|
||||||
, store = require('./store')
|
|
||||||
, client = require('socket.io-client')
|
|
||||||
, transports = require('./transports')
|
|
||||||
, Logger = require('./logger')
|
|
||||||
, Socket = require('./socket')
|
|
||||||
, MemoryStore = require('./stores/memory')
|
|
||||||
, SocketNamespace = require('./namespace')
|
|
||||||
, Static = require('./static')
|
|
||||||
, EventEmitter = process.EventEmitter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = Manager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default transports.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var defaultTransports = exports.defaultTransports = [
|
|
||||||
'websocket'
|
|
||||||
, 'htmlfile'
|
|
||||||
, 'xhr-polling'
|
|
||||||
, 'jsonp-polling'
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherited defaults.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var parent = module.parent.exports
|
|
||||||
, protocol = parent.protocol
|
|
||||||
, jsonpolling_re = /^\d+$/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manager constructor.
|
|
||||||
*
|
|
||||||
* @param {HTTPServer} server
|
|
||||||
* @param {Object} options, optional
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Manager (server, options) {
|
|
||||||
this.server = server;
|
|
||||||
this.namespaces = {};
|
|
||||||
this.sockets = this.of('');
|
|
||||||
this.settings = {
|
|
||||||
origins: '*:*'
|
|
||||||
, log: true
|
|
||||||
, store: new MemoryStore
|
|
||||||
, logger: new Logger
|
|
||||||
, static: new Static(this)
|
|
||||||
, heartbeats: true
|
|
||||||
, resource: '/socket.io'
|
|
||||||
, transports: defaultTransports
|
|
||||||
, authorization: false
|
|
||||||
, blacklist: ['disconnect']
|
|
||||||
, 'log level': 3
|
|
||||||
, 'log colors': tty.isatty(process.stdout.fd)
|
|
||||||
, 'close timeout': 60
|
|
||||||
, 'heartbeat interval': 25
|
|
||||||
, 'heartbeat timeout': 60
|
|
||||||
, 'polling duration': 20
|
|
||||||
, 'flash policy server': true
|
|
||||||
, 'flash policy port': 10843
|
|
||||||
, 'destroy upgrade': true
|
|
||||||
, 'destroy buffer size': 10E7
|
|
||||||
, 'browser client': true
|
|
||||||
, 'browser client cache': true
|
|
||||||
, 'browser client minification': false
|
|
||||||
, 'browser client etag': false
|
|
||||||
, 'browser client expires': 315360000
|
|
||||||
, 'browser client gzip': false
|
|
||||||
, 'browser client handler': false
|
|
||||||
, 'client store expiration': 15
|
|
||||||
, 'match origin protocol': false
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var i in options) {
|
|
||||||
this.settings[i] = options[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// default error handler
|
|
||||||
server.on('error', function(err) {
|
|
||||||
self.log.warn('error raised: ' + err);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.initStore();
|
|
||||||
|
|
||||||
this.on('set:store', function() {
|
|
||||||
self.initStore();
|
|
||||||
});
|
|
||||||
|
|
||||||
// reset listeners
|
|
||||||
this.oldListeners = server.listeners('request');
|
|
||||||
server.removeAllListeners('request');
|
|
||||||
|
|
||||||
server.on('request', function (req, res) {
|
|
||||||
self.handleRequest(req, res);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.on('upgrade', function (req, socket, head) {
|
|
||||||
self.handleUpgrade(req, socket, head);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.on('close', function () {
|
|
||||||
clearInterval(self.gc);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.once('listening', function () {
|
|
||||||
self.gc = setInterval(self.garbageCollection.bind(self), 10000);
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var i in transports) {
|
|
||||||
if (transports[i].init) {
|
|
||||||
transports[i].init(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// forward-compatibility with 1.0
|
|
||||||
var self = this;
|
|
||||||
this.sockets.on('connection', function (conn) {
|
|
||||||
self.emit('connection', conn);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.log.info('socket.io started');
|
|
||||||
};
|
|
||||||
|
|
||||||
Manager.prototype.__proto__ = EventEmitter.prototype
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store accessor shortcut.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.__defineGetter__('store', function () {
|
|
||||||
var store = this.get('store');
|
|
||||||
store.manager = this;
|
|
||||||
return store;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger accessor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.__defineGetter__('log', function () {
|
|
||||||
var logger = this.get('logger');
|
|
||||||
|
|
||||||
logger.level = this.get('log level') || -1;
|
|
||||||
logger.colors = this.get('log colors');
|
|
||||||
logger.enabled = this.enabled('log');
|
|
||||||
|
|
||||||
return logger;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static accessor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.__defineGetter__('static', function () {
|
|
||||||
return this.get('static');
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get settings.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.get = function (key) {
|
|
||||||
return this.settings[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set settings
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.set = function (key, value) {
|
|
||||||
if (arguments.length == 1) return this.get(key);
|
|
||||||
this.settings[key] = value;
|
|
||||||
this.emit('set:' + key, this.settings[key], key);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable a setting
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.enable = function (key) {
|
|
||||||
this.settings[key] = true;
|
|
||||||
this.emit('set:' + key, this.settings[key], key);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable a setting
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.disable = function (key) {
|
|
||||||
this.settings[key] = false;
|
|
||||||
this.emit('set:' + key, this.settings[key], key);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a setting is enabled
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.enabled = function (key) {
|
|
||||||
return !!this.settings[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a setting is disabled
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.disabled = function (key) {
|
|
||||||
return !this.settings[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure callbacks.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.configure = function (env, fn) {
|
|
||||||
if ('function' == typeof env) {
|
|
||||||
env.call(this);
|
|
||||||
} else if (env == (process.env.NODE_ENV || 'development')) {
|
|
||||||
fn.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes everything related to the message dispatcher.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.initStore = function () {
|
|
||||||
this.handshaken = {};
|
|
||||||
this.connected = {};
|
|
||||||
this.open = {};
|
|
||||||
this.closed = {};
|
|
||||||
this.rooms = {};
|
|
||||||
this.roomClients = {};
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.store.subscribe('handshake', function (id, data) {
|
|
||||||
self.onHandshake(id, data);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('connect', function (id) {
|
|
||||||
self.onConnect(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('open', function (id) {
|
|
||||||
self.onOpen(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('join', function (id, room) {
|
|
||||||
self.onJoin(id, room);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('leave', function (id, room) {
|
|
||||||
self.onLeave(id, room);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('close', function (id) {
|
|
||||||
self.onClose(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('dispatch', function (room, packet, volatile, exceptions) {
|
|
||||||
self.onDispatch(room, packet, volatile, exceptions);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('disconnect', function (id) {
|
|
||||||
self.onDisconnect(id);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client handshakes.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onHandshake = function (id, data) {
|
|
||||||
this.handshaken[id] = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client connects (ie: transport first opens)
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onConnect = function (id) {
|
|
||||||
this.connected[id] = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client opens a request in a different node.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onOpen = function (id) {
|
|
||||||
this.open[id] = true;
|
|
||||||
|
|
||||||
// if we were buffering messages for the client, clear them
|
|
||||||
if (this.closed[id]) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.store.unsubscribe('dispatch:' + id, function () {
|
|
||||||
delete self.closed[id];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear the current transport
|
|
||||||
if (this.transports[id]) {
|
|
||||||
this.transports[id].discard();
|
|
||||||
this.transports[id] = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a message is sent to a namespace and/or room.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onDispatch = function (room, packet, volatile, exceptions) {
|
|
||||||
if (this.rooms[room]) {
|
|
||||||
for (var i = 0, l = this.rooms[room].length; i < l; i++) {
|
|
||||||
var id = this.rooms[room][i];
|
|
||||||
|
|
||||||
if (!~exceptions.indexOf(id)) {
|
|
||||||
if (this.transports[id] && this.transports[id].open) {
|
|
||||||
this.transports[id].onDispatch(packet, volatile);
|
|
||||||
} else if (!volatile) {
|
|
||||||
this.onClientDispatch(id, packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client joins a nsp / room.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onJoin = function (id, name) {
|
|
||||||
if (!this.roomClients[id]) {
|
|
||||||
this.roomClients[id] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.rooms[name]) {
|
|
||||||
this.rooms[name] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!~this.rooms[name].indexOf(id)) {
|
|
||||||
this.rooms[name].push(id);
|
|
||||||
this.roomClients[id][name] = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client leaves a nsp / room.
|
|
||||||
*
|
|
||||||
* @param private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onLeave = function (id, room) {
|
|
||||||
if (this.rooms[room]) {
|
|
||||||
var index = this.rooms[room].indexOf(id);
|
|
||||||
|
|
||||||
if (index >= 0) {
|
|
||||||
this.rooms[room].splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.rooms[room].length) {
|
|
||||||
delete this.rooms[room];
|
|
||||||
}
|
|
||||||
delete this.roomClients[id][room];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client closes a request in different node.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onClose = function (id) {
|
|
||||||
if (this.open[id]) {
|
|
||||||
delete this.open[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.closed[id] = [];
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.store.subscribe('dispatch:' + id, function (packet, volatile) {
|
|
||||||
if (!volatile) {
|
|
||||||
self.onClientDispatch(id, packet);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a message for a closed client.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onClientDispatch = function (id, packet) {
|
|
||||||
if (this.closed[id]) {
|
|
||||||
this.closed[id].push(packet);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives a message for a client.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onClientMessage = function (id, packet) {
|
|
||||||
if (this.namespaces[packet.endpoint]) {
|
|
||||||
this.namespaces[packet.endpoint].handlePacket(id, packet);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a client disconnects (not triggered).
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onClientDisconnect = function (id, reason) {
|
|
||||||
for (var name in this.namespaces) {
|
|
||||||
this.namespaces[name].handleDisconnect(id, reason, typeof this.roomClients[id] !== 'undefined' &&
|
|
||||||
typeof this.roomClients[id][name] !== 'undefined');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onDisconnect(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a client disconnects.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.onDisconnect = function (id, local) {
|
|
||||||
delete this.handshaken[id];
|
|
||||||
|
|
||||||
if (this.open[id]) {
|
|
||||||
delete this.open[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.connected[id]) {
|
|
||||||
delete this.connected[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.transports[id]) {
|
|
||||||
this.transports[id].discard();
|
|
||||||
delete this.transports[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.closed[id]) {
|
|
||||||
delete this.closed[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.roomClients[id]) {
|
|
||||||
for (var room in this.roomClients[id]) {
|
|
||||||
this.onLeave(id, room);
|
|
||||||
}
|
|
||||||
delete this.roomClients[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.store.destroyClient(id, this.get('client store expiration'));
|
|
||||||
|
|
||||||
this.store.unsubscribe('dispatch:' + id);
|
|
||||||
|
|
||||||
if (local) {
|
|
||||||
this.store.unsubscribe('message:' + id);
|
|
||||||
this.store.unsubscribe('disconnect:' + id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an HTTP request.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.handleRequest = function (req, res) {
|
|
||||||
var data = this.checkRequest(req);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
for (var i = 0, l = this.oldListeners.length; i < l; i++) {
|
|
||||||
this.oldListeners[i].call(this.server, req, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.static || !data.transport && !data.protocol) {
|
|
||||||
if (data.static && this.enabled('browser client')) {
|
|
||||||
this.static.write(data.path, req, res);
|
|
||||||
} else {
|
|
||||||
res.writeHead(200);
|
|
||||||
res.end('Welcome to socket.io.');
|
|
||||||
|
|
||||||
this.log.info('unhandled socket.io url');
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.protocol != protocol) {
|
|
||||||
res.writeHead(500);
|
|
||||||
res.end('Protocol version not supported.');
|
|
||||||
|
|
||||||
this.log.info('client protocol version unsupported');
|
|
||||||
} else {
|
|
||||||
if (data.id) {
|
|
||||||
this.handleHTTPRequest(data, req, res);
|
|
||||||
} else {
|
|
||||||
this.handleHandshake(data, req, res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an HTTP Upgrade.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.handleUpgrade = function (req, socket, head) {
|
|
||||||
var data = this.checkRequest(req)
|
|
||||||
, self = this;
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
if (this.enabled('destroy upgrade')) {
|
|
||||||
socket.end();
|
|
||||||
this.log.debug('destroying non-socket.io upgrade');
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
req.head = head;
|
|
||||||
this.handleClient(data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a normal handshaken HTTP request (eg: long-polling)
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.handleHTTPRequest = function (data, req, res) {
|
|
||||||
req.res = res;
|
|
||||||
this.handleClient(data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intantiantes a new client.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.handleClient = function (data, req) {
|
|
||||||
var socket = req.socket
|
|
||||||
, store = this.store
|
|
||||||
, self = this;
|
|
||||||
|
|
||||||
if (undefined != data.query.disconnect) {
|
|
||||||
if (this.transports[data.id] && this.transports[data.id].open) {
|
|
||||||
this.transports[data.id].onForcedDisconnect();
|
|
||||||
} else {
|
|
||||||
this.store.publish('disconnect-force:' + data.id);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!~this.get('transports').indexOf(data.transport)) {
|
|
||||||
this.log.warn('unknown transport: "' + data.transport + '"');
|
|
||||||
req.connection.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var transport = new transports[data.transport](this, data, req)
|
|
||||||
, handshaken = this.handshaken[data.id];
|
|
||||||
|
|
||||||
if (transport.disconnected) {
|
|
||||||
// failed during transport setup
|
|
||||||
req.connection.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (handshaken) {
|
|
||||||
if (transport.open) {
|
|
||||||
if (this.closed[data.id] && this.closed[data.id].length) {
|
|
||||||
transport.payload(this.closed[data.id]);
|
|
||||||
this.closed[data.id] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onOpen(data.id);
|
|
||||||
this.store.publish('open', data.id);
|
|
||||||
this.transports[data.id] = transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.connected[data.id]) {
|
|
||||||
this.onConnect(data.id);
|
|
||||||
this.store.publish('connect', data.id);
|
|
||||||
|
|
||||||
// flag as used
|
|
||||||
delete handshaken.issued;
|
|
||||||
this.onHandshake(data.id, handshaken);
|
|
||||||
this.store.publish('handshake', data.id, handshaken);
|
|
||||||
|
|
||||||
// initialize the socket for all namespaces
|
|
||||||
for (var i in this.namespaces) {
|
|
||||||
var socket = this.namespaces[i].socket(data.id, true);
|
|
||||||
|
|
||||||
// echo back connect packet and fire connection event
|
|
||||||
if (i === '') {
|
|
||||||
this.namespaces[i].handlePacket(data.id, { type: 'connect' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.store.subscribe('message:' + data.id, function (packet) {
|
|
||||||
self.onClientMessage(data.id, packet);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('disconnect:' + data.id, function (reason) {
|
|
||||||
self.onClientDisconnect(data.id, reason);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (transport.open) {
|
|
||||||
transport.error('client not handshaken', 'reconnect');
|
|
||||||
}
|
|
||||||
|
|
||||||
transport.discard();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a session id.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.generateId = function () {
|
|
||||||
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
|
|
||||||
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a handshake request.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.handleHandshake = function (data, req, res) {
|
|
||||||
var self = this
|
|
||||||
, origin = req.headers.origin
|
|
||||||
, headers = {
|
|
||||||
'Content-Type': 'text/plain'
|
|
||||||
};
|
|
||||||
|
|
||||||
function writeErr (status, message) {
|
|
||||||
if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) {
|
|
||||||
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
|
||||||
res.end('io.j[' + data.query.jsonp + '](new Error("' + message + '"));');
|
|
||||||
} else {
|
|
||||||
res.writeHead(status, headers);
|
|
||||||
res.end(message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function error (err) {
|
|
||||||
writeErr(500, 'handshake error');
|
|
||||||
self.log.warn('handshake error ' + err);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!this.verifyOrigin(req)) {
|
|
||||||
writeErr(403, 'handshake bad origin');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var handshakeData = this.handshakeData(data);
|
|
||||||
|
|
||||||
if (origin) {
|
|
||||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
|
||||||
headers['Access-Control-Allow-Origin'] = origin;
|
|
||||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.authorize(handshakeData, function (err, authorized, newData) {
|
|
||||||
if (err) return error(err);
|
|
||||||
|
|
||||||
if (authorized) {
|
|
||||||
var id = self.generateId()
|
|
||||||
, hs = [
|
|
||||||
id
|
|
||||||
, self.enabled('heartbeats') ? self.get('heartbeat timeout') || '' : ''
|
|
||||||
, self.get('close timeout') || ''
|
|
||||||
, self.transports(data).join(',')
|
|
||||||
].join(':');
|
|
||||||
|
|
||||||
if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) {
|
|
||||||
hs = 'io.j[' + data.query.jsonp + '](' + JSON.stringify(hs) + ');';
|
|
||||||
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
|
||||||
} else {
|
|
||||||
res.writeHead(200, headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.end(hs);
|
|
||||||
|
|
||||||
self.onHandshake(id, newData || handshakeData);
|
|
||||||
self.store.publish('handshake', id, newData || handshakeData);
|
|
||||||
|
|
||||||
self.log.info('handshake authorized', id);
|
|
||||||
} else {
|
|
||||||
writeErr(403, 'handshake unauthorized');
|
|
||||||
self.log.info('handshake unauthorized');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets normalized handshake data
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.handshakeData = function (data) {
|
|
||||||
var connection = data.request.connection
|
|
||||||
, connectionAddress
|
|
||||||
, date = new Date;
|
|
||||||
|
|
||||||
if (connection.remoteAddress) {
|
|
||||||
connectionAddress = {
|
|
||||||
address: connection.remoteAddress
|
|
||||||
, port: connection.remotePort
|
|
||||||
};
|
|
||||||
} else if (connection.socket && connection.socket.remoteAddress) {
|
|
||||||
connectionAddress = {
|
|
||||||
address: connection.socket.remoteAddress
|
|
||||||
, port: connection.socket.remotePort
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
headers: data.headers
|
|
||||||
, address: connectionAddress
|
|
||||||
, time: date.toString()
|
|
||||||
, query: data.query
|
|
||||||
, url: data.request.url
|
|
||||||
, xdomain: !!data.request.headers.origin
|
|
||||||
, secure: data.request.connection.secure
|
|
||||||
, issued: +date
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies the origin of a request.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.verifyOrigin = function (request) {
|
|
||||||
var origin = request.headers.origin || request.headers.referer
|
|
||||||
, origins = this.get('origins');
|
|
||||||
|
|
||||||
if (origin === 'null') origin = '*';
|
|
||||||
|
|
||||||
if (origins.indexOf('*:*') !== -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (origin) {
|
|
||||||
try {
|
|
||||||
var parts = url.parse(origin);
|
|
||||||
parts.port = parts.port || 80;
|
|
||||||
var ok =
|
|
||||||
~origins.indexOf(parts.hostname + ':' + parts.port) ||
|
|
||||||
~origins.indexOf(parts.hostname + ':*') ||
|
|
||||||
~origins.indexOf('*:' + parts.port);
|
|
||||||
if (!ok) this.log.warn('illegal origin: ' + origin);
|
|
||||||
return ok;
|
|
||||||
} catch (ex) {
|
|
||||||
this.log.warn('error parsing origin');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.log.warn('origin missing from handshake, yet required by config');
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an incoming packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.handlePacket = function (sessid, packet) {
|
|
||||||
this.of(packet.endpoint || '').handlePacket(sessid, packet);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs authentication.
|
|
||||||
*
|
|
||||||
* @param Object client request data
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.authorize = function (data, fn) {
|
|
||||||
if (this.get('authorization')) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.get('authorization').call(this, data, function (err, authorized) {
|
|
||||||
self.log.debug('client ' + authorized ? 'authorized' : 'unauthorized');
|
|
||||||
fn(err, authorized);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.log.debug('client authorized');
|
|
||||||
fn(null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the transports adviced to the user.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.transports = function (data) {
|
|
||||||
var transp = this.get('transports')
|
|
||||||
, ret = [];
|
|
||||||
|
|
||||||
for (var i = 0, l = transp.length; i < l; i++) {
|
|
||||||
var transport = transp[i];
|
|
||||||
|
|
||||||
if (transport) {
|
|
||||||
if (!transport.checkClient || transport.checkClient(data)) {
|
|
||||||
ret.push(transport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether a request is a socket.io one.
|
|
||||||
*
|
|
||||||
* @return {Object} a client request data object or `false`
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var regexp = /^\/([^\/]+)\/?([^\/]+)?\/?([^\/]+)?\/?$/
|
|
||||||
|
|
||||||
Manager.prototype.checkRequest = function (req) {
|
|
||||||
var resource = this.get('resource');
|
|
||||||
|
|
||||||
var match;
|
|
||||||
if (typeof resource === 'string') {
|
|
||||||
match = req.url.substr(0, resource.length);
|
|
||||||
if (match !== resource) match = null;
|
|
||||||
} else {
|
|
||||||
match = resource.exec(req.url);
|
|
||||||
if (match) match = match[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
var uri = url.parse(req.url.substr(match.length), true)
|
|
||||||
, path = uri.pathname || ''
|
|
||||||
, pieces = path.match(regexp);
|
|
||||||
|
|
||||||
// client request data
|
|
||||||
var data = {
|
|
||||||
query: uri.query || {}
|
|
||||||
, headers: req.headers
|
|
||||||
, request: req
|
|
||||||
, path: path
|
|
||||||
};
|
|
||||||
|
|
||||||
if (pieces) {
|
|
||||||
data.protocol = Number(pieces[1]);
|
|
||||||
data.transport = pieces[2];
|
|
||||||
data.id = pieces[3];
|
|
||||||
data.static = !!this.static.has(path);
|
|
||||||
};
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declares a socket namespace
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.of = function (nsp) {
|
|
||||||
if (this.namespaces[nsp]) {
|
|
||||||
return this.namespaces[nsp];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.namespaces[nsp] = new SocketNamespace(this, nsp);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform garbage collection on long living objects and properties that cannot
|
|
||||||
* be removed automatically.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Manager.prototype.garbageCollection = function () {
|
|
||||||
// clean up unused handshakes
|
|
||||||
var ids = Object.keys(this.handshaken)
|
|
||||||
, i = ids.length
|
|
||||||
, now = Date.now()
|
|
||||||
, handshake;
|
|
||||||
|
|
||||||
while (i--) {
|
|
||||||
handshake = this.handshaken[ids[i]];
|
|
||||||
|
|
||||||
if ('issued' in handshake && (now - handshake.issued) >= 3E4) {
|
|
||||||
this.onDisconnect(ids[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
355
node_modules/socket.io/lib/namespace.js
generated
vendored
355
node_modules/socket.io/lib/namespace.js
generated
vendored
|
|
@ -1,355 +0,0 @@
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Socket = require('./socket')
|
|
||||||
, EventEmitter = process.EventEmitter
|
|
||||||
, parser = require('./parser')
|
|
||||||
, util = require('./util');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exports the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = SocketNamespace;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @api public.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function SocketNamespace (mgr, name) {
|
|
||||||
this.manager = mgr;
|
|
||||||
this.name = name || '';
|
|
||||||
this.sockets = {};
|
|
||||||
this.auth = false;
|
|
||||||
this.setFlags();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from EventEmitter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies emit since we override it.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.$emit = EventEmitter.prototype.emit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves all clients as Socket instances as an array.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.clients = function (room) {
|
|
||||||
var room = this.name + (room !== undefined ?
|
|
||||||
'/' + room : '');
|
|
||||||
|
|
||||||
if (!this.manager.rooms[room]) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.manager.rooms[room].map(function (id) {
|
|
||||||
return this.socket(id);
|
|
||||||
}, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access logger interface.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.__defineGetter__('log', function () {
|
|
||||||
return this.manager.log;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access store.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.__defineGetter__('store', function () {
|
|
||||||
return this.manager.store;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON message flag.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.__defineGetter__('json', function () {
|
|
||||||
this.flags.json = true;
|
|
||||||
return this;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Volatile message flag.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.__defineGetter__('volatile', function () {
|
|
||||||
this.flags.volatile = true;
|
|
||||||
return this;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the room to relay messages to (flag).
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) {
|
|
||||||
this.flags.endpoint = this.name + (room ? '/' + room : '');
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a session id we should prevent relaying messages to (flag).
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.except = function (id) {
|
|
||||||
this.flags.exceptions.push(id);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default flags.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.setFlags = function () {
|
|
||||||
this.flags = {
|
|
||||||
endpoint: this.name
|
|
||||||
, exceptions: []
|
|
||||||
};
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends out a packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.packet = function (packet) {
|
|
||||||
packet.endpoint = this.name;
|
|
||||||
|
|
||||||
var store = this.store
|
|
||||||
, log = this.log
|
|
||||||
, volatile = this.flags.volatile
|
|
||||||
, exceptions = this.flags.exceptions
|
|
||||||
, packet = parser.encodePacket(packet);
|
|
||||||
|
|
||||||
this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions);
|
|
||||||
this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions);
|
|
||||||
|
|
||||||
this.setFlags();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends to everyone.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.send = function (data) {
|
|
||||||
return this.packet({
|
|
||||||
type: this.flags.json ? 'json' : 'message'
|
|
||||||
, data: data
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emits to everyone (override).
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.emit = function (name) {
|
|
||||||
if (name == 'newListener') {
|
|
||||||
return this.$emit.apply(this, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.packet({
|
|
||||||
type: 'event'
|
|
||||||
, name: name
|
|
||||||
, args: util.toArray(arguments).slice(1)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves or creates a write-only socket for a client, unless specified.
|
|
||||||
*
|
|
||||||
* @param {Boolean} whether the socket will be readable when initialized
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.socket = function (sid, readable) {
|
|
||||||
if (!this.sockets[sid]) {
|
|
||||||
this.sockets[sid] = new Socket(this.manager, sid, this, readable);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.sockets[sid];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets authorization for this namespace.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.authorization = function (fn) {
|
|
||||||
this.auth = fn;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a socket disconnects entirely.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) {
|
|
||||||
if (this.sockets[sid] && this.sockets[sid].readable) {
|
|
||||||
if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason);
|
|
||||||
delete this.sockets[sid];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs authentication.
|
|
||||||
*
|
|
||||||
* @param Object client request data
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.authorize = function (data, fn) {
|
|
||||||
if (this.auth) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.auth.call(this, data, function (err, authorized) {
|
|
||||||
self.log.debug('client ' +
|
|
||||||
(authorized ? '' : 'un') + 'authorized for ' + self.name);
|
|
||||||
fn(err, authorized);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.log.debug('client authorized for ' + this.name);
|
|
||||||
fn(null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
SocketNamespace.prototype.handlePacket = function (sessid, packet) {
|
|
||||||
var socket = this.socket(sessid)
|
|
||||||
, dataAck = packet.ack == 'data'
|
|
||||||
, manager = this.manager
|
|
||||||
, self = this;
|
|
||||||
|
|
||||||
function ack () {
|
|
||||||
self.log.debug('sending data ack packet');
|
|
||||||
socket.packet({
|
|
||||||
type: 'ack'
|
|
||||||
, args: util.toArray(arguments)
|
|
||||||
, ackId: packet.id
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function error (err) {
|
|
||||||
self.log.warn('handshake error ' + err + ' for ' + self.name);
|
|
||||||
socket.packet({ type: 'error', reason: err });
|
|
||||||
};
|
|
||||||
|
|
||||||
function connect () {
|
|
||||||
self.manager.onJoin(sessid, self.name);
|
|
||||||
self.store.publish('join', sessid, self.name);
|
|
||||||
|
|
||||||
// packet echo
|
|
||||||
socket.packet({ type: 'connect' });
|
|
||||||
|
|
||||||
// emit connection event
|
|
||||||
self.$emit('connection', socket);
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (packet.type) {
|
|
||||||
case 'connect':
|
|
||||||
if (packet.endpoint == '') {
|
|
||||||
connect();
|
|
||||||
} else {
|
|
||||||
var handshakeData = manager.handshaken[sessid];
|
|
||||||
|
|
||||||
this.authorize(handshakeData, function (err, authorized, newData) {
|
|
||||||
if (err) return error(err);
|
|
||||||
|
|
||||||
if (authorized) {
|
|
||||||
manager.onHandshake(sessid, newData || handshakeData);
|
|
||||||
self.store.publish('handshake', sessid, newData || handshakeData);
|
|
||||||
connect();
|
|
||||||
} else {
|
|
||||||
error('unauthorized');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ack':
|
|
||||||
if (socket.acks[packet.ackId]) {
|
|
||||||
socket.acks[packet.ackId].apply(socket, packet.args);
|
|
||||||
} else {
|
|
||||||
this.log.info('unknown ack packet');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'event':
|
|
||||||
// check if the emitted event is not blacklisted
|
|
||||||
if (-~manager.get('blacklist').indexOf(packet.name)) {
|
|
||||||
this.log.debug('ignoring blacklisted event `' + packet.name + '`');
|
|
||||||
} else {
|
|
||||||
var params = [packet.name].concat(packet.args);
|
|
||||||
|
|
||||||
if (dataAck) {
|
|
||||||
params.push(ack);
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.$emit.apply(socket, params);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'disconnect':
|
|
||||||
this.manager.onLeave(sessid, this.name);
|
|
||||||
this.store.publish('leave', sessid, this.name);
|
|
||||||
|
|
||||||
socket.$emit('disconnect', packet.reason || 'packet');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'json':
|
|
||||||
case 'message':
|
|
||||||
var params = ['message', packet.data];
|
|
||||||
|
|
||||||
if (dataAck)
|
|
||||||
params.push(ack);
|
|
||||||
|
|
||||||
socket.$emit.apply(socket, params);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
249
node_modules/socket.io/lib/parser.js
generated
vendored
249
node_modules/socket.io/lib/parser.js
generated
vendored
|
|
@ -1,249 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet types.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var packets = exports.packets = {
|
|
||||||
'disconnect': 0
|
|
||||||
, 'connect': 1
|
|
||||||
, 'heartbeat': 2
|
|
||||||
, 'message': 3
|
|
||||||
, 'json': 4
|
|
||||||
, 'event': 5
|
|
||||||
, 'ack': 6
|
|
||||||
, 'error': 7
|
|
||||||
, 'noop': 8
|
|
||||||
}
|
|
||||||
, packetslist = Object.keys(packets);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Errors reasons.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var reasons = exports.reasons = {
|
|
||||||
'transport not supported': 0
|
|
||||||
, 'client not handshaken': 1
|
|
||||||
, 'unauthorized': 2
|
|
||||||
}
|
|
||||||
, reasonslist = Object.keys(reasons);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Errors advice.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var advice = exports.advice = {
|
|
||||||
'reconnect': 0
|
|
||||||
}
|
|
||||||
, advicelist = Object.keys(advice);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encodes a packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.encodePacket = function (packet) {
|
|
||||||
var type = packets[packet.type]
|
|
||||||
, id = packet.id || ''
|
|
||||||
, endpoint = packet.endpoint || ''
|
|
||||||
, ack = packet.ack
|
|
||||||
, data = null;
|
|
||||||
|
|
||||||
switch (packet.type) {
|
|
||||||
case 'message':
|
|
||||||
if (packet.data !== '')
|
|
||||||
data = packet.data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'event':
|
|
||||||
var ev = { name: packet.name };
|
|
||||||
|
|
||||||
if (packet.args && packet.args.length) {
|
|
||||||
ev.args = packet.args;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = JSON.stringify(ev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'json':
|
|
||||||
data = JSON.stringify(packet.data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ack':
|
|
||||||
data = packet.ackId
|
|
||||||
+ (packet.args && packet.args.length
|
|
||||||
? '+' + JSON.stringify(packet.args) : '');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'connect':
|
|
||||||
if (packet.qs)
|
|
||||||
data = packet.qs;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'error':
|
|
||||||
var reason = packet.reason ? reasons[packet.reason] : ''
|
|
||||||
, adv = packet.advice ? advice[packet.advice] : ''
|
|
||||||
|
|
||||||
if (reason !== '' || adv !== '')
|
|
||||||
data = reason + (adv !== '' ? ('+' + adv) : '')
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// construct packet with required fragments
|
|
||||||
var encoded = type + ':' + id + (ack == 'data' ? '+' : '') + ':' + endpoint;
|
|
||||||
|
|
||||||
// data fragment is optional
|
|
||||||
if (data !== null && data !== undefined)
|
|
||||||
encoded += ':' + data;
|
|
||||||
|
|
||||||
return encoded;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encodes multiple messages (payload).
|
|
||||||
*
|
|
||||||
* @param {Array} messages
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.encodePayload = function (packets) {
|
|
||||||
var decoded = '';
|
|
||||||
|
|
||||||
if (packets.length == 1)
|
|
||||||
return packets[0];
|
|
||||||
|
|
||||||
for (var i = 0, l = packets.length; i < l; i++) {
|
|
||||||
var packet = packets[i];
|
|
||||||
decoded += '\ufffd' + packet.length + '\ufffd' + packets[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
return decoded;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decodes a packet
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the JSON.parse in a seperate function the crankshaft optimizer will
|
|
||||||
* only punish this function for the usage for try catch
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parse (data) {
|
|
||||||
try { return JSON.parse(data) }
|
|
||||||
catch (e) { return false }
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.decodePacket = function (data) {
|
|
||||||
var pieces = data.match(regexp);
|
|
||||||
|
|
||||||
if (!pieces) return {};
|
|
||||||
|
|
||||||
var id = pieces[2] || ''
|
|
||||||
, data = pieces[5] || ''
|
|
||||||
, packet = {
|
|
||||||
type: packetslist[pieces[1]]
|
|
||||||
, endpoint: pieces[4] || ''
|
|
||||||
};
|
|
||||||
|
|
||||||
// whether we need to acknowledge the packet
|
|
||||||
if (id) {
|
|
||||||
packet.id = id;
|
|
||||||
if (pieces[3])
|
|
||||||
packet.ack = 'data';
|
|
||||||
else
|
|
||||||
packet.ack = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle different packet types
|
|
||||||
switch (packet.type) {
|
|
||||||
case 'message':
|
|
||||||
packet.data = data || '';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'event':
|
|
||||||
pieces = parse(data);
|
|
||||||
if (pieces) {
|
|
||||||
packet.name = pieces.name;
|
|
||||||
packet.args = pieces.args;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet.args = packet.args || [];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'json':
|
|
||||||
packet.data = parse(data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'connect':
|
|
||||||
packet.qs = data || '';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ack':
|
|
||||||
pieces = data.match(/^([0-9]+)(\+)?(.*)/);
|
|
||||||
if (pieces) {
|
|
||||||
packet.ackId = pieces[1];
|
|
||||||
packet.args = [];
|
|
||||||
|
|
||||||
if (pieces[3]) {
|
|
||||||
packet.args = parse(pieces[3]) || [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'error':
|
|
||||||
pieces = data.split('+');
|
|
||||||
packet.reason = reasonslist[pieces[0]] || '';
|
|
||||||
packet.advice = advicelist[pieces[1]] || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decodes data payload. Detects multiple messages
|
|
||||||
*
|
|
||||||
* @return {Array} messages
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.decodePayload = function (data) {
|
|
||||||
if (undefined == data || null == data) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[0] == '\ufffd') {
|
|
||||||
var ret = [];
|
|
||||||
|
|
||||||
for (var i = 1, length = ''; i < data.length; i++) {
|
|
||||||
if (data[i] == '\ufffd') {
|
|
||||||
ret.push(exports.decodePacket(data.substr(i + 1, length)));
|
|
||||||
i += Number(length) + 1;
|
|
||||||
length = '';
|
|
||||||
} else {
|
|
||||||
length += data[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
return [exports.decodePacket(data)];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
136
node_modules/socket.io/lib/socket.io.js
generated
vendored
136
node_modules/socket.io/lib/socket.io.js
generated
vendored
|
|
@ -1,136 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var client = require('socket.io-client');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.version = '0.9.5';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Supported protocol version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.protocol = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client that we serve.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.clientVersion = client.version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attaches a manager
|
|
||||||
*
|
|
||||||
* @param {HTTPServer/Number} a HTTP/S server or a port number to listen on.
|
|
||||||
* @param {Object} opts to be passed to Manager and/or http server
|
|
||||||
* @param {Function} callback if a port is supplied
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.listen = function (server, options, fn) {
|
|
||||||
if ('function' == typeof options) {
|
|
||||||
fn = options;
|
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('undefined' == typeof server) {
|
|
||||||
// create a server that listens on port 80
|
|
||||||
server = 80;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('number' == typeof server) {
|
|
||||||
// if a port number is passed
|
|
||||||
var port = server;
|
|
||||||
|
|
||||||
if (options && options.key)
|
|
||||||
server = require('https').createServer(options);
|
|
||||||
else
|
|
||||||
server = require('http').createServer();
|
|
||||||
|
|
||||||
// default response
|
|
||||||
server.on('request', function (req, res) {
|
|
||||||
res.writeHead(200);
|
|
||||||
res.end('Welcome to socket.io.');
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(port, fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise assume a http/s server
|
|
||||||
return new exports.Manager(server, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manager constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.Manager = require('./manager');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.Transport = require('./transport');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.Socket = require('./socket');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.Static = require('./static');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.Store = require('./store');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory Store constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.MemoryStore = require('./stores/memory');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis Store constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.RedisStore = require('./stores/redis');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.parser = require('./parser');
|
|
||||||
369
node_modules/socket.io/lib/socket.js
generated
vendored
369
node_modules/socket.io/lib/socket.js
generated
vendored
|
|
@ -1,369 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var parser = require('./parser')
|
|
||||||
, util = require('./util')
|
|
||||||
, EventEmitter = process.EventEmitter
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = Socket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default error event listener to prevent uncaught exceptions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var defaultError = function () {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket constructor.
|
|
||||||
*
|
|
||||||
* @param {Manager} manager instance
|
|
||||||
* @param {String} session id
|
|
||||||
* @param {Namespace} namespace the socket belongs to
|
|
||||||
* @param {Boolean} whether the
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Socket (manager, id, nsp, readable) {
|
|
||||||
this.id = id;
|
|
||||||
this.namespace = nsp;
|
|
||||||
this.manager = manager;
|
|
||||||
this.disconnected = false;
|
|
||||||
this.ackPackets = 0;
|
|
||||||
this.acks = {};
|
|
||||||
this.setFlags();
|
|
||||||
this.readable = readable;
|
|
||||||
this.store = this.manager.store.client(this.id);
|
|
||||||
this.on('error', defaultError);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from EventEmitter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessor shortcut for the handshake data
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.__defineGetter__('handshake', function () {
|
|
||||||
return this.manager.handshaken[this.id];
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessor shortcut for the transport type
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.__defineGetter__('transport', function () {
|
|
||||||
return this.manager.transports[this.id].name;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessor shortcut for the logger.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.__defineGetter__('log', function () {
|
|
||||||
return this.manager.log;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON message flag.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.__defineGetter__('json', function () {
|
|
||||||
this.flags.json = true;
|
|
||||||
return this;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Volatile message flag.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.__defineGetter__('volatile', function () {
|
|
||||||
this.flags.volatile = true;
|
|
||||||
return this;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Broadcast message flag.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.__defineGetter__('broadcast', function () {
|
|
||||||
this.flags.broadcast = true;
|
|
||||||
return this;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the room to broadcast messages to (flag)
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.to = Socket.prototype.in = function (room) {
|
|
||||||
this.flags.room = room;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets flags
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.setFlags = function () {
|
|
||||||
this.flags = {
|
|
||||||
endpoint: this.namespace.name
|
|
||||||
, room: ''
|
|
||||||
};
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered on disconnect
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.onDisconnect = function (reason) {
|
|
||||||
if (!this.disconnected) {
|
|
||||||
this.$emit('disconnect', reason);
|
|
||||||
this.disconnected = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Joins a user to a room.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.join = function (name, fn) {
|
|
||||||
var nsp = this.namespace.name
|
|
||||||
, name = (nsp + '/') + name;
|
|
||||||
|
|
||||||
this.manager.onJoin(this.id, name);
|
|
||||||
this.manager.store.publish('join', this.id, name);
|
|
||||||
|
|
||||||
if (fn) {
|
|
||||||
this.log.warn('Client#join callback is deprecated');
|
|
||||||
fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Un-joins a user from a room.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.leave = function (name, fn) {
|
|
||||||
var nsp = this.namespace.name
|
|
||||||
, name = (nsp + '/') + name;
|
|
||||||
|
|
||||||
this.manager.onLeave(this.id, name);
|
|
||||||
this.manager.store.publish('leave', this.id, name);
|
|
||||||
|
|
||||||
if (fn) {
|
|
||||||
this.log.warn('Client#leave callback is deprecated');
|
|
||||||
fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transmits a packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.packet = function (packet) {
|
|
||||||
if (this.flags.broadcast) {
|
|
||||||
this.log.debug('broadcasting packet');
|
|
||||||
this.namespace.in(this.flags.room).except(this.id).packet(packet);
|
|
||||||
} else {
|
|
||||||
packet.endpoint = this.flags.endpoint;
|
|
||||||
packet = parser.encodePacket(packet);
|
|
||||||
|
|
||||||
this.dispatch(packet, this.flags.volatile);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setFlags();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a packet
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.dispatch = function (packet, volatile) {
|
|
||||||
if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
|
|
||||||
this.manager.transports[this.id].onDispatch(packet, volatile);
|
|
||||||
} else {
|
|
||||||
if (!volatile) {
|
|
||||||
this.manager.onClientDispatch(this.id, packet, volatile);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.manager.store.publish('dispatch:' + this.id, packet, volatile);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores data for the client.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.set = function (key, value, fn) {
|
|
||||||
this.store.set(key, value, fn);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves data for the client
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.get = function (key, fn) {
|
|
||||||
this.store.get(key, fn);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks data for the client
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.has = function (key, fn) {
|
|
||||||
this.store.has(key, fn);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes data for the client
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.del = function (key, fn) {
|
|
||||||
this.store.del(key, fn);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kicks client
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.disconnect = function () {
|
|
||||||
if (!this.disconnected) {
|
|
||||||
this.log.info('booting client');
|
|
||||||
|
|
||||||
if ('' === this.namespace.name) {
|
|
||||||
if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
|
|
||||||
this.manager.transports[this.id].onForcedDisconnect();
|
|
||||||
} else {
|
|
||||||
this.manager.onClientDisconnect(this.id);
|
|
||||||
this.manager.store.publish('disconnect:' + this.id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.packet({type: 'disconnect'});
|
|
||||||
this.manager.onLeave(this.id, this.namespace.name);
|
|
||||||
this.$emit('disconnect', 'booted');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.send = function (data, fn) {
|
|
||||||
var packet = {
|
|
||||||
type: this.flags.json ? 'json' : 'message'
|
|
||||||
, data: data
|
|
||||||
};
|
|
||||||
|
|
||||||
if (fn) {
|
|
||||||
packet.id = ++this.ackPackets;
|
|
||||||
packet.ack = true;
|
|
||||||
this.acks[packet.id] = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.packet(packet);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Original emit function.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.$emit = EventEmitter.prototype.emit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit override for custom events.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.prototype.emit = function (ev) {
|
|
||||||
if (ev == 'newListener') {
|
|
||||||
return this.$emit.apply(this, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
var args = util.toArray(arguments).slice(1)
|
|
||||||
, lastArg = args[args.length - 1]
|
|
||||||
, packet = {
|
|
||||||
type: 'event'
|
|
||||||
, name: ev
|
|
||||||
};
|
|
||||||
|
|
||||||
if ('function' == typeof lastArg) {
|
|
||||||
packet.id = ++this.ackPackets;
|
|
||||||
packet.ack = lastArg.length ? 'data' : true;
|
|
||||||
this.acks[packet.id] = lastArg;
|
|
||||||
args = args.slice(0, args.length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
packet.args = args;
|
|
||||||
|
|
||||||
return this.packet(packet);
|
|
||||||
};
|
|
||||||
395
node_modules/socket.io/lib/static.js
generated
vendored
395
node_modules/socket.io/lib/static.js
generated
vendored
|
|
@ -1,395 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var client = require('socket.io-client')
|
|
||||||
, cp = require('child_process')
|
|
||||||
, fs = require('fs')
|
|
||||||
, util = require('./util');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File type details.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var mime = {
|
|
||||||
js: {
|
|
||||||
type: 'application/javascript'
|
|
||||||
, encoding: 'utf8'
|
|
||||||
, gzip: true
|
|
||||||
}
|
|
||||||
, swf: {
|
|
||||||
type: 'application/x-shockwave-flash'
|
|
||||||
, encoding: 'binary'
|
|
||||||
, gzip: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regexp for matching custom transport patterns. Users can configure their own
|
|
||||||
* socket.io bundle based on the url structure. Different transport names are
|
|
||||||
* concatinated using the `+` char. /socket.io/socket.io+websocket.js should
|
|
||||||
* create a bundle that only contains support for the websocket.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/
|
|
||||||
, versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = Static;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static constructor
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Static (manager) {
|
|
||||||
this.manager = manager;
|
|
||||||
this.cache = {};
|
|
||||||
this.paths = {};
|
|
||||||
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the Static by adding default file paths.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Static.prototype.init = function () {
|
|
||||||
/**
|
|
||||||
* Generates a unique id based the supplied transports array
|
|
||||||
*
|
|
||||||
* @param {Array} transports The array with transport types
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
function id (transports) {
|
|
||||||
var id = transports.join('').split('').map(function (char) {
|
|
||||||
return ('' + char.charCodeAt(0)).split('').pop();
|
|
||||||
}).reduce(function (char, id) {
|
|
||||||
return char +id;
|
|
||||||
});
|
|
||||||
|
|
||||||
return client.version + ':' + id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a socket.io-client file based on the supplied transports.
|
|
||||||
*
|
|
||||||
* @param {Array} transports The array with transport types
|
|
||||||
* @param {Function} callback Callback for the static.write
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function build (transports, callback) {
|
|
||||||
client.builder(transports, {
|
|
||||||
minify: self.manager.enabled('browser client minification')
|
|
||||||
}, function (err, content) {
|
|
||||||
callback(err, content ? new Buffer(content) : null, id(transports));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// add our default static files
|
|
||||||
this.add('/static/flashsocket/WebSocketMain.swf', {
|
|
||||||
file: client.dist + '/WebSocketMain.swf'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.add('/static/flashsocket/WebSocketMainInsecure.swf', {
|
|
||||||
file: client.dist + '/WebSocketMainInsecure.swf'
|
|
||||||
});
|
|
||||||
|
|
||||||
// generates dedicated build based on the available transports
|
|
||||||
this.add('/socket.io.js', function (path, callback) {
|
|
||||||
build(self.manager.get('transports'), callback);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.add('/socket.io.v', { mime: mime.js }, function (path, callback) {
|
|
||||||
build(self.manager.get('transports'), callback);
|
|
||||||
});
|
|
||||||
|
|
||||||
// allow custom builds based on url paths
|
|
||||||
this.add('/socket.io+', { mime: mime.js }, function (path, callback) {
|
|
||||||
var available = self.manager.get('transports')
|
|
||||||
, matches = path.match(bundle)
|
|
||||||
, transports = [];
|
|
||||||
|
|
||||||
if (!matches) return callback('No valid transports');
|
|
||||||
|
|
||||||
// make sure they valid transports
|
|
||||||
matches[0].split('.')[0].split('+').slice(1).forEach(function (transport) {
|
|
||||||
if (!!~available.indexOf(transport)) {
|
|
||||||
transports.push(transport);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!transports.length) return callback('No valid transports');
|
|
||||||
build(transports, callback);
|
|
||||||
});
|
|
||||||
|
|
||||||
// clear cache when transports change
|
|
||||||
this.manager.on('set:transports', function (key, value) {
|
|
||||||
delete self.cache['/socket.io.js'];
|
|
||||||
Object.keys(self.cache).forEach(function (key) {
|
|
||||||
if (bundle.test(key)) {
|
|
||||||
delete self.cache[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gzip compress buffers.
|
|
||||||
*
|
|
||||||
* @param {Buffer} data The buffer that needs gzip compression
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Static.prototype.gzip = function (data, callback) {
|
|
||||||
var gzip = cp.spawn('gzip', ['-9', '-c', '-f', '-n'])
|
|
||||||
, encoding = Buffer.isBuffer(data) ? 'binary' : 'utf8'
|
|
||||||
, buffer = []
|
|
||||||
, err;
|
|
||||||
|
|
||||||
gzip.stdout.on('data', function (data) {
|
|
||||||
buffer.push(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
gzip.stderr.on('data', function (data) {
|
|
||||||
err = data +'';
|
|
||||||
buffer.length = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
gzip.on('exit', function () {
|
|
||||||
if (err) return callback(err);
|
|
||||||
|
|
||||||
var size = 0
|
|
||||||
, index = 0
|
|
||||||
, i = buffer.length
|
|
||||||
, content;
|
|
||||||
|
|
||||||
while (i--) {
|
|
||||||
size += buffer[i].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
content = new Buffer(size);
|
|
||||||
i = buffer.length;
|
|
||||||
|
|
||||||
buffer.forEach(function (buffer) {
|
|
||||||
var length = buffer.length;
|
|
||||||
|
|
||||||
buffer.copy(content, index, 0, length);
|
|
||||||
index += length;
|
|
||||||
});
|
|
||||||
|
|
||||||
buffer.length = 0;
|
|
||||||
callback(null, content);
|
|
||||||
});
|
|
||||||
|
|
||||||
gzip.stdin.end(data, encoding);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the path a static file?
|
|
||||||
*
|
|
||||||
* @param {String} path The path that needs to be checked
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Static.prototype.has = function (path) {
|
|
||||||
// fast case
|
|
||||||
if (this.paths[path]) return this.paths[path];
|
|
||||||
|
|
||||||
var keys = Object.keys(this.paths)
|
|
||||||
, i = keys.length;
|
|
||||||
|
|
||||||
while (i--) {
|
|
||||||
if (-~path.indexOf(keys[i])) return this.paths[keys[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add new paths new paths that can be served using the static provider.
|
|
||||||
*
|
|
||||||
* @param {String} path The path to respond to
|
|
||||||
* @param {Options} options Options for writing out the response
|
|
||||||
* @param {Function} [callback] Optional callback if no options.file is
|
|
||||||
* supplied this would be called instead.
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Static.prototype.add = function (path, options, callback) {
|
|
||||||
var extension = /(?:\.(\w{1,4}))$/.exec(path);
|
|
||||||
|
|
||||||
if (!callback && typeof options == 'function') {
|
|
||||||
callback = options;
|
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
options.mime = options.mime || (extension ? mime[extension[1]] : false);
|
|
||||||
|
|
||||||
if (callback) options.callback = callback;
|
|
||||||
if (!(options.file || options.callback) || !options.mime) return false;
|
|
||||||
|
|
||||||
this.paths[path] = options;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a static response.
|
|
||||||
*
|
|
||||||
* @param {String} path The path for the static content
|
|
||||||
* @param {HTTPRequest} req The request object
|
|
||||||
* @param {HTTPResponse} res The response object
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Static.prototype.write = function (path, req, res) {
|
|
||||||
/**
|
|
||||||
* Write a response without throwing errors because can throw error if the
|
|
||||||
* response is no longer writable etc.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function write (status, headers, content, encoding) {
|
|
||||||
try {
|
|
||||||
res.writeHead(status, headers || undefined);
|
|
||||||
|
|
||||||
// only write content if it's not a HEAD request and we actually have
|
|
||||||
// some content to write (304's doesn't have content).
|
|
||||||
res.end(
|
|
||||||
req.method !== 'HEAD' && content ? content : ''
|
|
||||||
, encoding || undefined
|
|
||||||
);
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Answers requests depending on the request properties and the reply object.
|
|
||||||
*
|
|
||||||
* @param {Object} reply The details and content to reply the response with
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function answer (reply) {
|
|
||||||
var cached = req.headers['if-none-match'] === reply.etag;
|
|
||||||
if (cached && self.manager.enabled('browser client etag')) {
|
|
||||||
return write(304);
|
|
||||||
}
|
|
||||||
|
|
||||||
var accept = req.headers['accept-encoding'] || ''
|
|
||||||
, gzip = !!~accept.toLowerCase().indexOf('gzip')
|
|
||||||
, mime = reply.mime
|
|
||||||
, versioned = reply.versioned
|
|
||||||
, headers = {
|
|
||||||
'Content-Type': mime.type
|
|
||||||
};
|
|
||||||
|
|
||||||
// check if we can add a etag
|
|
||||||
if (self.manager.enabled('browser client etag') && reply.etag && !versioned) {
|
|
||||||
headers['Etag'] = reply.etag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if we need to set Expire headers because the path is versioned
|
|
||||||
if (versioned) {
|
|
||||||
var expires = self.manager.get('browser client expires');
|
|
||||||
headers['Cache-Control'] = 'private, x-gzip-ok="", max-age=' + expires;
|
|
||||||
headers['Date'] = new Date().toUTCString();
|
|
||||||
headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gzip && reply.gzip) {
|
|
||||||
headers['Content-Length'] = reply.gzip.length;
|
|
||||||
headers['Content-Encoding'] = 'gzip';
|
|
||||||
headers['Vary'] = 'Accept-Encoding';
|
|
||||||
write(200, headers, reply.gzip.content, mime.encoding);
|
|
||||||
} else {
|
|
||||||
headers['Content-Length'] = reply.length;
|
|
||||||
write(200, headers, reply.content, mime.encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.manager.log.debug('served static content ' + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this
|
|
||||||
, details;
|
|
||||||
|
|
||||||
// most common case first
|
|
||||||
if (this.manager.enabled('browser client cache') && this.cache[path]) {
|
|
||||||
return answer(this.cache[path]);
|
|
||||||
} else if (this.manager.get('browser client handler')) {
|
|
||||||
return this.manager.get('browser client handler').call(this, req, res);
|
|
||||||
} else if ((details = this.has(path))) {
|
|
||||||
/**
|
|
||||||
* A small helper function that will let us deal with fs and dynamic files
|
|
||||||
*
|
|
||||||
* @param {Object} err Optional error
|
|
||||||
* @param {Buffer} content The data
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function ready (err, content, etag) {
|
|
||||||
if (err) {
|
|
||||||
self.manager.log.warn('Unable to serve file. ' + (err.message || err));
|
|
||||||
return write(500, null, 'Error serving static ' + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// store the result in the cache
|
|
||||||
var reply = self.cache[path] = {
|
|
||||||
content: content
|
|
||||||
, length: content.length
|
|
||||||
, mime: details.mime
|
|
||||||
, etag: etag || client.version
|
|
||||||
, versioned: versioning.test(path)
|
|
||||||
};
|
|
||||||
|
|
||||||
// check if gzip is enabled
|
|
||||||
if (details.mime.gzip && self.manager.enabled('browser client gzip')) {
|
|
||||||
self.gzip(content, function (err, content) {
|
|
||||||
if (!err) {
|
|
||||||
reply.gzip = {
|
|
||||||
content: content
|
|
||||||
, length: content.length
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
answer(reply);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
answer(reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (details.file) {
|
|
||||||
fs.readFile(details.file, ready);
|
|
||||||
} else if(details.callback) {
|
|
||||||
details.callback.call(this, path, ready);
|
|
||||||
} else {
|
|
||||||
write(404, null, 'File handle not found');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
write(404, null, 'File not found');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
98
node_modules/socket.io/lib/store.js
generated
vendored
98
node_modules/socket.io/lib/store.js
generated
vendored
|
|
@ -1,98 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expose the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = Store;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var EventEmitter = process.EventEmitter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store interface
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Store (options) {
|
|
||||||
this.options = options;
|
|
||||||
this.clients = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherit from EventEmitter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Store.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a client store
|
|
||||||
*
|
|
||||||
* @param {String} id
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Store.prototype.client = function (id) {
|
|
||||||
if (!this.clients[id]) {
|
|
||||||
this.clients[id] = new (this.constructor.Client)(this, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.clients[id];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys a client
|
|
||||||
*
|
|
||||||
* @api {String} sid
|
|
||||||
* @param {Number} number of seconds to expire client data
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Store.prototype.destroyClient = function (id, expiration) {
|
|
||||||
if (this.clients[id]) {
|
|
||||||
this.clients[id].destroy(expiration);
|
|
||||||
delete this.clients[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the store
|
|
||||||
*
|
|
||||||
* @param {Number} number of seconds to expire client data
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Store.prototype.destroy = function (clientExpiration) {
|
|
||||||
var keys = Object.keys(this.clients)
|
|
||||||
, count = keys.length;
|
|
||||||
|
|
||||||
for (var i = 0, l = count; i < l; i++) {
|
|
||||||
this.destroyClient(keys[i], clientExpiration);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.clients = {};
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Store.Client = function (store, id) {
|
|
||||||
this.store = store;
|
|
||||||
this.id = id;
|
|
||||||
};
|
|
||||||
143
node_modules/socket.io/lib/stores/memory.js
generated
vendored
143
node_modules/socket.io/lib/stores/memory.js
generated
vendored
|
|
@ -1,143 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var crypto = require('crypto')
|
|
||||||
, Store = require('../store');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exports the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = Memory;
|
|
||||||
Memory.Client = Client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory store
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Memory (opts) {
|
|
||||||
Store.call(this, opts);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Store.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Memory.prototype.__proto__ = Store.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Publishes a message.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Memory.prototype.publish = function () { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscribes to a channel
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Memory.prototype.subscribe = function () { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsubscribes
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Memory.prototype.unsubscribe = function () { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client constructor
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Client () {
|
|
||||||
Store.Client.apply(this, arguments);
|
|
||||||
this.data = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Store.Client
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.__proto__ = Store.Client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a key
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.get = function (key, fn) {
|
|
||||||
fn(null, this.data[key] === undefined ? null : this.data[key]);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a key
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.set = function (key, value, fn) {
|
|
||||||
this.data[key] = value;
|
|
||||||
fn && fn(null);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Has a key
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.has = function (key, fn) {
|
|
||||||
fn(null, key in this.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a key
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.del = function (key, fn) {
|
|
||||||
delete this.data[key];
|
|
||||||
fn && fn(null);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the client.
|
|
||||||
*
|
|
||||||
* @param {Number} number of seconds to expire data
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.destroy = function (expiration) {
|
|
||||||
if ('number' != typeof expiration) {
|
|
||||||
this.data = {};
|
|
||||||
} else {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
self.data = {};
|
|
||||||
}, expiration * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
269
node_modules/socket.io/lib/stores/redis.js
generated
vendored
269
node_modules/socket.io/lib/stores/redis.js
generated
vendored
|
|
@ -1,269 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var crypto = require('crypto')
|
|
||||||
, Store = require('../store')
|
|
||||||
, assert = require('assert');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exports the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = Redis;
|
|
||||||
Redis.Client = Client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis store.
|
|
||||||
* Options:
|
|
||||||
* - nodeId (fn) gets an id that uniquely identifies this node
|
|
||||||
* - redis (fn) redis constructor, defaults to redis
|
|
||||||
* - redisPub (object) options to pass to the pub redis client
|
|
||||||
* - redisSub (object) options to pass to the sub redis client
|
|
||||||
* - redisClient (object) options to pass to the general redis client
|
|
||||||
* - pack (fn) custom packing, defaults to JSON or msgpack if installed
|
|
||||||
* - unpack (fn) custom packing, defaults to JSON or msgpack if installed
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Redis (opts) {
|
|
||||||
opts = opts || {};
|
|
||||||
|
|
||||||
// node id to uniquely identify this node
|
|
||||||
var nodeId = opts.nodeId || function () {
|
|
||||||
// by default, we generate a random id
|
|
||||||
return Math.abs(Math.random() * Math.random() * Date.now() | 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.nodeId = nodeId();
|
|
||||||
|
|
||||||
// packing / unpacking mechanism
|
|
||||||
if (opts.pack) {
|
|
||||||
this.pack = opts.pack;
|
|
||||||
this.unpack = opts.unpack;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
var msgpack = require('msgpack');
|
|
||||||
this.pack = msgpack.pack;
|
|
||||||
this.unpack = msgpack.unpack;
|
|
||||||
} catch (e) {
|
|
||||||
this.pack = JSON.stringify;
|
|
||||||
this.unpack = JSON.parse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var redis = opts.redis || require('redis')
|
|
||||||
, RedisClient = redis.RedisClient;
|
|
||||||
|
|
||||||
// initialize a pubsub client and a regular client
|
|
||||||
if (opts.redisPub instanceof RedisClient) {
|
|
||||||
this.pub = opts.redisPub;
|
|
||||||
} else {
|
|
||||||
opts.redisPub || (opts.redisPub = {});
|
|
||||||
this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
|
|
||||||
}
|
|
||||||
if (opts.redisSub instanceof RedisClient) {
|
|
||||||
this.sub = opts.redisSub;
|
|
||||||
} else {
|
|
||||||
opts.redisSub || (opts.redisSub = {});
|
|
||||||
this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
|
|
||||||
}
|
|
||||||
if (opts.redisClient instanceof RedisClient) {
|
|
||||||
this.cmd = opts.redisClient;
|
|
||||||
} else {
|
|
||||||
opts.redisClient || (opts.redisClient = {});
|
|
||||||
this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
Store.call(this, opts);
|
|
||||||
|
|
||||||
this.sub.setMaxListeners(0);
|
|
||||||
this.setMaxListeners(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Store.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Redis.prototype.__proto__ = Store.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Publishes a message.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Redis.prototype.publish = function (name) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args }));
|
|
||||||
this.emit.apply(this, ['publish', name].concat(args));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscribes to a channel
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Redis.prototype.subscribe = function (name, consumer, fn) {
|
|
||||||
this.sub.subscribe(name);
|
|
||||||
|
|
||||||
if (consumer || fn) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.sub.on('subscribe', function subscribe (ch) {
|
|
||||||
if (name == ch) {
|
|
||||||
function message (ch, msg) {
|
|
||||||
if (name == ch) {
|
|
||||||
msg = self.unpack(msg);
|
|
||||||
|
|
||||||
// we check that the message consumed wasnt emitted by this node
|
|
||||||
if (self.nodeId != msg.nodeId) {
|
|
||||||
consumer.apply(null, msg.args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.sub.on('message', message);
|
|
||||||
|
|
||||||
self.on('unsubscribe', function unsubscribe (ch) {
|
|
||||||
if (name == ch) {
|
|
||||||
self.sub.removeListener('message', message);
|
|
||||||
self.removeListener('unsubscribe', unsubscribe);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
self.sub.removeListener('subscribe', subscribe);
|
|
||||||
|
|
||||||
fn && fn();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('subscribe', name, consumer, fn);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsubscribes
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Redis.prototype.unsubscribe = function (name, fn) {
|
|
||||||
this.sub.unsubscribe(name);
|
|
||||||
|
|
||||||
if (fn) {
|
|
||||||
var client = this.sub;
|
|
||||||
|
|
||||||
client.on('unsubscribe', function unsubscribe (ch) {
|
|
||||||
if (name == ch) {
|
|
||||||
fn();
|
|
||||||
client.removeListener('unsubscribe', unsubscribe);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('unsubscribe', name, fn);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the store
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Redis.prototype.destroy = function () {
|
|
||||||
Store.prototype.destroy.call(this);
|
|
||||||
|
|
||||||
this.pub.end();
|
|
||||||
this.sub.end();
|
|
||||||
this.cmd.end();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client constructor
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Client (store, id) {
|
|
||||||
Store.Client.call(this, store, id);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Store.Client
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.__proto__ = Store.Client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis hash get
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.get = function (key, fn) {
|
|
||||||
this.store.cmd.hget(this.id, key, fn);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis hash set
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.set = function (key, value, fn) {
|
|
||||||
this.store.cmd.hset(this.id, key, value, fn);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis hash del
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.del = function (key, fn) {
|
|
||||||
this.store.cmd.hdel(this.id, key, fn);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis hash has
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.has = function (key, fn) {
|
|
||||||
this.store.cmd.hexists(this.id, key, function (err, has) {
|
|
||||||
if (err) return fn(err);
|
|
||||||
fn(null, !!has);
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys client
|
|
||||||
*
|
|
||||||
* @param {Number} number of seconds to expire data
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Client.prototype.destroy = function (expiration) {
|
|
||||||
if ('number' != typeof expiration) {
|
|
||||||
this.store.cmd.del(this.id);
|
|
||||||
} else {
|
|
||||||
this.store.cmd.expire(this.id, expiration);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
534
node_modules/socket.io/lib/transport.js
generated
vendored
534
node_modules/socket.io/lib/transport.js
generated
vendored
|
|
@ -1,534 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var parser = require('./parser');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expose the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = Transport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Transport (mng, data, req) {
|
|
||||||
this.manager = mng;
|
|
||||||
this.id = data.id;
|
|
||||||
this.disconnected = false;
|
|
||||||
this.drained = true;
|
|
||||||
this.handleRequest(req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access the logger.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.__defineGetter__('log', function () {
|
|
||||||
return this.manager.log;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access the store.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.__defineGetter__('store', function () {
|
|
||||||
return this.manager.store;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a request when it's set.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.handleRequest = function (req) {
|
|
||||||
this.log.debug('setting request', req.method, req.url);
|
|
||||||
this.req = req;
|
|
||||||
|
|
||||||
if (req.method == 'GET') {
|
|
||||||
this.socket = req.socket;
|
|
||||||
this.open = true;
|
|
||||||
this.drained = true;
|
|
||||||
this.setHeartbeatInterval();
|
|
||||||
|
|
||||||
this.setHandlers();
|
|
||||||
this.onSocketConnect();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a connection is first set.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onSocketConnect = function () { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets transport handlers
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.setHandlers = function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// we need to do this in a pub/sub way since the client can POST the message
|
|
||||||
// over a different socket (ie: different Transport instance)
|
|
||||||
this.store.subscribe('heartbeat-clear:' + this.id, function () {
|
|
||||||
self.onHeartbeatClear();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('disconnect-force:' + this.id, function () {
|
|
||||||
self.onForcedDisconnect();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.subscribe('dispatch:' + this.id, function (packet, volatile) {
|
|
||||||
self.onDispatch(packet, volatile);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.bound = {
|
|
||||||
end: this.onSocketEnd.bind(this)
|
|
||||||
, close: this.onSocketClose.bind(this)
|
|
||||||
, error: this.onSocketError.bind(this)
|
|
||||||
, drain: this.onSocketDrain.bind(this)
|
|
||||||
};
|
|
||||||
|
|
||||||
this.socket.on('end', this.bound.end);
|
|
||||||
this.socket.on('close', this.bound.close);
|
|
||||||
this.socket.on('error', this.bound.error);
|
|
||||||
this.socket.on('drain', this.bound.drain);
|
|
||||||
|
|
||||||
this.handlersSet = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes transport handlers
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.clearHandlers = function () {
|
|
||||||
if (this.handlersSet) {
|
|
||||||
this.store.unsubscribe('disconnect-force:' + this.id);
|
|
||||||
this.store.unsubscribe('heartbeat-clear:' + this.id);
|
|
||||||
this.store.unsubscribe('dispatch:' + this.id);
|
|
||||||
|
|
||||||
this.socket.removeListener('end', this.bound.end);
|
|
||||||
this.socket.removeListener('close', this.bound.close);
|
|
||||||
this.socket.removeListener('error', this.bound.error);
|
|
||||||
this.socket.removeListener('drain', this.bound.drain);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the connection dies
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onSocketEnd = function () {
|
|
||||||
this.end('socket end');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the connection dies
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onSocketClose = function (error) {
|
|
||||||
this.end(error ? 'socket error' : 'socket close');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the connection has an error.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onSocketError = function (err) {
|
|
||||||
if (this.open) {
|
|
||||||
this.socket.destroy();
|
|
||||||
this.onClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.info('socket error ' + err.stack);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the connection is drained.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onSocketDrain = function () {
|
|
||||||
this.drained = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called upon receiving a heartbeat packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onHeartbeatClear = function () {
|
|
||||||
this.clearHeartbeatTimeout();
|
|
||||||
this.setHeartbeatInterval();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called upon a forced disconnection.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onForcedDisconnect = function () {
|
|
||||||
if (!this.disconnected) {
|
|
||||||
this.log.info('transport end by forced client disconnection');
|
|
||||||
if (this.open) {
|
|
||||||
this.packet({ type: 'disconnect' });
|
|
||||||
}
|
|
||||||
this.end('booted');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onDispatch = function (packet, volatile) {
|
|
||||||
if (volatile) {
|
|
||||||
this.writeVolatile(packet);
|
|
||||||
} else {
|
|
||||||
this.write(packet);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the close timeout.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.setCloseTimeout = function () {
|
|
||||||
if (!this.closeTimeout) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.closeTimeout = setTimeout(function () {
|
|
||||||
self.log.debug('fired close timeout for client', self.id);
|
|
||||||
self.closeTimeout = null;
|
|
||||||
self.end('close timeout');
|
|
||||||
}, this.manager.get('close timeout') * 1000);
|
|
||||||
|
|
||||||
this.log.debug('set close timeout for client', this.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the close timeout.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.clearCloseTimeout = function () {
|
|
||||||
if (this.closeTimeout) {
|
|
||||||
clearTimeout(this.closeTimeout);
|
|
||||||
this.closeTimeout = null;
|
|
||||||
|
|
||||||
this.log.debug('cleared close timeout for client', this.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the heartbeat timeout
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.setHeartbeatTimeout = function () {
|
|
||||||
if (!this.heartbeatTimeout && this.manager.enabled('heartbeats')) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.heartbeatTimeout = setTimeout(function () {
|
|
||||||
self.log.debug('fired heartbeat timeout for client', self.id);
|
|
||||||
self.heartbeatTimeout = null;
|
|
||||||
self.end('heartbeat timeout');
|
|
||||||
}, this.manager.get('heartbeat timeout') * 1000);
|
|
||||||
|
|
||||||
this.log.debug('set heartbeat timeout for client', this.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the heartbeat timeout
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.clearHeartbeatTimeout = function () {
|
|
||||||
if (this.heartbeatTimeout && this.manager.enabled('heartbeats')) {
|
|
||||||
clearTimeout(this.heartbeatTimeout);
|
|
||||||
this.heartbeatTimeout = null;
|
|
||||||
this.log.debug('cleared heartbeat timeout for client', this.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the heartbeat interval. To be called when a connection opens and when
|
|
||||||
* a heartbeat is received.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.setHeartbeatInterval = function () {
|
|
||||||
if (!this.heartbeatInterval && this.manager.enabled('heartbeats')) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.heartbeatInterval = setTimeout(function () {
|
|
||||||
self.heartbeat();
|
|
||||||
self.heartbeatInterval = null;
|
|
||||||
}, this.manager.get('heartbeat interval') * 1000);
|
|
||||||
|
|
||||||
this.log.debug('set heartbeat interval for client', this.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears all timeouts.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.clearTimeouts = function () {
|
|
||||||
this.clearCloseTimeout();
|
|
||||||
this.clearHeartbeatTimeout();
|
|
||||||
this.clearHeartbeatInterval();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a heartbeat
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.heartbeat = function () {
|
|
||||||
if (this.open) {
|
|
||||||
this.log.debug('emitting heartbeat for client', this.id);
|
|
||||||
this.packet({ type: 'heartbeat' });
|
|
||||||
this.setHeartbeatTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a message.
|
|
||||||
*
|
|
||||||
* @param {Object} packet object
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onMessage = function (packet) {
|
|
||||||
var current = this.manager.transports[this.id];
|
|
||||||
|
|
||||||
if ('heartbeat' == packet.type) {
|
|
||||||
this.log.debug('got heartbeat packet');
|
|
||||||
|
|
||||||
if (current && current.open) {
|
|
||||||
current.onHeartbeatClear();
|
|
||||||
} else {
|
|
||||||
this.store.publish('heartbeat-clear:' + this.id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ('disconnect' == packet.type && packet.endpoint == '') {
|
|
||||||
this.log.debug('got disconnection packet');
|
|
||||||
|
|
||||||
if (current) {
|
|
||||||
current.onForcedDisconnect();
|
|
||||||
} else {
|
|
||||||
this.store.publish('disconnect-force:' + this.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.id && packet.ack != 'data') {
|
|
||||||
this.log.debug('acknowledging packet automatically');
|
|
||||||
|
|
||||||
var ack = parser.encodePacket({
|
|
||||||
type: 'ack'
|
|
||||||
, ackId: packet.id
|
|
||||||
, endpoint: packet.endpoint || ''
|
|
||||||
});
|
|
||||||
|
|
||||||
if (current && current.open) {
|
|
||||||
current.onDispatch(ack);
|
|
||||||
} else {
|
|
||||||
this.manager.onClientDispatch(this.id, ack);
|
|
||||||
this.store.publish('dispatch:' + this.id, ack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle packet locally or publish it
|
|
||||||
if (current) {
|
|
||||||
this.manager.onClientMessage(this.id, packet);
|
|
||||||
} else {
|
|
||||||
this.store.publish('message:' + this.id, packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the heartbeat interval
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.clearHeartbeatInterval = function () {
|
|
||||||
if (this.heartbeatInterval && this.manager.enabled('heartbeats')) {
|
|
||||||
clearTimeout(this.heartbeatInterval);
|
|
||||||
this.heartbeatInterval = null;
|
|
||||||
this.log.debug('cleared heartbeat interval for client', this.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finishes the connection and makes sure client doesn't reopen
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.disconnect = function (reason) {
|
|
||||||
this.packet({ type: 'disconnect' });
|
|
||||||
this.end(reason);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the connection.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.close = function () {
|
|
||||||
if (this.open) {
|
|
||||||
this.doClose();
|
|
||||||
this.onClose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called upon a connection close.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.onClose = function () {
|
|
||||||
if (this.open) {
|
|
||||||
this.setCloseTimeout();
|
|
||||||
this.clearHandlers();
|
|
||||||
this.open = false;
|
|
||||||
this.manager.onClose(this.id);
|
|
||||||
this.store.publish('close', this.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up the connection, considers the client disconnected.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.end = function (reason) {
|
|
||||||
if (!this.disconnected) {
|
|
||||||
this.log.info('transport end (' + reason + ')');
|
|
||||||
|
|
||||||
var local = this.manager.transports[this.id];
|
|
||||||
|
|
||||||
this.close();
|
|
||||||
this.clearTimeouts();
|
|
||||||
this.disconnected = true;
|
|
||||||
|
|
||||||
if (local) {
|
|
||||||
this.manager.onClientDisconnect(this.id, reason, true);
|
|
||||||
} else {
|
|
||||||
this.store.publish('disconnect:' + this.id, reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals that the transport should pause and buffer data.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.discard = function () {
|
|
||||||
this.log.debug('discarding transport');
|
|
||||||
this.discarded = true;
|
|
||||||
this.clearTimeouts();
|
|
||||||
this.clearHandlers();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an error packet with the specified reason and advice.
|
|
||||||
*
|
|
||||||
* @param {Number} advice
|
|
||||||
* @param {Number} reason
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.error = function (reason, advice) {
|
|
||||||
this.packet({
|
|
||||||
type: 'error'
|
|
||||||
, reason: reason
|
|
||||||
, advice: advice
|
|
||||||
});
|
|
||||||
|
|
||||||
this.log.warn(reason, advice ? ('client should ' + advice) : '');
|
|
||||||
this.end('error');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a packet.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.packet = function (obj) {
|
|
||||||
return this.write(parser.encodePacket(obj));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a volatile message.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Transport.prototype.writeVolatile = function (msg) {
|
|
||||||
if (this.open) {
|
|
||||||
if (this.drained) {
|
|
||||||
this.write(msg);
|
|
||||||
} else {
|
|
||||||
this.log.debug('ignoring volatile packet, buffer not drained');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.log.debug('ignoring volatile packet, transport not open');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
106
node_modules/socket.io/lib/transports/flashsocket.js
generated
vendored
106
node_modules/socket.io/lib/transports/flashsocket.js
generated
vendored
|
|
@ -1,106 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
var WebSocket = require('./websocket');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = FlashSocket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The FlashSocket transport is just a proxy
|
|
||||||
* for WebSocket connections.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function FlashSocket (mng, data, req) {
|
|
||||||
return WebSocket.call(this, mng, data, req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from WebSocket.
|
|
||||||
*/
|
|
||||||
|
|
||||||
FlashSocket.prototype.__proto__ = WebSocket.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
FlashSocket.prototype.name = 'flashsocket';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listens for new configuration changes of the Manager
|
|
||||||
* this way we can enable and disable the flash server.
|
|
||||||
*
|
|
||||||
* @param {Manager} Manager instance.
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
FlashSocket.init = function (manager) {
|
|
||||||
var server;
|
|
||||||
function create () {
|
|
||||||
server = require('policyfile').createServer({
|
|
||||||
log: function(msg){
|
|
||||||
manager.log.info(msg.toLowerCase());
|
|
||||||
}
|
|
||||||
}, manager.get('origins'));
|
|
||||||
|
|
||||||
server.on('close', function (e) {
|
|
||||||
server = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(manager.get('flash policy port'), manager.server);
|
|
||||||
|
|
||||||
manager.flashPolicyServer = server;
|
|
||||||
}
|
|
||||||
|
|
||||||
// listen for origin changes, so we can update the server
|
|
||||||
manager.on('set:origins', function (value, key) {
|
|
||||||
if (!server) return;
|
|
||||||
|
|
||||||
// update the origins and compile a new response buffer
|
|
||||||
server.origins = Array.isArray(value) ? value : [value];
|
|
||||||
server.compile();
|
|
||||||
});
|
|
||||||
|
|
||||||
// destory the server and create a new server
|
|
||||||
manager.on('set:flash policy port', function (value, key) {
|
|
||||||
var transports = manager.get('transports');
|
|
||||||
if (~transports.indexOf('flashsocket')) {
|
|
||||||
if (server) {
|
|
||||||
if (server.port === value) return;
|
|
||||||
// destroy the server and rebuild it on a new port
|
|
||||||
try {
|
|
||||||
server.close();
|
|
||||||
}
|
|
||||||
catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ }
|
|
||||||
}
|
|
||||||
create();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// only start the server
|
|
||||||
manager.on('set:transports', function (value, key){
|
|
||||||
if (!server && ~manager.get('transports').indexOf('flashsocket')) {
|
|
||||||
create();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// check if we need to initialize at start
|
|
||||||
if (~manager.get('transports').indexOf('flashsocket')){
|
|
||||||
create();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
82
node_modules/socket.io/lib/transports/htmlfile.js
generated
vendored
82
node_modules/socket.io/lib/transports/htmlfile.js
generated
vendored
|
|
@ -1,82 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var HTTPTransport = require('./http');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = HTMLFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTMLFile transport constructor.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function HTMLFile (mng, data, req) {
|
|
||||||
HTTPTransport.call(this, mng, data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Transport.
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTMLFile.prototype.__proto__ = HTTPTransport.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTMLFile.prototype.name = 'htmlfile';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the request.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTMLFile.prototype.handleRequest = function (req) {
|
|
||||||
HTTPTransport.prototype.handleRequest.call(this, req);
|
|
||||||
|
|
||||||
if (req.method == 'GET') {
|
|
||||||
req.res.writeHead(200, {
|
|
||||||
'Content-Type': 'text/html; charset=UTF-8'
|
|
||||||
, 'Connection': 'keep-alive'
|
|
||||||
, 'Transfer-Encoding': 'chunked'
|
|
||||||
});
|
|
||||||
|
|
||||||
req.res.write(
|
|
||||||
'<html><body>'
|
|
||||||
+ '<script>var _ = function (msg) { parent.s._(msg, document); };</script>'
|
|
||||||
+ new Array(174).join(' ')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs the write.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTMLFile.prototype.write = function (data) {
|
|
||||||
data = '<script>_(' + JSON.stringify(data) + ');</script>';
|
|
||||||
|
|
||||||
if (this.response.write(data)) {
|
|
||||||
this.drained = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.debug(this.name + ' writing', data);
|
|
||||||
};
|
|
||||||
147
node_modules/socket.io/lib/transports/http-polling.js
generated
vendored
147
node_modules/socket.io/lib/transports/http-polling.js
generated
vendored
|
|
@ -1,147 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var HTTPTransport = require('./http');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exports the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = HTTPPolling;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP polling constructor.
|
|
||||||
*
|
|
||||||
* @api public.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function HTTPPolling (mng, data, req) {
|
|
||||||
HTTPTransport.call(this, mng, data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from HTTPTransport.
|
|
||||||
*
|
|
||||||
* @api public.
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.__proto__ = HTTPTransport.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.name = 'httppolling';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override setHandlers
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.setHandlers = function () {
|
|
||||||
HTTPTransport.prototype.setHandlers.call(this);
|
|
||||||
this.socket.removeListener('end', this.bound.end);
|
|
||||||
this.socket.removeListener('close', this.bound.close);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes heartbeat timeouts for polling.
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.setHeartbeatInterval = function () {
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a request
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.handleRequest = function (req) {
|
|
||||||
HTTPTransport.prototype.handleRequest.call(this, req);
|
|
||||||
|
|
||||||
if (req.method == 'GET') {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.pollTimeout = setTimeout(function () {
|
|
||||||
self.packet({ type: 'noop' });
|
|
||||||
self.log.debug(self.name + ' closed due to exceeded duration');
|
|
||||||
}, this.manager.get('polling duration') * 1000);
|
|
||||||
|
|
||||||
this.log.debug('setting poll timeout');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears polling timeout
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.clearPollTimeout = function () {
|
|
||||||
if (this.pollTimeout) {
|
|
||||||
clearTimeout(this.pollTimeout);
|
|
||||||
this.pollTimeout = null;
|
|
||||||
this.log.debug('clearing poll timeout');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override clear timeouts to clear the poll timeout
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.clearTimeouts = function () {
|
|
||||||
HTTPTransport.prototype.clearTimeouts.call(this);
|
|
||||||
|
|
||||||
this.clearPollTimeout();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* doWrite to clear poll timeout
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.doWrite = function () {
|
|
||||||
this.clearPollTimeout();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs a write.
|
|
||||||
*
|
|
||||||
* @api private.
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.write = function (data, close) {
|
|
||||||
this.doWrite(data);
|
|
||||||
this.response.end();
|
|
||||||
this.onClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override end.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPPolling.prototype.end = function (reason) {
|
|
||||||
this.clearPollTimeout();
|
|
||||||
return HTTPTransport.prototype.end.call(this, reason);
|
|
||||||
};
|
|
||||||
|
|
||||||
119
node_modules/socket.io/lib/transports/http.js
generated
vendored
119
node_modules/socket.io/lib/transports/http.js
generated
vendored
|
|
@ -1,119 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Transport = require('../transport')
|
|
||||||
, parser = require('../parser')
|
|
||||||
, qs = require('querystring');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = HTTPTransport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP interface constructor. For all non-websocket transports.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function HTTPTransport (mng, data, req) {
|
|
||||||
Transport.call(this, mng, data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Transport.
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPTransport.prototype.__proto__ = Transport.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a request.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPTransport.prototype.handleRequest = function (req) {
|
|
||||||
if (req.method == 'POST') {
|
|
||||||
var buffer = ''
|
|
||||||
, res = req.res
|
|
||||||
, origin = req.headers.origin
|
|
||||||
, headers = { 'Content-Length': 1, 'Content-Type': 'text/plain; charset=UTF-8' }
|
|
||||||
, self = this;
|
|
||||||
|
|
||||||
req.on('data', function (data) {
|
|
||||||
buffer += data;
|
|
||||||
|
|
||||||
if (Buffer.byteLength(buffer) >= self.manager.get('destroy buffer size')) {
|
|
||||||
buffer = '';
|
|
||||||
req.connection.destroy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('end', function () {
|
|
||||||
res.writeHead(200, headers);
|
|
||||||
res.end('1');
|
|
||||||
|
|
||||||
self.onData(self.postEncoded ? qs.parse(buffer).d : buffer);
|
|
||||||
});
|
|
||||||
|
|
||||||
// prevent memory leaks for uncompleted requests
|
|
||||||
req.on('close', function () {
|
|
||||||
buffer = '';
|
|
||||||
self.onClose();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (origin) {
|
|
||||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
|
||||||
headers['Access-Control-Allow-Origin'] = origin;
|
|
||||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.response = req.res;
|
|
||||||
|
|
||||||
Transport.prototype.handleRequest.call(this, req);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles data payload.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPTransport.prototype.onData = function (data) {
|
|
||||||
var messages = parser.decodePayload(data);
|
|
||||||
this.log.debug(this.name + ' received data packet', data);
|
|
||||||
|
|
||||||
for (var i = 0, l = messages.length; i < l; i++) {
|
|
||||||
this.onMessage(messages[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the request-response cycle
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPTransport.prototype.doClose = function () {
|
|
||||||
this.response.end();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a payload of messages
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPTransport.prototype.payload = function (msgs) {
|
|
||||||
this.write(parser.encodePayload(msgs));
|
|
||||||
};
|
|
||||||
12
node_modules/socket.io/lib/transports/index.js
generated
vendored
12
node_modules/socket.io/lib/transports/index.js
generated
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Export transports.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
websocket: require('./websocket')
|
|
||||||
, flashsocket: require('./flashsocket')
|
|
||||||
, htmlfile: require('./htmlfile')
|
|
||||||
, 'xhr-polling': require('./xhr-polling')
|
|
||||||
, 'jsonp-polling': require('./jsonp-polling')
|
|
||||||
};
|
|
||||||
97
node_modules/socket.io/lib/transports/jsonp-polling.js
generated
vendored
97
node_modules/socket.io/lib/transports/jsonp-polling.js
generated
vendored
|
|
@ -1,97 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var HTTPPolling = require('./http-polling');
|
|
||||||
var jsonpolling_re = /^\d+$/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = JSONPPolling;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON-P polling transport.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function JSONPPolling (mng, data, req) {
|
|
||||||
HTTPPolling.call(this, mng, data, req);
|
|
||||||
|
|
||||||
this.head = 'io.j[0](';
|
|
||||||
this.foot = ');';
|
|
||||||
|
|
||||||
if (data.query.i && jsonpolling_re.test(data.query.i)) {
|
|
||||||
this.head = 'io.j[' + data.query.i + '](';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Transport.
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSONPPolling.prototype.__proto__ = HTTPPolling.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSONPPolling.prototype.name = 'jsonppolling';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure POST are decoded.
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSONPPolling.prototype.postEncoded = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles incoming data.
|
|
||||||
* Due to a bug in \n handling by browsers, we expect a JSONified string.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSONPPolling.prototype.onData = function (data) {
|
|
||||||
try {
|
|
||||||
data = JSON.parse(data);
|
|
||||||
} catch (e) {
|
|
||||||
this.error('parse', 'reconnect');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPPolling.prototype.onData.call(this, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs the write.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
JSONPPolling.prototype.doWrite = function (data) {
|
|
||||||
HTTPPolling.prototype.doWrite.call(this);
|
|
||||||
|
|
||||||
var data = data === undefined
|
|
||||||
? '' : this.head + JSON.stringify(data) + this.foot;
|
|
||||||
|
|
||||||
this.response.writeHead(200, {
|
|
||||||
'Content-Type': 'text/javascript; charset=UTF-8'
|
|
||||||
, 'Content-Length': Buffer.byteLength(data)
|
|
||||||
, 'Connection': 'Keep-Alive'
|
|
||||||
, 'X-XSS-Protection': '0'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.response.write(data);
|
|
||||||
this.log.debug(this.name + ' writing', data);
|
|
||||||
};
|
|
||||||
36
node_modules/socket.io/lib/transports/websocket.js
generated
vendored
36
node_modules/socket.io/lib/transports/websocket.js
generated
vendored
|
|
@ -1,36 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var protocolVersions = require('./websocket/');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = WebSocket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP interface constructor. Interface compatible with all transports that
|
|
||||||
* depend on request-response cycles.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function WebSocket (mng, data, req) {
|
|
||||||
var transport
|
|
||||||
, version = req.headers['sec-websocket-version'];
|
|
||||||
if (typeof version !== 'undefined' && typeof protocolVersions[version] !== 'undefined') {
|
|
||||||
transport = new protocolVersions[version](mng, data, req);
|
|
||||||
}
|
|
||||||
else transport = new protocolVersions['default'](mng, data, req);
|
|
||||||
if (typeof this.name !== 'undefined') transport.name = this.name;
|
|
||||||
return transport;
|
|
||||||
};
|
|
||||||
360
node_modules/socket.io/lib/transports/websocket/default.js
generated
vendored
360
node_modules/socket.io/lib/transports/websocket/default.js
generated
vendored
|
|
@ -1,360 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Transport = require('../../transport')
|
|
||||||
, EventEmitter = process.EventEmitter
|
|
||||||
, crypto = require('crypto')
|
|
||||||
, parser = require('../../parser');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = WebSocket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP interface constructor. Interface compatible with all transports that
|
|
||||||
* depend on request-response cycles.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function WebSocket (mng, data, req) {
|
|
||||||
// parser
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.parser = new Parser();
|
|
||||||
this.parser.on('data', function (packet) {
|
|
||||||
self.log.debug(self.name + ' received data packet', packet);
|
|
||||||
self.onMessage(parser.decodePacket(packet));
|
|
||||||
});
|
|
||||||
this.parser.on('close', function () {
|
|
||||||
self.end();
|
|
||||||
});
|
|
||||||
this.parser.on('error', function () {
|
|
||||||
self.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
Transport.call(this, mng, data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Transport.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.__proto__ = Transport.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.name = 'websocket';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Websocket draft version
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.protocolVersion = 'hixie-76';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the socket connects.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.onSocketConnect = function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.socket.setNoDelay(true);
|
|
||||||
|
|
||||||
this.buffer = true;
|
|
||||||
this.buffered = [];
|
|
||||||
|
|
||||||
if (this.req.headers.upgrade !== 'WebSocket') {
|
|
||||||
this.log.warn(this.name + ' connection invalid');
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var origin = this.req.headers['origin']
|
|
||||||
, location = ((this.manager.settings['match origin protocol'] ?
|
|
||||||
origin.match(/^https/) : this.socket.encrypted) ?
|
|
||||||
'wss' : 'ws')
|
|
||||||
+ '://' + this.req.headers.host + this.req.url
|
|
||||||
, waitingForNonce = false;
|
|
||||||
|
|
||||||
if (this.req.headers['sec-websocket-key1']) {
|
|
||||||
// If we don't have the nonce yet, wait for it (HAProxy compatibility).
|
|
||||||
if (! (this.req.head && this.req.head.length >= 8)) {
|
|
||||||
waitingForNonce = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var headers = [
|
|
||||||
'HTTP/1.1 101 WebSocket Protocol Handshake'
|
|
||||||
, 'Upgrade: WebSocket'
|
|
||||||
, 'Connection: Upgrade'
|
|
||||||
, 'Sec-WebSocket-Origin: ' + origin
|
|
||||||
, 'Sec-WebSocket-Location: ' + location
|
|
||||||
];
|
|
||||||
|
|
||||||
if (this.req.headers['sec-websocket-protocol']){
|
|
||||||
headers.push('Sec-WebSocket-Protocol: '
|
|
||||||
+ this.req.headers['sec-websocket-protocol']);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var headers = [
|
|
||||||
'HTTP/1.1 101 Web Socket Protocol Handshake'
|
|
||||||
, 'Upgrade: WebSocket'
|
|
||||||
, 'Connection: Upgrade'
|
|
||||||
, 'WebSocket-Origin: ' + origin
|
|
||||||
, 'WebSocket-Location: ' + location
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.socket.write(headers.concat('', '').join('\r\n'));
|
|
||||||
this.socket.setTimeout(0);
|
|
||||||
this.socket.setNoDelay(true);
|
|
||||||
this.socket.setEncoding('utf8');
|
|
||||||
} catch (e) {
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitingForNonce) {
|
|
||||||
this.socket.setEncoding('binary');
|
|
||||||
} else if (this.proveReception(headers)) {
|
|
||||||
self.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
var headBuffer = '';
|
|
||||||
|
|
||||||
this.socket.on('data', function (data) {
|
|
||||||
if (waitingForNonce) {
|
|
||||||
headBuffer += data;
|
|
||||||
|
|
||||||
if (headBuffer.length < 8) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the connection to utf8 encoding after receiving the nonce
|
|
||||||
self.socket.setEncoding('utf8');
|
|
||||||
waitingForNonce = false;
|
|
||||||
|
|
||||||
// Stuff the nonce into the location where it's expected to be
|
|
||||||
self.req.head = headBuffer.substr(0, 8);
|
|
||||||
headBuffer = '';
|
|
||||||
|
|
||||||
if (self.proveReception(headers)) {
|
|
||||||
self.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.parser.add(data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes to the socket.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.write = function (data) {
|
|
||||||
if (this.open) {
|
|
||||||
this.drained = false;
|
|
||||||
|
|
||||||
if (this.buffer) {
|
|
||||||
this.buffered.push(data);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
var length = Buffer.byteLength(data)
|
|
||||||
, buffer = new Buffer(2 + length);
|
|
||||||
|
|
||||||
buffer.write('\x00', 'binary');
|
|
||||||
buffer.write(data, 1, 'utf8');
|
|
||||||
buffer.write('\xff', 1 + length, 'binary');
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (this.socket.write(buffer)) {
|
|
||||||
this.drained = true;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.debug(this.name + ' writing', data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flushes the internal buffer
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.flush = function () {
|
|
||||||
this.buffer = false;
|
|
||||||
|
|
||||||
for (var i = 0, l = this.buffered.length; i < l; i++) {
|
|
||||||
this.write(this.buffered.splice(0, 1)[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finishes the handshake.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.proveReception = function (headers) {
|
|
||||||
var self = this
|
|
||||||
, k1 = this.req.headers['sec-websocket-key1']
|
|
||||||
, k2 = this.req.headers['sec-websocket-key2'];
|
|
||||||
|
|
||||||
if (k1 && k2){
|
|
||||||
var md5 = crypto.createHash('md5');
|
|
||||||
|
|
||||||
[k1, k2].forEach(function (k) {
|
|
||||||
var n = parseInt(k.replace(/[^\d]/g, ''))
|
|
||||||
, spaces = k.replace(/[^ ]/g, '').length;
|
|
||||||
|
|
||||||
if (spaces === 0 || n % spaces !== 0){
|
|
||||||
self.log.warn('Invalid ' + self.name + ' key: "' + k + '".');
|
|
||||||
self.end();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
n /= spaces;
|
|
||||||
|
|
||||||
md5.update(String.fromCharCode(
|
|
||||||
n >> 24 & 0xFF,
|
|
||||||
n >> 16 & 0xFF,
|
|
||||||
n >> 8 & 0xFF,
|
|
||||||
n & 0xFF));
|
|
||||||
});
|
|
||||||
|
|
||||||
md5.update(this.req.head.toString('binary'));
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.socket.write(md5.digest('binary'), 'binary');
|
|
||||||
} catch (e) {
|
|
||||||
this.end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a payload.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.payload = function (msgs) {
|
|
||||||
for (var i = 0, l = msgs.length; i < l; i++) {
|
|
||||||
this.write(msgs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the connection.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.doClose = function () {
|
|
||||||
this.socket.end();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebSocket parser
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Parser () {
|
|
||||||
this.buffer = '';
|
|
||||||
this.i = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from EventEmitter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds data to the buffer.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.add = function (data) {
|
|
||||||
this.buffer += data;
|
|
||||||
this.parse();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the buffer.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.parse = function () {
|
|
||||||
for (var i = this.i, chr, l = this.buffer.length; i < l; i++){
|
|
||||||
chr = this.buffer[i];
|
|
||||||
|
|
||||||
if (this.buffer.length == 2 && this.buffer[1] == '\u0000') {
|
|
||||||
this.emit('close');
|
|
||||||
this.buffer = '';
|
|
||||||
this.i = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i === 0){
|
|
||||||
if (chr != '\u0000')
|
|
||||||
this.error('Bad framing. Expected null byte as first frame');
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chr == '\ufffd'){
|
|
||||||
this.emit('data', this.buffer.substr(1, i - 1));
|
|
||||||
this.buffer = this.buffer.substr(i + 1);
|
|
||||||
this.i = 0;
|
|
||||||
return this.parse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an error
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.error = function (reason) {
|
|
||||||
this.buffer = '';
|
|
||||||
this.i = 0;
|
|
||||||
this.emit('error', reason);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
622
node_modules/socket.io/lib/transports/websocket/hybi-07-12.js
generated
vendored
622
node_modules/socket.io/lib/transports/websocket/hybi-07-12.js
generated
vendored
|
|
@ -1,622 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Transport = require('../../transport')
|
|
||||||
, EventEmitter = process.EventEmitter
|
|
||||||
, crypto = require('crypto')
|
|
||||||
, url = require('url')
|
|
||||||
, parser = require('../../parser')
|
|
||||||
, util = require('../../util');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = WebSocket;
|
|
||||||
exports.Parser = Parser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP interface constructor. Interface compatible with all transports that
|
|
||||||
* depend on request-response cycles.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function WebSocket (mng, data, req) {
|
|
||||||
// parser
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.manager = mng;
|
|
||||||
this.parser = new Parser();
|
|
||||||
this.parser.on('data', function (packet) {
|
|
||||||
self.onMessage(parser.decodePacket(packet));
|
|
||||||
});
|
|
||||||
this.parser.on('ping', function () {
|
|
||||||
// version 8 ping => pong
|
|
||||||
try {
|
|
||||||
self.socket.write('\u008a\u0000');
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
self.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.parser.on('close', function () {
|
|
||||||
self.end();
|
|
||||||
});
|
|
||||||
this.parser.on('error', function (reason) {
|
|
||||||
self.log.warn(self.name + ' parser error: ' + reason);
|
|
||||||
self.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
Transport.call(this, mng, data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Transport.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.__proto__ = Transport.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.name = 'websocket';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Websocket draft version
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.protocolVersion = '07-12';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the socket connects.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.onSocketConnect = function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (typeof this.req.headers.upgrade === 'undefined' ||
|
|
||||||
this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
|
||||||
this.log.warn(this.name + ' connection invalid');
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var origin = this.req.headers['sec-websocket-origin']
|
|
||||||
, location = ((this.manager.settings['match origin protocol'] ?
|
|
||||||
origin.match(/^https/) : this.socket.encrypted) ?
|
|
||||||
'wss' : 'ws')
|
|
||||||
+ '://' + this.req.headers.host + this.req.url;
|
|
||||||
|
|
||||||
if (!this.verifyOrigin(origin)) {
|
|
||||||
this.log.warn(this.name + ' connection invalid: origin mismatch');
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.req.headers['sec-websocket-key']) {
|
|
||||||
this.log.warn(this.name + ' connection invalid: received no key');
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calc key
|
|
||||||
var key = this.req.headers['sec-websocket-key'];
|
|
||||||
var shasum = crypto.createHash('sha1');
|
|
||||||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
|
||||||
key = shasum.digest('base64');
|
|
||||||
|
|
||||||
var headers = [
|
|
||||||
'HTTP/1.1 101 Switching Protocols'
|
|
||||||
, 'Upgrade: websocket'
|
|
||||||
, 'Connection: Upgrade'
|
|
||||||
, 'Sec-WebSocket-Accept: ' + key
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.socket.write(headers.concat('', '').join('\r\n'));
|
|
||||||
this.socket.setTimeout(0);
|
|
||||||
this.socket.setNoDelay(true);
|
|
||||||
} catch (e) {
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.socket.on('data', function (data) {
|
|
||||||
self.parser.add(data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies the origin of a request.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.verifyOrigin = function (origin) {
|
|
||||||
var origins = this.manager.get('origins');
|
|
||||||
|
|
||||||
if (origin === 'null') origin = '*';
|
|
||||||
|
|
||||||
if (origins.indexOf('*:*') !== -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (origin) {
|
|
||||||
try {
|
|
||||||
var parts = url.parse(origin);
|
|
||||||
parts.port = parts.port || 80;
|
|
||||||
var ok =
|
|
||||||
~origins.indexOf(parts.hostname + ':' + parts.port) ||
|
|
||||||
~origins.indexOf(parts.hostname + ':*') ||
|
|
||||||
~origins.indexOf('*:' + parts.port);
|
|
||||||
if (!ok) this.log.warn('illegal origin: ' + origin);
|
|
||||||
return ok;
|
|
||||||
} catch (ex) {
|
|
||||||
this.log.warn('error parsing origin');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.log.warn('origin missing from websocket call, yet required by config');
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes to the socket.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.write = function (data) {
|
|
||||||
if (this.open) {
|
|
||||||
var buf = this.frame(0x81, data);
|
|
||||||
try {
|
|
||||||
this.socket.write(buf, 'binary');
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.log.debug(this.name + ' writing', data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a payload.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.payload = function (msgs) {
|
|
||||||
for (var i = 0, l = msgs.length; i < l; i++) {
|
|
||||||
this.write(msgs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frame server-to-client output as a text packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.frame = function (opcode, str) {
|
|
||||||
var dataBuffer = new Buffer(str)
|
|
||||||
, dataLength = dataBuffer.length
|
|
||||||
, startOffset = 2
|
|
||||||
, secondByte = dataLength;
|
|
||||||
if (dataLength > 65536) {
|
|
||||||
startOffset = 10;
|
|
||||||
secondByte = 127;
|
|
||||||
}
|
|
||||||
else if (dataLength > 125) {
|
|
||||||
startOffset = 4;
|
|
||||||
secondByte = 126;
|
|
||||||
}
|
|
||||||
var outputBuffer = new Buffer(dataLength + startOffset);
|
|
||||||
outputBuffer[0] = opcode;
|
|
||||||
outputBuffer[1] = secondByte;
|
|
||||||
dataBuffer.copy(outputBuffer, startOffset);
|
|
||||||
switch (secondByte) {
|
|
||||||
case 126:
|
|
||||||
outputBuffer[2] = dataLength >>> 8;
|
|
||||||
outputBuffer[3] = dataLength % 256;
|
|
||||||
break;
|
|
||||||
case 127:
|
|
||||||
var l = dataLength;
|
|
||||||
for (var i = 1; i <= 8; ++i) {
|
|
||||||
outputBuffer[startOffset - i] = l & 0xff;
|
|
||||||
l >>>= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return outputBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the connection.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.doClose = function () {
|
|
||||||
this.socket.end();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebSocket parser
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Parser () {
|
|
||||||
this.state = {
|
|
||||||
activeFragmentedOperation: null,
|
|
||||||
lastFragment: false,
|
|
||||||
masked: false,
|
|
||||||
opcode: 0
|
|
||||||
};
|
|
||||||
this.overflow = null;
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectHandler = null;
|
|
||||||
this.currentMessage = '';
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.opcodeHandlers = {
|
|
||||||
// text
|
|
||||||
'1': function(data) {
|
|
||||||
var finish = function(mask, data) {
|
|
||||||
self.currentMessage += self.unmask(mask, data);
|
|
||||||
if (self.state.lastFragment) {
|
|
||||||
self.emit('data', self.currentMessage);
|
|
||||||
self.currentMessage = '';
|
|
||||||
}
|
|
||||||
self.endPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectData = function(length) {
|
|
||||||
if (self.state.masked) {
|
|
||||||
self.expect('Mask', 4, function(data) {
|
|
||||||
var mask = data;
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(mask, data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(null, data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode length
|
|
||||||
var firstLength = data[1] & 0x7f;
|
|
||||||
if (firstLength < 126) {
|
|
||||||
expectData(firstLength);
|
|
||||||
}
|
|
||||||
else if (firstLength == 126) {
|
|
||||||
self.expect('Length', 2, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (firstLength == 127) {
|
|
||||||
self.expect('Length', 8, function(data) {
|
|
||||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
|
||||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// binary
|
|
||||||
'2': function(data) {
|
|
||||||
var finish = function(mask, data) {
|
|
||||||
if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list
|
|
||||||
self.currentMessage.push(self.unmask(mask, data, true));
|
|
||||||
if (self.state.lastFragment) {
|
|
||||||
self.emit('binary', self.concatBuffers(self.currentMessage));
|
|
||||||
self.currentMessage = '';
|
|
||||||
}
|
|
||||||
self.endPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectData = function(length) {
|
|
||||||
if (self.state.masked) {
|
|
||||||
self.expect('Mask', 4, function(data) {
|
|
||||||
var mask = data;
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(mask, data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(null, data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode length
|
|
||||||
var firstLength = data[1] & 0x7f;
|
|
||||||
if (firstLength < 126) {
|
|
||||||
expectData(firstLength);
|
|
||||||
}
|
|
||||||
else if (firstLength == 126) {
|
|
||||||
self.expect('Length', 2, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (firstLength == 127) {
|
|
||||||
self.expect('Length', 8, function(data) {
|
|
||||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
|
||||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// close
|
|
||||||
'8': function(data) {
|
|
||||||
self.emit('close');
|
|
||||||
self.reset();
|
|
||||||
},
|
|
||||||
// ping
|
|
||||||
'9': function(data) {
|
|
||||||
if (self.state.lastFragment == false) {
|
|
||||||
self.error('fragmented ping is not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var finish = function(mask, data) {
|
|
||||||
self.emit('ping', self.unmask(mask, data));
|
|
||||||
self.endPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectData = function(length) {
|
|
||||||
if (self.state.masked) {
|
|
||||||
self.expect('Mask', 4, function(data) {
|
|
||||||
var mask = data;
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(mask, data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(null, data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode length
|
|
||||||
var firstLength = data[1] & 0x7f;
|
|
||||||
if (firstLength == 0) {
|
|
||||||
finish(null, null);
|
|
||||||
}
|
|
||||||
else if (firstLength < 126) {
|
|
||||||
expectData(firstLength);
|
|
||||||
}
|
|
||||||
else if (firstLength == 126) {
|
|
||||||
self.expect('Length', 2, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (firstLength == 127) {
|
|
||||||
self.expect('Length', 8, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.expect('Opcode', 2, this.processPacket);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from EventEmitter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add new data to the parser.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.add = function(data) {
|
|
||||||
if (this.expectBuffer == null) {
|
|
||||||
this.addToOverflow(data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset);
|
|
||||||
data.copy(this.expectBuffer, this.expectOffset, 0, toRead);
|
|
||||||
this.expectOffset += toRead;
|
|
||||||
if (toRead < data.length) {
|
|
||||||
// at this point the overflow buffer shouldn't at all exist
|
|
||||||
this.overflow = new Buffer(data.length - toRead);
|
|
||||||
data.copy(this.overflow, 0, toRead, toRead + this.overflow.length);
|
|
||||||
}
|
|
||||||
if (this.expectOffset == this.expectBuffer.length) {
|
|
||||||
var bufferForHandler = this.expectBuffer;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectHandler.call(this, bufferForHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a piece of data to the overflow.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.addToOverflow = function(data) {
|
|
||||||
if (this.overflow == null) this.overflow = data;
|
|
||||||
else {
|
|
||||||
var prevOverflow = this.overflow;
|
|
||||||
this.overflow = new Buffer(this.overflow.length + data.length);
|
|
||||||
prevOverflow.copy(this.overflow, 0);
|
|
||||||
data.copy(this.overflow, prevOverflow.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for a certain amount of bytes to be available, then fires a callback.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.expect = function(what, length, handler) {
|
|
||||||
this.expectBuffer = new Buffer(length);
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectHandler = handler;
|
|
||||||
if (this.overflow != null) {
|
|
||||||
var toOverflow = this.overflow;
|
|
||||||
this.overflow = null;
|
|
||||||
this.add(toOverflow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start processing a new packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.processPacket = function (data) {
|
|
||||||
if ((data[0] & 0x70) != 0) {
|
|
||||||
this.error('reserved fields must be empty');
|
|
||||||
}
|
|
||||||
this.state.lastFragment = (data[0] & 0x80) == 0x80;
|
|
||||||
this.state.masked = (data[1] & 0x80) == 0x80;
|
|
||||||
var opcode = data[0] & 0xf;
|
|
||||||
if (opcode == 0) {
|
|
||||||
// continuation frame
|
|
||||||
this.state.opcode = this.state.activeFragmentedOperation;
|
|
||||||
if (!(this.state.opcode == 1 || this.state.opcode == 2)) {
|
|
||||||
this.error('continuation frame cannot follow current opcode')
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.state.opcode = opcode;
|
|
||||||
if (this.state.lastFragment === false) {
|
|
||||||
this.state.activeFragmentedOperation = opcode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var handler = this.opcodeHandlers[this.state.opcode];
|
|
||||||
if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode);
|
|
||||||
else handler(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endprocessing a packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.endPacket = function() {
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectHandler = null;
|
|
||||||
if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) {
|
|
||||||
// end current fragmented operation
|
|
||||||
this.state.activeFragmentedOperation = null;
|
|
||||||
}
|
|
||||||
this.state.lastFragment = false;
|
|
||||||
this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0;
|
|
||||||
this.state.masked = false;
|
|
||||||
this.expect('Opcode', 2, this.processPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the parser state.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.reset = function() {
|
|
||||||
this.state = {
|
|
||||||
activeFragmentedOperation: null,
|
|
||||||
lastFragment: false,
|
|
||||||
masked: false,
|
|
||||||
opcode: 0
|
|
||||||
};
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectHandler = null;
|
|
||||||
this.overflow = null;
|
|
||||||
this.currentMessage = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unmask received data.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.unmask = function (mask, buf, binary) {
|
|
||||||
if (mask != null) {
|
|
||||||
for (var i = 0, ll = buf.length; i < ll; i++) {
|
|
||||||
buf[i] ^= mask[i % 4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (binary) return buf;
|
|
||||||
return buf != null ? buf.toString('utf8') : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concatenates a list of buffers.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.concatBuffers = function(buffers) {
|
|
||||||
var length = 0;
|
|
||||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
|
||||||
length += buffers[i].length;
|
|
||||||
}
|
|
||||||
var mergedBuffer = new Buffer(length);
|
|
||||||
var offset = 0;
|
|
||||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
|
||||||
buffers[i].copy(mergedBuffer, offset);
|
|
||||||
offset += buffers[i].length;
|
|
||||||
}
|
|
||||||
return mergedBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an error
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.error = function (reason) {
|
|
||||||
this.reset();
|
|
||||||
this.emit('error', reason);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
622
node_modules/socket.io/lib/transports/websocket/hybi-16.js
generated
vendored
622
node_modules/socket.io/lib/transports/websocket/hybi-16.js
generated
vendored
|
|
@ -1,622 +0,0 @@
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Transport = require('../../transport')
|
|
||||||
, EventEmitter = process.EventEmitter
|
|
||||||
, crypto = require('crypto')
|
|
||||||
, url = require('url')
|
|
||||||
, parser = require('../../parser')
|
|
||||||
, util = require('../../util');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = WebSocket;
|
|
||||||
exports.Parser = Parser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP interface constructor. Interface compatible with all transports that
|
|
||||||
* depend on request-response cycles.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function WebSocket (mng, data, req) {
|
|
||||||
// parser
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.manager = mng;
|
|
||||||
this.parser = new Parser();
|
|
||||||
this.parser.on('data', function (packet) {
|
|
||||||
self.onMessage(parser.decodePacket(packet));
|
|
||||||
});
|
|
||||||
this.parser.on('ping', function () {
|
|
||||||
// version 8 ping => pong
|
|
||||||
try {
|
|
||||||
self.socket.write('\u008a\u0000');
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
self.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.parser.on('close', function () {
|
|
||||||
self.end();
|
|
||||||
});
|
|
||||||
this.parser.on('error', function (reason) {
|
|
||||||
self.log.warn(self.name + ' parser error: ' + reason);
|
|
||||||
self.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
Transport.call(this, mng, data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Transport.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.__proto__ = Transport.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.name = 'websocket';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Websocket draft version
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.protocolVersion = '16';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the socket connects.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.onSocketConnect = function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (typeof this.req.headers.upgrade === 'undefined' ||
|
|
||||||
this.req.headers.upgrade.toLowerCase() !== 'websocket') {
|
|
||||||
this.log.warn(this.name + ' connection invalid');
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var origin = this.req.headers['origin'] || ''
|
|
||||||
, location = ((this.manager.settings['match origin protocol'] ?
|
|
||||||
origin.match(/^https/) : this.socket.encrypted) ?
|
|
||||||
'wss' : 'ws')
|
|
||||||
+ '://' + this.req.headers.host + this.req.url;
|
|
||||||
|
|
||||||
if (!this.verifyOrigin(origin)) {
|
|
||||||
this.log.warn(this.name + ' connection invalid: origin mismatch');
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.req.headers['sec-websocket-key']) {
|
|
||||||
this.log.warn(this.name + ' connection invalid: received no key');
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calc key
|
|
||||||
var key = this.req.headers['sec-websocket-key'];
|
|
||||||
var shasum = crypto.createHash('sha1');
|
|
||||||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
|
||||||
key = shasum.digest('base64');
|
|
||||||
|
|
||||||
var headers = [
|
|
||||||
'HTTP/1.1 101 Switching Protocols'
|
|
||||||
, 'Upgrade: websocket'
|
|
||||||
, 'Connection: Upgrade'
|
|
||||||
, 'Sec-WebSocket-Accept: ' + key
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.socket.write(headers.concat('', '').join('\r\n'));
|
|
||||||
this.socket.setTimeout(0);
|
|
||||||
this.socket.setNoDelay(true);
|
|
||||||
} catch (e) {
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.socket.on('data', function (data) {
|
|
||||||
self.parser.add(data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies the origin of a request.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.verifyOrigin = function (origin) {
|
|
||||||
var origins = this.manager.get('origins');
|
|
||||||
|
|
||||||
if (origin === 'null') origin = '*';
|
|
||||||
|
|
||||||
if (origins.indexOf('*:*') !== -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (origin) {
|
|
||||||
try {
|
|
||||||
var parts = url.parse(origin);
|
|
||||||
parts.port = parts.port || 80;
|
|
||||||
var ok =
|
|
||||||
~origins.indexOf(parts.hostname + ':' + parts.port) ||
|
|
||||||
~origins.indexOf(parts.hostname + ':*') ||
|
|
||||||
~origins.indexOf('*:' + parts.port);
|
|
||||||
if (!ok) this.log.warn('illegal origin: ' + origin);
|
|
||||||
return ok;
|
|
||||||
} catch (ex) {
|
|
||||||
this.log.warn('error parsing origin');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.log.warn('origin missing from websocket call, yet required by config');
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes to the socket.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.write = function (data) {
|
|
||||||
if (this.open) {
|
|
||||||
var buf = this.frame(0x81, data);
|
|
||||||
try {
|
|
||||||
this.socket.write(buf, 'binary');
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.log.debug(this.name + ' writing', data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a payload.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.payload = function (msgs) {
|
|
||||||
for (var i = 0, l = msgs.length; i < l; i++) {
|
|
||||||
this.write(msgs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frame server-to-client output as a text packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.frame = function (opcode, str) {
|
|
||||||
var dataBuffer = new Buffer(str)
|
|
||||||
, dataLength = dataBuffer.length
|
|
||||||
, startOffset = 2
|
|
||||||
, secondByte = dataLength;
|
|
||||||
if (dataLength > 65536) {
|
|
||||||
startOffset = 10;
|
|
||||||
secondByte = 127;
|
|
||||||
}
|
|
||||||
else if (dataLength > 125) {
|
|
||||||
startOffset = 4;
|
|
||||||
secondByte = 126;
|
|
||||||
}
|
|
||||||
var outputBuffer = new Buffer(dataLength + startOffset);
|
|
||||||
outputBuffer[0] = opcode;
|
|
||||||
outputBuffer[1] = secondByte;
|
|
||||||
dataBuffer.copy(outputBuffer, startOffset);
|
|
||||||
switch (secondByte) {
|
|
||||||
case 126:
|
|
||||||
outputBuffer[2] = dataLength >>> 8;
|
|
||||||
outputBuffer[3] = dataLength % 256;
|
|
||||||
break;
|
|
||||||
case 127:
|
|
||||||
var l = dataLength;
|
|
||||||
for (var i = 1; i <= 8; ++i) {
|
|
||||||
outputBuffer[startOffset - i] = l & 0xff;
|
|
||||||
l >>>= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return outputBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the connection.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
WebSocket.prototype.doClose = function () {
|
|
||||||
this.socket.end();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebSocket parser
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Parser () {
|
|
||||||
this.state = {
|
|
||||||
activeFragmentedOperation: null,
|
|
||||||
lastFragment: false,
|
|
||||||
masked: false,
|
|
||||||
opcode: 0
|
|
||||||
};
|
|
||||||
this.overflow = null;
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectHandler = null;
|
|
||||||
this.currentMessage = '';
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.opcodeHandlers = {
|
|
||||||
// text
|
|
||||||
'1': function(data) {
|
|
||||||
var finish = function(mask, data) {
|
|
||||||
self.currentMessage += self.unmask(mask, data);
|
|
||||||
if (self.state.lastFragment) {
|
|
||||||
self.emit('data', self.currentMessage);
|
|
||||||
self.currentMessage = '';
|
|
||||||
}
|
|
||||||
self.endPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectData = function(length) {
|
|
||||||
if (self.state.masked) {
|
|
||||||
self.expect('Mask', 4, function(data) {
|
|
||||||
var mask = data;
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(mask, data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(null, data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode length
|
|
||||||
var firstLength = data[1] & 0x7f;
|
|
||||||
if (firstLength < 126) {
|
|
||||||
expectData(firstLength);
|
|
||||||
}
|
|
||||||
else if (firstLength == 126) {
|
|
||||||
self.expect('Length', 2, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (firstLength == 127) {
|
|
||||||
self.expect('Length', 8, function(data) {
|
|
||||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
|
||||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// binary
|
|
||||||
'2': function(data) {
|
|
||||||
var finish = function(mask, data) {
|
|
||||||
if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list
|
|
||||||
self.currentMessage.push(self.unmask(mask, data, true));
|
|
||||||
if (self.state.lastFragment) {
|
|
||||||
self.emit('binary', self.concatBuffers(self.currentMessage));
|
|
||||||
self.currentMessage = '';
|
|
||||||
}
|
|
||||||
self.endPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectData = function(length) {
|
|
||||||
if (self.state.masked) {
|
|
||||||
self.expect('Mask', 4, function(data) {
|
|
||||||
var mask = data;
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(mask, data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(null, data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode length
|
|
||||||
var firstLength = data[1] & 0x7f;
|
|
||||||
if (firstLength < 126) {
|
|
||||||
expectData(firstLength);
|
|
||||||
}
|
|
||||||
else if (firstLength == 126) {
|
|
||||||
self.expect('Length', 2, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (firstLength == 127) {
|
|
||||||
self.expect('Length', 8, function(data) {
|
|
||||||
if (util.unpack(data.slice(0, 4)) != 0) {
|
|
||||||
self.error('packets with length spanning more than 32 bit is currently not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var lengthBytes = data.slice(4); // note: cap to 32 bit length
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// close
|
|
||||||
'8': function(data) {
|
|
||||||
self.emit('close');
|
|
||||||
self.reset();
|
|
||||||
},
|
|
||||||
// ping
|
|
||||||
'9': function(data) {
|
|
||||||
if (self.state.lastFragment == false) {
|
|
||||||
self.error('fragmented ping is not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var finish = function(mask, data) {
|
|
||||||
self.emit('ping', self.unmask(mask, data));
|
|
||||||
self.endPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectData = function(length) {
|
|
||||||
if (self.state.masked) {
|
|
||||||
self.expect('Mask', 4, function(data) {
|
|
||||||
var mask = data;
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(mask, data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.expect('Data', length, function(data) {
|
|
||||||
finish(null, data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode length
|
|
||||||
var firstLength = data[1] & 0x7f;
|
|
||||||
if (firstLength == 0) {
|
|
||||||
finish(null, null);
|
|
||||||
}
|
|
||||||
else if (firstLength < 126) {
|
|
||||||
expectData(firstLength);
|
|
||||||
}
|
|
||||||
else if (firstLength == 126) {
|
|
||||||
self.expect('Length', 2, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (firstLength == 127) {
|
|
||||||
self.expect('Length', 8, function(data) {
|
|
||||||
expectData(util.unpack(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.expect('Opcode', 2, this.processPacket);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from EventEmitter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add new data to the parser.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.add = function(data) {
|
|
||||||
if (this.expectBuffer == null) {
|
|
||||||
this.addToOverflow(data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset);
|
|
||||||
data.copy(this.expectBuffer, this.expectOffset, 0, toRead);
|
|
||||||
this.expectOffset += toRead;
|
|
||||||
if (toRead < data.length) {
|
|
||||||
// at this point the overflow buffer shouldn't at all exist
|
|
||||||
this.overflow = new Buffer(data.length - toRead);
|
|
||||||
data.copy(this.overflow, 0, toRead, toRead + this.overflow.length);
|
|
||||||
}
|
|
||||||
if (this.expectOffset == this.expectBuffer.length) {
|
|
||||||
var bufferForHandler = this.expectBuffer;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectHandler.call(this, bufferForHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a piece of data to the overflow.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.addToOverflow = function(data) {
|
|
||||||
if (this.overflow == null) this.overflow = data;
|
|
||||||
else {
|
|
||||||
var prevOverflow = this.overflow;
|
|
||||||
this.overflow = new Buffer(this.overflow.length + data.length);
|
|
||||||
prevOverflow.copy(this.overflow, 0);
|
|
||||||
data.copy(this.overflow, prevOverflow.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for a certain amount of bytes to be available, then fires a callback.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.expect = function(what, length, handler) {
|
|
||||||
this.expectBuffer = new Buffer(length);
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectHandler = handler;
|
|
||||||
if (this.overflow != null) {
|
|
||||||
var toOverflow = this.overflow;
|
|
||||||
this.overflow = null;
|
|
||||||
this.add(toOverflow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start processing a new packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.processPacket = function (data) {
|
|
||||||
if ((data[0] & 0x70) != 0) {
|
|
||||||
this.error('reserved fields must be empty');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.state.lastFragment = (data[0] & 0x80) == 0x80;
|
|
||||||
this.state.masked = (data[1] & 0x80) == 0x80;
|
|
||||||
var opcode = data[0] & 0xf;
|
|
||||||
if (opcode == 0) {
|
|
||||||
// continuation frame
|
|
||||||
this.state.opcode = this.state.activeFragmentedOperation;
|
|
||||||
if (!(this.state.opcode == 1 || this.state.opcode == 2)) {
|
|
||||||
this.error('continuation frame cannot follow current opcode')
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.state.opcode = opcode;
|
|
||||||
if (this.state.lastFragment === false) {
|
|
||||||
this.state.activeFragmentedOperation = opcode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var handler = this.opcodeHandlers[this.state.opcode];
|
|
||||||
if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode);
|
|
||||||
else handler(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endprocessing a packet.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.endPacket = function() {
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectHandler = null;
|
|
||||||
if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) {
|
|
||||||
// end current fragmented operation
|
|
||||||
this.state.activeFragmentedOperation = null;
|
|
||||||
}
|
|
||||||
this.state.lastFragment = false;
|
|
||||||
this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0;
|
|
||||||
this.state.masked = false;
|
|
||||||
this.expect('Opcode', 2, this.processPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the parser state.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.reset = function() {
|
|
||||||
this.state = {
|
|
||||||
activeFragmentedOperation: null,
|
|
||||||
lastFragment: false,
|
|
||||||
masked: false,
|
|
||||||
opcode: 0
|
|
||||||
};
|
|
||||||
this.expectOffset = 0;
|
|
||||||
this.expectBuffer = null;
|
|
||||||
this.expectHandler = null;
|
|
||||||
this.overflow = null;
|
|
||||||
this.currentMessage = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unmask received data.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.unmask = function (mask, buf, binary) {
|
|
||||||
if (mask != null) {
|
|
||||||
for (var i = 0, ll = buf.length; i < ll; i++) {
|
|
||||||
buf[i] ^= mask[i % 4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (binary) return buf;
|
|
||||||
return buf != null ? buf.toString('utf8') : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concatenates a list of buffers.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.concatBuffers = function(buffers) {
|
|
||||||
var length = 0;
|
|
||||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
|
||||||
length += buffers[i].length;
|
|
||||||
}
|
|
||||||
var mergedBuffer = new Buffer(length);
|
|
||||||
var offset = 0;
|
|
||||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
|
||||||
buffers[i].copy(mergedBuffer, offset);
|
|
||||||
offset += buffers[i].length;
|
|
||||||
}
|
|
||||||
return mergedBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an error
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Parser.prototype.error = function (reason) {
|
|
||||||
this.reset();
|
|
||||||
this.emit('error', reason);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
11
node_modules/socket.io/lib/transports/websocket/index.js
generated
vendored
11
node_modules/socket.io/lib/transports/websocket/index.js
generated
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Export websocket versions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
7: require('./hybi-07-12'),
|
|
||||||
8: require('./hybi-07-12'),
|
|
||||||
13: require('./hybi-16'),
|
|
||||||
default: require('./default')
|
|
||||||
};
|
|
||||||
69
node_modules/socket.io/lib/transports/xhr-polling.js
generated
vendored
69
node_modules/socket.io/lib/transports/xhr-polling.js
generated
vendored
|
|
@ -1,69 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module requirements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var HTTPPolling = require('./http-polling');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the constructor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports = module.exports = XHRPolling;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ajax polling transport.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function XHRPolling (mng, data, req) {
|
|
||||||
HTTPPolling.call(this, mng, data, req);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherits from Transport.
|
|
||||||
*/
|
|
||||||
|
|
||||||
XHRPolling.prototype.__proto__ = HTTPPolling.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport name
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
XHRPolling.prototype.name = 'xhr-polling';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frames data prior to write.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
XHRPolling.prototype.doWrite = function (data) {
|
|
||||||
HTTPPolling.prototype.doWrite.call(this);
|
|
||||||
|
|
||||||
var origin = this.req.headers.origin
|
|
||||||
, headers = {
|
|
||||||
'Content-Type': 'text/plain; charset=UTF-8'
|
|
||||||
, 'Content-Length': data === undefined ? 0 : Buffer.byteLength(data)
|
|
||||||
, 'Connection': 'Keep-Alive'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (origin) {
|
|
||||||
// https://developer.mozilla.org/En/HTTP_Access_Control
|
|
||||||
headers['Access-Control-Allow-Origin'] = origin;
|
|
||||||
headers['Access-Control-Allow-Credentials'] = 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.response.writeHead(200, headers);
|
|
||||||
this.response.write(data);
|
|
||||||
this.log.debug(this.name + ' writing', data);
|
|
||||||
};
|
|
||||||
50
node_modules/socket.io/lib/util.js
generated
vendored
50
node_modules/socket.io/lib/util.js
generated
vendored
|
|
@ -1,50 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* socket.io-node
|
|
||||||
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an enumerable to an array.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.toArray = function (enu) {
|
|
||||||
var arr = [];
|
|
||||||
|
|
||||||
for (var i = 0, l = enu.length; i < l; i++)
|
|
||||||
arr.push(enu[i]);
|
|
||||||
|
|
||||||
return arr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unpacks a buffer to a number.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.unpack = function (buffer) {
|
|
||||||
var n = 0;
|
|
||||||
for (var i = 0; i < buffer.length; ++i) {
|
|
||||||
n = (i == 0) ? buffer[i] : (n * 256) + buffer[i];
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Left pads a string.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.padl = function (s,n,c) {
|
|
||||||
return new Array(1 + n - s.length).join(c) + s;
|
|
||||||
}
|
|
||||||
|
|
||||||
1
node_modules/socket.io/node_modules/policyfile/.npmignore
generated
vendored
1
node_modules/socket.io/node_modules/policyfile/.npmignore
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
node_modules
|
|
||||||
19
node_modules/socket.io/node_modules/policyfile/LICENSE
generated
vendored
19
node_modules/socket.io/node_modules/policyfile/LICENSE
generated
vendored
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2011 Arnout Kazemier,3rd-Eden
|
|
||||||
|
|
||||||
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 the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
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.
|
|
||||||
7
node_modules/socket.io/node_modules/policyfile/Makefile
generated
vendored
7
node_modules/socket.io/node_modules/policyfile/Makefile
generated
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
doc:
|
|
||||||
dox --title "FlashPolicyFileServer" lib/* > doc/index.html
|
|
||||||
|
|
||||||
test:
|
|
||||||
expresso -I lib $(TESTFLAGS) tests/*.test.js
|
|
||||||
|
|
||||||
.PHONY: test doc
|
|
||||||
98
node_modules/socket.io/node_modules/policyfile/README.md
generated
vendored
98
node_modules/socket.io/node_modules/policyfile/README.md
generated
vendored
|
|
@ -1,98 +0,0 @@
|
||||||
## LOL, WUT?
|
|
||||||
It basically allows you to allow or disallow Flash Player sockets from accessing your site.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install policyfile
|
|
||||||
```
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
The server is based on the regular and know `net` and `http` server patterns. So it you can just listen
|
|
||||||
for all the events that a `net` based server emits etc. But there is one extra event, the `connect_failed`
|
|
||||||
event. This event is triggered when we are unable to listen on the supplied port number.
|
|
||||||
|
|
||||||
### createServer
|
|
||||||
Creates a new server instance and accepts 2 optional arguments:
|
|
||||||
|
|
||||||
- `options` **Object** Options to configure the server instance
|
|
||||||
- `log` **Boolean** Enable logging to STDOUT and STDERR (defaults to true)
|
|
||||||
- `origins` **Array** An Array of origins that are allowed by the server (defaults to *:*)
|
|
||||||
|
|
||||||
```js
|
|
||||||
var pf = require('policyfile');
|
|
||||||
pf.createServer();
|
|
||||||
pf.listen();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### server.listen
|
|
||||||
Start listening on the server and it takes 3 optional arguments
|
|
||||||
|
|
||||||
- `port` **Number** On which port number should we listen? (defaults to 843, which is the first port number the FlashPlayer checks)
|
|
||||||
- `server` **Server** A http server, if we are unable to accept requests or run the server we can also answer the policy requests inline over the supplied HTTP server.
|
|
||||||
- `callback` **Function** A callback function that is called when listening to the server was successful.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var pf = require('policyfile');
|
|
||||||
pf.createServer();
|
|
||||||
pf.listen(1337, function(){
|
|
||||||
console.log(':3 yay')
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Changing port numbers can be handy if you do not want to run your server as root and have port 843 forward to a non root port number (aka a number above 1024).
|
|
||||||
|
|
||||||
```js
|
|
||||||
var pf = require('policyfile')
|
|
||||||
, http = require('http');
|
|
||||||
|
|
||||||
server = http.createServer(function(q,r){r.writeHead(200);r.end('hello world')});
|
|
||||||
server.listen(80);
|
|
||||||
|
|
||||||
pf.createServer();
|
|
||||||
pf.listen(1337, server, function(){
|
|
||||||
console.log(':3 yay')
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Support for serving inline requests over a existing HTTP connection as the FlashPlayer will first check port 843, but if it's unable to get a response there it will send a policy file request over port 80, which is usually your http server.
|
|
||||||
|
|
||||||
#### server.add
|
|
||||||
Adds more origins to the policy file you can add as many arguments as you like.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var pf = require('policyfile');
|
|
||||||
pf.createServer(['google.com:80']);
|
|
||||||
pf.listen();
|
|
||||||
pf.add('blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080'); // now has 3 origins
|
|
||||||
```
|
|
||||||
|
|
||||||
#### server.add
|
|
||||||
Adds more origins to the policy file you can add as many arguments as you like.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var pf = require('policyfile');
|
|
||||||
pf.createServer(['blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080']);
|
|
||||||
pf.listen();
|
|
||||||
pf.remove('blog.3rd-Eden.com:8080'); // only contains the :80 version now
|
|
||||||
```
|
|
||||||
|
|
||||||
#### server.close
|
|
||||||
Shuts down the server
|
|
||||||
|
|
||||||
```js
|
|
||||||
var pf = require('policyfile');
|
|
||||||
pf.createServer();
|
|
||||||
pf.listen();
|
|
||||||
pf.close(); // OH NVM.
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
|
||||||
http://3rd-eden.com/FlashPolicyFileServer/
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
See https://github.com/3rd-Eden/FlashPolicyFileServer/tree/master/examples for examples
|
|
||||||
|
|
||||||
## Licence
|
|
||||||
|
|
||||||
MIT see LICENSE file in the repository
|
|
||||||
375
node_modules/socket.io/node_modules/policyfile/doc/index.html
generated
vendored
375
node_modules/socket.io/node_modules/policyfile/doc/index.html
generated
vendored
|
|
@ -1,375 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>FlashPolicyFileServer</title>
|
|
||||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
|
|
||||||
<style>body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font: 14px/1.5 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
|
||||||
color: #252519;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #252519;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
color: #19469D;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 12px 0;
|
|
||||||
}
|
|
||||||
h1, h2, h3 {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
table#source {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
table#source td:first-child {
|
|
||||||
padding: 30px 40px 30px 40px;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
table#source td:first-child,
|
|
||||||
table#source td:first-child pre {
|
|
||||||
width: 450px;
|
|
||||||
}
|
|
||||||
table#source td:last-child {
|
|
||||||
padding: 30px 0 30px 40px;
|
|
||||||
border-left: 1px solid #E5E5EE;
|
|
||||||
background: #F5F5FF;
|
|
||||||
}
|
|
||||||
table#source tr {
|
|
||||||
border-bottom: 1px solid #E5E5EE;
|
|
||||||
}
|
|
||||||
table#source tr.filename {
|
|
||||||
padding-top: 40px;
|
|
||||||
border-top: 1px solid #E5E5EE;
|
|
||||||
}
|
|
||||||
table#source tr.filename td:first-child {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
table#source tr.filename td:last-child {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
table#source tr.filename h2 {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
table#source tr.code h1,
|
|
||||||
table#source tr.code h2,
|
|
||||||
table#source tr.code h3 {
|
|
||||||
margin-top: 30px;
|
|
||||||
font-family: "Lucida Grande", "Helvetica Nueue", Arial, sans-serif;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
table#source tr.code h2 {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
table#source tr.code h3 {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
table#source tr.code ul {
|
|
||||||
margin: 15px 0 15px 35px;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
table#source tr.code ul li {
|
|
||||||
margin: 0;
|
|
||||||
padding: 1px 0;
|
|
||||||
}
|
|
||||||
table#source tr.code ul li p {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
table#source tr.code td:first-child pre {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
#ribbon {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
code .string { color: #219161; }
|
|
||||||
code .regexp { color: #219161; }
|
|
||||||
code .keyword { color: #954121; }
|
|
||||||
code .number { color: #19469D; }
|
|
||||||
code .comment { color: #bbb; }
|
|
||||||
code .this { color: #19469D; }</style>
|
|
||||||
<script>
|
|
||||||
$(function(){
|
|
||||||
$('tr.code').hide();
|
|
||||||
$('tr.filename').toggle(function(){
|
|
||||||
$(this).nextUntil('.filename').fadeIn();
|
|
||||||
}, function(){
|
|
||||||
$(this).nextUntil('.filename').fadeOut();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<table id="source"><tbody><tr><td><h1>FlashPolicyFileServer</h1></td><td></td></tr><tr class="filename"><td><h2 id="lib/server.js"><a href="#">server</a></h2></td><td>lib/server.js</td></tr><tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Module dependencies and cached references.
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="keyword">var</span> <span class="variable">slice</span> = <span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">slice</span>
|
|
||||||
, <span class="variable">net</span> = <span class="variable">require</span>(<span class="string">'net'</span>);</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>The server that does the Policy File severing</p>
|
|
||||||
|
|
||||||
<h2>Options</h2>
|
|
||||||
|
|
||||||
<ul><li><code>log</code> false or a function that can output log information, defaults to console.log?</li></ul>
|
|
||||||
|
|
||||||
<h2></h2>
|
|
||||||
|
|
||||||
<ul><li><p><strong>param</strong>: <em>Object</em> options Options to customize the servers functionality.</p></li><li><p><strong>param</strong>: <em>Array</em> origins The origins that are allowed on this server, defaults to <code>*:*</code>.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="keyword">function</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
|
|
||||||
<span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>;
|
|
||||||
|
|
||||||
<span class="this">this</span>.<span class="variable">origins</span> = <span class="variable">origins</span> || [<span class="string">'*:*'</span>];
|
|
||||||
<span class="this">this</span>.<span class="variable">port</span> = <span class="number integer">843</span>;
|
|
||||||
<span class="this">this</span>.<span class="variable">log</span> = <span class="variable">console</span>.<span class="variable">log</span>;
|
|
||||||
|
|
||||||
<span class="comment">// merge `this` with the options</span>
|
|
||||||
<span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">options</span>).<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">key</span>){
|
|
||||||
<span class="variable">me</span>[<span class="variable">key</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">me</span>[<span class="variable">key</span>] = <span class="variable">options</span>[<span class="variable">key</span>])
|
|
||||||
});
|
|
||||||
|
|
||||||
<span class="comment">// create the net server</span>
|
|
||||||
<span class="this">this</span>.<span class="variable">socket</span> = <span class="variable">net</span>.<span class="variable">createServer</span>(<span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">socket</span>){
|
|
||||||
<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">socketError</span>(){ <span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>) });
|
|
||||||
<span class="variable">me</span>.<span class="variable">responder</span>.<span class="variable">call</span>(<span class="variable">me</span>, <span class="variable">socket</span>);
|
|
||||||
});
|
|
||||||
|
|
||||||
<span class="comment">// Listen for errors as the port might be blocked because we do not have root priv.</span>
|
|
||||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'error'</span>, <span class="keyword">function</span> <span class="variable">serverError</span>(<span class="variable">err</span>){
|
|
||||||
<span class="comment">// Special and common case error handling</span>
|
|
||||||
<span class="keyword">if</span> (<span class="variable">err</span>.<span class="variable">errno</span> == <span class="number integer">13</span>){
|
|
||||||
<span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(
|
|
||||||
<span class="string">'Unable to listen to port `'</span> + <span class="variable">me</span>.<span class="variable">port</span> + <span class="string">'` as your Node.js instance does not have root privileges. '</span> +
|
|
||||||
(
|
|
||||||
<span class="variable">me</span>.<span class="variable">server</span>
|
|
||||||
? <span class="string">'The Flash Policy file will now be served inline over the supplied HTTP server, Flash Policy files request will suffer.'</span>
|
|
||||||
: <span class="string">'No fallback server supplied.'</span>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
<span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
|
|
||||||
<span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">socket</span>;
|
|
||||||
|
|
||||||
<span class="variable">me</span>.<span class="variable">emit</span>(<span class="string">'connect_failed'</span>, <span class="variable">err</span>);
|
|
||||||
} <span class="keyword">else</span> {
|
|
||||||
<span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'FlashPolicyFileServer received a error event:\n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'timeout'</span>, <span class="keyword">function</span> <span class="variable">serverTimeout</span>(){});
|
|
||||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">on</span>(<span class="string">'close'</span>, <span class="keyword">function</span> <span class="variable">serverClosed</span>(<span class="variable">err</span>){
|
|
||||||
<span class="variable">err</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Server closing due to an error: \n'</span> + (<span class="variable">err</span>.<span class="variable">message</span> ? <span class="variable">err</span>.<span class="variable">message</span> : <span class="variable">err</span>));
|
|
||||||
|
|
||||||
<span class="keyword">if</span> (<span class="variable">me</span>.<span class="variable">server</span>){
|
|
||||||
<span class="comment">// not online anymore</span>
|
|
||||||
<span class="keyword">delete</span> <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>;
|
|
||||||
|
|
||||||
<span class="comment">// Remove the inline policy listener if we close down</span>
|
|
||||||
<span class="comment">// but only when the server was `online` (see listen prototype)</span>
|
|
||||||
<span class="keyword">if</span>( <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>] &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">online</span>){
|
|
||||||
<span class="variable">me</span>.<span class="variable">server</span>.<span class="variable">removeListener</span>(<span class="string">'connection'</span>, <span class="variable">me</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
<span class="variable">me</span>.<span class="variable">log</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">me</span>.<span class="variable">log</span>(<span class="string">'Shutting down FlashPolicyFileServer'</span>);
|
|
||||||
});
|
|
||||||
|
|
||||||
<span class="comment">// Compile the initial `buffer`</span>
|
|
||||||
<span class="this">this</span>.<span class="variable">compile</span>();
|
|
||||||
}</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Start listening for requests</p>
|
|
||||||
|
|
||||||
<h2></h2>
|
|
||||||
|
|
||||||
<ul><li><p><strong>param</strong>: <em>Number</em> port The port number it should be listening to.</p></li><li><p><strong>param</strong>: <em>Server</em> server A HTTP server instance, this will be used to listen for inline requests</p></li><li><p><strong>param</strong>: <em>Function</em> cb The callback needs to be called once server is ready</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">listen</span> = <span class="keyword">function</span> <span class="variable">listen</span>(<span class="variable">port</span>, <span class="variable">server</span>, <span class="variable">cb</span>){
|
|
||||||
<span class="keyword">var</span> <span class="variable">me</span> = <span class="this">this</span>
|
|
||||||
, <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
|
|
||||||
, <span class="variable">callback</span>;
|
|
||||||
|
|
||||||
<span class="comment">// assign the correct vars, for flexible arguments</span>
|
|
||||||
<span class="variable">args</span>.<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">args</span>(<span class="variable">arg</span>){
|
|
||||||
<span class="keyword">var</span> <span class="variable">type</span> = <span class="keyword">typeof</span> <span class="variable">arg</span>;
|
|
||||||
|
|
||||||
<span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'number'</span>) <span class="variable">me</span>.<span class="variable">port</span> = <span class="variable">arg</span>;
|
|
||||||
<span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'function'</span>) <span class="variable">callback</span> = <span class="variable">arg</span>;
|
|
||||||
<span class="keyword">if</span> (<span class="variable">type</span> === <span class="string">'object'</span>) <span class="variable">me</span>.<span class="variable">server</span> = <span class="variable">arg</span>;
|
|
||||||
});
|
|
||||||
|
|
||||||
<span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">server</span>){
|
|
||||||
|
|
||||||
<span class="comment">// no one in their right mind would ever create a `@` prototype, so Im just gonna store</span>
|
|
||||||
<span class="comment">// my function on the server, so I can remove it later again once the server(s) closes</span>
|
|
||||||
<span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>] = <span class="keyword">function</span> <span class="variable">connection</span>(<span class="variable">socket</span>){
|
|
||||||
<span class="variable">socket</span>.<span class="variable">once</span>(<span class="string">'data'</span>, <span class="keyword">function</span> <span class="variable">requestData</span>(<span class="variable">data</span>){
|
|
||||||
<span class="comment">// if it's a Flash policy request, and we can write to the </span>
|
|
||||||
<span class="keyword">if</span> (
|
|
||||||
<span class="variable">data</span>
|
|
||||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>[<span class="number integer">0</span>] === <span class="number integer">60</span>
|
|
||||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>.<span class="variable">toString</span>() === <span class="string">'<policy-file-request/>\0'</span>
|
|
||||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">socket</span>
|
|
||||||
&<span class="variable">amp</span>;&<span class="variable">amp</span>; (<span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'open'</span> || <span class="variable">socket</span>.<span class="variable">readyState</span> === <span class="string">'writeOnly'</span>)
|
|
||||||
){
|
|
||||||
<span class="comment">// send the buffer</span>
|
|
||||||
<span class="variable">socket</span>.<span class="variable">end</span>(<span class="variable">me</span>.<span class="variable">buffer</span>);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
<span class="comment">// attach it</span>
|
|
||||||
<span class="this">this</span>.<span class="variable">server</span>.<span class="variable">on</span>(<span class="string">'connection'</span>, <span class="this">this</span>.<span class="variable">server</span>[<span class="string">'@'</span>]);
|
|
||||||
}
|
|
||||||
|
|
||||||
<span class="comment">// We add a callback method, so we can set a flag for when the server is `enabled` or `online`.</span>
|
|
||||||
<span class="comment">// this flag is needed because if a error occurs and the we cannot boot up the server the</span>
|
|
||||||
<span class="comment">// fallback functionality should not be removed during the `close` event</span>
|
|
||||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">listen</span>(<span class="this">this</span>.<span class="variable">port</span>, <span class="keyword">function</span> <span class="variable">serverListening</span>(){
|
|
||||||
<span class="variable">me</span>.<span class="variable">socket</span>.<span class="variable">online</span> = <span class="variable">true</span>;
|
|
||||||
|
|
||||||
<span class="keyword">if</span> (<span class="variable">callback</span>) <span class="variable">callback</span>(), <span class="variable">callback</span> = <span class="variable">undefined</span>;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
<span class="keyword">return</span> <span class="this">this</span>;
|
|
||||||
};</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Adds a new origin to the Flash Policy File.</p>
|
|
||||||
|
|
||||||
<h2></h2>
|
|
||||||
|
|
||||||
<ul><li><p><strong>param</strong>: <em>Arguments</em> The origins that need to be added.</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">add</span> = <span class="keyword">function</span> <span class="variable">add</span>(){
|
|
||||||
<span class="keyword">var</span> <span class="variable">args</span> = <span class="variable">slice</span>.<span class="variable">call</span>(<span class="variable">arguments</span>, <span class="number integer">0</span>)
|
|
||||||
, <span class="variable">i</span> = <span class="variable">args</span>.<span class="variable">length</span>;
|
|
||||||
|
|
||||||
<span class="comment">// flag duplicates</span>
|
|
||||||
<span class="keyword">while</span> (<span class="variable">i</span>--){
|
|
||||||
<span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">args</span>[<span class="variable">i</span>]) &<span class="variable">gt</span>;= <span class="number integer">0</span>){
|
|
||||||
<span class="variable">args</span>[<span class="variable">i</span>] = <span class="keyword">null</span>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<span class="comment">// Add all the arguments to the array</span>
|
|
||||||
<span class="comment">// but first we want to remove all `falsy` values from the args</span>
|
|
||||||
<span class="class">Array</span>.<span class="variable">prototype</span>.<span class="variable">push</span>.<span class="variable">apply</span>(
|
|
||||||
<span class="this">this</span>.<span class="variable">origins</span>
|
|
||||||
, <span class="variable">args</span>.<span class="variable">filter</span>(<span class="keyword">function</span>(<span class="variable">value</span>){ <span class="keyword">return</span> !!<span class="variable">value</span> })
|
|
||||||
);
|
|
||||||
|
|
||||||
<span class="this">this</span>.<span class="variable">compile</span>();
|
|
||||||
<span class="keyword">return</span> <span class="this">this</span>;
|
|
||||||
};</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Removes a origin from the Flash Policy File.</p>
|
|
||||||
|
|
||||||
<h2></h2>
|
|
||||||
|
|
||||||
<ul><li><p><strong>param</strong>: <em>String</em> origin The origin that needs to be removed from the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">remove</span> = <span class="keyword">function</span> <span class="variable">remove</span>(<span class="variable">origin</span>){
|
|
||||||
<span class="keyword">var</span> <span class="variable">position</span> = <span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">indexOf</span>(<span class="variable">origin</span>);
|
|
||||||
|
|
||||||
<span class="comment">// only remove and recompile if we have a match</span>
|
|
||||||
<span class="keyword">if</span> (<span class="variable">position</span> &<span class="variable">gt</span>; <span class="number integer">0</span>){
|
|
||||||
<span class="this">this</span>.<span class="variable">origins</span>.<span class="variable">splice</span>(<span class="variable">position</span>,<span class="number integer">1</span>);
|
|
||||||
<span class="this">this</span>.<span class="variable">compile</span>();
|
|
||||||
}
|
|
||||||
|
|
||||||
<span class="keyword">return</span> <span class="this">this</span>;
|
|
||||||
};</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Closes and cleans up the server</p>
|
|
||||||
|
|
||||||
<ul><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="class">Server</span>.<span class="variable">prototype</span>.<span class="variable">close</span> = <span class="keyword">function</span> <span class="variable">close</span>(){
|
|
||||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">removeAllListeners</span>();
|
|
||||||
<span class="this">this</span>.<span class="variable">socket</span>.<span class="variable">close</span>();
|
|
||||||
|
|
||||||
<span class="keyword">return</span> <span class="this">this</span>;
|
|
||||||
};</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Proxy the event listener requests to the created Net server
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">process</span>.<span class="class">EventEmitter</span>.<span class="variable">prototype</span>).<span class="variable">forEach</span>(<span class="keyword">function</span> <span class="variable">proxy</span>(<span class="variable">key</span>){
|
|
||||||
<span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] = <span class="class">Server</span>.<span class="variable">prototype</span>[<span class="variable">key</span>] || <span class="keyword">function</span> (){
|
|
||||||
<span class="keyword">if</span> (<span class="this">this</span>.<span class="variable">socket</span>) <span class="this">this</span>.<span class="variable">socket</span>[<span class="variable">key</span>].<span class="variable">apply</span>(<span class="this">this</span>.<span class="variable">socket</span>, <span class="variable">arguments</span>);
|
|
||||||
<span class="keyword">return</span> <span class="this">this</span>;
|
|
||||||
};
|
|
||||||
});</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Creates a new server instance.</p>
|
|
||||||
|
|
||||||
<h2></h2>
|
|
||||||
|
|
||||||
<ul><li><p><strong>param</strong>: <em>Object</em> options A options object to override the default config</p></li><li><p><strong>param</strong>: <em>Array</em> origins The origins that should be allowed by the server</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="variable">exports</span>.<span class="variable">createServer</span> = <span class="keyword">function</span> <span class="variable">createServer</span>(<span class="variable">options</span>, <span class="variable">origins</span>){
|
|
||||||
<span class="variable">origins</span> = <span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">origins</span>) ? <span class="variable">origins</span> : (<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) ? <span class="variable">options</span> : <span class="variable">false</span>);
|
|
||||||
<span class="variable">options</span> = !<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">options</span>) &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">options</span> ? <span class="variable">options</span> : {};
|
|
||||||
|
|
||||||
<span class="keyword">return</span> <span class="keyword">new</span> <span class="class">Server</span>(<span class="variable">options</span>, <span class="variable">origins</span>);
|
|
||||||
};</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Provide a hook to the original server, so it can be extended if needed.
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="variable">exports</span>.<span class="class">Server</span> = <span class="class">Server</span>;</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="code">
|
|
||||||
<td class="docs">
|
|
||||||
<p>Module version
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
<td class="code">
|
|
||||||
<pre><code><span class="variable">exports</span>.<span class="variable">version</span> = <span class="string">'0.0.2'</span>;
|
|
||||||
</code></pre>
|
|
||||||
</td>
|
|
||||||
</tr> </body>
|
|
||||||
</html></tbody></table>
|
|
||||||
8
node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js
generated
vendored
8
node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js
generated
vendored
|
|
@ -1,8 +0,0 @@
|
||||||
var http = require('http')
|
|
||||||
, fspfs = require('../');
|
|
||||||
|
|
||||||
var server = http.createServer(function(q,r){ r.writeHead(200); r.end(':3') })
|
|
||||||
, flash = fspfs.createServer();
|
|
||||||
|
|
||||||
server.listen(8080);
|
|
||||||
flash.listen(8081,server);
|
|
||||||
5
node_modules/socket.io/node_modules/policyfile/examples/basic.js
generated
vendored
5
node_modules/socket.io/node_modules/policyfile/examples/basic.js
generated
vendored
|
|
@ -1,5 +0,0 @@
|
||||||
var http = require('http')
|
|
||||||
, fspfs = require('../');
|
|
||||||
|
|
||||||
var flash = fspfs.createServer();
|
|
||||||
flash.listen();
|
|
||||||
1
node_modules/socket.io/node_modules/policyfile/index.js
generated
vendored
1
node_modules/socket.io/node_modules/policyfile/index.js
generated
vendored
|
|
@ -1 +0,0 @@
|
||||||
module.exports = require('./lib/server.js');
|
|
||||||
289
node_modules/socket.io/node_modules/policyfile/lib/server.js
generated
vendored
289
node_modules/socket.io/node_modules/policyfile/lib/server.js
generated
vendored
|
|
@ -1,289 +0,0 @@
|
||||||
/**
|
|
||||||
* Module dependencies and cached references.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var slice = Array.prototype.slice
|
|
||||||
, net = require('net');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The server that does the Policy File severing
|
|
||||||
*
|
|
||||||
* Options:
|
|
||||||
* - `log` false or a function that can output log information, defaults to console.log?
|
|
||||||
*
|
|
||||||
* @param {Object} options Options to customize the servers functionality.
|
|
||||||
* @param {Array} origins The origins that are allowed on this server, defaults to `*:*`.
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Server (options, origins) {
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
this.origins = origins || ['*:*'];
|
|
||||||
this.port = 843;
|
|
||||||
this.log = console.log;
|
|
||||||
|
|
||||||
// merge `this` with the options
|
|
||||||
Object.keys(options).forEach(function (key) {
|
|
||||||
me[key] && (me[key] = options[key])
|
|
||||||
});
|
|
||||||
|
|
||||||
// create the net server
|
|
||||||
this.socket = net.createServer(function createServer (socket) {
|
|
||||||
socket.on('error', function socketError () {
|
|
||||||
me.responder.call(me, socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
me.responder.call(me, socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Listen for errors as the port might be blocked because we do not have root priv.
|
|
||||||
this.socket.on('error', function serverError (err) {
|
|
||||||
// Special and common case error handling
|
|
||||||
if (err.errno == 13) {
|
|
||||||
me.log && me.log(
|
|
||||||
'Unable to listen to port `' + me.port + '` as your Node.js instance does not have root privileges. ' +
|
|
||||||
(
|
|
||||||
me.server
|
|
||||||
? 'The Flash Policy File requests will only be served inline over the supplied HTTP server. Inline serving is slower than a dedicated server instance.'
|
|
||||||
: 'No fallback server supplied, we will be unable to answer Flash Policy File requests.'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
me.emit('connect_failed', err);
|
|
||||||
me.socket.removeAllListeners();
|
|
||||||
delete me.socket;
|
|
||||||
} else {
|
|
||||||
me.log && me.log('FlashPolicyFileServer received an error event:\n' + (err.message ? err.message : err));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.socket.on('timeout', function serverTimeout () {});
|
|
||||||
this.socket.on('close', function serverClosed (err) {
|
|
||||||
err && me.log && me.log('Server closing due to an error: \n' + (err.message ? err.message : err));
|
|
||||||
|
|
||||||
if (me.server) {
|
|
||||||
// Remove the inline policy listener if we close down
|
|
||||||
// but only when the server was `online` (see listen prototype)
|
|
||||||
if (me.server['@'] && me.server.online) {
|
|
||||||
me.server.removeListener('connection', me.server['@']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// not online anymore
|
|
||||||
delete me.server.online;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Compile the initial `buffer`
|
|
||||||
this.compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start listening for requests
|
|
||||||
*
|
|
||||||
* @param {Number} port The port number it should be listening to.
|
|
||||||
* @param {Server} server A HTTP server instance, this will be used to listen for inline requests
|
|
||||||
* @param {Function} cb The callback needs to be called once server is ready
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Server.prototype.listen = function listen (port, server, cb){
|
|
||||||
var me = this
|
|
||||||
, args = slice.call(arguments, 0)
|
|
||||||
, callback;
|
|
||||||
|
|
||||||
// assign the correct vars, for flexible arguments
|
|
||||||
args.forEach(function args (arg){
|
|
||||||
var type = typeof arg;
|
|
||||||
|
|
||||||
if (type === 'number') me.port = arg;
|
|
||||||
if (type === 'function') callback = arg;
|
|
||||||
if (type === 'object') me.server = arg;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.server) {
|
|
||||||
|
|
||||||
// no one in their right mind would ever create a `@` prototype, so Im just gonna store
|
|
||||||
// my function on the server, so I can remove it later again once the server(s) closes
|
|
||||||
this.server['@'] = function connection (socket) {
|
|
||||||
socket.once('data', function requestData (data) {
|
|
||||||
// if it's a Flash policy request, and we can write to the
|
|
||||||
if (
|
|
||||||
data
|
|
||||||
&& data[0] === 60
|
|
||||||
&& data.toString() === '<policy-file-request/>\0'
|
|
||||||
&& socket
|
|
||||||
&& (socket.readyState === 'open' || socket.readyState === 'writeOnly')
|
|
||||||
){
|
|
||||||
// send the buffer
|
|
||||||
try {
|
|
||||||
socket.end(me.buffer);
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// attach it
|
|
||||||
this.server.on('connection', this.server['@']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We add a callback method, so we can set a flag for when the server is `enabled` or `online`.
|
|
||||||
// this flag is needed because if a error occurs and the we cannot boot up the server the
|
|
||||||
// fallback functionality should not be removed during the `close` event
|
|
||||||
this.port >= 0 && this.socket.listen(this.port, function serverListening () {
|
|
||||||
me.socket.online = true;
|
|
||||||
if (callback) {
|
|
||||||
callback.call(me);
|
|
||||||
callback = undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Responds to socket connects and writes the compile policy file.
|
|
||||||
*
|
|
||||||
* @param {net.Socket} socket The socket that needs to receive the message
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Server.prototype.responder = function responder (socket){
|
|
||||||
if (socket && socket.readyState == 'open' && socket.end) {
|
|
||||||
try {
|
|
||||||
socket.end(this.buffer);
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the supplied origins to a Flash Policy File format and stores it in a Node.js Buffer
|
|
||||||
* this way it can be send over the wire without any performance loss.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
Server.prototype.compile = function compile (){
|
|
||||||
var xml = [
|
|
||||||
'<?xml version="1.0"?>'
|
|
||||||
, '<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">'
|
|
||||||
, '<cross-domain-policy>'
|
|
||||||
];
|
|
||||||
|
|
||||||
// add the allow access element
|
|
||||||
this.origins.forEach(function origin (origin){
|
|
||||||
var parts = origin.split(':');
|
|
||||||
xml.push('<allow-access-from domain="' + parts[0] + '" to-ports="'+ parts[1] +'"/>');
|
|
||||||
});
|
|
||||||
|
|
||||||
xml.push('</cross-domain-policy>');
|
|
||||||
|
|
||||||
// store the result in a buffer so we don't have to re-generate it all the time
|
|
||||||
this.buffer = new Buffer(xml.join(''), 'utf8');
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new origin to the Flash Policy File.
|
|
||||||
*
|
|
||||||
* @param {Arguments} The origins that need to be added.
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Server.prototype.add = function add(){
|
|
||||||
var args = slice.call(arguments, 0)
|
|
||||||
, i = args.length;
|
|
||||||
|
|
||||||
// flag duplicates
|
|
||||||
while (i--) {
|
|
||||||
if (this.origins.indexOf(args[i]) >= 0){
|
|
||||||
args[i] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all the arguments to the array
|
|
||||||
// but first we want to remove all `falsy` values from the args
|
|
||||||
Array.prototype.push.apply(
|
|
||||||
this.origins
|
|
||||||
, args.filter(function filter (value) {
|
|
||||||
return !!value;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
this.compile();
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a origin from the Flash Policy File.
|
|
||||||
*
|
|
||||||
* @param {String} origin The origin that needs to be removed from the server
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Server.prototype.remove = function remove (origin){
|
|
||||||
var position = this.origins.indexOf(origin);
|
|
||||||
|
|
||||||
// only remove and recompile if we have a match
|
|
||||||
if (position > 0) {
|
|
||||||
this.origins.splice(position,1);
|
|
||||||
this.compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes and cleans up the server
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Server.prototype.close = function close () {
|
|
||||||
this.socket.removeAllListeners();
|
|
||||||
this.socket.close();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy the event listener requests to the created Net server
|
|
||||||
*/
|
|
||||||
|
|
||||||
Object.keys(process.EventEmitter.prototype).forEach(function proxy (key){
|
|
||||||
Server.prototype[key] = Server.prototype[key] || function () {
|
|
||||||
if (this.socket) {
|
|
||||||
this.socket[key].apply(this.socket, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new server instance.
|
|
||||||
*
|
|
||||||
* @param {Object} options A options object to override the default config
|
|
||||||
* @param {Array} origins The origins that should be allowed by the server
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.createServer = function createServer(options, origins){
|
|
||||||
origins = Array.isArray(origins) ? origins : (Array.isArray(options) ? options : false);
|
|
||||||
options = !Array.isArray(options) && options ? options : {};
|
|
||||||
|
|
||||||
return new Server(options, origins);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide a hook to the original server, so it can be extended if needed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.Server = Server;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module version
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.version = '0.0.4';
|
|
||||||
55
node_modules/socket.io/node_modules/policyfile/package.json
generated
vendored
55
node_modules/socket.io/node_modules/policyfile/package.json
generated
vendored
|
|
@ -1,55 +0,0 @@
|
||||||
{
|
|
||||||
"name": "policyfile",
|
|
||||||
"version": "0.0.4",
|
|
||||||
"author": {
|
|
||||||
"name": "Arnout Kazemier"
|
|
||||||
},
|
|
||||||
"description": "Flash Socket Policy File Server. A server to respond to Flash Socket Policy requests, both inline and through a dedicated server instance.",
|
|
||||||
"main": "index",
|
|
||||||
"keywords": [
|
|
||||||
"flash",
|
|
||||||
"socket",
|
|
||||||
"policy",
|
|
||||||
"file",
|
|
||||||
"server",
|
|
||||||
"Flash Socket Policy File Server",
|
|
||||||
"cross domain"
|
|
||||||
],
|
|
||||||
"directories": {
|
|
||||||
"lib": "./lib"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "Arnout Kazemier",
|
|
||||||
"email": "info@3rd-Eden.com",
|
|
||||||
"url": "http://blog.3rd-Eden.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"licenses": [
|
|
||||||
{
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "https://github.com/3rd-Eden/FlashPolicyFileServer/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repositories": [
|
|
||||||
{
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/3rd-Eden/FlashPolicyFileServer.git"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"_id": "policyfile@0.0.4",
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {},
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"_engineSupported": true,
|
|
||||||
"_npmVersion": "1.1.9",
|
|
||||||
"_nodeVersion": "v0.6.13",
|
|
||||||
"_defaultsLoaded": true,
|
|
||||||
"dist": {
|
|
||||||
"shasum": "5d68831f86284d31ba967d0211f70ffc12206879"
|
|
||||||
},
|
|
||||||
"_from": "policyfile@0.0.4"
|
|
||||||
}
|
|
||||||
21
node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt
generated
vendored
21
node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt
generated
vendored
|
|
@ -1,21 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDXTCCAkWgAwIBAgIJAMUSOvlaeyQHMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
|
||||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
|
||||||
aWRnaXRzIFB0eSBMdGQwHhcNMTAxMTE2MDkzMjQ5WhcNMTMxMTE1MDkzMjQ5WjBF
|
|
||||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
|
||||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
|
||||||
CgKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEVwfPQQp4X
|
|
||||||
wtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+1FAE0c5o
|
|
||||||
exPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404WthquTqg
|
|
||||||
S7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy25IyBK3QJ
|
|
||||||
c+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWAQsqW+COL
|
|
||||||
0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABo1AwTjAdBgNVHQ4EFgQUDnV4d6mD
|
|
||||||
tOnluLoCjkUHTX/n4agwHwYDVR0jBBgwFoAUDnV4d6mDtOnluLoCjkUHTX/n4agw
|
|
||||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAFwV4MQfTo+qMv9JMiyno
|
|
||||||
IEiqfOz4RgtmBqRnXUffcjS2dhc7/z+FPZnM79Kej8eLHoVfxCyWRHFlzm93vEdv
|
|
||||||
wxOCrD13EDOi08OOZfxWyIlCa6Bg8cMAKqQzd2OvQOWqlRWBTThBJIhWflU33izX
|
|
||||||
Qn5GdmYqhfpc+9ZHHGhvXNydtRQkdxVK2dZNzLBvBlLlRmtoClU7xm3A+/5dddeP
|
|
||||||
AQHEPtyFlUw49VYtZ3ru6KqPms7MKvcRhYLsy9rwSfuuniMlx4d0bDR7TOkw0QQS
|
|
||||||
A0N8MGQRQpzl4mw4jLzyM5d5QtuGBh2P6hPGa0YQxtI3RPT/p6ENzzBiAKXiSfzo
|
|
||||||
xw==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
27
node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key
generated
vendored
27
node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key
generated
vendored
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEV
|
|
||||||
wfPQQp4XwtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+
|
|
||||||
1FAE0c5oexPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404
|
|
||||||
WthquTqgS7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy2
|
|
||||||
5IyBK3QJc+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWA
|
|
||||||
QsqW+COL0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABAoIBAGe4+9VqZfJN+dsq
|
|
||||||
8Osyuz01uQ8OmC0sAWTIqUlQgENIyf9rCJsUBlYmwR5BT6Z69XP6QhHdpSK+TiAR
|
|
||||||
XUz0EqG9HYzcxHIBaACP7j6iRoQ8R4kbbiWKo0z3WqQGIOqFjvD/mKEuQdE5mEYw
|
|
||||||
eOUCG6BnX1WY2Yr8WKd2AA/tp0/Y4d8z04u9eodMpSTbHTzYMJb5SbBN1vo6FY7q
|
|
||||||
8zSuO0BMzXlAxUsCwHsk1GQHFr8Oh3zIR7bQGtMBouI+6Lhh7sjFYsfxJboqMTBV
|
|
||||||
IKaA216M6ggHG7MU1/jeKcMGDmEfqQLQoyWp29rMK6TklUgipME2L3UD7vTyAVzz
|
|
||||||
xbVOpZkCgYEA8CXW4sZBBrSSrLR5SB+Ubu9qNTggLowOsC/kVKB2WJ4+xooc5HQo
|
|
||||||
mFhq1v/WxPQoWIxdYsfg2odlL+JclK5Qcy6vXmRSdAQ5lK9gBDKxZSYc3NwAw2HA
|
|
||||||
zyHCTK+I0n8PBYQ+yGcrxu0WqTGnlLW+Otk4CejO34WlgHwbH9bbY5UCgYEA3ZvT
|
|
||||||
C4+OoMHXlmICSt29zUrYiL33IWsR3/MaONxTEDuvgkOSXXQOl/8Ebd6Nu+3WbsSN
|
|
||||||
bjiPC/JyL1YCVmijdvFpl4gjtgvfJifs4G+QHvO6YfsYoVANk4u6g6rUuBIOwNK4
|
|
||||||
RwYxwDc0oysp+g7tPxoSgDHReEVKJNzGBe9NGGsCgYEA4O4QP4gCEA3B9BF2J5+s
|
|
||||||
n9uPVxmiyvZUK6Iv8zP4pThTBBMIzNIf09G9AHPQ7djikU2nioY8jXKTzC3xGTHM
|
|
||||||
GJZ5m6fLsu7iH+nDvSreDSeNkTBfZqGAvoGYQ8uGE+L+ZuRfCcXYsxIOT5s6o4c3
|
|
||||||
Dle2rVFpsuKzCY00urW796ECgYBn3go75+xEwrYGQSer6WR1nTgCV29GVYXKPooy
|
|
||||||
zmmMOT1Yw80NSkEw0pFD4cTyqVYREsTrPU0mn1sPfrOXxnGfZSVFpcR/Je9QVfQ7
|
|
||||||
eW7GYxwfom335aqHVj10SxRqteP+UoWWnHujCPz94VRKZMakBddYCIGSan+G6YdS
|
|
||||||
7sdmwwKBgBc2qj0wvGXDF2kCLwSGfWoMf8CS1+5fIiUIdT1e/+7MfDdbmLMIFVjF
|
|
||||||
QKS3zVViXCbrG5SY6wS9hxoc57f6E2A8vcaX6zy2xkZlGHQCpWRtEM5R01OWJQaH
|
|
||||||
HsHMmQZGUQVoDm1oRkDhrTFK4K3ukc3rAxzeTZ96utOQN8/KJsTv
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
231
node_modules/socket.io/node_modules/policyfile/tests/unit.test.js
generated
vendored
231
node_modules/socket.io/node_modules/policyfile/tests/unit.test.js
generated
vendored
|
|
@ -1,231 +0,0 @@
|
||||||
var fspfs = require('../')
|
|
||||||
, fs = require('fs')
|
|
||||||
, http = require('http')
|
|
||||||
, https = require('https')
|
|
||||||
, net = require('net')
|
|
||||||
, should = require('should')
|
|
||||||
, assert = require('assert');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
// Library version should be Semver compatible
|
|
||||||
'Library version': function(){
|
|
||||||
fspfs.version.should.match(/^\d+\.\d+\.\d+$/);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creating a server instace should not cause any problems
|
|
||||||
// either using the new Server or createServer method.
|
|
||||||
, 'Create Server instance': function(){
|
|
||||||
var server = fspfs.createServer()
|
|
||||||
, server2 = new fspfs.Server({log:false}, ['blog.3rd-Eden.com:1337']);
|
|
||||||
|
|
||||||
// server 2 options test
|
|
||||||
server2.log.should.be.false;
|
|
||||||
server2.origins.length.should.equal(1);
|
|
||||||
server2.origins[0].should.equal('blog.3rd-Eden.com:1337');
|
|
||||||
|
|
||||||
// server defaults
|
|
||||||
(typeof server.log).should.be.equal('function');
|
|
||||||
server.origins.length.should.equal(1);
|
|
||||||
server.origins[0].should.equal('*:*');
|
|
||||||
|
|
||||||
// instance checking, sanity check
|
|
||||||
assert.ok(server instanceof fspfs.Server);
|
|
||||||
assert.ok(!!server.buffer);
|
|
||||||
|
|
||||||
// more options testing
|
|
||||||
server = fspfs.createServer(['blog.3rd-Eden.com:80']);
|
|
||||||
server.origins.length.should.equal(1);
|
|
||||||
server.origins[0].should.equal('blog.3rd-Eden.com:80');
|
|
||||||
|
|
||||||
server = fspfs.createServer({log:false},['blog.3rd-Eden.com:80']);
|
|
||||||
server.log.should.be.false;
|
|
||||||
server.origins.length.should.equal(1);
|
|
||||||
server.origins[0].should.equal('blog.3rd-Eden.com:80');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'Add origin': function(){
|
|
||||||
var server = fspfs.createServer();
|
|
||||||
server.add('google.com:80', 'blog.3rd-Eden.com:1337');
|
|
||||||
|
|
||||||
server.origins.length.should.equal(3);
|
|
||||||
server.origins.indexOf('google.com:80').should.be.above(0);
|
|
||||||
|
|
||||||
// don't allow duplicates
|
|
||||||
server.add('google.com:80', 'google.com:80');
|
|
||||||
|
|
||||||
var i = server.origins.length
|
|
||||||
, count = 0;
|
|
||||||
|
|
||||||
while(i--){
|
|
||||||
if (server.origins[i] === 'google.com:80'){
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
count.should.equal(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'Remove origin': function(){
|
|
||||||
var server = fspfs.createServer();
|
|
||||||
server.add('google.com:80', 'blog.3rd-Eden.com:1337');
|
|
||||||
server.origins.length.should.equal(3);
|
|
||||||
|
|
||||||
server.remove('google.com:80');
|
|
||||||
server.origins.length.should.equal(2);
|
|
||||||
server.origins.indexOf('google.com:80').should.equal(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'Buffer': function(){
|
|
||||||
var server = fspfs.createServer();
|
|
||||||
|
|
||||||
Buffer.isBuffer(server.buffer).should.be.true;
|
|
||||||
server.buffer.toString().indexOf('to-ports="*"').should.be.above(0);
|
|
||||||
server.buffer.toString().indexOf('domain="*"').should.be.above(0);
|
|
||||||
server.buffer.toString().indexOf('domain="google.com"').should.equal(-1);
|
|
||||||
|
|
||||||
// The buffers should be rebuild when new origins are added
|
|
||||||
server.add('google.com:80');
|
|
||||||
server.buffer.toString().indexOf('to-ports="80"').should.be.above(0);
|
|
||||||
server.buffer.toString().indexOf('domain="google.com"').should.be.above(0);
|
|
||||||
|
|
||||||
server.remove('google.com:80');
|
|
||||||
server.buffer.toString().indexOf('to-ports="80"').should.equal(-1);
|
|
||||||
server.buffer.toString().indexOf('domain="google.com"').should.equal(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'Responder': function(){
|
|
||||||
var server = fspfs.createServer()
|
|
||||||
, calls = 0
|
|
||||||
// dummy socket to emulate a `real` socket
|
|
||||||
, dummySocket = {
|
|
||||||
readyState: 'open'
|
|
||||||
, end: function(buffer){
|
|
||||||
calls++;
|
|
||||||
Buffer.isBuffer(buffer).should.be.true;
|
|
||||||
buffer.toString().should.equal(server.buffer.toString());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
server.responder(dummySocket);
|
|
||||||
calls.should.equal(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'Event proxy': function(){
|
|
||||||
var server = fspfs.createServer()
|
|
||||||
, calls = 0;
|
|
||||||
|
|
||||||
Object.keys(process.EventEmitter.prototype).forEach(function proxy(key){
|
|
||||||
assert.ok(!!server[key] && typeof server[key] === 'function');
|
|
||||||
});
|
|
||||||
|
|
||||||
// test if it works by calling a none default event
|
|
||||||
server.on('pew', function(){
|
|
||||||
calls++;
|
|
||||||
});
|
|
||||||
|
|
||||||
server.emit('pew');
|
|
||||||
calls.should.equal(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'inline response http': function(){
|
|
||||||
var port = 1335
|
|
||||||
, httpserver = http.createServer(function(q,r){r.writeHead(200);r.end(':3')})
|
|
||||||
, server = fspfs.createServer();
|
|
||||||
|
|
||||||
httpserver.listen(port, function(){
|
|
||||||
server.listen(port + 1, httpserver, function(){
|
|
||||||
var client = net.createConnection(port);
|
|
||||||
client.write('<policy-file-request/>\0');
|
|
||||||
client.on('error', function(err){
|
|
||||||
assert.ok(!err, err)
|
|
||||||
});
|
|
||||||
client.on('data', function(data){
|
|
||||||
|
|
||||||
var response = data.toString();
|
|
||||||
console.log(response);
|
|
||||||
|
|
||||||
response.indexOf('to-ports="*"').should.be.above(0);
|
|
||||||
response.indexOf('domain="*"').should.be.above(0);
|
|
||||||
response.indexOf('domain="google.com"').should.equal(-1);
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
client.destroy();
|
|
||||||
server.close();
|
|
||||||
httpserver.close();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'server response': function(){
|
|
||||||
var port = 1340
|
|
||||||
, server = fspfs.createServer();
|
|
||||||
|
|
||||||
server.listen(port, function(){
|
|
||||||
var client = net.createConnection(port);
|
|
||||||
client.write('<policy-file-request/>\0');
|
|
||||||
client.on('error', function(err){
|
|
||||||
assert.ok(!err, err)
|
|
||||||
});
|
|
||||||
client.on('data', function(data){
|
|
||||||
|
|
||||||
var response = data.toString();
|
|
||||||
|
|
||||||
response.indexOf('to-ports="*"').should.be.above(0);
|
|
||||||
response.indexOf('domain="*"').should.be.above(0);
|
|
||||||
response.indexOf('domain="google.com"').should.equal(-1);
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
client.destroy();
|
|
||||||
server.close();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'inline response https': function(){
|
|
||||||
var port = 1345
|
|
||||||
, ssl = {
|
|
||||||
key: fs.readFileSync(__dirname + '/ssl/ssl.private.key').toString()
|
|
||||||
, cert: fs.readFileSync(__dirname + '/ssl/ssl.crt').toString()
|
|
||||||
}
|
|
||||||
, httpserver = https.createServer(ssl, function(q,r){r.writeHead(200);r.end(':3')})
|
|
||||||
, server = fspfs.createServer();
|
|
||||||
|
|
||||||
httpserver.listen(port, function(){
|
|
||||||
server.listen(port + 1, httpserver, function(){
|
|
||||||
var client = net.createConnection(port);
|
|
||||||
client.write('<policy-file-request/>\0');
|
|
||||||
client.on('error', function(err){
|
|
||||||
assert.ok(!err, err)
|
|
||||||
});
|
|
||||||
client.on('data', function(data){
|
|
||||||
|
|
||||||
var response = data.toString();
|
|
||||||
|
|
||||||
response.indexOf('to-ports="*"').should.be.above(0);
|
|
||||||
response.indexOf('domain="*"').should.be.above(0);
|
|
||||||
response.indexOf('domain="google.com"').should.equal(-1);
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
client.destroy();
|
|
||||||
server.close();
|
|
||||||
httpserver.close();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
, 'connect_failed': function(){
|
|
||||||
var server = fspfs.createServer();
|
|
||||||
|
|
||||||
server.on('connect_failed', function(){
|
|
||||||
assert.ok(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(function(){
|
|
||||||
assert.ok(false, 'Run this test without root access');
|
|
||||||
server.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
567
node_modules/socket.io/node_modules/redis/README.md
generated
vendored
567
node_modules/socket.io/node_modules/redis/README.md
generated
vendored
|
|
@ -1,567 +0,0 @@
|
||||||
redis - a node.js redis client
|
|
||||||
===========================
|
|
||||||
|
|
||||||
This is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from
|
|
||||||
experimental Redis server branches.
|
|
||||||
|
|
||||||
|
|
||||||
Install with:
|
|
||||||
|
|
||||||
npm install redis
|
|
||||||
|
|
||||||
Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do:
|
|
||||||
|
|
||||||
npm install hiredis redis
|
|
||||||
|
|
||||||
If `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used.
|
|
||||||
|
|
||||||
If you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can
|
|
||||||
happen between node and native code modules after a node upgrade.
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Simple example, included as `examples/simple.js`:
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
client.on("error", function (err) {
|
|
||||||
console.log("Error " + err);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.set("string key", "string val", redis.print);
|
|
||||||
client.hset("hash key", "hashtest 1", "some value", redis.print);
|
|
||||||
client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
|
|
||||||
client.hkeys("hash key", function (err, replies) {
|
|
||||||
console.log(replies.length + " replies:");
|
|
||||||
replies.forEach(function (reply, i) {
|
|
||||||
console.log(" " + i + ": " + reply);
|
|
||||||
});
|
|
||||||
client.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
This will display:
|
|
||||||
|
|
||||||
mjr:~/work/node_redis (master)$ node example.js
|
|
||||||
Reply: OK
|
|
||||||
Reply: 0
|
|
||||||
Reply: 0
|
|
||||||
2 replies:
|
|
||||||
0: hashtest 1
|
|
||||||
1: hashtest 2
|
|
||||||
mjr:~/work/node_redis (master)$
|
|
||||||
|
|
||||||
|
|
||||||
## Performance
|
|
||||||
|
|
||||||
Here are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution.
|
|
||||||
It uses 50 concurrent connections with no pipelining.
|
|
||||||
|
|
||||||
JavaScript parser:
|
|
||||||
|
|
||||||
PING: 20000 ops 42283.30 ops/sec 0/5/1.182
|
|
||||||
SET: 20000 ops 32948.93 ops/sec 1/7/1.515
|
|
||||||
GET: 20000 ops 28694.40 ops/sec 0/9/1.740
|
|
||||||
INCR: 20000 ops 39370.08 ops/sec 0/8/1.269
|
|
||||||
LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370
|
|
||||||
LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048
|
|
||||||
LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072
|
|
||||||
|
|
||||||
hiredis parser:
|
|
||||||
|
|
||||||
PING: 20000 ops 46189.38 ops/sec 1/4/1.082
|
|
||||||
SET: 20000 ops 41237.11 ops/sec 0/6/1.210
|
|
||||||
GET: 20000 ops 39682.54 ops/sec 1/7/1.257
|
|
||||||
INCR: 20000 ops 40080.16 ops/sec 0/8/1.242
|
|
||||||
LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212
|
|
||||||
LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363
|
|
||||||
LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287
|
|
||||||
|
|
||||||
The performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs.
|
|
||||||
|
|
||||||
|
|
||||||
### Sending Commands
|
|
||||||
|
|
||||||
Each Redis command is exposed as a function on the `client` object.
|
|
||||||
All functions take either take either an `args` Array plus optional `callback` Function or
|
|
||||||
a variable number of individual arguments followed by an optional callback.
|
|
||||||
Here is an example of passing an array of arguments and a callback:
|
|
||||||
|
|
||||||
client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});
|
|
||||||
|
|
||||||
Here is that same call in the second style:
|
|
||||||
|
|
||||||
client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});
|
|
||||||
|
|
||||||
Note that in either form the `callback` is optional:
|
|
||||||
|
|
||||||
client.set("some key", "some val");
|
|
||||||
client.set(["some other key", "some val"]);
|
|
||||||
|
|
||||||
For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)
|
|
||||||
|
|
||||||
The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`.
|
|
||||||
|
|
||||||
Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,
|
|
||||||
integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a
|
|
||||||
JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys.
|
|
||||||
|
|
||||||
# API
|
|
||||||
|
|
||||||
## Connection Events
|
|
||||||
|
|
||||||
`client` will emit some events about the state of the connection to the Redis server.
|
|
||||||
|
|
||||||
### "ready"
|
|
||||||
|
|
||||||
`client` will emit `ready` a connection is established to the Redis server and the server reports
|
|
||||||
that it is ready to receive commands. Commands issued before the `ready` event are queued,
|
|
||||||
then replayed just before this event is emitted.
|
|
||||||
|
|
||||||
### "connect"
|
|
||||||
|
|
||||||
`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check`
|
|
||||||
is set. If this options is set, `connect` will be emitted when the stream is connected, and then
|
|
||||||
you are free to try to send commands.
|
|
||||||
|
|
||||||
### "error"
|
|
||||||
|
|
||||||
`client` will emit `error` when encountering an error connecting to the Redis server.
|
|
||||||
|
|
||||||
Note that "error" is a special event type in node. If there are no listeners for an
|
|
||||||
"error" event, node will exit. This is usually what you want, but it can lead to some
|
|
||||||
cryptic error messages like this:
|
|
||||||
|
|
||||||
mjr:~/work/node_redis (master)$ node example.js
|
|
||||||
|
|
||||||
node.js:50
|
|
||||||
throw e;
|
|
||||||
^
|
|
||||||
Error: ECONNREFUSED, Connection refused
|
|
||||||
at IOWatcher.callback (net:870:22)
|
|
||||||
at node.js:607:9
|
|
||||||
|
|
||||||
Not very useful in diagnosing the problem, but if your program isn't ready to handle this,
|
|
||||||
it is probably the right thing to just exit.
|
|
||||||
|
|
||||||
`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason.
|
|
||||||
It would be nice to distinguish these two cases.
|
|
||||||
|
|
||||||
### "end"
|
|
||||||
|
|
||||||
`client` will emit `end` when an established Redis server connection has closed.
|
|
||||||
|
|
||||||
### "drain"
|
|
||||||
|
|
||||||
`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now
|
|
||||||
writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,
|
|
||||||
you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can
|
|
||||||
resume sending when you get `drain`.
|
|
||||||
|
|
||||||
### "idle"
|
|
||||||
|
|
||||||
`client` will emit `idle` when there are no outstanding commands that are awaiting a response.
|
|
||||||
|
|
||||||
## redis.createClient(port, host, options)
|
|
||||||
|
|
||||||
Create a new client connection. `port` defaults to `6379` and `host` defaults
|
|
||||||
to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for
|
|
||||||
port and host are probably fine. `options` in an object with the following possible properties:
|
|
||||||
|
|
||||||
* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed.
|
|
||||||
This may also be set to `javascript`.
|
|
||||||
* `return_buffers`: defaults to false. If set to `true`, then bulk data replies will be returned as node Buffer
|
|
||||||
objects instead of JavaScript Strings.
|
|
||||||
|
|
||||||
`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.
|
|
||||||
|
|
||||||
## client.auth(password, callback)
|
|
||||||
|
|
||||||
When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the
|
|
||||||
first command after connecting. This can be tricky to coordinate with reconnections, the ready check,
|
|
||||||
etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,
|
|
||||||
including reconnections. `callback` is invoked only once, after the response to the very first
|
|
||||||
`AUTH` command sent.
|
|
||||||
|
|
||||||
## client.end()
|
|
||||||
|
|
||||||
Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.
|
|
||||||
If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies.
|
|
||||||
|
|
||||||
This example closes the connection to the Redis server before the replies have been read. You probably don't
|
|
||||||
want to do this:
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
client.set("foo_rand000000000000", "some fantastic value");
|
|
||||||
client.get("foo_rand000000000000", function (err, reply) {
|
|
||||||
console.log(reply.toString());
|
|
||||||
});
|
|
||||||
client.end();
|
|
||||||
|
|
||||||
`client.end()` is useful for timeout cases where something is stuck or taking too long and you want
|
|
||||||
to start over.
|
|
||||||
|
|
||||||
## Friendlier hash commands
|
|
||||||
|
|
||||||
Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. When dealing with hash values, there are a couple of useful exceptions to this.
|
|
||||||
|
|
||||||
### client.hgetall(hash)
|
|
||||||
|
|
||||||
The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact
|
|
||||||
with the responses using JavaScript syntax.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234");
|
|
||||||
client.hgetall("hosts", function (err, obj) {
|
|
||||||
console.dir(obj);
|
|
||||||
});
|
|
||||||
|
|
||||||
Output:
|
|
||||||
|
|
||||||
{ mjr: '1', another: '23', home: '1234' }
|
|
||||||
|
|
||||||
### client.hmset(hash, obj, [callback])
|
|
||||||
|
|
||||||
Multiple values in a hash can be set by supplying an object:
|
|
||||||
|
|
||||||
client.HMSET(key2, {
|
|
||||||
"0123456789": "abcdefghij",
|
|
||||||
"some manner of key": "a type of value"
|
|
||||||
});
|
|
||||||
|
|
||||||
The properties and values of this Object will be set as keys and values in the Redis hash.
|
|
||||||
|
|
||||||
### client.hmset(hash, key1, val1, ... keyn, valn, [callback])
|
|
||||||
|
|
||||||
Multiple values may also be set by supplying a list:
|
|
||||||
|
|
||||||
client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value");
|
|
||||||
|
|
||||||
|
|
||||||
## Publish / Subscribe
|
|
||||||
|
|
||||||
Here is a simple example of the API for publish / subscribe. This program opens two
|
|
||||||
client connections, subscribes to a channel on one of them, and publishes to that
|
|
||||||
channel on the other:
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client1 = redis.createClient(), client2 = redis.createClient(),
|
|
||||||
msg_count = 0;
|
|
||||||
|
|
||||||
client1.on("subscribe", function (channel, count) {
|
|
||||||
client2.publish("a nice channel", "I am sending a message.");
|
|
||||||
client2.publish("a nice channel", "I am sending a second message.");
|
|
||||||
client2.publish("a nice channel", "I am sending my last message.");
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.on("message", function (channel, message) {
|
|
||||||
console.log("client1 channel " + channel + ": " + message);
|
|
||||||
msg_count += 1;
|
|
||||||
if (msg_count === 3) {
|
|
||||||
client1.unsubscribe();
|
|
||||||
client1.end();
|
|
||||||
client2.end();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.incr("did a thing");
|
|
||||||
client1.subscribe("a nice channel");
|
|
||||||
|
|
||||||
When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into "pub/sub" mode.
|
|
||||||
At that point, only commands that modify the subscription set are valid. When the subscription
|
|
||||||
set is empty, the connection is put back into regular mode.
|
|
||||||
|
|
||||||
If you need to send regular commands to Redis while in pub/sub mode, just open another connection.
|
|
||||||
|
|
||||||
## Pub / Sub Events
|
|
||||||
|
|
||||||
If a client has subscriptions active, it may emit these events:
|
|
||||||
|
|
||||||
### "message" (channel, message)
|
|
||||||
|
|
||||||
Client will emit `message` for every message received that matches an active subscription.
|
|
||||||
Listeners are passed the channel name as `channel` and the message Buffer as `message`.
|
|
||||||
|
|
||||||
### "pmessage" (pattern, channel, message)
|
|
||||||
|
|
||||||
Client will emit `pmessage` for every message received that matches an active subscription pattern.
|
|
||||||
Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel
|
|
||||||
name as `channel`, and the message Buffer as `message`.
|
|
||||||
|
|
||||||
### "subscribe" (channel, count)
|
|
||||||
|
|
||||||
Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the
|
|
||||||
channel name as `channel` and the new count of subscriptions for this client as `count`.
|
|
||||||
|
|
||||||
### "psubscribe" (pattern, count)
|
|
||||||
|
|
||||||
Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the
|
|
||||||
original pattern as `pattern`, and the new count of subscriptions for this client as `count`.
|
|
||||||
|
|
||||||
### "unsubscribe" (channel, count)
|
|
||||||
|
|
||||||
Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the
|
|
||||||
channel name as `channel` and the new count of subscriptions for this client as `count`. When
|
|
||||||
`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
|
|
||||||
|
|
||||||
### "punsubscribe" (pattern, count)
|
|
||||||
|
|
||||||
Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the
|
|
||||||
channel name as `channel` and the new count of subscriptions for this client as `count`. When
|
|
||||||
`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
|
|
||||||
|
|
||||||
## client.multi([commands])
|
|
||||||
|
|
||||||
`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by
|
|
||||||
Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`.
|
|
||||||
|
|
||||||
var redis = require("./index"),
|
|
||||||
client = redis.createClient(), set_size = 20;
|
|
||||||
|
|
||||||
client.sadd("bigset", "a member");
|
|
||||||
client.sadd("bigset", "another member");
|
|
||||||
|
|
||||||
while (set_size > 0) {
|
|
||||||
client.sadd("bigset", "member " + set_size);
|
|
||||||
set_size -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// multi chain with an individual callback
|
|
||||||
client.multi()
|
|
||||||
.scard("bigset")
|
|
||||||
.smembers("bigset")
|
|
||||||
.keys("*", function (err, replies) {
|
|
||||||
client.mget(replies, redis.print);
|
|
||||||
})
|
|
||||||
.dbsize()
|
|
||||||
.exec(function (err, replies) {
|
|
||||||
console.log("MULTI got " + replies.length + " replies");
|
|
||||||
replies.forEach(function (reply, index) {
|
|
||||||
console.log("Reply " + index + ": " + reply.toString());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the
|
|
||||||
same command methods as `client` objects do. Commands are queued up inside the `Multi` object
|
|
||||||
until `Multi.exec()` is invoked.
|
|
||||||
|
|
||||||
You can either chain together `MULTI` commands as in the above example, or you can queue individual
|
|
||||||
commands while still sending regular client command as in this example:
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient(), multi;
|
|
||||||
|
|
||||||
// start a separate multi command queue
|
|
||||||
multi = client.multi();
|
|
||||||
multi.incr("incr thing", redis.print);
|
|
||||||
multi.incr("incr other thing", redis.print);
|
|
||||||
|
|
||||||
// runs immediately
|
|
||||||
client.mset("incr thing", 100, "incr other thing", 1, redis.print);
|
|
||||||
|
|
||||||
// drains multi queue and runs atomically
|
|
||||||
multi.exec(function (err, replies) {
|
|
||||||
console.log(replies); // 101, 2
|
|
||||||
});
|
|
||||||
|
|
||||||
// you can re-run the same transaction if you like
|
|
||||||
multi.exec(function (err, replies) {
|
|
||||||
console.log(replies); // 102, 3
|
|
||||||
client.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
In addition to adding commands to the `MULTI` queue individually, you can also pass an array
|
|
||||||
of commands and arguments to the constructor:
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient(), multi;
|
|
||||||
|
|
||||||
client.multi([
|
|
||||||
["mget", "multifoo", "multibar", redis.print],
|
|
||||||
["incr", "multifoo"],
|
|
||||||
["incr", "multibar"]
|
|
||||||
]).exec(function (err, replies) {
|
|
||||||
console.log(replies);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
## Monitor mode
|
|
||||||
|
|
||||||
Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server
|
|
||||||
across all client connections, including from other client libraries and other computers.
|
|
||||||
|
|
||||||
After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis`
|
|
||||||
will emit a `monitor` event for every new monitor message that comes across. The callback for the
|
|
||||||
`monitor` event takes a timestamp from the Redis server and an array of command arguments.
|
|
||||||
|
|
||||||
Here is a simple example:
|
|
||||||
|
|
||||||
var client = require("redis").createClient(),
|
|
||||||
util = require("util");
|
|
||||||
|
|
||||||
client.monitor(function (err, res) {
|
|
||||||
console.log("Entering monitoring mode.");
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("monitor", function (time, args) {
|
|
||||||
console.log(time + ": " + util.inspect(args));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
# Extras
|
|
||||||
|
|
||||||
Some other things you might like to know about.
|
|
||||||
|
|
||||||
## client.server_info
|
|
||||||
|
|
||||||
After the ready probe completes, the results from the INFO command are saved in the `client.server_info`
|
|
||||||
object.
|
|
||||||
|
|
||||||
The `versions` key contains an array of the elements of the version string for easy comparison.
|
|
||||||
|
|
||||||
> client.server_info.redis_version
|
|
||||||
'2.3.0'
|
|
||||||
> client.server_info.versions
|
|
||||||
[ 2, 3, 0 ]
|
|
||||||
|
|
||||||
## redis.print()
|
|
||||||
|
|
||||||
A handy callback function for displaying return values when testing. Example:
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
client.on("connect", function () {
|
|
||||||
client.set("foo_rand000000000000", "some fantastic value", redis.print);
|
|
||||||
client.get("foo_rand000000000000", redis.print);
|
|
||||||
});
|
|
||||||
|
|
||||||
This will print:
|
|
||||||
|
|
||||||
Reply: OK
|
|
||||||
Reply: some fantastic value
|
|
||||||
|
|
||||||
Note that this program will not exit cleanly because the client is still connected.
|
|
||||||
|
|
||||||
## redis.debug_mode
|
|
||||||
|
|
||||||
Boolean to enable debug mode and protocol tracing.
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
redis.debug_mode = true;
|
|
||||||
|
|
||||||
client.on("connect", function () {
|
|
||||||
client.set("foo_rand000000000000", "some fantastic value");
|
|
||||||
});
|
|
||||||
|
|
||||||
This will display:
|
|
||||||
|
|
||||||
mjr:~/work/node_redis (master)$ node ~/example.js
|
|
||||||
send command: *3
|
|
||||||
$3
|
|
||||||
SET
|
|
||||||
$20
|
|
||||||
foo_rand000000000000
|
|
||||||
$20
|
|
||||||
some fantastic value
|
|
||||||
|
|
||||||
on_data: +OK
|
|
||||||
|
|
||||||
`send command` is data sent into Redis and `on_data` is data received from Redis.
|
|
||||||
|
|
||||||
## client.send_command(command_name, args, callback)
|
|
||||||
|
|
||||||
Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis
|
|
||||||
Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before
|
|
||||||
this library is updated, you can use `send_command()` to send arbitrary commands to Redis.
|
|
||||||
|
|
||||||
All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or individual arguments,
|
|
||||||
or omitted completely.
|
|
||||||
|
|
||||||
## client.connected
|
|
||||||
|
|
||||||
Boolean tracking the state of the connection to the Redis server.
|
|
||||||
|
|
||||||
## client.command_queue.length
|
|
||||||
|
|
||||||
The number of commands that have been sent to the Redis server but not yet replied to. You can use this to
|
|
||||||
enforce some kind of maximum queue depth for commands while connected.
|
|
||||||
|
|
||||||
Don't mess with `client.command_queue` though unless you really know what you are doing.
|
|
||||||
|
|
||||||
## client.offline_queue.length
|
|
||||||
|
|
||||||
The number of commands that have been queued up for a future connection. You can use this to enforce
|
|
||||||
some kind of maximum queue depth for pre-connection commands.
|
|
||||||
|
|
||||||
## client.retry_delay
|
|
||||||
|
|
||||||
Current delay in milliseconds before a connection retry will be attempted. This starts at `250`.
|
|
||||||
|
|
||||||
## client.retry_backoff
|
|
||||||
|
|
||||||
Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries.
|
|
||||||
Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc.
|
|
||||||
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
Better tests for monitor mode, auth, disconnect/reconnect, and all combinations thereof.
|
|
||||||
|
|
||||||
Stream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory.
|
|
||||||
|
|
||||||
Performance can be better for very large values.
|
|
||||||
|
|
||||||
I think there are more performance improvements left in there for smaller values, especially for large lists of small values.
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
Some people have have added features and fixed bugs in `node_redis` other than me.
|
|
||||||
|
|
||||||
In order of first contribution, they are:
|
|
||||||
|
|
||||||
* [Tim Smart](https://github.com/Tim-Smart)
|
|
||||||
* [TJ Holowaychuk](https://github.com/visionmedia)
|
|
||||||
* [Rick Olson](https://github.com/technoweenie)
|
|
||||||
* [Orion Henry](https://github.com/orionz)
|
|
||||||
* [Hank Sims](https://github.com/hanksims)
|
|
||||||
* [Aivo Paas](https://github.com/aivopaas)
|
|
||||||
* [Paul Carey](https://github.com/paulcarey)
|
|
||||||
* [Pieter Noordhuis](https://github.com/pietern)
|
|
||||||
* [Vladimir Dronnikov](https://github.com/dvv)
|
|
||||||
* [Dave Hoover](https://github.com/redsquirrel)
|
|
||||||
|
|
||||||
Thanks.
|
|
||||||
|
|
||||||
## LICENSE - "MIT License"
|
|
||||||
|
|
||||||
Copyright (c) 2010 Matthew Ranney, http://ranney.com/
|
|
||||||
|
|
||||||
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 the Software without
|
|
||||||
restriction, including without limitation the rights to use,
|
|
||||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE 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.
|
|
||||||
|
|
||||||

|
|
||||||
184
node_modules/socket.io/node_modules/redis/changelog.md
generated
vendored
184
node_modules/socket.io/node_modules/redis/changelog.md
generated
vendored
|
|
@ -1,184 +0,0 @@
|
||||||
Changelog
|
|
||||||
=========
|
|
||||||
|
|
||||||
## v0.6.7 - July 30, 2011
|
|
||||||
|
|
||||||
(accidentally skipped v0.6.6)
|
|
||||||
|
|
||||||
Fix and test for [GH-123]
|
|
||||||
|
|
||||||
Passing an Array as as the last argument should expand as users
|
|
||||||
expect. The old behavior was to coerce the arguments into Strings,
|
|
||||||
which did surprising things with Arrays.
|
|
||||||
|
|
||||||
## v0.6.5 - July 6, 2011
|
|
||||||
|
|
||||||
Contributed changes:
|
|
||||||
|
|
||||||
* Support SlowBuffers (Umair Siddique)
|
|
||||||
* Add Multi to exports (Louis-Philippe Perron)
|
|
||||||
* Fix for drain event calculation (Vladimir Dronnikov)
|
|
||||||
|
|
||||||
Thanks!
|
|
||||||
|
|
||||||
## v0.6.4 - June 30, 2011
|
|
||||||
|
|
||||||
Fix bug with optional callbacks for hmset.
|
|
||||||
|
|
||||||
## v0.6.2 - June 30, 2011
|
|
||||||
|
|
||||||
Bugs fixed:
|
|
||||||
|
|
||||||
* authentication retry while server is loading db (danmaz74) [GH-101]
|
|
||||||
* command arguments processing issue with arrays
|
|
||||||
|
|
||||||
New features:
|
|
||||||
|
|
||||||
* Auto update of new commands from redis.io (Dave Hoover)
|
|
||||||
* Performance improvements and backpressure controls.
|
|
||||||
* Commands now return the true/false value from the underlying socket write(s).
|
|
||||||
* Implement command_queue high water and low water for more better control of queueing.
|
|
||||||
|
|
||||||
See `examples/backpressure_drain.js` for more information.
|
|
||||||
|
|
||||||
## v0.6.1 - June 29, 2011
|
|
||||||
|
|
||||||
Add support and tests for Redis scripting through EXEC command.
|
|
||||||
|
|
||||||
Bug fix for monitor mode. (forddg)
|
|
||||||
|
|
||||||
Auto update of new commands from redis.io (Dave Hoover)
|
|
||||||
|
|
||||||
## v0.6.0 - April 21, 2011
|
|
||||||
|
|
||||||
Lots of bugs fixed.
|
|
||||||
|
|
||||||
* connection error did not properly trigger reconnection logic [GH-85]
|
|
||||||
* client.hmget(key, [val1, val2]) was not expanding properly [GH-66]
|
|
||||||
* client.quit() while in pub/sub mode would throw an error [GH-87]
|
|
||||||
* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92]
|
|
||||||
* unsubscribe before subscribe would make things very confused [GH-88]
|
|
||||||
* Add BRPOPLPUSH [GH-79]
|
|
||||||
|
|
||||||
## v0.5.11 - April 7, 2011
|
|
||||||
|
|
||||||
Added DISCARD
|
|
||||||
|
|
||||||
I originally didn't think DISCARD would do anything here because of the clever MULTI interface, but somebody
|
|
||||||
pointed out to me that DISCARD can be used to flush the WATCH set.
|
|
||||||
|
|
||||||
## v0.5.10 - April 6, 2011
|
|
||||||
|
|
||||||
Added HVALS
|
|
||||||
|
|
||||||
## v0.5.9 - March 14, 2011
|
|
||||||
|
|
||||||
Fix bug with empty Array arguments - Andy Ray
|
|
||||||
|
|
||||||
## v0.5.8 - March 14, 2011
|
|
||||||
|
|
||||||
Add `MONITOR` command and special monitor command reply parsing.
|
|
||||||
|
|
||||||
## v0.5.7 - February 27, 2011
|
|
||||||
|
|
||||||
Add magical auth command.
|
|
||||||
|
|
||||||
Authentication is now remembered by the client and will be automatically sent to the server
|
|
||||||
on every connection, including any reconnections.
|
|
||||||
|
|
||||||
## v0.5.6 - February 22, 2011
|
|
||||||
|
|
||||||
Fix bug in ready check with `return_buffers` set to `true`.
|
|
||||||
|
|
||||||
Thanks to Dean Mao and Austin Chau.
|
|
||||||
|
|
||||||
## v0.5.5 - February 16, 2011
|
|
||||||
|
|
||||||
Add probe for server readiness.
|
|
||||||
|
|
||||||
When a Redis server starts up, it might take a while to load the dataset into memory.
|
|
||||||
During this time, the server will accept connections, but will return errors for all non-INFO
|
|
||||||
commands. Now node_redis will send an INFO command whenever it connects to a server.
|
|
||||||
If the info command indicates that the server is not ready, the client will keep trying until
|
|
||||||
the server is ready. Once it is ready, the client will emit a "ready" event as well as the
|
|
||||||
"connect" event. The client will queue up all commands sent before the server is ready, just
|
|
||||||
like it did before. When the server is ready, all offline/non-ready commands will be replayed.
|
|
||||||
This should be backward compatible with previous versions.
|
|
||||||
|
|
||||||
To disable this ready check behavior, set `options.no_ready_check` when creating the client.
|
|
||||||
|
|
||||||
As a side effect of this change, the key/val params from the info command are available as
|
|
||||||
`client.server_options`. Further, the version string is decomposed into individual elements
|
|
||||||
in `client.server_options.versions`.
|
|
||||||
|
|
||||||
## v0.5.4 - February 11, 2011
|
|
||||||
|
|
||||||
Fix excess memory consumption from Queue backing store.
|
|
||||||
|
|
||||||
Thanks to Gustaf Sjöberg.
|
|
||||||
|
|
||||||
## v0.5.3 - February 5, 2011
|
|
||||||
|
|
||||||
Fix multi/exec error reply callback logic.
|
|
||||||
|
|
||||||
Thanks to Stella Laurenzo.
|
|
||||||
|
|
||||||
## v0.5.2 - January 18, 2011
|
|
||||||
|
|
||||||
Fix bug where unhandled error replies confuse the parser.
|
|
||||||
|
|
||||||
## v0.5.1 - January 18, 2011
|
|
||||||
|
|
||||||
Fix bug where subscribe commands would not handle redis-server startup error properly.
|
|
||||||
|
|
||||||
## v0.5.0 - December 29, 2010
|
|
||||||
|
|
||||||
Some bug fixes:
|
|
||||||
|
|
||||||
* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after
|
|
||||||
a reconnect.
|
|
||||||
* Changed error callback argument to be an actual Error object.
|
|
||||||
|
|
||||||
New feature:
|
|
||||||
|
|
||||||
* Add friendly syntax for HMSET using an object.
|
|
||||||
|
|
||||||
## v0.4.1 - December 8, 2010
|
|
||||||
|
|
||||||
Remove warning about missing hiredis. You probably do want it though.
|
|
||||||
|
|
||||||
## v0.4.0 - December 5, 2010
|
|
||||||
|
|
||||||
Support for multiple response parsers and hiredis C library from Pieter Noordhuis.
|
|
||||||
Return Strings instead of Buffers by default.
|
|
||||||
Empty nested mb reply bug fix.
|
|
||||||
|
|
||||||
## v0.3.9 - November 30, 2010
|
|
||||||
|
|
||||||
Fix parser bug on failed EXECs.
|
|
||||||
|
|
||||||
## v0.3.8 - November 10, 2010
|
|
||||||
|
|
||||||
Fix for null MULTI response when WATCH condition fails.
|
|
||||||
|
|
||||||
## v0.3.7 - November 9, 2010
|
|
||||||
|
|
||||||
Add "drain" and "idle" events.
|
|
||||||
|
|
||||||
## v0.3.6 - November 3, 2010
|
|
||||||
|
|
||||||
Add all known Redis commands from Redis master, even ones that are coming in 2.2 and beyond.
|
|
||||||
|
|
||||||
Send a friendlier "error" event message on stream errors like connection refused / reset.
|
|
||||||
|
|
||||||
## v0.3.5 - October 21, 2010
|
|
||||||
|
|
||||||
A few bug fixes.
|
|
||||||
|
|
||||||
* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts.
|
|
||||||
* Only emit `end` once when connection goes away.
|
|
||||||
* Fixed bug in `test.js` where driver finished before all tests completed.
|
|
||||||
|
|
||||||
## unversioned wasteland
|
|
||||||
|
|
||||||
See the git history for what happened before.
|
|
||||||
9
node_modules/socket.io/node_modules/redis/eval_test.js
generated
vendored
9
node_modules/socket.io/node_modules/redis/eval_test.js
generated
vendored
|
|
@ -1,9 +0,0 @@
|
||||||
var redis = require("./index"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
redis.debug_mode = true;
|
|
||||||
|
|
||||||
client.eval("return 100.5", 0, function (err, res) {
|
|
||||||
console.dir(err);
|
|
||||||
console.dir(res);
|
|
||||||
});
|
|
||||||
5
node_modules/socket.io/node_modules/redis/examples/auth.js
generated
vendored
5
node_modules/socket.io/node_modules/redis/examples/auth.js
generated
vendored
|
|
@ -1,5 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
// This command is magical. Client stashes the password and will issue on every connect.
|
|
||||||
client.auth("somepass");
|
|
||||||
33
node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js
generated
vendored
33
node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js
generated
vendored
|
|
@ -1,33 +0,0 @@
|
||||||
var redis = require("../index"),
|
|
||||||
client = redis.createClient(null, null, {
|
|
||||||
command_queue_high_water: 5,
|
|
||||||
command_queue_low_water: 1
|
|
||||||
}),
|
|
||||||
remaining_ops = 100000, paused = false;
|
|
||||||
|
|
||||||
function op() {
|
|
||||||
if (remaining_ops <= 0) {
|
|
||||||
console.error("Finished.");
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
remaining_ops--;
|
|
||||||
if (client.hset("test hash", "val " + remaining_ops, remaining_ops) === false) {
|
|
||||||
console.log("Pausing at " + remaining_ops);
|
|
||||||
paused = true;
|
|
||||||
} else {
|
|
||||||
process.nextTick(op);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.on("drain", function () {
|
|
||||||
if (paused) {
|
|
||||||
console.log("Resuming at " + remaining_ops);
|
|
||||||
paused = false;
|
|
||||||
process.nextTick(op);
|
|
||||||
} else {
|
|
||||||
console.log("Got drain while not paused at " + remaining_ops);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
op();
|
|
||||||
24
node_modules/socket.io/node_modules/redis/examples/extend.js
generated
vendored
24
node_modules/socket.io/node_modules/redis/examples/extend.js
generated
vendored
|
|
@ -1,24 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
// Extend the RedisClient prototype to add a custom method
|
|
||||||
// This one converts the results from "INFO" into a JavaScript Object
|
|
||||||
|
|
||||||
redis.RedisClient.prototype.parse_info = function (callback) {
|
|
||||||
this.info(function (err, res) {
|
|
||||||
var lines = res.toString().split("\r\n").sort();
|
|
||||||
var obj = {};
|
|
||||||
lines.forEach(function (line) {
|
|
||||||
var parts = line.split(':');
|
|
||||||
if (parts[1]) {
|
|
||||||
obj[parts[0]] = parts[1];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
callback(obj)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
client.parse_info(function (info) {
|
|
||||||
console.dir(info);
|
|
||||||
client.quit();
|
|
||||||
});
|
|
||||||
32
node_modules/socket.io/node_modules/redis/examples/file.js
generated
vendored
32
node_modules/socket.io/node_modules/redis/examples/file.js
generated
vendored
|
|
@ -1,32 +0,0 @@
|
||||||
// Read a file from disk, store it in Redis, then read it back from Redis.
|
|
||||||
|
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient(),
|
|
||||||
fs = require("fs"),
|
|
||||||
filename = "kids_in_cart.jpg";
|
|
||||||
|
|
||||||
// Get the file I use for testing like this:
|
|
||||||
// curl http://ranney.com/kids_in_cart.jpg -o kids_in_cart.jpg
|
|
||||||
// or just use your own file.
|
|
||||||
|
|
||||||
// Read a file from fs, store it in Redis, get it back from Redis, write it back to fs.
|
|
||||||
fs.readFile(filename, function (err, data) {
|
|
||||||
if (err) throw err
|
|
||||||
console.log("Read " + data.length + " bytes from filesystem.");
|
|
||||||
|
|
||||||
client.set(filename, data, redis.print); // set entire file
|
|
||||||
client.get(filename, function (err, reply) { // get entire file
|
|
||||||
if (err) {
|
|
||||||
console.log("Get error: " + err);
|
|
||||||
} else {
|
|
||||||
fs.writeFile("duplicate_" + filename, reply, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Error on write: " + err)
|
|
||||||
} else {
|
|
||||||
console.log("File written.");
|
|
||||||
}
|
|
||||||
client.end();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
5
node_modules/socket.io/node_modules/redis/examples/mget.js
generated
vendored
5
node_modules/socket.io/node_modules/redis/examples/mget.js
generated
vendored
|
|
@ -1,5 +0,0 @@
|
||||||
var client = require("redis").createClient();
|
|
||||||
|
|
||||||
client.mget(["sessions started", "sessions started", "foo"], function (err, res) {
|
|
||||||
console.dir(res);
|
|
||||||
});
|
|
||||||
10
node_modules/socket.io/node_modules/redis/examples/monitor.js
generated
vendored
10
node_modules/socket.io/node_modules/redis/examples/monitor.js
generated
vendored
|
|
@ -1,10 +0,0 @@
|
||||||
var client = require("../index").createClient(),
|
|
||||||
util = require("util");
|
|
||||||
|
|
||||||
client.monitor(function (err, res) {
|
|
||||||
console.log("Entering monitoring mode.");
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("monitor", function (time, args) {
|
|
||||||
console.log(time + ": " + util.inspect(args));
|
|
||||||
});
|
|
||||||
46
node_modules/socket.io/node_modules/redis/examples/multi.js
generated
vendored
46
node_modules/socket.io/node_modules/redis/examples/multi.js
generated
vendored
|
|
@ -1,46 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient(), set_size = 20;
|
|
||||||
|
|
||||||
client.sadd("bigset", "a member");
|
|
||||||
client.sadd("bigset", "another member");
|
|
||||||
|
|
||||||
while (set_size > 0) {
|
|
||||||
client.sadd("bigset", "member " + set_size);
|
|
||||||
set_size -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// multi chain with an individual callback
|
|
||||||
client.multi()
|
|
||||||
.scard("bigset")
|
|
||||||
.smembers("bigset")
|
|
||||||
.keys("*", function (err, replies) {
|
|
||||||
client.mget(replies, redis.print);
|
|
||||||
})
|
|
||||||
.dbsize()
|
|
||||||
.exec(function (err, replies) {
|
|
||||||
console.log("MULTI got " + replies.length + " replies");
|
|
||||||
replies.forEach(function (reply, index) {
|
|
||||||
console.log("Reply " + index + ": " + reply.toString());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
client.mset("incr thing", 100, "incr other thing", 1, redis.print);
|
|
||||||
|
|
||||||
// start a separate multi command queue
|
|
||||||
var multi = client.multi();
|
|
||||||
multi.incr("incr thing", redis.print);
|
|
||||||
multi.incr("incr other thing", redis.print);
|
|
||||||
|
|
||||||
// runs immediately
|
|
||||||
client.get("incr thing", redis.print); // 100
|
|
||||||
|
|
||||||
// drains multi queue and runs atomically
|
|
||||||
multi.exec(function (err, replies) {
|
|
||||||
console.log(replies); // 101, 2
|
|
||||||
});
|
|
||||||
|
|
||||||
// you can re-run the same transaction if you like
|
|
||||||
multi.exec(function (err, replies) {
|
|
||||||
console.log(replies); // 102, 3
|
|
||||||
client.quit();
|
|
||||||
});
|
|
||||||
29
node_modules/socket.io/node_modules/redis/examples/multi2.js
generated
vendored
29
node_modules/socket.io/node_modules/redis/examples/multi2.js
generated
vendored
|
|
@ -1,29 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient(), multi;
|
|
||||||
|
|
||||||
// start a separate command queue for multi
|
|
||||||
multi = client.multi();
|
|
||||||
multi.incr("incr thing", redis.print);
|
|
||||||
multi.incr("incr other thing", redis.print);
|
|
||||||
|
|
||||||
// runs immediately
|
|
||||||
client.mset("incr thing", 100, "incr other thing", 1, redis.print);
|
|
||||||
|
|
||||||
// drains multi queue and runs atomically
|
|
||||||
multi.exec(function (err, replies) {
|
|
||||||
console.log(replies); // 101, 2
|
|
||||||
});
|
|
||||||
|
|
||||||
// you can re-run the same transaction if you like
|
|
||||||
multi.exec(function (err, replies) {
|
|
||||||
console.log(replies); // 102, 3
|
|
||||||
client.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
client.multi([
|
|
||||||
["mget", "multifoo", "multibar", redis.print],
|
|
||||||
["incr", "multifoo"],
|
|
||||||
["incr", "multibar"]
|
|
||||||
]).exec(function (err, replies) {
|
|
||||||
console.log(replies.toString());
|
|
||||||
});
|
|
||||||
33
node_modules/socket.io/node_modules/redis/examples/psubscribe.js
generated
vendored
33
node_modules/socket.io/node_modules/redis/examples/psubscribe.js
generated
vendored
|
|
@ -1,33 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client1 = redis.createClient(),
|
|
||||||
client2 = redis.createClient(),
|
|
||||||
client3 = redis.createClient(),
|
|
||||||
client4 = redis.createClient(),
|
|
||||||
msg_count = 0;
|
|
||||||
|
|
||||||
redis.debug_mode = false;
|
|
||||||
|
|
||||||
client1.on("psubscribe", function (pattern, count) {
|
|
||||||
console.log("client1 psubscribed to " + pattern + ", " + count + " total subscriptions");
|
|
||||||
client2.publish("channeltwo", "Me!");
|
|
||||||
client3.publish("channelthree", "Me too!");
|
|
||||||
client4.publish("channelfour", "And me too!");
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.on("punsubscribe", function (pattern, count) {
|
|
||||||
console.log("client1 punsubscribed from " + pattern + ", " + count + " total subscriptions");
|
|
||||||
client4.end();
|
|
||||||
client3.end();
|
|
||||||
client2.end();
|
|
||||||
client1.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.on("pmessage", function (pattern, channel, message) {
|
|
||||||
console.log("("+ pattern +")" + " client1 received message on " + channel + ": " + message);
|
|
||||||
msg_count += 1;
|
|
||||||
if (msg_count === 3) {
|
|
||||||
client1.punsubscribe();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.psubscribe("channel*");
|
|
||||||
41
node_modules/socket.io/node_modules/redis/examples/pub_sub.js
generated
vendored
41
node_modules/socket.io/node_modules/redis/examples/pub_sub.js
generated
vendored
|
|
@ -1,41 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client1 = redis.createClient(), msg_count = 0,
|
|
||||||
client2 = redis.createClient();
|
|
||||||
|
|
||||||
redis.debug_mode = false;
|
|
||||||
|
|
||||||
// Most clients probably don't do much on "subscribe". This example uses it to coordinate things within one program.
|
|
||||||
client1.on("subscribe", function (channel, count) {
|
|
||||||
console.log("client1 subscribed to " + channel + ", " + count + " total subscriptions");
|
|
||||||
if (count === 2) {
|
|
||||||
client2.publish("a nice channel", "I am sending a message.");
|
|
||||||
client2.publish("another one", "I am sending a second message.");
|
|
||||||
client2.publish("a nice channel", "I am sending my last message.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.on("unsubscribe", function (channel, count) {
|
|
||||||
console.log("client1 unsubscribed from " + channel + ", " + count + " total subscriptions");
|
|
||||||
if (count === 0) {
|
|
||||||
client2.end();
|
|
||||||
client1.end();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.on("message", function (channel, message) {
|
|
||||||
console.log("client1 channel " + channel + ": " + message);
|
|
||||||
msg_count += 1;
|
|
||||||
if (msg_count === 3) {
|
|
||||||
client1.unsubscribe();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client1.on("ready", function () {
|
|
||||||
// if you need auth, do it here
|
|
||||||
client1.incr("did a thing");
|
|
||||||
client1.subscribe("a nice channel", "another one");
|
|
||||||
});
|
|
||||||
|
|
||||||
client2.on("ready", function () {
|
|
||||||
// if you need auth, do it here
|
|
||||||
});
|
|
||||||
17
node_modules/socket.io/node_modules/redis/examples/simple.js
generated
vendored
17
node_modules/socket.io/node_modules/redis/examples/simple.js
generated
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient();
|
|
||||||
|
|
||||||
client.on("error", function (err) {
|
|
||||||
console.log("Redis connection error to " + client.host + ":" + client.port + " - " + err);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.set("string key", "string val", redis.print);
|
|
||||||
client.hset("hash key", "hashtest 1", "some value", redis.print);
|
|
||||||
client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
|
|
||||||
client.hkeys("hash key", function (err, replies) {
|
|
||||||
console.log(replies.length + " replies:");
|
|
||||||
replies.forEach(function (reply, i) {
|
|
||||||
console.log(" " + i + ": " + reply);
|
|
||||||
});
|
|
||||||
client.quit();
|
|
||||||
});
|
|
||||||
15
node_modules/socket.io/node_modules/redis/examples/subqueries.js
generated
vendored
15
node_modules/socket.io/node_modules/redis/examples/subqueries.js
generated
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
// Sending commands in response to other commands.
|
|
||||||
// This example runs "type" against every key in the database
|
|
||||||
//
|
|
||||||
var client = require("redis").createClient();
|
|
||||||
|
|
||||||
client.keys("*", function (err, keys) {
|
|
||||||
keys.forEach(function (key, pos) {
|
|
||||||
client.type(key, function (err, keytype) {
|
|
||||||
console.log(key + " is " + keytype);
|
|
||||||
if (pos === (keys.length - 1)) {
|
|
||||||
client.quit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
19
node_modules/socket.io/node_modules/redis/examples/subquery.js
generated
vendored
19
node_modules/socket.io/node_modules/redis/examples/subquery.js
generated
vendored
|
|
@ -1,19 +0,0 @@
|
||||||
var client = require("redis").createClient();
|
|
||||||
|
|
||||||
function print_results(obj) {
|
|
||||||
console.dir(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// build a map of all keys and their types
|
|
||||||
client.keys("*", function (err, all_keys) {
|
|
||||||
var key_types = {};
|
|
||||||
|
|
||||||
all_keys.forEach(function (key, pos) { // use second arg of forEach to get pos
|
|
||||||
client.type(key, function (err, type) {
|
|
||||||
key_types[key] = type;
|
|
||||||
if (pos === all_keys.length - 1) { // callbacks all run in order
|
|
||||||
print_results(key_types);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
29
node_modules/socket.io/node_modules/redis/examples/unix_socket.js
generated
vendored
29
node_modules/socket.io/node_modules/redis/examples/unix_socket.js
generated
vendored
|
|
@ -1,29 +0,0 @@
|
||||||
var redis = require("redis"),
|
|
||||||
client = redis.createClient("/tmp/redis.sock"),
|
|
||||||
profiler = require("v8-profiler");
|
|
||||||
|
|
||||||
client.on("connect", function () {
|
|
||||||
console.log("Got Unix socket connection.")
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on("error", function (err) {
|
|
||||||
console.log(err.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.set("space chars", "space value");
|
|
||||||
|
|
||||||
setInterval(function () {
|
|
||||||
client.get("space chars");
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
function done() {
|
|
||||||
client.info(function (err, reply) {
|
|
||||||
console.log(reply.toString());
|
|
||||||
client.quit();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
console.log("Taking snapshot.");
|
|
||||||
var snap = profiler.takeSnapshot();
|
|
||||||
}, 5000);
|
|
||||||
31
node_modules/socket.io/node_modules/redis/examples/web_server.js
generated
vendored
31
node_modules/socket.io/node_modules/redis/examples/web_server.js
generated
vendored
|
|
@ -1,31 +0,0 @@
|
||||||
// A simple web server that generates dyanmic content based on responses from Redis
|
|
||||||
|
|
||||||
var http = require("http"), server,
|
|
||||||
redis_client = require("redis").createClient();
|
|
||||||
|
|
||||||
server = http.createServer(function (request, response) {
|
|
||||||
response.writeHead(200, {
|
|
||||||
"Content-Type": "text/plain"
|
|
||||||
});
|
|
||||||
|
|
||||||
var redis_info, total_requests;
|
|
||||||
|
|
||||||
redis_client.info(function (err, reply) {
|
|
||||||
redis_info = reply; // stash response in outer scope
|
|
||||||
});
|
|
||||||
redis_client.incr("requests", function (err, reply) {
|
|
||||||
total_requests = reply; // stash response in outer scope
|
|
||||||
});
|
|
||||||
redis_client.hincrby("ip", request.connection.remoteAddress, 1);
|
|
||||||
redis_client.hgetall("ip", function (err, reply) {
|
|
||||||
// This is the last reply, so all of the previous replies must have completed already
|
|
||||||
response.write("This page was generated after talking to redis.\n\n" +
|
|
||||||
"Redis info:\n" + redis_info + "\n" +
|
|
||||||
"Total requests: " + total_requests + "\n\n" +
|
|
||||||
"IP count: \n");
|
|
||||||
Object.keys(reply).forEach(function (ip) {
|
|
||||||
response.write(" " + ip + ": " + reply[ip] + "\n");
|
|
||||||
});
|
|
||||||
response.end();
|
|
||||||
});
|
|
||||||
}).listen(80);
|
|
||||||
40
node_modules/socket.io/node_modules/redis/generate_commands.js
generated
vendored
40
node_modules/socket.io/node_modules/redis/generate_commands.js
generated
vendored
|
|
@ -1,40 +0,0 @@
|
||||||
var http = require("http"),
|
|
||||||
sys = require("sys"),
|
|
||||||
fs = require("fs");
|
|
||||||
|
|
||||||
function prettyCurrentTime() {
|
|
||||||
var date = new Date();
|
|
||||||
return date.toLocaleString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function write_file(commands, path) {
|
|
||||||
var file_contents, out_commands;
|
|
||||||
|
|
||||||
console.log("Writing " + Object.keys(commands).length + " commands to " + path);
|
|
||||||
|
|
||||||
file_contents = "// This file was generated by ./generate_commands.js on " + prettyCurrentTime() + "\n";
|
|
||||||
|
|
||||||
out_commands = Object.keys(commands).map(function (key) {
|
|
||||||
return key.toLowerCase();
|
|
||||||
});
|
|
||||||
|
|
||||||
file_contents += "module.exports = " + JSON.stringify(out_commands, null, " ") + ";\n";
|
|
||||||
|
|
||||||
fs.writeFile(path, file_contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
http.get({host: "redis.io", path: "/commands.json"}, function (res) {
|
|
||||||
var body = "";
|
|
||||||
|
|
||||||
console.log("Response from redis.io/commands.json: " + res.statusCode);
|
|
||||||
|
|
||||||
res.on('data', function (chunk) {
|
|
||||||
body += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on('end', function () {
|
|
||||||
write_file(JSON.parse(body), "lib/commands.js");
|
|
||||||
});
|
|
||||||
}).on('error', function (e) {
|
|
||||||
console.log("Error fetching command list from redis.io: " + e.message);
|
|
||||||
});
|
|
||||||
860
node_modules/socket.io/node_modules/redis/index.js
generated
vendored
860
node_modules/socket.io/node_modules/redis/index.js
generated
vendored
|
|
@ -1,860 +0,0 @@
|
||||||
/*global Buffer require exports console setTimeout */
|
|
||||||
|
|
||||||
var net = require("net"),
|
|
||||||
util = require("./lib/util").util,
|
|
||||||
Queue = require("./lib/queue").Queue,
|
|
||||||
to_array = require("./lib/to_array"),
|
|
||||||
events = require("events"),
|
|
||||||
parsers = [], commands,
|
|
||||||
default_port = 6379,
|
|
||||||
default_host = "127.0.0.1";
|
|
||||||
|
|
||||||
// can set this to true to enable for all connections
|
|
||||||
exports.debug_mode = false;
|
|
||||||
|
|
||||||
// hiredis might not be installed
|
|
||||||
try {
|
|
||||||
require("./lib/parser/hiredis");
|
|
||||||
parsers.push(require("./lib/parser/hiredis"));
|
|
||||||
} catch (err) {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("hiredis parser not installed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parsers.push(require("./lib/parser/javascript"));
|
|
||||||
|
|
||||||
function RedisClient(stream, options) {
|
|
||||||
this.stream = stream;
|
|
||||||
this.options = options || {};
|
|
||||||
|
|
||||||
this.connected = false;
|
|
||||||
this.ready = false;
|
|
||||||
this.connections = 0;
|
|
||||||
this.attempts = 1;
|
|
||||||
this.should_buffer = false;
|
|
||||||
this.command_queue_high_water = this.options.command_queue_high_water || 1000;
|
|
||||||
this.command_queue_low_water = this.options.command_queue_low_water || 0;
|
|
||||||
this.command_queue = new Queue(); // holds sent commands to de-pipeline them
|
|
||||||
this.offline_queue = new Queue(); // holds commands issued but not able to be sent
|
|
||||||
this.commands_sent = 0;
|
|
||||||
this.retry_delay = 250; // inital reconnection delay
|
|
||||||
this.current_retry_delay = this.retry_delay;
|
|
||||||
this.retry_backoff = 1.7; // each retry waits current delay * retry_backoff
|
|
||||||
this.subscriptions = false;
|
|
||||||
this.monitoring = false;
|
|
||||||
this.closing = false;
|
|
||||||
this.server_info = {};
|
|
||||||
this.auth_pass = null;
|
|
||||||
|
|
||||||
var parser_module, self = this;
|
|
||||||
|
|
||||||
if (self.options.parser) {
|
|
||||||
if (! parsers.some(function (parser) {
|
|
||||||
if (parser.name === self.options.parser) {
|
|
||||||
parser_module = parser;
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Using parser module: " + parser_module.name);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
})) {
|
|
||||||
throw new Error("Couldn't find named parser " + self.options.parser + " on this system");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Using default parser module: " + parsers[0].name);
|
|
||||||
}
|
|
||||||
parser_module = parsers[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
parser_module.debug_mode = exports.debug_mode;
|
|
||||||
this.reply_parser = new parser_module.Parser({
|
|
||||||
return_buffers: self.options.return_buffers || false
|
|
||||||
});
|
|
||||||
|
|
||||||
// "reply error" is an error sent back by Redis
|
|
||||||
this.reply_parser.on("reply error", function (reply) {
|
|
||||||
self.return_error(new Error(reply));
|
|
||||||
});
|
|
||||||
this.reply_parser.on("reply", function (reply) {
|
|
||||||
self.return_reply(reply);
|
|
||||||
});
|
|
||||||
// "error" is bad. Somehow the parser got confused. It'll try to reset and continue.
|
|
||||||
this.reply_parser.on("error", function (err) {
|
|
||||||
self.emit("error", new Error("Redis reply parser error: " + err.stack));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.stream.on("connect", function () {
|
|
||||||
self.on_connect();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.stream.on("data", function (buffer_from_socket) {
|
|
||||||
self.on_data(buffer_from_socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.stream.on("error", function (msg) {
|
|
||||||
if (this.closing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = "Redis connection to " + self.host + ":" + self.port + " failed - " + msg.message;
|
|
||||||
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.warn(message);
|
|
||||||
}
|
|
||||||
self.offline_queue.forEach(function (args) {
|
|
||||||
if (typeof args[2] === "function") {
|
|
||||||
args[2](message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.offline_queue = new Queue();
|
|
||||||
|
|
||||||
self.command_queue.forEach(function (args) {
|
|
||||||
if (typeof args[2] === "function") {
|
|
||||||
args[2](message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.command_queue = new Queue();
|
|
||||||
|
|
||||||
self.connected = false;
|
|
||||||
self.ready = false;
|
|
||||||
|
|
||||||
self.emit("error", new Error(message));
|
|
||||||
// "error" events get turned into exceptions if they aren't listened for. If the user handled this error
|
|
||||||
// then we should try to reconnect.
|
|
||||||
self.connection_gone("error");
|
|
||||||
});
|
|
||||||
|
|
||||||
this.stream.on("close", function () {
|
|
||||||
self.connection_gone("close");
|
|
||||||
});
|
|
||||||
|
|
||||||
this.stream.on("end", function () {
|
|
||||||
self.connection_gone("end");
|
|
||||||
});
|
|
||||||
|
|
||||||
this.stream.on("drain", function () {
|
|
||||||
self.should_buffer = false;
|
|
||||||
self.emit("drain");
|
|
||||||
});
|
|
||||||
|
|
||||||
events.EventEmitter.call(this);
|
|
||||||
}
|
|
||||||
util.inherits(RedisClient, events.EventEmitter);
|
|
||||||
exports.RedisClient = RedisClient;
|
|
||||||
|
|
||||||
RedisClient.prototype.do_auth = function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Sending auth to " + self.host + ":" + self.port + " fd " + self.stream.fd);
|
|
||||||
}
|
|
||||||
self.send_anyway = true;
|
|
||||||
self.send_command("auth", [this.auth_pass], function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
if (err.toString().match("LOADING")) {
|
|
||||||
// if redis is still loading the db, it will not authenticate and everything else will fail
|
|
||||||
console.log("Redis still loading, trying to authenticate later");
|
|
||||||
setTimeout(function () {
|
|
||||||
self.do_auth();
|
|
||||||
}, 2000); // TODO - magic number alert
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
return self.emit("error", "Auth error: " + err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res.toString() !== "OK") {
|
|
||||||
return self.emit("error", "Auth failed: " + res.toString());
|
|
||||||
}
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Auth succeeded " + self.host + ":" + self.port + " fd " + self.stream.fd);
|
|
||||||
}
|
|
||||||
if (self.auth_callback) {
|
|
||||||
self.auth_callback(err, res);
|
|
||||||
self.auth_callback = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we are really connected
|
|
||||||
self.emit("connect");
|
|
||||||
if (self.options.no_ready_check) {
|
|
||||||
self.ready = true;
|
|
||||||
self.send_offline_queue();
|
|
||||||
} else {
|
|
||||||
self.ready_check();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.send_anyway = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.on_connect = function () {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Stream connected " + this.host + ":" + this.port + " fd " + this.stream.fd);
|
|
||||||
}
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.connected = true;
|
|
||||||
this.ready = false;
|
|
||||||
this.attempts = 0;
|
|
||||||
this.connections += 1;
|
|
||||||
this.command_queue = new Queue();
|
|
||||||
this.emitted_end = false;
|
|
||||||
this.retry_timer = null;
|
|
||||||
this.current_retry_delay = this.retry_time;
|
|
||||||
this.stream.setNoDelay();
|
|
||||||
this.stream.setTimeout(0);
|
|
||||||
|
|
||||||
if (this.auth_pass) {
|
|
||||||
this.do_auth();
|
|
||||||
} else {
|
|
||||||
this.emit("connect");
|
|
||||||
|
|
||||||
if (this.options.no_ready_check) {
|
|
||||||
this.ready = true;
|
|
||||||
this.send_offline_queue();
|
|
||||||
} else {
|
|
||||||
this.ready_check();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.ready_check = function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
function send_info_cmd() {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("checking server ready state...");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.send_anyway = true; // secret flag to send_command to send something even if not "ready"
|
|
||||||
self.info(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
return self.emit("error", "Ready check failed: " + err);
|
|
||||||
}
|
|
||||||
|
|
||||||
var lines = res.toString().split("\r\n"), obj = {}, retry_time;
|
|
||||||
|
|
||||||
lines.forEach(function (line) {
|
|
||||||
var parts = line.split(':');
|
|
||||||
if (parts[1]) {
|
|
||||||
obj[parts[0]] = parts[1];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
obj.versions = [];
|
|
||||||
obj.redis_version.split('.').forEach(function (num) {
|
|
||||||
obj.versions.push(+num);
|
|
||||||
});
|
|
||||||
|
|
||||||
// expose info key/vals to users
|
|
||||||
self.server_info = obj;
|
|
||||||
|
|
||||||
if (!obj.loading || (obj.loading && obj.loading === "0")) {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Redis server ready.");
|
|
||||||
}
|
|
||||||
self.ready = true;
|
|
||||||
|
|
||||||
self.send_offline_queue();
|
|
||||||
self.emit("ready");
|
|
||||||
} else {
|
|
||||||
retry_time = obj.loading_eta_seconds * 1000;
|
|
||||||
if (retry_time > 1000) {
|
|
||||||
retry_time = 1000;
|
|
||||||
}
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Redis server still loading, trying again in " + retry_time);
|
|
||||||
}
|
|
||||||
setTimeout(send_info_cmd, retry_time);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.send_anyway = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_info_cmd();
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.send_offline_queue = function () {
|
|
||||||
var command_obj, buffered_writes = 0;
|
|
||||||
while (this.offline_queue.length > 0) {
|
|
||||||
command_obj = this.offline_queue.shift();
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Sending offline command: " + command_obj.command);
|
|
||||||
}
|
|
||||||
buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback);
|
|
||||||
}
|
|
||||||
this.offline_queue = new Queue();
|
|
||||||
// Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue
|
|
||||||
|
|
||||||
if (!buffered_writes) {
|
|
||||||
this.should_buffer = false;
|
|
||||||
this.emit("drain");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.connection_gone = function (why) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// If a retry is already in progress, just let that happen
|
|
||||||
if (this.retry_timer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that this may trigger another "close" or "end" event
|
|
||||||
this.stream.destroy();
|
|
||||||
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.warn("Redis connection is gone from " + why + " event.");
|
|
||||||
}
|
|
||||||
this.connected = false;
|
|
||||||
this.ready = false;
|
|
||||||
this.subscriptions = false;
|
|
||||||
this.monitoring = false;
|
|
||||||
|
|
||||||
// since we are collapsing end and close, users don't expect to be called twice
|
|
||||||
if (! this.emitted_end) {
|
|
||||||
this.emit("end");
|
|
||||||
this.emitted_end = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.command_queue.forEach(function (args) {
|
|
||||||
if (typeof args[2] === "function") {
|
|
||||||
args[2]("Server connection closed");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.command_queue = new Queue();
|
|
||||||
|
|
||||||
// If this is a requested shutdown, then don't retry
|
|
||||||
if (this.closing) {
|
|
||||||
this.retry_timer = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.current_retry_delay = this.retry_delay * this.retry_backoff;
|
|
||||||
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Retry connection in " + this.current_retry_delay + " ms");
|
|
||||||
}
|
|
||||||
this.attempts += 1;
|
|
||||||
this.emit("reconnecting", {
|
|
||||||
delay: this.current_retry_delay,
|
|
||||||
attempt: this.attempts
|
|
||||||
});
|
|
||||||
this.retry_timer = setTimeout(function () {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Retrying connection...");
|
|
||||||
}
|
|
||||||
self.stream.connect(self.port, self.host);
|
|
||||||
self.retry_timer = null;
|
|
||||||
}, this.current_retry_delay);
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.on_data = function (data) {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("net read " + this.host + ":" + this.port + " fd " + this.stream.fd + ": " + data.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.reply_parser.execute(data);
|
|
||||||
} catch (err) {
|
|
||||||
// This is an unexpected parser problem, an exception that came from the parser code itself.
|
|
||||||
// Parser should emit "error" events if it notices things are out of whack.
|
|
||||||
// Callbacks that throw exceptions will land in return_reply(), below.
|
|
||||||
// TODO - it might be nice to have a different "error" event for different types of errors
|
|
||||||
this.emit("error", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.return_error = function (err) {
|
|
||||||
var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength();
|
|
||||||
|
|
||||||
if (this.subscriptions === false && queue_len === 0) {
|
|
||||||
this.emit("idle");
|
|
||||||
this.command_queue = new Queue();
|
|
||||||
}
|
|
||||||
if (this.should_buffer && queue_len <= this.command_queue_low_water) {
|
|
||||||
this.emit("drain");
|
|
||||||
this.should_buffer = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command_obj && typeof command_obj.callback === "function") {
|
|
||||||
try {
|
|
||||||
command_obj.callback(err);
|
|
||||||
} catch (callback_err) {
|
|
||||||
// if a callback throws an exception, re-throw it on a new stack so the parser can keep going
|
|
||||||
process.nextTick(function () {
|
|
||||||
throw callback_err;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log("node_redis: no callback to send error: " + err.message);
|
|
||||||
// this will probably not make it anywhere useful, but we might as well throw
|
|
||||||
process.nextTick(function () {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.return_reply = function (reply) {
|
|
||||||
var command_obj = this.command_queue.shift(),
|
|
||||||
obj, i, len, key, val, type, timestamp, args, queue_len = this.command_queue.getLength();
|
|
||||||
|
|
||||||
if (this.subscriptions === false && queue_len === 0) {
|
|
||||||
this.emit("idle");
|
|
||||||
this.command_queue = new Queue(); // explicitly reclaim storage from old Queue
|
|
||||||
}
|
|
||||||
if (this.should_buffer && queue_len <= this.command_queue_low_water) {
|
|
||||||
this.emit("drain");
|
|
||||||
this.should_buffer = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command_obj && !command_obj.sub_command) {
|
|
||||||
if (typeof command_obj.callback === "function") {
|
|
||||||
// HGETALL special case replies with keyed Buffers
|
|
||||||
if (reply && 'hgetall' === command_obj.command.toLowerCase()) {
|
|
||||||
obj = {};
|
|
||||||
for (i = 0, len = reply.length; i < len; i += 2) {
|
|
||||||
key = reply[i].toString();
|
|
||||||
val = reply[i + 1];
|
|
||||||
obj[key] = val;
|
|
||||||
}
|
|
||||||
reply = obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
command_obj.callback(null, reply);
|
|
||||||
} catch (err) {
|
|
||||||
// if a callback throws an exception, re-throw it on a new stack so the parser can keep going
|
|
||||||
process.nextTick(function () {
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (exports.debug_mode) {
|
|
||||||
console.log("no callback for reply: " + (reply && reply.toString && reply.toString()));
|
|
||||||
}
|
|
||||||
} else if (this.subscriptions || (command_obj && command_obj.sub_command)) {
|
|
||||||
if (Array.isArray(reply)) {
|
|
||||||
type = reply[0].toString();
|
|
||||||
|
|
||||||
if (type === "message") {
|
|
||||||
this.emit("message", reply[1].toString(), reply[2]); // channel, message
|
|
||||||
} else if (type === "pmessage") {
|
|
||||||
this.emit("pmessage", reply[1].toString(), reply[2].toString(), reply[3]); // pattern, channel, message
|
|
||||||
} else if (type === "subscribe" || type === "unsubscribe" || type === "psubscribe" || type === "punsubscribe") {
|
|
||||||
if (reply[2] === 0) {
|
|
||||||
this.subscriptions = false;
|
|
||||||
if (this.debug_mode) {
|
|
||||||
console.log("All subscriptions removed, exiting pub/sub mode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.emit(type, reply[1].toString(), reply[2]); // channel, count
|
|
||||||
} else {
|
|
||||||
throw new Error("subscriptions are active but got unknown reply type " + type);
|
|
||||||
}
|
|
||||||
} else if (! this.closing) {
|
|
||||||
throw new Error("subscriptions are active but got an invalid reply: " + reply);
|
|
||||||
}
|
|
||||||
} else if (this.monitoring) {
|
|
||||||
len = reply.indexOf(" ");
|
|
||||||
timestamp = reply.slice(0, len);
|
|
||||||
// TODO - this de-quoting doesn't work correctly if you put JSON strings in your values.
|
|
||||||
args = reply.slice(len + 1).match(/"[^"]+"/g).map(function (elem) {
|
|
||||||
return elem.replace(/"/g, "");
|
|
||||||
});
|
|
||||||
this.emit("monitor", timestamp, args);
|
|
||||||
} else {
|
|
||||||
throw new Error("node_redis command queue state error. If you can reproduce this, please report it.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This Command constructor is ever so slightly faster than using an object literal
|
|
||||||
function Command(command, args, sub_command, callback) {
|
|
||||||
this.command = command;
|
|
||||||
this.args = args;
|
|
||||||
this.sub_command = sub_command;
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
RedisClient.prototype.send_command = function (command, args, callback) {
|
|
||||||
var arg, this_args, command_obj, i, il, elem_count, stream = this.stream, buffer_args, command_str = "", buffered_writes = 0;
|
|
||||||
|
|
||||||
if (typeof command !== "string") {
|
|
||||||
throw new Error("First argument to send_command must be the command name string, not " + typeof command);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(args)) {
|
|
||||||
if (typeof callback === "function") {
|
|
||||||
// probably the fastest way:
|
|
||||||
// client.command([arg1, arg2], cb); (straight passthrough)
|
|
||||||
// send_command(command, [arg1, arg2], cb);
|
|
||||||
} else if (! callback) {
|
|
||||||
// most people find this variable argument length form more convenient, but it uses arguments, which is slower
|
|
||||||
// client.command(arg1, arg2, cb); (wraps up arguments into an array)
|
|
||||||
// send_command(command, [arg1, arg2, cb]);
|
|
||||||
// client.command(arg1, arg2); (callback is optional)
|
|
||||||
// send_command(command, [arg1, arg2]);
|
|
||||||
if (typeof args[args.length - 1] === "function") {
|
|
||||||
callback = args[args.length - 1];
|
|
||||||
args.length -= 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error("send_command: last argument must be a callback or undefined");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error("send_command: second argument must be an array");
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the last argument is an array, expand it out. This allows commands like this:
|
|
||||||
// client.command(arg1, [arg2, arg3, arg4], cb);
|
|
||||||
// and converts to:
|
|
||||||
// client.command(arg1, arg2, arg3, arg4, cb);
|
|
||||||
// which is convenient for some things like sadd
|
|
||||||
if (Array.isArray(args[args.length - 1])) {
|
|
||||||
args = args.slice(0, -1).concat(args[args.length - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
command_obj = new Command(command, args, false, callback);
|
|
||||||
|
|
||||||
if ((!this.ready && !this.send_anyway) || !stream.writable) {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
if (!stream.writable) {
|
|
||||||
console.log("send command: stream is not writeable.");
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Queueing " + command + " for next server connection.");
|
|
||||||
}
|
|
||||||
this.offline_queue.push(command_obj);
|
|
||||||
this.should_buffer = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command === "subscribe" || command === "psubscribe" || command === "unsubscribe" || command === "punsubscribe") {
|
|
||||||
if (this.subscriptions === false && exports.debug_mode) {
|
|
||||||
console.log("Entering pub/sub mode from " + command);
|
|
||||||
}
|
|
||||||
command_obj.sub_command = true;
|
|
||||||
this.subscriptions = true;
|
|
||||||
} else if (command === "monitor") {
|
|
||||||
this.monitoring = true;
|
|
||||||
} else if (command === "quit") {
|
|
||||||
this.closing = true;
|
|
||||||
} else if (this.subscriptions === true) {
|
|
||||||
throw new Error("Connection in pub/sub mode, only pub/sub commands may be used");
|
|
||||||
}
|
|
||||||
this.command_queue.push(command_obj);
|
|
||||||
this.commands_sent += 1;
|
|
||||||
|
|
||||||
elem_count = 1;
|
|
||||||
buffer_args = false;
|
|
||||||
|
|
||||||
elem_count += args.length;
|
|
||||||
|
|
||||||
// Always use "Multi bulk commands", but if passed any Buffer args, then do multiple writes, one for each arg
|
|
||||||
// This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer.
|
|
||||||
// Also, why am I putting user documentation in the library source code?
|
|
||||||
|
|
||||||
command_str = "*" + elem_count + "\r\n$" + command.length + "\r\n" + command + "\r\n";
|
|
||||||
|
|
||||||
for (i = 0, il = args.length, arg; i < il; i += 1) {
|
|
||||||
if (Buffer.isBuffer(args[i])) {
|
|
||||||
buffer_args = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! buffer_args) { // Build up a string and send entire command in one write
|
|
||||||
for (i = 0, il = args.length, arg; i < il; i += 1) {
|
|
||||||
arg = args[i];
|
|
||||||
if (typeof arg !== "string") {
|
|
||||||
arg = String(arg);
|
|
||||||
}
|
|
||||||
command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n";
|
|
||||||
}
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("send " + this.host + ":" + this.port + " fd " + this.stream.fd + ": " + command_str);
|
|
||||||
}
|
|
||||||
buffered_writes += !stream.write(command_str);
|
|
||||||
} else {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("send command (" + command_str + ") has Buffer arguments");
|
|
||||||
}
|
|
||||||
buffered_writes += !stream.write(command_str);
|
|
||||||
|
|
||||||
for (i = 0, il = args.length, arg; i < il; i += 1) {
|
|
||||||
arg = args[i];
|
|
||||||
if (!(Buffer.isBuffer(arg) || arg instanceof String)) {
|
|
||||||
arg = String(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Buffer.isBuffer(arg)) {
|
|
||||||
if (arg.length === 0) {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("send_command: using empty string for 0 length buffer");
|
|
||||||
}
|
|
||||||
buffered_writes += !stream.write("$0\r\n\r\n");
|
|
||||||
} else {
|
|
||||||
buffered_writes += !stream.write("$" + arg.length + "\r\n");
|
|
||||||
buffered_writes += !stream.write(arg);
|
|
||||||
buffered_writes += !stream.write("\r\n");
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("send_command: buffer send " + arg.length + " bytes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("send_command: string send " + Buffer.byteLength(arg) + " bytes: " + arg);
|
|
||||||
}
|
|
||||||
buffered_writes += !stream.write("$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("send_command buffered_writes: " + buffered_writes, " should_buffer: " + this.should_buffer);
|
|
||||||
}
|
|
||||||
if (buffered_writes || this.command_queue.getLength() >= this.command_queue_high_water) {
|
|
||||||
this.should_buffer = true;
|
|
||||||
}
|
|
||||||
return !this.should_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.end = function () {
|
|
||||||
this.stream._events = {};
|
|
||||||
this.connected = false;
|
|
||||||
this.ready = false;
|
|
||||||
return this.stream.end();
|
|
||||||
};
|
|
||||||
|
|
||||||
function Multi(client, args) {
|
|
||||||
this.client = client;
|
|
||||||
this.queue = [["MULTI"]];
|
|
||||||
if (Array.isArray(args)) {
|
|
||||||
this.queue = this.queue.concat(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.Multi = Multi;
|
|
||||||
|
|
||||||
// take 2 arrays and return the union of their elements
|
|
||||||
function set_union(seta, setb) {
|
|
||||||
var obj = {};
|
|
||||||
|
|
||||||
seta.forEach(function (val) {
|
|
||||||
obj[val] = true;
|
|
||||||
});
|
|
||||||
setb.forEach(function (val) {
|
|
||||||
obj[val] = true;
|
|
||||||
});
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This static list of commands is updated from time to time. ./lib/commands.js can be updated with generate_commands.js
|
|
||||||
commands = set_union(["get", "set", "setnx", "setex", "append", "strlen", "del", "exists", "setbit", "getbit", "setrange", "getrange", "substr",
|
|
||||||
"incr", "decr", "mget", "rpush", "lpush", "rpushx", "lpushx", "linsert", "rpop", "lpop", "brpop", "brpoplpush", "blpop", "llen", "lindex",
|
|
||||||
"lset", "lrange", "ltrim", "lrem", "rpoplpush", "sadd", "srem", "smove", "sismember", "scard", "spop", "srandmember", "sinter", "sinterstore",
|
|
||||||
"sunion", "sunionstore", "sdiff", "sdiffstore", "smembers", "zadd", "zincrby", "zrem", "zremrangebyscore", "zremrangebyrank", "zunionstore",
|
|
||||||
"zinterstore", "zrange", "zrangebyscore", "zrevrangebyscore", "zcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "hset", "hsetnx",
|
|
||||||
"hget", "hmset", "hmget", "hincrby", "hdel", "hlen", "hkeys", "hvals", "hgetall", "hexists", "incrby", "decrby", "getset", "mset", "msetnx",
|
|
||||||
"randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo", "save", "bgsave",
|
|
||||||
"bgrewriteaof", "shutdown", "lastsave", "type", "multi", "exec", "discard", "sync", "flushdb", "flushall", "sort", "info", "monitor", "ttl",
|
|
||||||
"persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch", "cluster",
|
|
||||||
"restore", "migrate", "dump", "object", "client", "eval", "evalsha"], require("./lib/commands"));
|
|
||||||
|
|
||||||
commands.forEach(function (command) {
|
|
||||||
RedisClient.prototype[command] = function (args, callback) {
|
|
||||||
if (Array.isArray(args) && typeof callback === "function") {
|
|
||||||
return this.send_command(command, args, callback);
|
|
||||||
} else {
|
|
||||||
return this.send_command(command, to_array(arguments));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command];
|
|
||||||
|
|
||||||
Multi.prototype[command] = function () {
|
|
||||||
this.queue.push([command].concat(to_array(arguments)));
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
Multi.prototype[command.toUpperCase()] = Multi.prototype[command];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Stash auth for connect and reconnect. Send immediately if already connected.
|
|
||||||
RedisClient.prototype.auth = function () {
|
|
||||||
var args = to_array(arguments);
|
|
||||||
this.auth_pass = args[0];
|
|
||||||
this.auth_callback = args[1];
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Saving auth as " + this.auth_pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.connected) {
|
|
||||||
this.send_command("auth", args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
RedisClient.prototype.AUTH = RedisClient.prototype.auth;
|
|
||||||
|
|
||||||
RedisClient.prototype.hmget = function (arg1, arg2, arg3) {
|
|
||||||
if (Array.isArray(arg2) && typeof arg3 === "function") {
|
|
||||||
return this.send_command("hmget", [arg1].concat(arg2), arg3);
|
|
||||||
} else if (Array.isArray(arg1) && typeof arg2 === "function") {
|
|
||||||
return this.send_command("hmget", arg1, arg2);
|
|
||||||
} else {
|
|
||||||
return this.send_command("hmget", to_array(arguments));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
RedisClient.prototype.HMGET = RedisClient.prototype.hmget;
|
|
||||||
|
|
||||||
RedisClient.prototype.hmset = function (args, callback) {
|
|
||||||
var tmp_args, tmp_keys, i, il, key;
|
|
||||||
|
|
||||||
if (Array.isArray(args) && typeof callback === "function") {
|
|
||||||
return this.send_command("hmset", args, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
args = to_array(arguments);
|
|
||||||
if (typeof args[args.length - 1] === "function") {
|
|
||||||
callback = args[args.length - 1];
|
|
||||||
args.length -= 1;
|
|
||||||
} else {
|
|
||||||
callback = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length === 2 && typeof args[0] === "string" && typeof args[1] === "object") {
|
|
||||||
// User does: client.hmset(key, {key1: val1, key2: val2})
|
|
||||||
tmp_args = [ args[0] ];
|
|
||||||
tmp_keys = Object.keys(args[1]);
|
|
||||||
for (i = 0, il = tmp_keys.length; i < il ; i++) {
|
|
||||||
key = tmp_keys[i];
|
|
||||||
tmp_args.push(key);
|
|
||||||
tmp_args.push(args[1][key]);
|
|
||||||
}
|
|
||||||
args = tmp_args;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.send_command("hmset", args, callback);
|
|
||||||
};
|
|
||||||
RedisClient.prototype.HMSET = RedisClient.prototype.hmset;
|
|
||||||
|
|
||||||
Multi.prototype.hmset = function () {
|
|
||||||
var args = to_array(arguments), tmp_args;
|
|
||||||
if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") {
|
|
||||||
tmp_args = [ "hmset", args[0] ];
|
|
||||||
Object.keys(args[1]).map(function (key) {
|
|
||||||
tmp_args.push(key);
|
|
||||||
tmp_args.push(args[1][key]);
|
|
||||||
});
|
|
||||||
if (args[2]) {
|
|
||||||
tmp_args.push(args[2]);
|
|
||||||
}
|
|
||||||
args = tmp_args;
|
|
||||||
} else {
|
|
||||||
args.unshift("hmset");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.queue.push(args);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
Multi.prototype.HMSET = Multi.prototype.hmset;
|
|
||||||
|
|
||||||
Multi.prototype.exec = function (callback) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// drain queue, callback will catch "QUEUED" or error
|
|
||||||
// TODO - get rid of all of these anonymous functions which are elegant but slow
|
|
||||||
this.queue.forEach(function (args, index) {
|
|
||||||
var command = args[0], obj;
|
|
||||||
if (typeof args[args.length - 1] === "function") {
|
|
||||||
args = args.slice(1, -1);
|
|
||||||
} else {
|
|
||||||
args = args.slice(1);
|
|
||||||
}
|
|
||||||
if (args.length === 1 && Array.isArray(args[0])) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
if (command === 'hmset' && typeof args[1] === 'object') {
|
|
||||||
obj = args.pop();
|
|
||||||
Object.keys(obj).forEach(function (key) {
|
|
||||||
args.push(key);
|
|
||||||
args.push(obj[key]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.client.send_command(command, args, function (err, reply) {
|
|
||||||
if (err) {
|
|
||||||
var cur = self.queue[index];
|
|
||||||
if (typeof cur[cur.length - 1] === "function") {
|
|
||||||
cur[cur.length - 1](err);
|
|
||||||
} else {
|
|
||||||
throw new Error(err);
|
|
||||||
}
|
|
||||||
self.queue.splice(index, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
// TODO - make this callback part of Multi.prototype instead of creating it each time
|
|
||||||
return this.client.send_command("EXEC", [], function (err, replies) {
|
|
||||||
if (err) {
|
|
||||||
if (callback) {
|
|
||||||
callback(new Error(err));
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
throw new Error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var i, il, j, jl, reply, args, obj, key, val;
|
|
||||||
|
|
||||||
if (replies) {
|
|
||||||
for (i = 1, il = self.queue.length; i < il; i += 1) {
|
|
||||||
reply = replies[i - 1];
|
|
||||||
args = self.queue[i];
|
|
||||||
|
|
||||||
// Convert HGETALL reply to object
|
|
||||||
if (reply && args[0].toLowerCase() === "hgetall") {
|
|
||||||
obj = {};
|
|
||||||
for (j = 0, jl = reply.length; j < jl; j += 2) {
|
|
||||||
key = reply[j].toString();
|
|
||||||
val = reply[j + 1];
|
|
||||||
obj[key] = val;
|
|
||||||
}
|
|
||||||
replies[i - 1] = reply = obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof args[args.length - 1] === "function") {
|
|
||||||
args[args.length - 1](null, reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) {
|
|
||||||
callback(null, replies);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisClient.prototype.multi = function (args) {
|
|
||||||
return new Multi(this, args);
|
|
||||||
};
|
|
||||||
RedisClient.prototype.MULTI = function (args) {
|
|
||||||
return new Multi(this, args);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.createClient = function (port_arg, host_arg, options) {
|
|
||||||
var port = port_arg || default_port,
|
|
||||||
host = host_arg || default_host,
|
|
||||||
redis_client, net_client;
|
|
||||||
|
|
||||||
net_client = net.createConnection(port, host);
|
|
||||||
|
|
||||||
redis_client = new RedisClient(net_client, options);
|
|
||||||
|
|
||||||
redis_client.port = port;
|
|
||||||
redis_client.host = host;
|
|
||||||
|
|
||||||
return redis_client;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.print = function (err, reply) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Error: " + err);
|
|
||||||
} else {
|
|
||||||
console.log("Reply: " + reply);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
126
node_modules/socket.io/node_modules/redis/lib/commands.js
generated
vendored
126
node_modules/socket.io/node_modules/redis/lib/commands.js
generated
vendored
|
|
@ -1,126 +0,0 @@
|
||||||
// This file was generated by ./generate_commands.js on Tue Jun 28 2011 22:37:02 GMT-0700 (PDT)
|
|
||||||
module.exports = [
|
|
||||||
"append",
|
|
||||||
"auth",
|
|
||||||
"bgrewriteaof",
|
|
||||||
"bgsave",
|
|
||||||
"blpop",
|
|
||||||
"brpop",
|
|
||||||
"brpoplpush",
|
|
||||||
"config get",
|
|
||||||
"config set",
|
|
||||||
"config resetstat",
|
|
||||||
"dbsize",
|
|
||||||
"debug object",
|
|
||||||
"debug segfault",
|
|
||||||
"decr",
|
|
||||||
"decrby",
|
|
||||||
"del",
|
|
||||||
"discard",
|
|
||||||
"echo",
|
|
||||||
"exec",
|
|
||||||
"exists",
|
|
||||||
"expire",
|
|
||||||
"expireat",
|
|
||||||
"flushall",
|
|
||||||
"flushdb",
|
|
||||||
"get",
|
|
||||||
"getbit",
|
|
||||||
"getrange",
|
|
||||||
"getset",
|
|
||||||
"hdel",
|
|
||||||
"hexists",
|
|
||||||
"hget",
|
|
||||||
"hgetall",
|
|
||||||
"hincrby",
|
|
||||||
"hkeys",
|
|
||||||
"hlen",
|
|
||||||
"hmget",
|
|
||||||
"hmset",
|
|
||||||
"hset",
|
|
||||||
"hsetnx",
|
|
||||||
"hvals",
|
|
||||||
"incr",
|
|
||||||
"incrby",
|
|
||||||
"info",
|
|
||||||
"keys",
|
|
||||||
"lastsave",
|
|
||||||
"lindex",
|
|
||||||
"linsert",
|
|
||||||
"llen",
|
|
||||||
"lpop",
|
|
||||||
"lpush",
|
|
||||||
"lpushx",
|
|
||||||
"lrange",
|
|
||||||
"lrem",
|
|
||||||
"lset",
|
|
||||||
"ltrim",
|
|
||||||
"mget",
|
|
||||||
"monitor",
|
|
||||||
"move",
|
|
||||||
"mset",
|
|
||||||
"msetnx",
|
|
||||||
"multi",
|
|
||||||
"object",
|
|
||||||
"persist",
|
|
||||||
"ping",
|
|
||||||
"psubscribe",
|
|
||||||
"publish",
|
|
||||||
"punsubscribe",
|
|
||||||
"quit",
|
|
||||||
"randomkey",
|
|
||||||
"rename",
|
|
||||||
"renamenx",
|
|
||||||
"rpop",
|
|
||||||
"rpoplpush",
|
|
||||||
"rpush",
|
|
||||||
"rpushx",
|
|
||||||
"sadd",
|
|
||||||
"save",
|
|
||||||
"scard",
|
|
||||||
"sdiff",
|
|
||||||
"sdiffstore",
|
|
||||||
"select",
|
|
||||||
"set",
|
|
||||||
"setbit",
|
|
||||||
"setex",
|
|
||||||
"setnx",
|
|
||||||
"setrange",
|
|
||||||
"shutdown",
|
|
||||||
"sinter",
|
|
||||||
"sinterstore",
|
|
||||||
"sismember",
|
|
||||||
"slaveof",
|
|
||||||
"smembers",
|
|
||||||
"smove",
|
|
||||||
"sort",
|
|
||||||
"spop",
|
|
||||||
"srandmember",
|
|
||||||
"srem",
|
|
||||||
"strlen",
|
|
||||||
"subscribe",
|
|
||||||
"sunion",
|
|
||||||
"sunionstore",
|
|
||||||
"sync",
|
|
||||||
"ttl",
|
|
||||||
"type",
|
|
||||||
"unsubscribe",
|
|
||||||
"unwatch",
|
|
||||||
"watch",
|
|
||||||
"zadd",
|
|
||||||
"zcard",
|
|
||||||
"zcount",
|
|
||||||
"zincrby",
|
|
||||||
"zinterstore",
|
|
||||||
"zrange",
|
|
||||||
"zrangebyscore",
|
|
||||||
"zrank",
|
|
||||||
"zrem",
|
|
||||||
"zremrangebyrank",
|
|
||||||
"zremrangebyscore",
|
|
||||||
"zrevrange",
|
|
||||||
"zrevrangebyscore",
|
|
||||||
"zrevrank",
|
|
||||||
"zscore",
|
|
||||||
"zunionstore"
|
|
||||||
];
|
|
||||||
41
node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js
generated
vendored
41
node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js
generated
vendored
|
|
@ -1,41 +0,0 @@
|
||||||
/*global Buffer require exports console setTimeout */
|
|
||||||
|
|
||||||
var events = require("events"),
|
|
||||||
util = require("../util").util,
|
|
||||||
hiredis = require("hiredis");
|
|
||||||
|
|
||||||
exports.debug_mode = false;
|
|
||||||
exports.name = "hiredis";
|
|
||||||
|
|
||||||
function HiredisReplyParser(options) {
|
|
||||||
this.name = exports.name;
|
|
||||||
this.options = options || {};
|
|
||||||
this.reset();
|
|
||||||
events.EventEmitter.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
util.inherits(HiredisReplyParser, events.EventEmitter);
|
|
||||||
|
|
||||||
exports.Parser = HiredisReplyParser;
|
|
||||||
|
|
||||||
HiredisReplyParser.prototype.reset = function () {
|
|
||||||
this.reader = new hiredis.Reader({
|
|
||||||
return_buffers: this.options.return_buffers || false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
HiredisReplyParser.prototype.execute = function (data) {
|
|
||||||
var reply;
|
|
||||||
this.reader.feed(data);
|
|
||||||
try {
|
|
||||||
while ((reply = this.reader.get()) !== undefined) {
|
|
||||||
if (reply && reply.constructor === Error) {
|
|
||||||
this.emit("reply error", reply);
|
|
||||||
} else {
|
|
||||||
this.emit("reply", reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
this.emit("error", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
316
node_modules/socket.io/node_modules/redis/lib/parser/javascript.js
generated
vendored
316
node_modules/socket.io/node_modules/redis/lib/parser/javascript.js
generated
vendored
|
|
@ -1,316 +0,0 @@
|
||||||
/*global Buffer require exports console setTimeout */
|
|
||||||
|
|
||||||
// TODO - incorporate these V8 pro tips:
|
|
||||||
// pre-allocate Arrays if length is known in advance
|
|
||||||
// do not use delete
|
|
||||||
// use numbers for parser state
|
|
||||||
|
|
||||||
var events = require("events"),
|
|
||||||
util = require("../util").util;
|
|
||||||
|
|
||||||
exports.debug_mode = false;
|
|
||||||
exports.name = "javascript";
|
|
||||||
|
|
||||||
function RedisReplyParser(options) {
|
|
||||||
this.name = exports.name;
|
|
||||||
this.options = options || {};
|
|
||||||
this.reset();
|
|
||||||
events.EventEmitter.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
util.inherits(RedisReplyParser, events.EventEmitter);
|
|
||||||
|
|
||||||
exports.Parser = RedisReplyParser;
|
|
||||||
|
|
||||||
// Buffer.toString() is quite slow for small strings
|
|
||||||
function small_toString(buf, len) {
|
|
||||||
var tmp = "", i;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i += 1) {
|
|
||||||
tmp += String.fromCharCode(buf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset parser to it's original state.
|
|
||||||
RedisReplyParser.prototype.reset = function () {
|
|
||||||
this.return_buffer = new Buffer(16384); // for holding replies, might grow
|
|
||||||
this.return_string = "";
|
|
||||||
this.tmp_string = ""; // for holding size fields
|
|
||||||
|
|
||||||
this.multi_bulk_length = 0;
|
|
||||||
this.multi_bulk_replies = null;
|
|
||||||
this.multi_bulk_pos = 0;
|
|
||||||
this.multi_bulk_nested_length = 0;
|
|
||||||
this.multi_bulk_nested_replies = null;
|
|
||||||
|
|
||||||
this.states = {
|
|
||||||
TYPE: 1,
|
|
||||||
SINGLE_LINE: 2,
|
|
||||||
MULTI_BULK_COUNT: 3,
|
|
||||||
INTEGER_LINE: 4,
|
|
||||||
BULK_LENGTH: 5,
|
|
||||||
ERROR_LINE: 6,
|
|
||||||
BULK_DATA: 7,
|
|
||||||
UNKNOWN_TYPE: 8,
|
|
||||||
FINAL_CR: 9,
|
|
||||||
FINAL_LF: 10,
|
|
||||||
MULTI_BULK_COUNT_LF: 11
|
|
||||||
};
|
|
||||||
|
|
||||||
this.state = this.states.TYPE;
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisReplyParser.prototype.parser_error = function (message) {
|
|
||||||
this.emit("error", message);
|
|
||||||
this.reset();
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisReplyParser.prototype.execute = function (incoming_buf) {
|
|
||||||
var pos = 0, bd_tmp, bd_str, i, il, states = this.states;
|
|
||||||
//, state_times = {}, start_execute = new Date(), start_switch, end_switch, old_state;
|
|
||||||
//start_switch = new Date();
|
|
||||||
|
|
||||||
while (pos < incoming_buf.length) {
|
|
||||||
// old_state = this.state;
|
|
||||||
// console.log("execute: " + this.state + ", " + pos + "/" + incoming_buf.length + ", " + String.fromCharCode(incoming_buf[pos]));
|
|
||||||
|
|
||||||
switch (this.state) {
|
|
||||||
case states.TYPE:
|
|
||||||
this.type = incoming_buf[pos];
|
|
||||||
pos += 1;
|
|
||||||
|
|
||||||
switch (this.type) {
|
|
||||||
case 43: // +
|
|
||||||
this.state = states.SINGLE_LINE;
|
|
||||||
this.return_buffer.end = 0;
|
|
||||||
this.return_string = "";
|
|
||||||
break;
|
|
||||||
case 42: // *
|
|
||||||
this.state = states.MULTI_BULK_COUNT;
|
|
||||||
this.tmp_string = "";
|
|
||||||
break;
|
|
||||||
case 58: // :
|
|
||||||
this.state = states.INTEGER_LINE;
|
|
||||||
this.return_buffer.end = 0;
|
|
||||||
this.return_string = "";
|
|
||||||
break;
|
|
||||||
case 36: // $
|
|
||||||
this.state = states.BULK_LENGTH;
|
|
||||||
this.tmp_string = "";
|
|
||||||
break;
|
|
||||||
case 45: // -
|
|
||||||
this.state = states.ERROR_LINE;
|
|
||||||
this.return_buffer.end = 0;
|
|
||||||
this.return_string = "";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.state = states.UNKNOWN_TYPE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case states.INTEGER_LINE:
|
|
||||||
if (incoming_buf[pos] === 13) {
|
|
||||||
this.send_reply(+small_toString(this.return_buffer, this.return_buffer.end));
|
|
||||||
this.state = states.FINAL_LF;
|
|
||||||
} else {
|
|
||||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
|
||||||
this.return_buffer.end += 1;
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case states.ERROR_LINE:
|
|
||||||
if (incoming_buf[pos] === 13) {
|
|
||||||
this.send_error(this.return_buffer.toString("ascii", 0, this.return_buffer.end));
|
|
||||||
this.state = states.FINAL_LF;
|
|
||||||
} else {
|
|
||||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
|
||||||
this.return_buffer.end += 1;
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case states.SINGLE_LINE:
|
|
||||||
if (incoming_buf[pos] === 13) {
|
|
||||||
this.send_reply(this.return_string);
|
|
||||||
this.state = states.FINAL_LF;
|
|
||||||
} else {
|
|
||||||
this.return_string += String.fromCharCode(incoming_buf[pos]);
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case states.MULTI_BULK_COUNT:
|
|
||||||
if (incoming_buf[pos] === 13) { // \r
|
|
||||||
this.state = states.MULTI_BULK_COUNT_LF;
|
|
||||||
} else {
|
|
||||||
this.tmp_string += String.fromCharCode(incoming_buf[pos]);
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case states.MULTI_BULK_COUNT_LF:
|
|
||||||
if (incoming_buf[pos] === 10) { // \n
|
|
||||||
if (this.multi_bulk_length) { // nested multi-bulk
|
|
||||||
this.multi_bulk_nested_length = this.multi_bulk_length;
|
|
||||||
this.multi_bulk_nested_replies = this.multi_bulk_replies;
|
|
||||||
this.multi_bulk_nested_pos = this.multi_bulk_pos;
|
|
||||||
}
|
|
||||||
this.multi_bulk_length = +this.tmp_string;
|
|
||||||
this.multi_bulk_pos = 0;
|
|
||||||
this.state = states.TYPE;
|
|
||||||
if (this.multi_bulk_length < 0) {
|
|
||||||
this.send_reply(null);
|
|
||||||
this.multi_bulk_length = 0;
|
|
||||||
} else if (this.multi_bulk_length === 0) {
|
|
||||||
this.multi_bulk_pos = 0;
|
|
||||||
this.multi_bulk_replies = null;
|
|
||||||
this.send_reply([]);
|
|
||||||
} else {
|
|
||||||
this.multi_bulk_replies = new Array(this.multi_bulk_length);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.parser_error(new Error("didn't see LF after NL reading multi bulk count"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case states.BULK_LENGTH:
|
|
||||||
if (incoming_buf[pos] === 13) { // \r
|
|
||||||
this.state = states.BULK_LF;
|
|
||||||
} else {
|
|
||||||
this.tmp_string += String.fromCharCode(incoming_buf[pos]);
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case states.BULK_LF:
|
|
||||||
if (incoming_buf[pos] === 10) { // \n
|
|
||||||
this.bulk_length = +this.tmp_string;
|
|
||||||
if (this.bulk_length === -1) {
|
|
||||||
this.send_reply(null);
|
|
||||||
this.state = states.TYPE;
|
|
||||||
} else if (this.bulk_length === 0) {
|
|
||||||
this.send_reply(new Buffer(""));
|
|
||||||
this.state = states.FINAL_CR;
|
|
||||||
} else {
|
|
||||||
this.state = states.BULK_DATA;
|
|
||||||
if (this.bulk_length > this.return_buffer.length) {
|
|
||||||
if (exports.debug_mode) {
|
|
||||||
console.log("Growing return_buffer from " + this.return_buffer.length + " to " + this.bulk_length);
|
|
||||||
}
|
|
||||||
this.return_buffer = new Buffer(this.bulk_length);
|
|
||||||
}
|
|
||||||
this.return_buffer.end = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.parser_error(new Error("didn't see LF after NL while reading bulk length"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case states.BULK_DATA:
|
|
||||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
|
||||||
this.return_buffer.end += 1;
|
|
||||||
pos += 1;
|
|
||||||
if (this.return_buffer.end === this.bulk_length) {
|
|
||||||
bd_tmp = new Buffer(this.bulk_length);
|
|
||||||
// When the response is small, Buffer.copy() is a lot slower.
|
|
||||||
if (this.bulk_length > 10) {
|
|
||||||
this.return_buffer.copy(bd_tmp, 0, 0, this.bulk_length);
|
|
||||||
} else {
|
|
||||||
for (i = 0, il = this.bulk_length; i < il; i += 1) {
|
|
||||||
bd_tmp[i] = this.return_buffer[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.send_reply(bd_tmp);
|
|
||||||
this.state = states.FINAL_CR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case states.FINAL_CR:
|
|
||||||
if (incoming_buf[pos] === 13) { // \r
|
|
||||||
this.state = states.FINAL_LF;
|
|
||||||
pos += 1;
|
|
||||||
} else {
|
|
||||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final CR"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case states.FINAL_LF:
|
|
||||||
if (incoming_buf[pos] === 10) { // \n
|
|
||||||
this.state = states.TYPE;
|
|
||||||
pos += 1;
|
|
||||||
} else {
|
|
||||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final LF"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.parser_error(new Error("invalid state " + this.state));
|
|
||||||
}
|
|
||||||
// end_switch = new Date();
|
|
||||||
// if (state_times[old_state] === undefined) {
|
|
||||||
// state_times[old_state] = 0;
|
|
||||||
// }
|
|
||||||
// state_times[old_state] += (end_switch - start_switch);
|
|
||||||
// start_switch = end_switch;
|
|
||||||
}
|
|
||||||
// console.log("execute ran for " + (Date.now() - start_execute) + " ms, on " + incoming_buf.length + " Bytes. ");
|
|
||||||
// Object.keys(state_times).forEach(function (state) {
|
|
||||||
// console.log(" " + state + ": " + state_times[state]);
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisReplyParser.prototype.send_error = function (reply) {
|
|
||||||
if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) {
|
|
||||||
// TODO - can this happen? Seems like maybe not.
|
|
||||||
this.add_multi_bulk_reply(reply);
|
|
||||||
} else {
|
|
||||||
this.emit("reply error", reply);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisReplyParser.prototype.send_reply = function (reply) {
|
|
||||||
if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) {
|
|
||||||
if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
|
|
||||||
this.add_multi_bulk_reply(reply.toString("utf8"));
|
|
||||||
} else {
|
|
||||||
this.add_multi_bulk_reply(reply);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
|
|
||||||
this.emit("reply", reply.toString("utf8"));
|
|
||||||
} else {
|
|
||||||
this.emit("reply", reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RedisReplyParser.prototype.add_multi_bulk_reply = function (reply) {
|
|
||||||
if (this.multi_bulk_replies) {
|
|
||||||
this.multi_bulk_replies[this.multi_bulk_pos] = reply;
|
|
||||||
this.multi_bulk_pos += 1;
|
|
||||||
if (this.multi_bulk_pos < this.multi_bulk_length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.multi_bulk_replies = reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.multi_bulk_nested_length > 0) {
|
|
||||||
this.multi_bulk_nested_replies[this.multi_bulk_nested_pos] = this.multi_bulk_replies;
|
|
||||||
this.multi_bulk_nested_pos += 1;
|
|
||||||
|
|
||||||
this.multi_bulk_length = 0;
|
|
||||||
this.multi_bulk_replies = null;
|
|
||||||
this.multi_bulk_pos = 0;
|
|
||||||
|
|
||||||
if (this.multi_bulk_nested_length === this.multi_bulk_nested_pos) {
|
|
||||||
this.emit("reply", this.multi_bulk_nested_replies);
|
|
||||||
this.multi_bulk_nested_length = 0;
|
|
||||||
this.multi_bulk_nested_pos = 0;
|
|
||||||
this.multi_bulk_nested_replies = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.emit("reply", this.multi_bulk_replies);
|
|
||||||
this.multi_bulk_length = 0;
|
|
||||||
this.multi_bulk_replies = null;
|
|
||||||
this.multi_bulk_pos = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
58
node_modules/socket.io/node_modules/redis/lib/queue.js
generated
vendored
58
node_modules/socket.io/node_modules/redis/lib/queue.js
generated
vendored
|
|
@ -1,58 +0,0 @@
|
||||||
var to_array = require("./to_array");
|
|
||||||
|
|
||||||
// Queue class adapted from Tim Caswell's pattern library
|
|
||||||
// http://github.com/creationix/pattern/blob/master/lib/pattern/queue.js
|
|
||||||
|
|
||||||
function Queue() {
|
|
||||||
this.tail = [];
|
|
||||||
this.head = to_array(arguments);
|
|
||||||
this.offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Queue.prototype.shift = function () {
|
|
||||||
if (this.offset === this.head.length) {
|
|
||||||
var tmp = this.head;
|
|
||||||
tmp.length = 0;
|
|
||||||
this.head = this.tail;
|
|
||||||
this.tail = tmp;
|
|
||||||
this.offset = 0;
|
|
||||||
if (this.head.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.head[this.offset++]; // sorry, JSLint
|
|
||||||
};
|
|
||||||
|
|
||||||
Queue.prototype.push = function (item) {
|
|
||||||
return this.tail.push(item);
|
|
||||||
};
|
|
||||||
|
|
||||||
Queue.prototype.forEach = function (fn, thisv) {
|
|
||||||
var array = this.head.slice(this.offset), i, il;
|
|
||||||
|
|
||||||
array.push.apply(array, this.tail);
|
|
||||||
|
|
||||||
if (thisv) {
|
|
||||||
for (i = 0, il = array.length; i < il; i += 1) {
|
|
||||||
fn.call(thisv, array[i], i, array);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i = 0, il = array.length; i < il; i += 1) {
|
|
||||||
fn(array[i], i, array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
};
|
|
||||||
|
|
||||||
Queue.prototype.getLength = function () {
|
|
||||||
return this.head.length - this.offset + this.tail.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(Queue.prototype, 'length', {
|
|
||||||
get: function () {
|
|
||||||
return this.getLength();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
exports.Queue = Queue;
|
|
||||||
12
node_modules/socket.io/node_modules/redis/lib/to_array.js
generated
vendored
12
node_modules/socket.io/node_modules/redis/lib/to_array.js
generated
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
function to_array(args) {
|
|
||||||
var len = args.length,
|
|
||||||
arr = new Array(len), i;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = args[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = to_array;
|
|
||||||
6
node_modules/socket.io/node_modules/redis/lib/util.js
generated
vendored
6
node_modules/socket.io/node_modules/redis/lib/util.js
generated
vendored
|
|
@ -1,6 +0,0 @@
|
||||||
if (process.versions.node.match(/^0.3/)) {
|
|
||||||
exports.util = require("util");
|
|
||||||
} else {
|
|
||||||
// This module is called "sys" in 0.2.x
|
|
||||||
exports.util = require("sys");
|
|
||||||
}
|
|
||||||
135
node_modules/socket.io/node_modules/redis/multi_bench.js
generated
vendored
135
node_modules/socket.io/node_modules/redis/multi_bench.js
generated
vendored
|
|
@ -1,135 +0,0 @@
|
||||||
var redis = require("./index"),
|
|
||||||
num_clients = parseInt(process.argv[2], 10) || 50,
|
|
||||||
active_clients = 0,
|
|
||||||
clients = new Array(num_clients),
|
|
||||||
num_requests = 20000,
|
|
||||||
issued_requests = 0,
|
|
||||||
latency = new Array(num_requests),
|
|
||||||
tests = [],
|
|
||||||
test_start, parser_logged = false,
|
|
||||||
client_options = {
|
|
||||||
return_buffers: false
|
|
||||||
};
|
|
||||||
|
|
||||||
redis.debug_mode = false;
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
descr: "PING",
|
|
||||||
command: ["ping"]
|
|
||||||
});
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
descr: "SET",
|
|
||||||
command: ["set", "foo_rand000000000000", "bar"]
|
|
||||||
});
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
descr: "GET",
|
|
||||||
command: ["get", "foo_rand000000000000"]
|
|
||||||
});
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
descr: "INCR",
|
|
||||||
command: ["incr", "counter_rand000000000000"]
|
|
||||||
});
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
descr: "LPUSH",
|
|
||||||
command: ["lpush", "mylist", new Array(8).join("-")]
|
|
||||||
});
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
descr: "LRANGE (10 elements)",
|
|
||||||
command: ["lrange", "mylist", "0", "9"]
|
|
||||||
});
|
|
||||||
|
|
||||||
tests.push({
|
|
||||||
descr: "LRANGE (100 elements)",
|
|
||||||
command: ["lrange", "mylist", "0", "99"]
|
|
||||||
});
|
|
||||||
|
|
||||||
function create_clients(callback) {
|
|
||||||
if (active_clients === num_clients) {
|
|
||||||
// common case is all clients are already created
|
|
||||||
console.log("create_clients: all clients already created " + num_clients);
|
|
||||||
callback();
|
|
||||||
} else {
|
|
||||||
var client, connected = active_clients;
|
|
||||||
|
|
||||||
while (active_clients < num_clients) {
|
|
||||||
client = clients[active_clients++] = redis.createClient(6379, "127.0.0.1", client_options);
|
|
||||||
if (! parser_logged) {
|
|
||||||
console.log("Using reply parser " + client.reply_parser.name);
|
|
||||||
parser_logged = true;
|
|
||||||
}
|
|
||||||
client.on("connect", function () {
|
|
||||||
// Fire callback when all clients are connected
|
|
||||||
connected += 1;
|
|
||||||
if (connected === num_clients) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// TODO - need to check for client disconnect
|
|
||||||
client.on("error", function (msg) {
|
|
||||||
console.log("Connect problem:" + msg.stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function issue_request(client, test, cmd, args) {
|
|
||||||
var i = issued_requests++;
|
|
||||||
latency[i] = Date.now();
|
|
||||||
|
|
||||||
client[cmd](args, function() {
|
|
||||||
latency[i] = Date.now() - latency[i];
|
|
||||||
if (issued_requests < num_requests) {
|
|
||||||
issue_request(client, test, cmd, args);
|
|
||||||
} else {
|
|
||||||
client.end();
|
|
||||||
if (--active_clients == 0)
|
|
||||||
test_complete(test);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_run(test) {
|
|
||||||
create_clients(function() {
|
|
||||||
var i = num_clients,
|
|
||||||
cmd = test.command[0],
|
|
||||||
args = test.command.slice(1);
|
|
||||||
|
|
||||||
test_start = Date.now();
|
|
||||||
issued_requests = 0;
|
|
||||||
while(i-- && issued_requests < num_requests) {
|
|
||||||
issue_request(clients[i], test, cmd, args);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_complete(test) {
|
|
||||||
var min, max, sum, avg;
|
|
||||||
var total_time = Date.now() - test_start;
|
|
||||||
var op_rate = (issued_requests / (total_time / 1000.0)).toFixed(2);
|
|
||||||
var i;
|
|
||||||
|
|
||||||
latency.sort();
|
|
||||||
min = latency[0];
|
|
||||||
max = latency[issued_requests-1];
|
|
||||||
for (sum = 0, i = 0; i < issued_requests; i++)
|
|
||||||
sum += latency[i];
|
|
||||||
avg = (sum / issued_requests).toFixed(3);
|
|
||||||
|
|
||||||
console.log(test.descr + ": " + issued_requests + " ops " + op_rate + " ops/sec " + min + "/" + max + "/" + avg);
|
|
||||||
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function next() {
|
|
||||||
var test = tests.shift();
|
|
||||||
if (test) {
|
|
||||||
test_run(test);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
67
node_modules/socket.io/node_modules/redis/package.json
generated
vendored
67
node_modules/socket.io/node_modules/redis/package.json
generated
vendored
|
|
@ -1,67 +0,0 @@
|
||||||
{
|
|
||||||
"name": "redis",
|
|
||||||
"version": "0.6.7",
|
|
||||||
"description": "Redis client library",
|
|
||||||
"author": {
|
|
||||||
"name": "Matt Ranney",
|
|
||||||
"email": "mjr@ranney.com"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Rick Olson"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tim-Smart"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "TJ Holowaychuk"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Orion Henry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Hank Sims"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Aivo Paas"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Paul Carey"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Pieter Noordhuis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Andy Ray"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Vladimir Dronnikov"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Dave Hoover"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"main": "./index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "node ./test.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/mranney/node_redis.git"
|
|
||||||
},
|
|
||||||
"_id": "redis@0.6.7",
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {},
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"_engineSupported": true,
|
|
||||||
"_npmVersion": "1.1.9",
|
|
||||||
"_nodeVersion": "v0.6.13",
|
|
||||||
"_defaultsLoaded": true,
|
|
||||||
"dist": {
|
|
||||||
"shasum": "641b2ae42d11301a04d76f26150f9dad08885e17"
|
|
||||||
},
|
|
||||||
"_from": "redis@0.6.7"
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue