linda-socket.io
Version:
Linda implementation on Socket.IO
114 lines (96 loc) • 3.88 kB
text/coffeescript
http = require 'http'
path = require 'path'
url = require 'url'
fs = require 'fs'
events = require 'eventemitter2'
socketio = require 'socket.io'
debug = require('debug')('linda-socket.io')
TupleSpace = require path.join(__dirname, 'tuplespace')
Tuple = require path.join(__dirname, 'tuple')
Client = require path.join(__dirname, 'linda-socketio-client')
module.exports.TupleSpace = TupleSpace
module.exports.Tuple = Tuple
module.exports.Client = Client
class Linda extends events.EventEmitter2
constructor: ->
@spaces = {}
fs.readFile path.join(__dirname, 'linda-socketio-client.js'),
(err, data) =>
throw new Error "client js load error" if err
@client_js_code = data
setInterval =>
debug "TupleSpace\tcheck expire"
for name, space of @spaces
if space?
space.check_expire()
debug "TupleSpace\tcheck expire done"
, 60*3*1000 # 3min
tuplespace: (name) ->
return @spaces[name] ||
@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 == "/linda/linda-socket.io.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'] ||
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).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).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
return @
module.exports.Linda = new Linda