From a27e8b9f0578a3bcb409ddb37eaf26315b25f6c5 Mon Sep 17 00:00:00 2001 From: TakumiBaba Date: Thu, 6 Aug 2015 15:09:11 +0900 Subject: [PATCH 1/3] add io modules --- lib/io/socket-io.js | 143 ++++++++++++++++++++++++++++++++++++++++ src/io/socket-io.coffee | 85 ++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 lib/io/socket-io.js create mode 100644 src/io/socket-io.coffee diff --git a/lib/io/socket-io.js b/lib/io/socket-io.js new file mode 100644 index 0000000..17f0b9a --- /dev/null +++ b/lib/io/socket-io.js @@ -0,0 +1,143 @@ +(function() { + var SocketIOModule, debug, events, http, url, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; + + http = require('http'); + + events = require('eventemitter2'); + + url = require('url'); + + debug = require('debug')('linda:io:socket-io'); + + module.exports = SocketIOModule = (function(superClass) { + extend(SocketIOModule, superClass); + + function SocketIOModule() {} + + SocketIOModule.prototype.attach = function(linda) { + this.linda = linda; + this.tuplespace = this.linda.tuplespace.bind(this.linda); + return this; + }; + + SocketIOModule.prototype.listen = function(opts) { + if (opts == null) { + opts = { + io: null, + server: null + }; + } + if (opts.io == null) { + throw new Error('"io" must be instance of Socket.IO'); + } + if (!(opts.server instanceof http.Server)) { + throw new Error('"server" must be instance of http.Server'); + } + this.io = opts.io; + this.server = opts.server; + this.oldListeners = this.server.listeners('request').splice(0); + this.server.removeAllListeners('request'); + this.server.on('request', (function(_this) { + return function(req, res) { + var _url, i, len, listener, ref, results; + _url = url.parse(decodeURI(req.url), true); + if (_url.pathname === "/linda/linda.js") { + debug("GET\t" + _url.pathname); + res.setHeader('Content-Type', 'application/javascript'); + res.writeHead(200); + res.end(_this.client_js_code); + return; + } + ref = _this.oldListeners; + results = []; + for (i = 0, len = ref.length; i < len; i++) { + listener = ref[i]; + results.push(listener.call(_this.server, req, res)); + } + return results; + }; + })(this)); + this.io.sockets.on('connection', (function(_this) { + return function(socket) { + var cids, info, ref, watch_cids; + cids = {}; + info = { + from: socket.handshake.headers['x-forwarded-for'] || ((ref = socket.handshake.address) != null ? ref.address : void 0) + }; + watch_cids = {}; + socket.on('__linda_write', function(data) { + var ref1; + if ((ref1 = data.options) != null) { + ref1.from = info.from; + } + _this.tuplespace(data.tuplespace).write(data.tuple, data.options); + debug("write\t" + (JSON.stringify(data)) + " from " + info.from); + return _this.linda.emit('write', data); + }); + socket.on('__linda_take', function(data) { + var cid; + cid = _this.tuplespace(data.tuplespace).option(data.options).take(data.tuple, function(err, tuple) { + cid = null; + return socket.emit("__linda_take_" + data.id, err, tuple); + }); + cids[data.id] = cid; + debug("take\t" + (JSON.stringify(data)) + " from " + info.from); + _this.linda.emit('take', data); + return socket.once('disconnect', function() { + if (cid) { + return _this.tuplespace(data.tuplespace).cancel(cid); + } + }); + }); + socket.on('__linda_read', function(data) { + var cid; + cid = _this.tuplespace(data.tuplespace).option(data.options).read(data.tuple, function(err, tuple) { + cid = null; + return socket.emit("__linda_read_" + data.id, err, tuple); + }); + cids[data.id] = cid; + debug("read\t" + (JSON.stringify(data)) + " from " + info.from); + _this.linda.emit('read', data); + return socket.once('disconnect', function() { + if (cid) { + return _this.tuplespace(data.tuplespace).cancel(cid); + } + }); + }); + watch_cids = {}; + socket.on('__linda_watch', function(data) { + var cid; + debug("watch\t" + (JSON.stringify(data)) + " from " + info.from); + _this.linda.emit('watch', data); + if (watch_cids[data.id]) { + return; + } + watch_cids[data.id] = true; + cid = _this.tuplespace(data.tuplespace).watch(data.tuple, function(err, tuple) { + return socket.emit("__linda_watch_" + data.id, err, tuple); + }); + cids[data.id] = cid; + return socket.once('disconnect', function() { + if (cid) { + return _this.tuplespace(data.tuplespace).cancel(cid); + } + }); + }); + return socket.on('__linda_cancel', function(data) { + debug("cancel\t" + (JSON.stringify(data)) + " from " + info.from); + _this.linda.emit('cancel', data); + _this.tuplespace(data.tuplespace).cancel(cids[data.id]); + return watch_cids[data.id] = false; + }); + }; + })(this)); + return this; + }; + + return SocketIOModule; + + })(events.EventEmitter2); + +}).call(this); diff --git a/src/io/socket-io.coffee b/src/io/socket-io.coffee new file mode 100644 index 0000000..35c19f8 --- /dev/null +++ b/src/io/socket-io.coffee @@ -0,0 +1,85 @@ +http = require 'http' +events = require 'eventemitter2' +url = require 'url' +debug = require('debug')('linda:io:socket-io') + +module.exports = class SocketIOModule extends events.EventEmitter2 + constructor: -> + + attach: (@linda) -> + @tuplespace = @linda.tuplespace.bind(@linda) + return @ + + listen: (opts = {io: null, server: null}) -> + unless opts.io? + throw new Error '"io" must be instance of Socket.IO' + unless opts.server instanceof http.Server + throw new Error '"server" must be instance of http.Server' + @io = opts.io + @server = opts.server + + @oldListeners = @server.listeners('request').splice(0) + @server.removeAllListeners 'request' + @server.on 'request', (req, res) => ## intercept requests + _url = url.parse(decodeURI(req.url), true) + if _url.pathname is "/linda/linda.js" + debug "GET\t#{_url.pathname}" + res.setHeader 'Content-Type', 'application/javascript' + res.writeHead 200 + res.end @client_js_code + return + for listener in @oldListeners + listener.call(@server, req, res) + + @io.sockets.on 'connection', (socket) => + cids = {} + info = { + from: (socket.handshake.headers['x-forwarded-for'] or + socket.handshake.address?.address) + } + watch_cids = {} + socket.on '__linda_write', (data) => + data.options?.from = info.from + @tuplespace(data.tuplespace).write data.tuple, data.options + debug "write\t#{JSON.stringify data} from #{info.from}" + @linda.emit 'write', data + + socket.on '__linda_take', (data) => + cid = @tuplespace(data.tuplespace).option(data.options).take data.tuple, (err, tuple) -> + cid = null + socket.emit "__linda_take_#{data.id}", err, tuple + cids[data.id] = cid + debug "take\t#{JSON.stringify data} from #{info.from}" + @linda.emit 'take', data + socket.once 'disconnect', => + @tuplespace(data.tuplespace).cancel cid if cid + + socket.on '__linda_read', (data) => + cid = @tuplespace(data.tuplespace).option(data.options).read data.tuple, (err, tuple) -> + cid = null + socket.emit "__linda_read_#{data.id}", err, tuple + cids[data.id] = cid + debug "read\t#{JSON.stringify data} from #{info.from}" + @linda.emit 'read', data + socket.once 'disconnect', => + @tuplespace(data.tuplespace).cancel cid if cid + + watch_cids = {} + socket.on '__linda_watch', (data) => + debug "watch\t#{JSON.stringify data} from #{info.from}" + @linda.emit 'watch', data + return if watch_cids[data.id] # not watch if already watching + watch_cids[data.id] = true + cid = @tuplespace(data.tuplespace).watch data.tuple, (err, tuple) -> + socket.emit "__linda_watch_#{data.id}", err, tuple + cids[data.id] = cid + socket.once 'disconnect', => + @tuplespace(data.tuplespace).cancel cid if cid + + socket.on '__linda_cancel', (data) => + debug "cancel\t#{JSON.stringify data} from #{info.from}" + @linda.emit 'cancel', data + @tuplespace(data.tuplespace).cancel cids[data.id] + watch_cids[data.id] = false + + return @ From fb14439845dc3e7d625ca11b337ebae962aa2fd0 Mon Sep 17 00:00:00 2001 From: TakumiBaba Date: Thu, 6 Aug 2015 15:09:33 +0900 Subject: [PATCH 2/3] separate io module - remove socketio controller from linda.coffee - implements attach method - implements socketio controller module --- lib/linda-client.js | 24 ++++---- lib/linda.js | 140 +++++++------------------------------------- lib/tuple.js | 12 ++-- lib/tuplespace.js | 64 ++++++++++---------- src/linda.coffee | 80 +++---------------------- 5 files changed, 79 insertions(+), 241 deletions(-) diff --git a/lib/linda-client.js b/lib/linda-client.js index bae716c..2507c7b 100644 --- a/lib/linda-client.js +++ b/lib/linda-client.js @@ -18,9 +18,9 @@ })(); TupleSpace = (function() { - function TupleSpace(linda, name) { + function TupleSpace(linda, name1) { this.linda = linda; - this.name = name; + this.name = name1; this.watch_callback_ids = {}; this.io_callbacks = []; this.linda.io.on('disconnect', (function(_this) { @@ -45,10 +45,10 @@ }; TupleSpace.prototype.remove_io_callbacks = function() { - var c, _i, _len, _ref; - _ref = this.io_callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - c = _ref[_i]; + var c, j, len, ref; + ref = this.io_callbacks; + for (j = 0, len = ref.length; j < len; j++) { + c = ref[j]; this.linda.io.removeListener(c.name, c.listener); } return this.io_callbacks = []; @@ -109,18 +109,18 @@ } return setTimeout((function(_this) { return function() { - var c, i, _i, _ref, _results; - _results = []; - for (i = _i = _ref = _this.io_callbacks.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) { + var c, i, j, ref, results; + results = []; + for (i = j = ref = _this.io_callbacks.length - 1; ref <= 0 ? j <= 0 : j >= 0; i = ref <= 0 ? ++j : --j) { c = _this.io_callbacks[i]; if (c.name.match(new RegExp("_" + id + "$"))) { _this.linda.io.removeListener(c.name, c.listener); - _results.push(_this.io_callbacks.splice(i, 1)); + results.push(_this.io_callbacks.splice(i, 1)); } else { - _results.push(void 0); + results.push(void 0); } } - return _results; + return results; }; })(this), 100); }; diff --git a/lib/linda.js b/lib/linda.js index 24489c1..f6572dc 100644 --- a/lib/linda.js +++ b/lib/linda.js @@ -1,7 +1,7 @@ (function() { - var Client, Linda, Tuple, TupleSpace, debug, events, fs, http, path, request, socketio, url, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + var Client, Linda, SocketIOModule, Tuple, TupleSpace, debug, events, fs, http, path, request, socketio, url, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; http = require('http'); @@ -25,14 +25,16 @@ Client = require(path.join(__dirname, 'linda-client')); + SocketIOModule = require(path.join(__dirname, 'io/socket-io')); + module.exports.TupleSpace = TupleSpace; module.exports.Tuple = Tuple; module.exports.Client = Client; - Linda = (function(_super) { - __extends(Linda, _super); + Linda = (function(superClass) { + extend(Linda, superClass); function Linda() { this.spaces = {}; @@ -46,11 +48,11 @@ })(this)); setInterval((function(_this) { return function() { - var name, space, _ref; + var name, ref, space; debug("TupleSpace\tcheck expire"); - _ref = _this.spaces; - for (name in _ref) { - space = _ref[name]; + ref = _this.spaces; + for (name in ref) { + space = ref[name]; if (space != null) { space.check_expire(); } @@ -64,119 +66,19 @@ return this.spaces[name] || (this.spaces[name] = new TupleSpace(name)); }; - Linda.prototype.listen = function(opts) { - if (opts == null) { - opts = { - io: null, - server: null - }; - } - if (opts.io == null) { - throw new Error('"io" must be instance of Socket.IO'); - } - if (!(opts.server instanceof http.Server)) { - throw new Error('"server" must be instance of http.Server'); - } - this.io = opts.io; - this.server = opts.server; - this.oldListeners = this.server.listeners('request').splice(0); - this.server.removeAllListeners('request'); - this.server.on('request', (function(_this) { - return function(req, res) { - var listener, _i, _len, _ref, _results, _url; - _url = url.parse(decodeURI(req.url), true); - if (_url.pathname === "/linda/linda.js") { - debug("GET\t" + _url.pathname); - res.setHeader('Content-Type', 'application/javascript'); - res.writeHead(200); - res.end(_this.client_js_code); - return; - } - _ref = _this.oldListeners; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - listener = _ref[_i]; - _results.push(listener.call(_this.server, req, res)); - } - return _results; - }; - })(this)); - this.io.sockets.on('connection', (function(_this) { - return function(socket) { - var cids, info, watch_cids, _ref; - cids = {}; - info = { - from: socket.handshake.headers['x-forwarded-for'] || ((_ref = socket.handshake.address) != null ? _ref.address : void 0) - }; - socket.on('__linda_write', function(data) { - var _ref1; - if ((_ref1 = data.options) != null) { - _ref1.from = info.from; - } - _this.tuplespace(data.tuplespace).write(data.tuple, data.options); - debug("write\t" + (JSON.stringify(data)) + " from " + info.from); - return _this.emit('write', data); - }); - socket.on('__linda_take', function(data) { - var cid; - cid = _this.tuplespace(data.tuplespace).option(data.options).take(data.tuple, function(err, tuple) { - cid = null; - return socket.emit("__linda_take_" + data.id, err, tuple); - }); - cids[data.id] = cid; - debug("take\t" + (JSON.stringify(data)) + " from " + info.from); - _this.emit('take', data); - return socket.once('disconnect', function() { - if (cid) { - return _this.tuplespace(data.tuplespace).cancel(cid); - } - }); - }); - socket.on('__linda_read', function(data) { - var cid; - cid = _this.tuplespace(data.tuplespace).option(data.options).read(data.tuple, function(err, tuple) { - cid = null; - return socket.emit("__linda_read_" + data.id, err, tuple); - }); - cids[data.id] = cid; - debug("read\t" + (JSON.stringify(data)) + " from " + info.from); - _this.emit('read', data); - return socket.once('disconnect', function() { - if (cid) { - return _this.tuplespace(data.tuplespace).cancel(cid); - } - }); - }); - watch_cids = {}; - socket.on('__linda_watch', function(data) { - var cid; - debug("watch\t" + (JSON.stringify(data)) + " from " + info.from); - _this.emit('watch', data); - if (watch_cids[data.id]) { - return; - } - watch_cids[data.id] = true; - cid = _this.tuplespace(data.tuplespace).watch(data.tuple, function(err, tuple) { - return socket.emit("__linda_watch_" + data.id, err, tuple); - }); - cids[data.id] = cid; - return socket.once('disconnect', function() { - if (cid) { - return _this.tuplespace(data.tuplespace).cancel(cid); - } - }); - }); - return socket.on('__linda_cancel', function(data) { - debug("cancel\t" + (JSON.stringify(data)) + " from " + info.from); - _this.emit('cancel', data); - _this.tuplespace(data.tuplespace).cancel(cids[data.id]); - return watch_cids[data.id] = false; - }); - }; - })(this)); + Linda.prototype.attach = function(io) { + this.io = io; + this.io.attach(this); return this; }; + Linda.prototype.listen = function() { + if (this.io == null) { + this.attach(new SocketIOModule()); + } + return this.io.listen(arguments[0]); + }; + return Linda; })(events.EventEmitter2); diff --git a/lib/tuple.js b/lib/tuple.js index b7ee208..1cb2eed 100644 --- a/lib/tuple.js +++ b/lib/tuple.js @@ -13,8 +13,8 @@ expire: 300 }; - function Tuple(data) { - this.data = data; + function Tuple(data1) { + this.data = data1; this.__defineSetter__('expire', function(sec) { return this.expire_at = Math.floor(Date.now() / 1000) + sec; }); @@ -22,14 +22,14 @@ } Tuple.prototype.match = function(tuple) { - var data, k, v, _ref; + var data, k, ref, v; if (!Tuple.isHash(tuple)) { return false; } data = tuple instanceof Tuple ? tuple.data : tuple; - _ref = this.data; - for (k in _ref) { - v = _ref[k]; + ref = this.data; + for (k in ref) { + v = ref[k]; if (typeof v === 'object') { if (typeof data[k] !== 'object') { return false; diff --git a/lib/tuplespace.js b/lib/tuplespace.js index 5f03915..1029f3d 100644 --- a/lib/tuplespace.js +++ b/lib/tuplespace.js @@ -20,7 +20,7 @@ }; TupleSpace.prototype.write = function(tuple, options) { - var c, called, i, taked, _i, _j, _ref; + var c, called, i, j, l, ref, taked; if (options == null) { options = { expire: Tuple.DEFAULT.expire @@ -36,7 +36,7 @@ tuple.from = options.from; called = []; taked = false; - for (i = _i = 0, _ref = this.callbacks.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + for (i = j = 0, ref = this.callbacks.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { c = this.callbacks[i]; if (c.tuple.match(tuple)) { if (c.type === 'take' || c.type === 'read') { @@ -53,8 +53,8 @@ } } } - for (_j = called.length - 1; _j >= 0; _j += -1) { - i = called[_j]; + for (l = called.length - 1; l >= 0; l += -1) { + i = called[l]; this.callbacks.splice(i, 1); } if (!taked) { @@ -99,11 +99,11 @@ }; TupleSpace.prototype.cancel = function(id) { - var c, i, _i, _ref; + var c, i, j, ref; if (id == null) { return; } - for (i = _i = 0, _ref = this.callbacks.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + for (i = j = 0, ref = this.callbacks.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { c = this.callbacks[i]; if (id === c.id) { setImmediate(function() { @@ -116,15 +116,15 @@ }; TupleSpace.prototype.check_expire = function() { - var expires, i, _i, _j, _ref; + var expires, i, j, l, ref; expires = []; - for (i = _i = 0, _ref = this.tuples.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + for (i = j = 0, ref = this.tuples.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { if (this.tuples[i].expire_at < Date.now() / 1000) { expires.push(i); } } - for (_j = expires.length - 1; _j >= 0; _j += -1) { - i = expires[_j]; + for (l = expires.length - 1; l >= 0; l += -1) { + i = expires[l]; this.tuples.splice(i, 1); } return expires.length; @@ -141,10 +141,10 @@ sort: 'stack' }; - function ReadTakeOption(ts, opts) { + function ReadTakeOption(ts, opts1) { var k, v; this.ts = ts; - this.opts = opts != null ? opts : {}; + this.opts = opts1 != null ? opts1 : {}; for (k in DEFAULT) { v = DEFAULT[k]; if (!this.opts.hasOwnProperty(k)) { @@ -154,7 +154,7 @@ } ReadTakeOption.prototype.read = function(tuple, callback) { - var i, id, seq, t, _i, _len; + var i, id, j, len, seq, t; if (typeof callback !== 'function') { return; } @@ -168,24 +168,24 @@ tuple = new Tuple(tuple); } seq = (function() { - var _i, _j, _ref, _ref1, _results, _results1; + var j, l, ref, ref1, results, results1; switch (this.opts.sort) { case 'queue': return (function() { - _results = []; - for (var _i = 0, _ref = this.ts.size - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } - return _results; + results = []; + for (var j = 0, ref = this.ts.size - 1; 0 <= ref ? j <= ref : j >= ref; 0 <= ref ? j++ : j--){ results.push(j); } + return results; }).apply(this); case 'stack': return (function() { - _results1 = []; - for (var _j = _ref1 = this.ts.size - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); } - return _results1; + results1 = []; + for (var l = ref1 = this.ts.size - 1; ref1 <= 0 ? l <= 0 : l >= 0; ref1 <= 0 ? l++ : l--){ results1.push(l); } + return results1; }).apply(this); } }).call(this); - for (_i = 0, _len = seq.length; _i < _len; _i++) { - i = seq[_i]; + for (j = 0, len = seq.length; j < len; j++) { + i = seq[j]; t = this.ts.tuples[i]; if (tuple.match(t)) { setImmediate(function() { @@ -205,7 +205,7 @@ }; ReadTakeOption.prototype.take = function(tuple, callback) { - var i, id, seq, t, _i, _len; + var i, id, j, len, seq, t; if (typeof callback !== 'function') { return; } @@ -219,24 +219,24 @@ tuple = new Tuple(tuple); } seq = (function() { - var _i, _j, _ref, _ref1, _results, _results1; + var j, l, ref, ref1, results, results1; switch (this.opts.sort) { case 'queue': return (function() { - _results = []; - for (var _i = 0, _ref = this.ts.size - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } - return _results; + results = []; + for (var j = 0, ref = this.ts.size - 1; 0 <= ref ? j <= ref : j >= ref; 0 <= ref ? j++ : j--){ results.push(j); } + return results; }).apply(this); case 'stack': return (function() { - _results1 = []; - for (var _j = _ref1 = this.ts.size - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); } - return _results1; + results1 = []; + for (var l = ref1 = this.ts.size - 1; ref1 <= 0 ? l <= 0 : l >= 0; ref1 <= 0 ? l++ : l--){ results1.push(l); } + return results1; }).apply(this); } }).call(this); - for (_i = 0, _len = seq.length; _i < _len; _i++) { - i = seq[_i]; + for (j = 0, len = seq.length; j < len; j++) { + i = seq[j]; t = this.ts.tuples[i]; if (tuple.match(t)) { setImmediate(function() { diff --git a/src/linda.coffee b/src/linda.coffee index 97459d2..ba28981 100644 --- a/src/linda.coffee +++ b/src/linda.coffee @@ -10,6 +10,7 @@ debug = require('debug')('linda') TupleSpace = require path.join(__dirname, 'tuplespace') Tuple = require path.join(__dirname, 'tuple') Client = require path.join(__dirname, 'linda-client') +SocketIOModule = require path.join(__dirname, 'io/socket-io') module.exports.TupleSpace = TupleSpace module.exports.Tuple = Tuple @@ -36,79 +37,14 @@ class Linda extends events.EventEmitter2 return @spaces[name] or @spaces[name] = new TupleSpace(name) - listen: (opts = {io: null, server: null}) -> - unless opts.io? - throw new Error '"io" must be instance of Socket.IO' - unless opts.server instanceof http.Server - throw new Error '"server" must be instance of http.Server' - @io = opts.io - @server = opts.server - - @oldListeners = @server.listeners('request').splice(0) - @server.removeAllListeners 'request' - @server.on 'request', (req, res) => ## intercept requests - _url = url.parse(decodeURI(req.url), true) - if _url.pathname is "/linda/linda.js" - debug "GET\t#{_url.pathname}" - res.setHeader 'Content-Type', 'application/javascript' - res.writeHead 200 - res.end @client_js_code - return - for listener in @oldListeners - listener.call(@server, req, res) - - @io.sockets.on 'connection', (socket) => - cids = {} - info = { - from: (socket.handshake.headers['x-forwarded-for'] or - socket.handshake.address?.address) - } - - socket.on '__linda_write', (data) => - data.options?.from = info.from - @tuplespace(data.tuplespace).write data.tuple, data.options - debug "write\t#{JSON.stringify data} from #{info.from}" - @emit 'write', data - - socket.on '__linda_take', (data) => - cid = @tuplespace(data.tuplespace).option(data.options).take data.tuple, (err, tuple) -> - cid = null - socket.emit "__linda_take_#{data.id}", err, tuple - cids[data.id] = cid - debug "take\t#{JSON.stringify data} from #{info.from}" - @emit 'take', data - socket.once 'disconnect', => - @tuplespace(data.tuplespace).cancel cid if cid - - socket.on '__linda_read', (data) => - cid = @tuplespace(data.tuplespace).option(data.options).read data.tuple, (err, tuple) -> - cid = null - socket.emit "__linda_read_#{data.id}", err, tuple - cids[data.id] = cid - debug "read\t#{JSON.stringify data} from #{info.from}" - @emit 'read', data - socket.once 'disconnect', => - @tuplespace(data.tuplespace).cancel cid if cid - - watch_cids = {} - socket.on '__linda_watch', (data) => - debug "watch\t#{JSON.stringify data} from #{info.from}" - @emit 'watch', data - return if watch_cids[data.id] # not watch if already watching - watch_cids[data.id] = true - cid = @tuplespace(data.tuplespace).watch data.tuple, (err, tuple) -> - socket.emit "__linda_watch_#{data.id}", err, tuple - cids[data.id] = cid - socket.once 'disconnect', => - @tuplespace(data.tuplespace).cancel cid if cid - - socket.on '__linda_cancel', (data) => - debug "cancel\t#{JSON.stringify data} from #{info.from}" - @emit 'cancel', data - @tuplespace(data.tuplespace).cancel cids[data.id] - watch_cids[data.id] = false - + attach: (@io) -> + @io.attach @ return @ + listen: -> + unless @io? + # set default IO module + @attach(new SocketIOModule()) + @io.listen arguments[0] module.exports.Server = new Linda From d05a06fa347d2551bfc99564fc88bdde049c4a94 Mon Sep 17 00:00:00 2001 From: TakumiBaba Date: Thu, 6 Aug 2015 15:11:48 +0900 Subject: [PATCH 3/3] github issue #23