Created
October 28, 2011 16:56
-
-
Save corruptmem/1322763 to your computer and use it in GitHub Desktop.
Post coffee-compilation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
var ClientState, util, uuid; | |
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; | |
uuid = require("node-uuid"); | |
util = require('util'); | |
ClientState = (function() { | |
function ClientState(client_id, redis, amqp, exch, send, terminate) { | |
this.client_id = client_id; | |
this.redis = redis; | |
this.amqp = amqp; | |
this.exch = exch; | |
this.send = send; | |
this.terminate = terminate; | |
this.cGoodbye = __bind(this.cGoodbye, this); | |
this.cConfirmMessage = __bind(this.cConfirmMessage, this); | |
this.cSendMessage = __bind(this.cSendMessage, this); | |
this.cSetInfo = __bind(this.cSetInfo, this); | |
this.cAuthenticate = __bind(this.cAuthenticate, this); | |
this.cResumeSession = __bind(this.cResumeSession, this); | |
this.cStartSession = __bind(this.cStartSession, this); | |
this.rPresenceNotification = __bind(this.rPresenceNotification, this); | |
this.rReject = __bind(this.rReject, this); | |
this.rConfirm = __bind(this.rConfirm, this); | |
this.rMessage = __bind(this.rMessage, this); | |
this.disconnected = __bind(this.disconnected, this); | |
this.clientMessage = __bind(this.clientMessage, this); | |
this.rabbitMessage = __bind(this.rabbitMessage, this); | |
this.authenticated = false; | |
this.outstandingMessages = false; | |
} | |
ClientState.prototype.rabbitMessage = function(message, headers, deliveryInfo) { | |
switch (message.type) { | |
case 'info': | |
if (message.user !== this.user) { | |
this.rPresenceNotification(message); | |
} | |
return this.q.shift(); | |
case 'message': | |
return this.rMessage(message); | |
case 'confirm': | |
this.rConfirm(message); | |
return this.q.shift(); | |
default: | |
util.log("Unknown message: " + message.type); | |
return this.q.reject(false); | |
} | |
}; | |
ClientState.prototype.clientMessage = function(msg, data) { | |
switch (msg) { | |
case "CNXS": | |
return this.cStartSession(data); | |
case "CNXR": | |
return this.cResumeSession(data); | |
case "AUTH": | |
return this.cAuthenticate(data); | |
case "INFO": | |
return this.cSetInfo(data); | |
case "SMSG": | |
return this.cSendMessage(data); | |
case "CONF": | |
return this.cConfirmMessage(data); | |
case "GBYE": | |
return this.cGoodbye(data); | |
} | |
}; | |
ClientState.prototype.disconnected = function() { | |
var finalCheck; | |
util.log("disconnected"); | |
this.status = "inaccessible"; | |
if ((this.q != null) && (this.q_ctag != null)) { | |
this.q.unsubscribe(this.q_ctag); | |
} | |
this.redis.set("info-" + this.user, JSON.stringify({ | |
user: this.user, | |
status: this.status, | |
display: this.display | |
})); | |
this.redis.expire("msgid-" + this.s_uuid, this.s_timeout); | |
this.exch.publish(this.user + ".info", { | |
type: 'info', | |
user: this.user, | |
status: this.status, | |
display: this.display | |
}); | |
finalCheck = __bind(function() { | |
util.log("Clearing up"); | |
return this.redis.exists("msgid-" + this.s_uuid, __bind(function(err, val) { | |
if (val === 0) { | |
util.log("Session is dead, destroying."); | |
return this.amqp.queue('simp-' + this.s_uuid, { | |
passive: true, | |
autoDelete: false | |
}, __bind(function(q) { | |
if (q) { | |
return q.destroy({ | |
ifUnused: true | |
}); | |
} | |
}, this)); | |
} | |
}, this)); | |
}, this); | |
return setTimeout(finalCheck, (this.s_timeout + 10) * 1000); | |
}; | |
ClientState.prototype.rMessage = function(message) { | |
return this.redis.incr("msgid-" + this.s_uuid, __bind(function(err, val) { | |
if (val === null) { | |
return; | |
} | |
this.redis.setex("in-map-" + this.s_uuid + "-" + val, this.s_timeout, message.id); | |
this.send("SMSG", { | |
u: message.u, | |
h: message.h, | |
m: message.m, | |
ts: message.ts, | |
id: val | |
}); | |
this.outstandingMessage = true; | |
return setTimeout(this.Reject, 5000); | |
}, this)); | |
}; | |
ClientState.prototype.rConfirm = function(message) { | |
this.redis.setex(this.s_uuid + "-msg" + message.id, this.s_timeout, message.confirmType); | |
return this.send("CONF", { | |
type: message.confirmType, | |
id: message.id | |
}); | |
}; | |
ClientState.prototype.rReject = function() { | |
if (this.outstandingMessage) { | |
this.q.reject(); | |
} | |
return this.outstandingMessage = false; | |
}; | |
ClientState.prototype.rPresenceNotification = function(message) { | |
return this.send("CINF", [ | |
{ | |
user: message.user, | |
host: "localhost", | |
tags: [], | |
display: message.display, | |
status: message.status, | |
exists: true | |
} | |
]); | |
}; | |
ClientState.prototype.cStartSession = function(data) { | |
this.client_name = data.name; | |
this.client_version = data.version; | |
this.s_uuid = uuid(); | |
this.s_timeout = 120; | |
this.redis.set("msgid-" + this.s_uuid, 0); | |
return this.amqp.queue('simp-' + this.s_uuid, { | |
autoDelete: false | |
}, __bind(function(q) { | |
this.q = q; | |
this.q.subscribe({ | |
ack: true | |
}, this.rabbitMessage).addCallback(__bind(function(ok) { | |
return this.q_ctag = ok.consumerTag; | |
}, this)); | |
this.q.bind(this.exch, '#.info'); | |
return this.send("CNXC", { | |
name: "StandardSIMP", | |
version: "0.1", | |
s_uuid: this.s_uuid, | |
s_timeout: this.s_timeout, | |
auth: ['basic'] | |
}); | |
}, this)); | |
}; | |
ClientState.prototype.cResumeSession = function(data) { | |
this.s_uuid = data.uuid; | |
this.s_timeout = 10; | |
this.client_name = data.name; | |
this.client_version = data.version; | |
return this.redis.exists("msgid-" + this.s_uuid, __bind(function(err, val) { | |
if (val !== 1) { | |
return this.terminate("session has expired"); | |
} | |
return this.amqp.queue('simp-' + this.s_uuid, { | |
passive: true, | |
autoDelete: false | |
}, __bind(function(q) { | |
if (this.q == null) { | |
return this.terminate("queue for session doesn't exist"); | |
} | |
this.redis.persist("msgid-" + this.s_uuid); | |
this.q = q; | |
this.q.subscribe({ | |
ack: true | |
}, this.RabbitMessage); | |
return this.send("CNXC", { | |
name: "StandardSIMP", | |
version: "0.1", | |
s_uuid: this.s_uuid, | |
s_timeout: this.s_timeout, | |
auth: ['basic'] | |
}); | |
}, this)); | |
}, this)); | |
}; | |
ClientState.prototype.cAuthenticate = function(data) { | |
if (data.type === 'basic' && data.data.password === 'testpwd') { | |
this.authenticated = true; | |
this.user = data.data.username; | |
this.host = "localhost"; | |
this.display = this.user + '@' + this.host; | |
this.status = 'offline'; | |
this.q.bind(this.exch, this.user + '.messages'); | |
this.q.bind(this.exch, this.user + '.confirms'); | |
this.send('AUOK', {}); | |
return this.redis.smembers("users", __bind(function(err, data) { | |
var info, u, _fn, _i, _len; | |
if (err) { | |
util.log("Redis Error: " + err); | |
return; | |
} | |
info = []; | |
_fn = __bind(function(u) { | |
if (u !== this.user) { | |
return info.push("info-" + u); | |
} | |
}, this); | |
for (_i = 0, _len = data.length; _i < _len; _i++) { | |
u = data[_i]; | |
_fn(u); | |
} | |
if (info.length === 0) { | |
return; | |
} | |
return this.redis.mget(info, __bind(function(err, data) { | |
var i, infos, _fn2, _j, _len2; | |
if (err) { | |
util.log("Error: " + err); | |
return; | |
} | |
infos = []; | |
_fn2 = function(i) { | |
var ip; | |
ip = JSON.parse(i); | |
return infos.push({ | |
user: ip.user, | |
host: "localhost", | |
status: ip.status, | |
display: ip.display | |
}); | |
}; | |
for (_j = 0, _len2 = data.length; _j < _len2; _j++) { | |
i = data[_j]; | |
_fn2(i); | |
} | |
return this.send("CINF", infos); | |
}, this)); | |
}, this)); | |
} else { | |
return this.send('AREJ', { | |
message: "Currently you can only authenticate with testpwd" | |
}); | |
} | |
}; | |
ClientState.prototype.cSetInfo = function(data) { | |
var _ref; | |
if (!this.authenticated) { | |
return this.terminate("wasn't authenticed"); | |
} else { | |
if ('status' in data && ((_ref = data.status) === 'online' || _ref === 'busy' || _ref === 'away' || _ref === 'offline')) { | |
this.status = data.status; | |
} | |
if ('display' in data) { | |
this.display = data.display; | |
} | |
this.exch.publish(this.user + ".info", { | |
type: 'info', | |
user: this.user, | |
status: this.status, | |
display: this.display | |
}); | |
this.redis.sadd("users", this.user); | |
this.redis.set("info-" + this.user, JSON.stringify({ | |
user: this.user, | |
status: this.status, | |
display: this.display | |
})); | |
return util.log("User set to " + this.display + " (" + this.status + ")"); | |
} | |
}; | |
ClientState.prototype.cSendMessage = function(data) { | |
if (!this.authenticated) { | |
return this.terminate("wasn't authenticated"); | |
} else { | |
return this.redis.get(this.s_uuid + "-msg" + data.id, __bind(function(err, result) { | |
if (result === null) { | |
return this.exch.publish(data.u + ".messages", { | |
type: "message", | |
m: data.m, | |
ts: data.ts, | |
id: data.id, | |
u: this.user, | |
h: this.host | |
}); | |
} else { | |
return this.send("CONF", { | |
type: result, | |
id: data.id | |
}); | |
} | |
}, this)); | |
} | |
}; | |
ClientState.prototype.cConfirmMessage = function(data) { | |
if (!this.authenticated) { | |
return this.terminate("wasn't authenticated"); | |
} else { | |
return this.redis.get("in-map-" + this.s_uuid + "-" + data.id, __bind(function(err, val) { | |
if (val === null) { | |
return; | |
} | |
if (this.outstandingMessage) { | |
this.q.shift(); | |
} | |
this.outstandingMessage = false; | |
return this.exch.publish(data.u + ".confirms", { | |
type: "confirm", | |
confType: data.type, | |
id: val | |
}); | |
}, this)); | |
} | |
}; | |
ClientState.prototype.cGoodbye = function(data) { | |
util.log("goodbye"); | |
if (this.q != null) { | |
this.q.destroy(); | |
} | |
this.redis.del("msgid-" + this.s_uuid); | |
this.status = "offline"; | |
this.redis.set("info-" + this.user, JSON.stringify({ | |
user: this.user, | |
status: this.status, | |
display: this.display | |
})); | |
this.exch.publish(this.user + ".info", { | |
type: 'info', | |
user: this.user, | |
status: this.status, | |
display: this.display | |
}); | |
return this.terminate(); | |
}; | |
return ClientState; | |
})(); | |
module.exports = ClientState; | |
}).call(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment