Created
November 21, 2011 05:26
-
-
Save c4pt0r/1381728 to your computer and use it in GitHub Desktop.
jakiro-comet-server
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
/* | |
* Jakiro | |
* @desc Yet Another Comet Server | |
* @author Dongxu Huang <[email protected]> | |
* @date 2011-11-18 | |
*/ | |
var port = 8899 // default listen port | |
var createServer = require("http").createServer // createserver function | |
var puts = require("util").puts // output log | |
var url = require("url") | |
var timeout = 50000 | |
var buf_size = 10 | |
// out put debug string | |
function log(msg) | |
{ | |
var time = new Date().toString().split(' ')[4] | |
puts('\033[32;49;1m['+time+']\033[39;49;0m '+msg) | |
} | |
// get current time stamp | |
function get_timestamp() | |
{ | |
return new Date().getTime() | |
} | |
// send response to client | |
function response(res, code, body, callback) | |
{ | |
var type; | |
body = JSON.stringify(body); | |
if (callback) | |
{ | |
body = callback + '(' + body + ');'; | |
type = 'application/javascript'; | |
} | |
else | |
{ | |
type = 'text/json'; | |
} | |
res.writeHeader(code, { | |
"Content-Type": type, | |
"Content-Length": body.length | |
}); | |
res.write(body); | |
res.end(); | |
} | |
// message body | |
function Message(time, data) | |
{ | |
this.time = time | |
this.data = data | |
} | |
// comet channel | |
function Channel() | |
{ | |
// store messages | |
var messages = [] | |
// current time stamp | |
var time = get_timestamp() | |
// waiting client's callbacks | |
var callbacks = [] | |
// push data into a channel | |
this.put = function(data) | |
{ | |
time = get_timestamp() | |
var message = new Message(time, data) | |
messages.push(message) | |
// call waiting clients' callback function | |
while(callbacks.length > 0) | |
callbacks.shift().callback([message]) | |
// clean message buffer | |
while(messages.length > buf_size) | |
messages.shift() | |
return time | |
}; | |
this.get = function(time, callback) | |
{ | |
var i, message, new_msgs = [] | |
for (i = 0;i < messages.length ; i++) | |
{ | |
message = messages[i] | |
if (message.time > time) | |
new_msgs.push(message) | |
} | |
if (new_msgs.length > 0) | |
{ | |
callback(new_msgs) | |
return 'unread' | |
} | |
else | |
{ | |
callbacks.push({time: get_timestamp(), callback: callback}) | |
return 'waiting' | |
} | |
}; | |
// update client time; client fetch server time | |
this.update = function() | |
{ | |
return time | |
} | |
// remove expire waiter or entire channel | |
this.remove = function(expire) | |
{ | |
// if this channel has no waiter in queue meanwhile live a long time | |
var isdeletechannel = callbacks.length === 0 && time < expire | |
while (callbacks.length > 0 && callbacks[0].time < expire) | |
{ | |
callbacks.shift().callback([]); | |
} | |
return isdeletechannel | |
}; | |
} | |
var channels = [] | |
// get channel by name, or create new channel | |
function get_channel(name) | |
{ | |
var channel = channels[name] | |
if (channel) | |
return channel | |
channels[name] = new Channel() | |
return channels[name]; | |
} | |
// check expire channels or clients | |
function check_channels() | |
{ | |
var expire = get_timestamp() - timeout; | |
for (channel in channels) | |
{ | |
if (channels[channel].remove(expire)) | |
{ | |
delete channels[channel] | |
} | |
} | |
} | |
// check timeout | |
setInterval(check_channels, 1000) | |
function on_client_arrive(req, res) | |
{ | |
log("New Client From: " + req.connection.remoteAddress + " Query: " + req.url) | |
var q = url.parse(req.url, true).query || {method:'update', channel:'test'} | |
var channel_name = q.channel || 'test' | |
var method = q.method || 'update' | |
var channel = get_channel(channel_name) | |
var callback = q.callback || false | |
// handle get | |
if (method == 'get') | |
{ | |
time = q.time || 0 | |
channel.get(time, function(messages) | |
{ | |
time = channel.update() | |
response(res, 200, {time:time, messages:messages}, callback) | |
}) | |
} | |
// handle put | |
else if (method == 'put') | |
{ | |
message = q.message || null | |
time = channel.put(message) | |
response(res, 200, {time:time}, callback); | |
} | |
// sync client time | |
else{ | |
time = channel.update(); | |
response(res, 200, {time:time}, callback); | |
} | |
} | |
var server = createServer(on_client_arrive); | |
server.listen(port); | |
log("Jakiro Server v0.01 Start ...") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
yet another comet server written in node.js