Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial 1.0 commit

  • Loading branch information...
commit b6a48996898a5cc4112373e91e56d4d1afc46cdf 1 parent 3af1ad9
@rauchg rauchg authored
Showing with 604 additions and 17,466 deletions.
  1. +5 −27 Makefile
  2. +8 −355 Readme.md
  3. +0 −64 benchmarks/decode.bench.js
  4. +0 −90 benchmarks/encode.bench.js
  5. +0 −55 benchmarks/runner.js
  6. +0 −80 examples/chat/app.js
  7. +0 −83 examples/chat/index.jade
  8. +0 −11 examples/chat/package.json
  9. +0 −96 examples/chat/public/stylesheets/mixins.styl
  10. +0 −188 examples/chat/public/stylesheets/style.css
  11. +0 −118 examples/chat/public/stylesheets/style.styl
  12. +0 −74 examples/irc-output/app.js
  13. +0 −28 examples/irc-output/index.jade
  14. +0 −164 examples/irc-output/irc.js
  15. +0 −10 examples/irc-output/package.json
  16. +0 −69 examples/irc-output/public/stylesheets/style.styl
  17. +3 −7 index.js
  18. +163 −0 lib/client.js
  19. +119 −0 lib/index.js
  20. +0 −97 lib/logger.js
  21. +0 −1,020 lib/manager.js
  22. +109 −264 lib/namespace.js
  23. +0 −249 lib/parser.js
  24. +0 −143 lib/socket.io.js
  25. +175 −233 lib/socket.js
  26. +0 −395 lib/static.js
  27. +0 −98 lib/store.js
  28. +0 −143 lib/stores/memory.js
  29. +0 −267 lib/stores/redis.js
  30. +0 −536 lib/transport.js
  31. +0 −129 lib/transports/flashsocket.js
  32. +0 −80 lib/transports/htmlfile.js
  33. +0 −147 lib/transports/http-polling.js
  34. +0 −121 lib/transports/http.js
  35. +0 −12 lib/transports/index.js
  36. +0 −97 lib/transports/jsonp-polling.js
  37. +0 −76 lib/transports/websocket.js
  38. +0 −363 lib/transports/websocket/default.js
  39. +0 −622 lib/transports/websocket/hybi-07-12.js
  40. +0 −638 lib/transports/websocket/hybi-16.js
  41. +0 −11 lib/transports/websocket/index.js
  42. +0 −68 lib/transports/xhr-polling.js
  43. +0 −50 lib/util.js
  44. +22 −36 package.json
  45. +0 −27 support/node-websocket-client/LICENSE
  46. +0 −22 support/node-websocket-client/Makefile
  47. +0 −41 support/node-websocket-client/README.md
  48. +0 −12 support/node-websocket-client/examples/client-unix.js
  49. +0 −10 support/node-websocket-client/examples/client.js
  50. +0 −13 support/node-websocket-client/examples/server-unix.js
  51. +0 −617 support/node-websocket-client/lib/websocket.js
  52. +0 −22 support/node-websocket-client/package.json
  53. +0 −68 support/node-websocket-client/test/test-basic.js
  54. +0 −43 support/node-websocket-client/test/test-client-close.js
  55. +0 −43 support/node-websocket-client/test/test-readonly-attrs.js
  56. +0 −26 support/node-websocket-client/test/test-ready-state.js
  57. +0 −41 support/node-websocket-client/test/test-server-close.js
  58. +0 −63 support/node-websocket-client/test/test-unix-send-fd.js
  59. +0 −46 support/node-websocket-client/test/test-unix-sockets.js
  60. +0 −278 test/common.js
  61. +0 −21 test/fixtures/cert.crt
  62. +0 −27 test/fixtures/key.key
  63. +0 −99 test/hybi-common.js
  64. +0 −125 test/io.test.js
  65. +0 −54 test/leaks/socket.leaktest.js
  66. +0 −589 test/manager.test.js
  67. +0 −327 test/namespace.test.js
  68. +0 −356 test/parser.test.js
  69. +0 −549 test/static.test.js
  70. +0 −190 test/stores.memory.test.js
  71. +0 −240 test/stores.redis.test.js
  72. +0 −187 test/transports.flashsocket.test.js
  73. +0 −458 test/transports.htmlfile.test.js
  74. +0 −774 test/transports.jsonp-polling.test.js
  75. +0 −1,891 test/transports.websocket.test.js
  76. +0 −2,793 test/transports.xhr-polling.test.js
