Skip to content

Instantly share code, notes, and snippets.

@corruptmem
Created October 28, 2011 16:56
Show Gist options
  • Save corruptmem/1322763 to your computer and use it in GitHub Desktop.
Save corruptmem/1322763 to your computer and use it in GitHub Desktop.
Post coffee-compilation
(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