UNPKG

6.75 kBJavaScriptView Raw
1(function() {
2 var Client, Linda, Tuple, TupleSpace, debug, events, fs, http, path, request, socketio, url,
3 __hasProp = {}.hasOwnProperty,
4 __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; };
5
6 http = require('http');
7
8 path = require('path');
9
10 url = require('url');
11
12 fs = require('fs');
13
14 request = require('request');
15
16 events = require('eventemitter2');
17
18 socketio = require('socket.io');
19
20 debug = require('debug')('linda');
21
22 TupleSpace = require(path.join(__dirname, 'tuplespace'));
23
24 Tuple = require(path.join(__dirname, 'tuple'));
25
26 Client = require(path.join(__dirname, 'linda-client'));
27
28 module.exports.TupleSpace = TupleSpace;
29
30 module.exports.Tuple = Tuple;
31
32 module.exports.Client = Client;
33
34 Linda = (function(_super) {
35 __extends(Linda, _super);
36
37 function Linda() {
38 this.spaces = {};
39 fs.readFile(path.join(__dirname, 'linda-client.js'), (function(_this) {
40 return function(err, data) {
41 if (err) {
42 throw new Error("client js load error");
43 }
44 return _this.client_js_code = data;
45 };
46 })(this));
47 setInterval((function(_this) {
48 return function() {
49 var name, space, _ref;
50 debug("TupleSpace\tcheck expire");
51 _ref = _this.spaces;
52 for (name in _ref) {
53 space = _ref[name];
54 if (space != null) {
55 space.check_expire();
56 }
57 }
58 return debug("TupleSpace\tcheck expire done");
59 };
60 })(this), 60 * 3 * 1000);
61 this.tuplespace('__linda').watch({
62 type: 'keepalive'
63 }, function(err, tuple) {
64 if (err || (tuple.data.to == null)) {
65 return;
66 }
67 if (/^https?:\/\/.+/.test(tuple.data.to)) {
68 return request("" + tuple.data.to + "?keepalive=" + (Date.now()));
69 }
70 });
71 }
72
73 Linda.prototype.tuplespace = function(name) {
74 return this.spaces[name] || (this.spaces[name] = new TupleSpace(name));
75 };
76
77 Linda.prototype.listen = function(opts) {
78 if (opts == null) {
79 opts = {
80 io: null,
81 server: null
82 };
83 }
84 if (opts.io == null) {
85 throw new Error('"io" must be instance of Socket.IO');
86 }
87 if (!(opts.server instanceof http.Server)) {
88 throw new Error('"server" must be instance of http.Server');
89 }
90 this.io = opts.io;
91 this.server = opts.server;
92 this.oldListeners = this.server.listeners('request').splice(0);
93 this.server.removeAllListeners('request');
94 this.server.on('request', (function(_this) {
95 return function(req, res) {
96 var listener, _i, _len, _ref, _results, _url;
97 _url = url.parse(decodeURI(req.url), true);
98 if (_url.pathname === "/linda/linda.js") {
99 debug("GET\t" + _url.pathname);
100 res.setHeader('Content-Type', 'application/javascript');
101 res.writeHead(200);
102 res.end(_this.client_js_code);
103 return;
104 }
105 _ref = _this.oldListeners;
106 _results = [];
107 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
108 listener = _ref[_i];
109 _results.push(listener.call(_this.server, req, res));
110 }
111 return _results;
112 };
113 })(this));
114 this.io.sockets.on('connection', (function(_this) {
115 return function(socket) {
116 var cids, info, watch_cids, _ref;
117 cids = {};
118 info = {
119 from: socket.handshake.headers['x-forwarded-for'] || ((_ref = socket.handshake.address) != null ? _ref.address : void 0)
120 };
121 socket.on('__linda_write', function(data) {
122 var _ref1;
123 if ((_ref1 = data.options) != null) {
124 _ref1.from = info.from;
125 }
126 _this.tuplespace(data.tuplespace).write(data.tuple, data.options);
127 debug("write\t" + (JSON.stringify(data)) + " from " + info.from);
128 return _this.emit('write', data);
129 });
130 socket.on('__linda_take', function(data) {
131 var cid;
132 cid = _this.tuplespace(data.tuplespace).take(data.tuple, function(err, tuple) {
133 cid = null;
134 return socket.emit("__linda_take_" + data.id, err, tuple);
135 });
136 cids[data.id] = cid;
137 debug("take\t" + (JSON.stringify(data)) + " from " + info.from);
138 _this.emit('take', data);
139 return socket.once('disconnect', function() {
140 if (cid) {
141 return _this.tuplespace(data.tuplespace).cancel(cid);
142 }
143 });
144 });
145 socket.on('__linda_read', function(data) {
146 var cid;
147 cid = _this.tuplespace(data.tuplespace).read(data.tuple, function(err, tuple) {
148 cid = null;
149 return socket.emit("__linda_read_" + data.id, err, tuple);
150 });
151 cids[data.id] = cid;
152 debug("read\t" + (JSON.stringify(data)) + " from " + info.from);
153 _this.emit('read', data);
154 return socket.once('disconnect', function() {
155 if (cid) {
156 return _this.tuplespace(data.tuplespace).cancel(cid);
157 }
158 });
159 });
160 watch_cids = {};
161 socket.on('__linda_watch', function(data) {
162 var cid;
163 debug("watch\t" + (JSON.stringify(data)) + " from " + info.from);
164 _this.emit('watch', data);
165 if (watch_cids[data.id]) {
166 return;
167 }
168 watch_cids[data.id] = true;
169 cid = _this.tuplespace(data.tuplespace).watch(data.tuple, function(err, tuple) {
170 return socket.emit("__linda_watch_" + data.id, err, tuple);
171 });
172 cids[data.id] = cid;
173 return socket.once('disconnect', function() {
174 if (cid) {
175 return _this.tuplespace(data.tuplespace).cancel(cid);
176 }
177 });
178 });
179 return socket.on('__linda_cancel', function(data) {
180 debug("cancel\t" + (JSON.stringify(data)) + " from " + info.from);
181 _this.emit('cancel', data);
182 _this.tuplespace(data.tuplespace).cancel(cids[data.id]);
183 return watch_cids[data.id] = false;
184 });
185 };
186 })(this));
187 return this;
188 };
189
190 return Linda;
191
192 })(events.EventEmitter2);
193
194 module.exports.Server = new Linda;
195
196}).call(this);