Permalink
Browse files

Add socket.io

  • Loading branch information...
1 parent 532502c commit 1fb9620ef73a59b1b81b0af28b9116d36613cc81 @ixti ixti committed Apr 17, 2012
Showing with 139 additions and 49 deletions.
  1. +122 −48 lib/init/http_server.js
  2. +2 −1 package.json
  3. +10 −0 server/common/test.js
  4. +5 −0 views/desktop/layouts/default.jade
View
@@ -9,7 +9,8 @@ var NLib = require('nlib');
// 3rd-party
-var connect = require('connect');
+var connect = require('connect');
+var socket_io = require('socket.io');
// HELPERS /////////////////////////////////////////////////////////////////////
@@ -26,52 +27,7 @@ function find_view(scope, api_path) {
}
-function start_server(app, next) {
- var server, host, port, err_handler;
-
- // create server
- host = nodeca.config.listen.host || 'localhost';
- port = nodeca.config.listen.port || 3000;
- server = require('http').createServer(app);
-
- err_handler = function (err) {
- var err_prefix = "Can't bind to <" + host + "> with port <" + port + ">: ";
-
- if ('EADDRINUSE' === err.code) {
- next(err_prefix + 'Address in use...');
- return;
- }
-
- if ('EADDRNOTAVAIL' === err.code) {
- // system has no such ip address
- next(err_prefix + 'Address is not available...');
- return;
- }
-
- if ('ENOENT' === err.code) {
- // failed resolve hostname to ip address
- next(err_prefix + "Failed to resolve IP address...");
- return;
- }
-
- // unexpected / unknown error
- next(err_prefix + err);
- };
-
- server.on('error', err_handler);
-
- // start server
- server.listen(port, host, function () {
- server.removeListener('error', err_handler);
- next();
- });
-}
-
-
-// MODULE EXPORTS //////////////////////////////////////////////////////////////
-
-
-module.exports = function (next) {
+function attach_connect_app(server) {
var app = connect(), static_helpers;
app.use("/assets/", nodeca.runtime.assets_server.middleware);
@@ -178,5 +134,123 @@ module.exports = function (next) {
}, env); // nodeca.filters.run
});
- start_server(app, next);
+ // connect application is a simple HTTP(S) request event handler
+ server.on('request', app);
+}
+
+
+function attach_socket_io(server) {
+ var methods = {}, noop = function () {};
+
+ (function traverse(obj, prefix) {
+ _.each(obj, function (val, key) {
+ if (_.isFunction(val)) {
+ methods[prefix + key] = val;
+ return;
+ }
+
+ traverse(val, key + '.');
+ });
+ }(nodeca.server, ''));
+
+ socket_io.listen(server).sockets.on('connection', function (socket) {
+ socket.on('call', function (name, params, cb) {
+ var env, fn = methods[name];
+
+ if (!fn) {
+ (cb || noop)(new Error('Unknown server method: ' + name));
+ return;
+ }
+
+ // prefill environment
+ env = {
+ request: {
+ origin: 'RT',
+ method: name,
+ namespace: name.split('.').shift()
+ },
+ session: {
+ // FIXME: use req.session instead
+ theme: 'desktop',
+ lang: nodeca.config.locales.default
+ },
+ response: {
+ err: {
+ code: null,
+ message: null
+ },
+ data: {},
+ layout: 'default',
+ view: name
+ }
+ };
+
+ nodeca.filters.run(name, params, fn, function (err) {
+ (cb || noop)(err, env.response);
+ }, env);
+ });
+ });
+}
+
+
+function start_server(next) {
+ var server, host, port, err_handler;
+
+ // create server
+ host = nodeca.config.listen.host || 'localhost';
+ port = nodeca.config.listen.port || 3000;
+ server = require('http').createServer();
+
+ err_handler = function (err) {
+ var err_prefix = "Can't bind to <" + host + "> with port <" + port + ">: ";
+
+ if ('EADDRINUSE' === err.code) {
+ next(err_prefix + 'Address in use...');
+ return;
+ }
+
+ if ('EADDRNOTAVAIL' === err.code) {
+ // system has no such ip address
+ next(err_prefix + 'Address is not available...');
+ return;
+ }
+
+ if ('ENOENT' === err.code) {
+ // failed resolve hostname to ip address
+ next(err_prefix + "Failed to resolve IP address...");
+ return;
+ }
+
+ // unexpected / unknown error
+ next(err_prefix + err);
+ };
+
+ server.on('error', err_handler);
+
+ // start server
+ server.listen(port, host, function () {
+ server.removeListener('error', err_handler);
+ next(null, server);
+ });
+}
+
+
+// MODULE EXPORTS //////////////////////////////////////////////////////////////
+
+
+module.exports = function (next) {
+ start_server(function (err, server) {
+ if (err) {
+ next(err);
+ return;
+ }
+
+ // Socket.IO removes and then wraps event listeners from the server,
+ // so it should be attached after connect applcation.
+
+ attach_connect_app(server);
+ attach_socket_io(server);
+
+ next();
+ });
};
View
@@ -17,7 +17,8 @@
"redis" : "0.7.1",
"mongoose" : "2.5.9",
"static-lulz" : "git://github.com/nodeca/static-lulz.git",
- "connect" : "git://github.com/senchalabs/connect.git"
+ "connect" : "git://github.com/senchalabs/connect.git",
+ "socket.io" : "0.9.5"
},
"devDependencies" : {
"vows": "~ 0.6.0"
View
@@ -0,0 +1,10 @@
+"use strict";
+
+
+/*global nodeca*/
+
+
+module.exports = function (params, callback) {
+ this.response.data = params;
+ callback();
+};
@@ -10,6 +10,11 @@ html
#contents!= content
// TODO: replace with helpers?
+ script(src='/socket.io/socket.io.js')
script(src="/assets/system/common/api.js")
script(src="/assets/system/forum/api.js")
script(src="/assets/system/blogs/api.js")
+
+ script
+ // TODO: Replace with bundled kickstarter
+ nodeca.runtime = {socket_io: io.connect()};

0 comments on commit 1fb9620

Please sign in to comment.