View
32 Makefile
@@ -1,31 +1,9 @@
-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)
+REPORTER = dot
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
+ @./node_modules/.bin/mocha \
+ --reporter $(REPORTER) \
+ --bail
-.PHONY: test bench profile
+.PHONY: test
View
363 Readme.md
@@ -1,364 +1,17 @@
-# 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
-```
+# 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:
-
-#### Express 3.x
-
```js
-var app = express()
- , server = require('http').createServer(app)
- , io = io.listen(server);
-
-server.listen(80);
-
-io.sockets.on('connection', function (socket) {
- socket.emit('news', { hello: 'world' });
- socket.on('my other event', function (data) {
- console.log(data);
- });
+var http = require('http').Server();
+var sockets = require('socket.io')(http);
+sockets.on('connection', function(socket){
+ socket.on('event', function(data){});
+ socket.on('disconnect', function(){});
});
```
-#### Express 2.x
-
-```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', prompt('What is your nickname?'));
- socket.on('ready', function () {
- console.log('Connected !');
- socket.emit('msg', prompt('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 &lt;guillermo@learnboost.com&gt;
-
-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.
+## License
-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.
+MIT
View
64 benchmarks/decode.bench.js
@@ -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;
-}
View
90 benchmarks/encode.bench.js
@@ -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;
-}
View
55 benchmarks/runner.js
@@ -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();
View
80 examples/chat/app.js
@@ -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);
- });
-});
View
83 examples/chat/index.jade
@@ -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
View
11 examples/chat/package.json
@@ -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"
- }
-}
View
96 examples/chat/public/stylesheets/mixins.styl
@@ -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)
View
188 examples/chat/public/stylesheets/style.css
@@ -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;
-}
View
118 examples/chat/public/stylesheets/style.styl
@@ -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()
View
74 examples/irc-output/app.js
@@ -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);
-});
View
28 examples/irc-output/index.jade
@@ -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
View
164 examples/irc-output/irc.js
@@ -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]
-};
View
10 examples/irc-output/package.json
@@ -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"
- }
-}
View
69 examples/irc-output/public/stylesheets/style.styl
@@ -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
View
10 index.js
@@ -1,8 +1,4 @@
-/*!
- * socket.io-node
- * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
- * MIT Licensed
- */
-
-module.exports = require('./lib/socket.io');
+module.exports = process.env.SIO_COV
+? require('./lib-cov/')
+: require('./lib/');
View
163 lib/client.js
@@ -0,0 +1,163 @@
+
+/**
+ * Module dependencies.
+ */
+
+var parser = require('socket.io-parser')
+ , encode = parser.encode
+ , decode = parser.decode
+ , debug = require('debug')('socket.io:client');
+
+/**
+ * Module exports.
+ */
+
+module.exports = Client;
+
+/**
+ * Client constructor.
+ *
+ * @param {Server} server instance
+ * @param {Socket} connection
+ * @api private
+ */
+
+function Client(server, conn){
+ this.server = server;
+ this.conn = conn;
+ this.id = conn.id;
+ this.request = conn.request;
+ this.setup();
+ this.sockets = [];
+ this.nsps = {};
+}
+
+/**
+ * Sets up event listeners.
+ *
+ * @api private
+ */
+
+Client.prototype.setup = function(){
+ this.onclose = this.onclose.bind(this);
+ this.ondata = this.ondata.bind(this);
+ this.conn.on('close', this.onclose);
+ this.conn.on('data', this.ondata);
+};
+
+/**
+ * Connects a client to a namespace.
+ *
+ * @param {String} namespace name
+ * @api private
+ */
+
+Client.prototype.connect = function(name){
+ debug('connecting to namespace %s', name);
+ var nsp = this.server.of(name);
+ var self = this;
+ var sockets = this.sockets;
+ var socket = nsp.add(this, function(){
+ self.sockets.push(socket);
+ self.nsps[nsp.name] = socket;
+ });
+};
+
+/**
+ * Removes a socket. Called by each `Socket`.
+ *
+ * @api private
+ */
+
+Client.prototype.remove = function(socket){
+ var i = this.sockets.indexOf(socket);
+ if (~i) {
+ var nsp = this.sockets[i].nsp.name;
+ this.sockets.splice(i, 1);
+ delete this.nsps[nsp];
+ } else {
+ debug('ignoring remove for %s', socket.id);
+ }
+};
+
+/**
+ * Closes the underlying connection.
+ *
+ * @api private
+ */
+
+Client.prototype.close = function(){
+ if ('open' == this.conn.readyState) {
+ debug('forcing transport close');
+ this.conn.close();
+ this.onclose('forced server close');
+ }
+};
+
+/**
+ * Writes a packet to the transport.
+ *
+ * @param {Object} packet object
+ * @api private
+ */
+
+Client.prototype.packet = function(packet){
+ if ('open' == this.conn.readyState) {
+ debug('writing packet %j', packet);
+ this.conn.write(encode(packet));
+ } else {
+ debug('ignoring packet write %j', packet);
+ }
+};
+
+/**
+ * Called with incoming transport data.
+ *
+ * @api private
+ */
+
+Client.prototype.ondata = function(data){
+ var packet = decode(data.toString());
+ debug('got packet %j', packet);
+
+ if (parser.CONNECT == packet.type) {
+ this.connect(packet.nsp);
+ } else {
+ var socket = this.nsps[packet.nsp];
+ if (socket) {
+ socket.onpacket(packet);
+ } else {
+ debug('no socket for namespace %s', packet.nsp);
+ }
+ }
+};
+
+/**
+ * Called upon transport close.
+ *
+ * @param {String} reason
+ * @api private
+ */
+
+Client.prototype.onclose = function(reason){
+ debug('client close with reason %s', reason);
+
+ // ignore a potential subsequent `close` event
+ this.destroy();
+
+ // `nsps` and `sockets` are cleaned up seamlessly
+ this.sockets.forEach(function(socket){
+ socket.onclose(reason);
+ });
+};
+
+/**
+ * Cleans up event listeners.
+ *
+ * @api private
+ */
+
+Client.prototype.destroy = function(){
+ this.conn.removeListener('data', this.ondata);
+ this.conn.removeListener('close', this.onclose);
+};
View
119 lib/index.js
@@ -0,0 +1,119 @@
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+ , engine = require('engine.io')
+ , Client = require('./client')
+ , Namespace = require('./namespace')
+ , debug = require('debug')('socket.io:server');
+
+/**
+ * Server constructor.
+ *
+ * @param {http.Server|Number|Object} http server, port or options
+ * @param {Object} options
+ * @api public
+ */
+
+function Server(srv, opts){
+ if (!(this instanceof Server)) return new Server(srv, opts);
+ if ('object' == typeof srv && !srv.listen) {
+ opts = srv;
+ srv = null;
+ }
+ opts = opts || {};
+ if (srv) this.attach(srv, opts);
+ this.sockets = this.of('/');
+}
+
+/**
+ * Attaches socket.io to a server or port.
+ *
+ * @param {http.Server|Number} server or port
+ * @param {Object} options
+ * @api public
+ */
+
+Server.prototype.attach = function(srv, opts){
+ if ('number' == typeof srv) {
+ debug('creating engine.io on port %d', srv);
+ srv = engine.listen(srv, opts);
+ } else {
+ debug('creating engine.io instance', opts);
+
+ if ('function' == typeof srv && srv.use) {
+ console.log(
+ '\033[91m' +
+ 'You are trying to attach socket.io to an express app.\n' +
+ 'HTTP long-polling will work, but WebSocket won\'t\n' +
+ 'In order for socket.io to listen to the `upgrade` event\n' +
+ 'you need to pass a Node `http.Server` instance.' +
+ '\033[39m'
+ );
+ }
+
+ srv = engine.attach(srv, opts);
+ }
+ this.bind(srv);
+};
+
+/**
+ * Binds socket.io to an engine.io instance.
+ *
+ * @param {engine.Server} engine.io (or compatible) server
+ * @api public
+ */
+
+Server.prototype.bind = function(engine){
+ this.engine = engine;
+ this.engine.on('connection', this.onconnection.bind(this));
+};
+
+/**
+ * Called with each incoming transport connection.
+ *
+ * @api public
+ */
+
+Server.prototype.onconnection = function(conn){
+ debug('incoming connection with id %s', conn.id);
+ var client = new Client(this, conn);
+ client.connect('/');
+ this.emit('client', client);
+};
+
+/**
+ * Looks up a namespace.
+ *
+ * @param {String} nsp name
+ * @api public
+ */
+
+Server.prototype.of = function(name){
+ if (!this.nsps[name]) {
+ debug('initializing namespace %s', name);
+ var nsp = new Namespace(this, name);
+ this.nsps[name] = nsp;
+ }
+ return this.nsps[name];
+};
+
+/**
+ * Expose main namespace (/).
+ */
+
+['use', 'to', 'in', 'emit', 'send', 'write'].forEach(function(name){
+ Server.prototype[name] = function(){
+ var nsp = this.sockets[name];
+ return nsp.apply(this.sockets, arguments);
+ };
+});
+
+Namespace.flags.forEach(function(flag){
+ Server.prototype.__defineGetter__(flag, function(name){
+ this.flags.push(name);
+ return this;
+ });
+});
View
97 lib/logger.js
@@ -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)));
- };
-});
View
1,020 lib/manager.js
@@ -1,1020 +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')
- , crypto = require('crypto')
- , base64id = require('base64id')
- , util = require('./util')
- , store = require('./store')
- , client = require('socket.io-client')
- , transports = require('./transports')
- , Logger = require('./logger')
- , Socket = require('./socket')
- , MemoryStore = require('./stores/memory')
- , WebSocketServer = require('ws').Server
- , 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) {
- if (options.hasOwnProperty(i)) {
- 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').splice(0);
- 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.hasOwnProperty(i)) {
- if (transports[i].init) {
- transports[i].init(this);
- }
- }
- }
-
- var self = this;
-
- // ws server
- this.ws = new WebSocketServer({
- noServer: true,
- clientTracking: false,
- verifyClient: function(info){
- return self.verifyOrigin({ headers: { origin: info.origin } });
- }
- });
-
- // forward-compatibility with 1.0
- this.sockets.on('connection', function (conn) {
- self.emit('connection', conn);
- });
-
- this.sequenceNumber = Date.now() | 0;
-
- 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.