Implement socket.io and break apart message/session/auth libraries.
* Library modularization inspired heavily by pjriot (http://bitbucket.org/pjriot/nodeim) * Remove dev server * Remove daemon library (not working) * Nix middleware scripts * Nix express.js usage
Esse commit está contido em:
+7
-26
@@ -27,31 +27,7 @@ AjaxIM = function(options, actions) {
|
||||
// upon calling the initialization function, and not set directly.//
|
||||
this.settings = $.extend(defaults, options);
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{actions}}}** ===
|
||||
//
|
||||
// Each individual action that the IM engine can execute is predefined here.
|
||||
// By default, it merely appends the action onto the end of the {{{pollServer}}} url,
|
||||
// however, it is possible to define actions individually. //The alternative actions
|
||||
// will be defined upon calling the initialization function, and not set directly.//
|
||||
//
|
||||
// Should you define an action at a different URL, Ajax IM will determine whether
|
||||
// or not this URL is within the current domain. If it is within a subdomain of
|
||||
// the current domain, it will set the document.domain variable for you,
|
||||
// to match a broader hostname scope; the action will continue to use {{{$.post}}}
|
||||
// (the default AJAX method for Ajax IM).
|
||||
//
|
||||
// On the other hand, should you choose a URL outside the current domain
|
||||
// Ajax IM will switch to {{{$.getJSON}}} (a get request) to avoid
|
||||
// cross-domain scripting issues. This means that a server on a different
|
||||
// port or at a different address will need to be able to handle GET
|
||||
// requests rather than POST requests (such as how the Node.JS Ajax IM
|
||||
// server works).
|
||||
this.actions = $.extend({
|
||||
listen: this.settings.pollServer + '/listen',
|
||||
send: this.settings.pollServer + '/message',
|
||||
status: this.settings.pollServer + '/status',
|
||||
signoff: this.settings.pollServer + '/signoff'
|
||||
}, actions);
|
||||
this.socket = new io.Socket();
|
||||
|
||||
// We load the theme dynamically based on the passed
|
||||
// settings. If the theme is set to false, we assume
|
||||
@@ -282,8 +258,13 @@ $.extend(AjaxIM.prototype, {
|
||||
if(this.username)
|
||||
this.storage();
|
||||
|
||||
this.listen();
|
||||
this.socket.connect();
|
||||
this.socket.on('connect', this.connected);
|
||||
this.socket.on('message', this.message);
|
||||
this.socket.on('disconnect', this.disconnected);
|
||||
},
|
||||
|
||||
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{storage()}}}** ===
|
||||
//
|
||||
|
||||
+16
-212
@@ -1,226 +1,30 @@
|
||||
#!/usr/bin/env node
|
||||
var sys = require('sys'),
|
||||
express = require('express'),
|
||||
var http = require('http'),
|
||||
io = require('./libs/socket.io'),
|
||||
packages = require('./libs/packages'),
|
||||
o_ = require('./libs/utils');
|
||||
o_ = require('./libs/utils'),
|
||||
server, socket;
|
||||
|
||||
o_.merge(global, require('./settings'));
|
||||
try { o_.merge(global, require('./settings.local')); } catch(e) {}
|
||||
|
||||
try {
|
||||
var daemon = require('./libs/daemon/daemon'),
|
||||
start = function() {
|
||||
daemon.init({
|
||||
lock: PID_FILE,
|
||||
stdin: '/dev/null',
|
||||
stdout: LOG_FILE,
|
||||
stderr: LOG_FILE,
|
||||
umask: 0,
|
||||
chroot: null,
|
||||
chdir: '.'
|
||||
});
|
||||
},
|
||||
stop = function() {
|
||||
process.kill(parseInt(require('fs').readFileSync(PID_FILE)));
|
||||
};
|
||||
|
||||
switch(process.argv[2]) {
|
||||
case 'stop':
|
||||
stop();
|
||||
process.exit(0);
|
||||
break;
|
||||
|
||||
case 'start':
|
||||
if(process.argv[3])
|
||||
process.env.EXPRESS_ENV = process.argv[3];
|
||||
start();
|
||||
break;
|
||||
|
||||
case 'restart':
|
||||
stop();
|
||||
start();
|
||||
process.exit(0);
|
||||
break;
|
||||
|
||||
case 'help':
|
||||
sys.puts('Usage: node app.js [start|stop|restart]');
|
||||
process.exit(0);
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
sys.puts('Daemon library not found! Please compile ' +
|
||||
'./libs/daemon/daemon.node if you would like to use it.');
|
||||
}
|
||||
|
||||
var app = express.createServer(
|
||||
express.methodOverride(),
|
||||
express.cookieDecoder(),
|
||||
express.bodyDecoder(),
|
||||
require('./middleware/im')({
|
||||
maxAge: 15 * 60 * 1000,
|
||||
reapInterval: 60 * 1000,
|
||||
authentication: require('./libs/authentication/' + AUTH_LIBRARY)
|
||||
})
|
||||
);
|
||||
|
||||
app.set('root', __dirname);
|
||||
|
||||
app.configure('development', function() {
|
||||
app.set('view engine', 'jade');
|
||||
app.set('views', __dirname + '/dev/views');
|
||||
|
||||
app.stack.unshift({
|
||||
route: '/dev',
|
||||
handle: function(req, res, next) {
|
||||
req.dev = true;
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
app.use(express.logger());
|
||||
app.use('/dev', express.router(require('./dev/app')));
|
||||
app.use(express.staticProvider(
|
||||
require('path').join(__dirname, '../client')));
|
||||
app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
|
||||
server = http.createServer(function(req, res) {
|
||||
// Any other server code goes here.
|
||||
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||
res.end('');
|
||||
});
|
||||
server.listen(APP_PORT, APP_HOST);
|
||||
|
||||
app.listen(APP_PORT, APP_HOST);
|
||||
|
||||
var socket = io.listen(app, {
|
||||
transportOptions: {
|
||||
'websocket': {closeTimeout: 20000},
|
||||
'flashsocket': {closeTimeout: 20000},
|
||||
'htmlfile': {closeTimeout: 20000},
|
||||
'xhr-multipart': {closeTimeout: 20000},
|
||||
'xhr-polling': {closeTimeout: 20000},
|
||||
'jsonp-polling': {closeTimeout: 20000}
|
||||
}
|
||||
}),
|
||||
auth = require('./libs/authentication/' + AUTH_LIBRARY);
|
||||
var auth_handler = require('./auth/' + AUTH_LIBRARY)(),
|
||||
session_store = require('./session/' + SESSION_STORE)(),
|
||||
msg_handler = require('./message/' + MESSAGE_HANDLER)(auth_handler, session_store);
|
||||
|
||||
socket = io.listen(server);
|
||||
socket.on('connection', function(client) {
|
||||
client.metadata = function(key, def) {
|
||||
return client._metadata[key] || def || false;
|
||||
};
|
||||
|
||||
client.sendTo = function(username, message) {
|
||||
try {
|
||||
Object.values(socket.clients).filter(function(cl) {
|
||||
return username == cl.metadata('username');
|
||||
}).each(function(user) {
|
||||
user.send(new packages.Message(
|
||||
client.metadata('username'),
|
||||
message
|
||||
));
|
||||
});
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
client.on('connect', function() {
|
||||
client.authenticated = false;
|
||||
client.key_id = null;
|
||||
client.send({type: 'auth', id: client.sessionId, key: auth.cookie});
|
||||
client.on('message', function(message) {
|
||||
msg_handler.message(client, message);
|
||||
});
|
||||
|
||||
client.on('message', function(data) {
|
||||
if(!data['type']) {
|
||||
client.send(new packages.Error('bad packet'));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(data);
|
||||
|
||||
if(!client.authenticated) {
|
||||
if(data.type == 'auth') {
|
||||
auth.authenticate(data.id, function(info) {
|
||||
if(info) {
|
||||
client.authenticated = true;
|
||||
client.key_id = data.id;
|
||||
client._metadata = info;
|
||||
|
||||
auth.friends(data.id, info, function(friends) {
|
||||
var friends_copy = friends.slice();
|
||||
Object.values(socket.clients).filter(function(friend) {
|
||||
return ~friends.indexOf(friend.metadata('username'));
|
||||
}).each(function(friend) {
|
||||
var username = friend.metadata('username');
|
||||
friends_copy[friends_copy.indexOf(username)] =
|
||||
[username, friend.metadata('status')];
|
||||
}, this);
|
||||
|
||||
client.friends = friends_copy;
|
||||
client.send({
|
||||
type: 'hello',
|
||||
username: client.metadata('username'),
|
||||
friends: friends
|
||||
});
|
||||
});
|
||||
} else {
|
||||
client.send(new packages.Error('invalid auth'));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
client.send(new packages.Error('not authenticated'));
|
||||
}
|
||||
} else {
|
||||
// do shit.
|
||||
client.send(data);
|
||||
client.sendTo(client.metadata('username'), 'hello');
|
||||
}
|
||||
});
|
||||
|
||||
client.on('disconnect', function() {
|
||||
|
||||
msg_handler.disconnect(client, SESSION_TIMEOUT);
|
||||
});
|
||||
});
|
||||
|
||||
// Listener endpoint; handled in middleware
|
||||
app.get('/listen', function(){});
|
||||
|
||||
app.post('/message', function(req, res) {
|
||||
res.find(req.body['to'], function(user) {
|
||||
if(!user)
|
||||
return res.send(new packages.Error('not online'));
|
||||
|
||||
res.message(user, new packages.Message(
|
||||
req.session.data('username'),
|
||||
req.body.body
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/message/typing', function(req, res) {
|
||||
if(~packages.TYPING_STATES.indexOf('typing' + req.body['state'])) {
|
||||
res.find(req.body['to'], function(user) {
|
||||
if(user) {
|
||||
res.message(user, new packages.Status(
|
||||
req.session.data('username'),
|
||||
'typing' + req.body.state
|
||||
));
|
||||
}
|
||||
|
||||
// Typing updates do not receive confirmations,
|
||||
// as they are not important enough.
|
||||
res.send('');
|
||||
});
|
||||
} else {
|
||||
res.send(new packages.Error('invalid state'));
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/status', function(req, res) {
|
||||
if(~packages.STATUSES.indexOf(req.body['status'])) {
|
||||
res.status(req.body.status, req.body.message);
|
||||
res.send(new packages.Success('status updated'));
|
||||
} else {
|
||||
res.send(new packages.Error('invalid status'));
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/signoff', function(req, res) {
|
||||
res.signOff();
|
||||
res.send(new packages.Success('goodbye'));
|
||||
});
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
var ExampleAuth = function() {};
|
||||
|
||||
ExampleAuth.prototype.authenticate = function(client, msg, callback) {
|
||||
callback({
|
||||
authenticated: true,
|
||||
username: 'username' + Math.round(Math.random() * 3)
|
||||
});
|
||||
};
|
||||
|
||||
ExampleAuth.prototype.friends = function(client, res, callback) {
|
||||
callback(['username1', 'username2', 'username3']);
|
||||
};
|
||||
|
||||
var instance = new ExampleAuth();
|
||||
module.exports = function getInstance() {
|
||||
return instance;
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
var utils = require('connect/utils');
|
||||
|
||||
module.exports = function(app) {
|
||||
app.get('/', function(req, res) {
|
||||
res.render('chat', {
|
||||
locals: {}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/socket', function(req, res) {
|
||||
res.render('socket', {
|
||||
locals: {}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/cookie', function(req, res) {
|
||||
res.send('cookie set', {
|
||||
'Set-Cookie': utils.serializeCookie('sessionid', utils.uid(),
|
||||
{path: '/'})
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
../../../client/js/
|
||||
@@ -1 +0,0 @@
|
||||
../../../client/themes/
|
||||
@@ -1,13 +0,0 @@
|
||||
!!! 5
|
||||
html
|
||||
head
|
||||
title Ajax IM
|
||||
script(src: '/js/jquery-1.4.1.js', type: 'text/javascript')
|
||||
script(src: '/js/md5.js', type: 'text/javascript')
|
||||
script(src: '/js/store.js', type: 'text/javascript')
|
||||
script(src: '/js/cookies.js', type: 'text/javascript')
|
||||
script(src: '/js/dateformat.js', type: 'text/javascript')
|
||||
script(src: '/js/im.js', type: 'text/javascript')
|
||||
script(type: 'text/javascript')
|
||||
| $(function(){var im = AjaxIM.init({theme: "/themes/default"});});
|
||||
body Hello.
|
||||
@@ -1 +0,0 @@
|
||||
!{body}
|
||||
@@ -1,10 +0,0 @@
|
||||
!!! 5
|
||||
html
|
||||
head
|
||||
title Ajax IM
|
||||
script(src: '/socket.io/socket.io.js', type: 'text/javascript')
|
||||
script(src: '/js/store.js', type: 'text/javascript')
|
||||
script(src: '/js/cookies.js', type: 'text/javascript')
|
||||
script(src: '/js/socket_test.js', type: 'text/javascript')
|
||||
|
||||
body Hello.
|
||||
@@ -1,24 +0,0 @@
|
||||
// Cookie that stores the session ID
|
||||
// Will be set as request.sessionID in `authenticate` and `friends` functions
|
||||
exports.cookie = 'sessionid';
|
||||
|
||||
exports.authenticate = function(request, callback) {
|
||||
// Verify user based on request.
|
||||
// On failure, redirect user to auth form
|
||||
|
||||
callback({
|
||||
username: 'username' + Math.floor(Math.random() * 1000),
|
||||
displayname: 'John Smith',
|
||||
otherinfo: 'any other relevant key/values'
|
||||
});
|
||||
};
|
||||
|
||||
exports.friends = function(request, data, callback) {
|
||||
// Create a friends list based on given user data
|
||||
|
||||
callback([
|
||||
'username1',
|
||||
'username2',
|
||||
'username3'
|
||||
]);
|
||||
};
|
||||
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
* Daemon.node
|
||||
*** A node.JS addon that allows creating Unix/Linux Daemons in pure Javascript.
|
||||
*** Copyright 2010 (c) <arthur@norgic.com>
|
||||
* Under MIT License. See LICENSE file.
|
||||
*/
|
||||
|
||||
#include <node/node.h>
|
||||
#include <v8.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PID_MAXLEN 10
|
||||
|
||||
using namespace v8;
|
||||
|
||||
// Go through special routines to become a daemon.
|
||||
// if successful, returns daemon's PID
|
||||
Handle<Value> Start(const Arguments& args) {
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if(pid > 0) exit(0);
|
||||
if(pid < 0) exit(1);
|
||||
|
||||
// Can be changed after with process.umaks
|
||||
umask(0);
|
||||
|
||||
setsid();
|
||||
|
||||
// Can be changed with process.chdir
|
||||
chdir("/");
|
||||
|
||||
return Integer::New(getpid());
|
||||
}
|
||||
|
||||
// Close Standard IN/OUT/ERR Streams
|
||||
Handle<Value> CloseIO(const Arguments& args) {
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
}
|
||||
|
||||
// File-lock to make sure that only one instance of daemon is running.. also for storing PID
|
||||
/* lock ( filename )
|
||||
*** filename: a path to a lock-file.
|
||||
*** Note: if filename doesn't exist, it will be created when function is called.
|
||||
*/
|
||||
Handle<Value> LockD(const Arguments& args) {
|
||||
if(!args[0]->IsString())
|
||||
return Boolean::New(false);
|
||||
|
||||
String::Utf8Value data(args[0]->ToString());
|
||||
char pid_str[PID_MAXLEN+1];
|
||||
|
||||
int lfp = open(*data, O_RDWR | O_CREAT, 0640);
|
||||
if(lfp < 0) exit(1);
|
||||
if(lockf(lfp, F_TLOCK, 0) < 0) exit(0);
|
||||
|
||||
int len = snprintf(pid_str, PID_MAXLEN, "%d", getpid());
|
||||
write(lfp, pid_str, len);
|
||||
|
||||
return Boolean::New(true);
|
||||
}
|
||||
|
||||
class StreamPtr : public node::ObjectWrap
|
||||
{
|
||||
public:
|
||||
explicit StreamPtr(FILE** fpp, const char *pmode);
|
||||
~StreamPtr();
|
||||
|
||||
static Handle<Value> Open(const Arguments& args);
|
||||
static Handle<Value> Close(const Arguments& args);
|
||||
static Handle<Value> Redirect(const Arguments& args);
|
||||
|
||||
static void Initialize(Handle<Object> target);
|
||||
static Handle<Value> New(const Arguments& args);
|
||||
|
||||
FILE** stream;
|
||||
const char *mode;
|
||||
private:
|
||||
static Persistent<FunctionTemplate> constructor_template;
|
||||
};
|
||||
|
||||
Persistent<FunctionTemplate> StreamPtr::constructor_template;
|
||||
|
||||
StreamPtr::StreamPtr(FILE** fpp, const char *pmode)
|
||||
: stream(fpp)
|
||||
, mode( pmode )
|
||||
{
|
||||
}
|
||||
|
||||
StreamPtr::~StreamPtr()
|
||||
{
|
||||
fclose(*stream);
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::Open(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
StreamPtr *fp = ObjectWrap::Unwrap<StreamPtr>(args.This());
|
||||
char *new_file = *String::Utf8Value(args[0]->ToString());
|
||||
*fp->stream = fopen(new_file, fp->mode);
|
||||
|
||||
// return if the creation of the new FILE* was successful;
|
||||
return Boolean::New( *fp->stream != NULL );
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::Close(const Arguments& args)
|
||||
{
|
||||
HandleScope handle_scope;
|
||||
|
||||
StreamPtr *fp = ObjectWrap::Unwrap<StreamPtr>(args.This());
|
||||
assert( fp && "object had no InternalField" );
|
||||
int ret = fclose(*fp->stream);
|
||||
|
||||
return Boolean::New(ret == 0);
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::Redirect(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
if (Close(args)->ToBoolean()->Value())
|
||||
{
|
||||
return Open(args);
|
||||
} else {
|
||||
return Boolean::New(false);
|
||||
}
|
||||
}
|
||||
|
||||
Persistent<Object> stdin_obj;
|
||||
Persistent<Object> stdout_obj;
|
||||
Persistent<Object> stderr_obj;
|
||||
|
||||
void StreamPtr::Initialize(Handle<Object> target)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<FunctionTemplate> file_pointer = FunctionTemplate::New(StreamPtr::New);
|
||||
constructor_template = Persistent<FunctionTemplate>::New(file_pointer);
|
||||
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "open", StreamPtr::Open);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", StreamPtr::Close);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "sendTo", StreamPtr::Redirect);
|
||||
|
||||
// Although we could expose the prototype directly, I see no reason to, as it's not
|
||||
// very useful for anything other than the intended purpose.
|
||||
//target->Set(String::NewSymbol("StreamPtr"), constructor_template->GetFunction());
|
||||
|
||||
stdin_obj = Persistent<Object>::New( constructor_template->GetFunction()->NewInstance() );
|
||||
Handle<External> stdin_ptr = External::New( new StreamPtr( &stdin, "r" ) );
|
||||
stdin_obj->SetInternalField(0, stdin_ptr);
|
||||
target->Set(String::NewSymbol("stdin"), stdin_obj);
|
||||
|
||||
stdout_obj = Persistent<Object>::New( constructor_template->GetFunction()->NewInstance() );
|
||||
Handle<External> stdout_ptr = External::New( new StreamPtr( &stdout, "w" ) );
|
||||
stdout_obj->SetInternalField(0, stdout_ptr);
|
||||
target->Set(String::NewSymbol("stdout"), stdout_obj);
|
||||
|
||||
stderr_obj = Persistent<Object>::New( constructor_template->GetFunction()->NewInstance() );
|
||||
Handle<External> stderr_ptr = External::New( new StreamPtr( &stderr, "w" ) );
|
||||
stderr_obj->SetInternalField(0, stderr_ptr);
|
||||
target->Set(String::NewSymbol("stderr"), stderr_obj);
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::New(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
/* The default object:
|
||||
* {
|
||||
* "fork": true,
|
||||
* "lock": "daemon.pid"
|
||||
* "stdout": null,
|
||||
* "stderr": null,
|
||||
* "stdin": null,
|
||||
* "umask": 0,
|
||||
* "chroot": null,
|
||||
* "chdir": ".",
|
||||
* }
|
||||
*/
|
||||
|
||||
#define SET_DEFAULT(obj, name, value) \
|
||||
do { \
|
||||
Local<String> str_##name = String::New(#name); \
|
||||
if( !obj->Has( str_##name ) ) \
|
||||
obj->Set( str_##name, (value) ); \
|
||||
} while (0)
|
||||
|
||||
static inline void setDefaults(Handle<Object> &arg)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
SET_DEFAULT( arg, fork, Boolean::New(true) );
|
||||
SET_DEFAULT( arg, lock, String::New("daemon.pid") );
|
||||
SET_DEFAULT( arg, stdin, Null() );
|
||||
SET_DEFAULT( arg, stdout, Null() );
|
||||
SET_DEFAULT( arg, stderr, Null() );
|
||||
SET_DEFAULT( arg, umask, Integer::New(0) );
|
||||
SET_DEFAULT( arg, chroot, Null() );
|
||||
SET_DEFAULT( arg, chdir, String::New(".") );
|
||||
//SET_DEFAULT( arg, close_fds, Boolean::New(false) );
|
||||
//SET_DEFAULT( arg, catch_signals, Boolean::New(false) );
|
||||
}
|
||||
|
||||
#undef SET_DEFAULT
|
||||
|
||||
Handle<Value> Init(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<Object> arg = args[0]->ToObject();
|
||||
setDefaults( arg );
|
||||
|
||||
pid_t pid = 0;
|
||||
if( arg->Get( String::New("fork") )->IsTrue() )
|
||||
{
|
||||
pid = fork();
|
||||
if(pid > 0) exit(0);
|
||||
if(pid < 0) exit(1);
|
||||
}
|
||||
|
||||
if( !arg->Get( String::New("lock") )->IsNull() )
|
||||
{
|
||||
Local<String> file = arg->Get( String::New( "lock" ) )->ToString();
|
||||
String::Utf8Value data(file);
|
||||
char pid_str[PID_MAXLEN+1];
|
||||
|
||||
int lfp = open(*data, O_RDWR | O_CREAT, 0640);
|
||||
if(lfp < 0) exit(1);
|
||||
if(lockf(lfp, F_TLOCK, 0) < 0) exit(0);
|
||||
|
||||
int len = snprintf(pid_str, PID_MAXLEN, "%d", getpid());
|
||||
write(lfp, pid_str, len);
|
||||
}
|
||||
|
||||
if( arg->Get( String::New("stdin") )->IsNull() )
|
||||
{
|
||||
Local<Function> close = Function::Cast( *stdin_obj->Get( String::New("close") ) );
|
||||
close->Call( stdin_obj, 0, NULL );
|
||||
} else {
|
||||
Local<Function> send_to = Function::Cast( *stdin_obj->Get( String::New("sendTo") ) );
|
||||
Local<Value> string_arg = arg->Get( String::New("stdin") );
|
||||
send_to->Call( stdin_obj, 1, &string_arg );
|
||||
}
|
||||
|
||||
if( arg->Get( String::New("stdout") )->IsNull() )
|
||||
{
|
||||
Local<Function> close = Function::Cast( *stdout_obj->Get( String::New("close") ) );
|
||||
close->Call( stdout_obj, 0, NULL );
|
||||
} else {
|
||||
Local<Function> send_to = Function::Cast( *stdout_obj->Get( String::New("sendTo") ) );
|
||||
Local<Value> string_arg = arg->Get( String::New("stdout") );
|
||||
send_to->Call( stdout_obj, 1, &string_arg );
|
||||
}
|
||||
|
||||
if( arg->Get( String::New("stderr") )->IsNull() )
|
||||
{
|
||||
Local<Function> close = Function::Cast( *stderr_obj->Get( String::New("close") ) );
|
||||
close->Call( stderr_obj, 0, NULL );
|
||||
} else {
|
||||
Local<Function> send_to = Function::Cast( *stderr_obj->Get( String::New("sendTo") ) );
|
||||
Local<Value> string_arg = arg->Get( String::New("stderr") );
|
||||
send_to->Call( stderr_obj, 1, &string_arg );
|
||||
}
|
||||
|
||||
Local<Integer> umask_arg = arg->Get( String::New("umask") )->ToInteger();
|
||||
umask( umask_arg->Value() );
|
||||
|
||||
if( !arg->Get( String::New("chroot") )->IsNull() )
|
||||
{
|
||||
char* dir = *String::AsciiValue( arg->Get( String::New("chroot") ) );
|
||||
chroot( dir );
|
||||
}
|
||||
|
||||
if( !arg->Get( String::New("chdir") )->IsNull() )
|
||||
{
|
||||
char* dir = *String::AsciiValue( arg->Get( String::New("chdir") ) );
|
||||
chdir( dir );
|
||||
}
|
||||
|
||||
return Integer::New(pid);
|
||||
}
|
||||
|
||||
extern "C" void init(Handle<Object> target) {
|
||||
HandleScope scope;
|
||||
|
||||
target->Set(String::New("start"), FunctionTemplate::New(Start)->GetFunction());
|
||||
target->Set(String::New("lock"), FunctionTemplate::New(LockD)->GetFunction());
|
||||
target->Set(String::New("closeIO"), FunctionTemplate::New(CloseIO)->GetFunction());
|
||||
target->Set(String::New("init"), FunctionTemplate::New(Init)->GetFunction());
|
||||
|
||||
StreamPtr::Initialize(target);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
srcdir = "."
|
||||
blddir = "build"
|
||||
VERSION = "0.0.1"
|
||||
|
||||
def set_options(opt):
|
||||
opt.tool_options("compiler_cxx")
|
||||
|
||||
def configure(conf):
|
||||
conf.check_tool("compiler_cxx")
|
||||
conf.check_tool("node_addon")
|
||||
|
||||
def build(bld):
|
||||
obj = bld.new_task_gen("cxx", "shlib", "node_addon")
|
||||
obj.target = "daemon"
|
||||
obj.source = "daemon.cc"
|
||||
@@ -1,88 +0,0 @@
|
||||
var sys = require('sys');
|
||||
|
||||
var Package = function() {};
|
||||
Package.prototype._sanitize = function(content) {
|
||||
// strip HTML
|
||||
return content.replace(/<(.|\n)*?>/g, '');
|
||||
};
|
||||
|
||||
var Error = exports.Error = function(error) {
|
||||
this.error = error;
|
||||
};
|
||||
sys.inherits(Error, Package);
|
||||
Error.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'error',
|
||||
error: this.error
|
||||
};
|
||||
};
|
||||
|
||||
var Success = exports.Success = function(success) {
|
||||
this.success = success;
|
||||
};
|
||||
sys.inherits(Success, Package);
|
||||
Success.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'success',
|
||||
success: this.success
|
||||
};
|
||||
};
|
||||
|
||||
var Message = exports.Message = function(from, body) {
|
||||
this.from = from;
|
||||
this.body = body;
|
||||
};
|
||||
sys.inherits(Message, Package);
|
||||
Message.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'message',
|
||||
user: this.from,
|
||||
body: this._sanitize(this.body)
|
||||
};
|
||||
};
|
||||
|
||||
var Notice = exports.Notice = function(username, info) {
|
||||
this.username = username;
|
||||
this.info = info;
|
||||
};
|
||||
sys.inherits(Notice, Package);
|
||||
Notice.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'notice',
|
||||
user: this.username,
|
||||
info: this.info
|
||||
};
|
||||
};
|
||||
|
||||
exports.TYPING_STATES = ['typing+', 'typing~', 'typing-'];
|
||||
exports.STATUSES = ['available', 'away', 'idle'];
|
||||
var Status = exports.Status = function(username, status, message) {
|
||||
var statuses = exports.STATUSES + exports.TYPING_STATES;
|
||||
|
||||
this.username = username;
|
||||
this.status = -~statuses.indexOf(status) ? status : statuses[0];
|
||||
this.message = message;
|
||||
};
|
||||
sys.inherits(Status, Package);
|
||||
Status.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'status',
|
||||
user: this.username,
|
||||
status: this.status,
|
||||
message: this._sanitize(this.message || '')
|
||||
};
|
||||
};
|
||||
|
||||
var Offline = exports.Offline = function(username) {
|
||||
this.username = username;
|
||||
};
|
||||
sys.inherits(Offline, Package);
|
||||
Offline.prototype.toJSON = function() {
|
||||
// A special type of status
|
||||
return {
|
||||
type: 'status',
|
||||
user: this.username,
|
||||
status: 'offline',
|
||||
message: ''
|
||||
};
|
||||
};
|
||||
Submodule server/libs/socket.io deleted from fbb9a46ba0
@@ -0,0 +1,154 @@
|
||||
var MessageHandler = function(auth_handler, session_store) {
|
||||
this.auth_handler = auth_handler;
|
||||
this.session_store = session_store;
|
||||
};
|
||||
|
||||
MessageHandler.prototype._auth = function(client, message) {
|
||||
var session = this.session_store.get('identifier', message.identifier);
|
||||
|
||||
if(session) {
|
||||
this.session_store.touch(session, client);
|
||||
client.send({
|
||||
type: 'AUTH',
|
||||
loggedin: true
|
||||
});
|
||||
} else {
|
||||
var auth_handler = this.auth_handler,
|
||||
session_store = this.session_store;
|
||||
|
||||
// authenticate the new user
|
||||
auth_handler.authenticate(client, message, function(res) {
|
||||
|
||||
// authentication succeeded, setup user
|
||||
if(res.authenticated) {
|
||||
|
||||
// get user's friends
|
||||
auth_handler.friends(client, res, function(friends_array) {
|
||||
var friends_list = {},
|
||||
sess,
|
||||
indentifier;
|
||||
|
||||
for(var i = 0, fl = friends_array.length; i < fl; i++) {
|
||||
sess = session_store.get('username', friends_array[i])
|
||||
|
||||
if(sess) {
|
||||
// notify friends that user has logged on
|
||||
sess.client.send({
|
||||
type: 'STATUS',
|
||||
username: res.username,
|
||||
status: 'online'
|
||||
});
|
||||
|
||||
friends_list[friends_array[i]] = sess.status;
|
||||
} else {
|
||||
friends_list[friends_array[i]] = 'offline';
|
||||
}
|
||||
}
|
||||
|
||||
identifier = session_store.create(res.username,
|
||||
client,
|
||||
friends_array
|
||||
);
|
||||
|
||||
// notify user that they're logged on
|
||||
client.send({
|
||||
type: 'AUTH',
|
||||
loggedin: true,
|
||||
friends: friends_dict
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// authentication failed
|
||||
client.send({
|
||||
type: 'AUTH',
|
||||
loggedin: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
MessageHandler.prototype._im = function(client, to, message) {
|
||||
var sender = this.session_handler.get('client', client),
|
||||
recipient;
|
||||
|
||||
if(session) {
|
||||
recipient = this.session_handler.get('username', to);
|
||||
|
||||
if(recipient) {
|
||||
recipient.client.send({
|
||||
type: 'IM',
|
||||
from: sender.username,
|
||||
message: message
|
||||
});
|
||||
} else {
|
||||
client.send({
|
||||
type: 'ERROR',
|
||||
origin: 'IM',
|
||||
to: to
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandler.prototype._status = function(client, status, status_msg) {
|
||||
var session = this.session_handler.get('client', client),
|
||||
friend;
|
||||
|
||||
if(['online', 'away', 'offline'].indexOf(status) != -1) {
|
||||
session.status = status;
|
||||
this.session_store.set(session.username, session);
|
||||
|
||||
// let user's friends know about the new status
|
||||
for(var i = 0, fl = session.friends.length; i < fl; i++) {
|
||||
friend = this.session_store.get('username', session.friends[i]);
|
||||
|
||||
if(friend) {
|
||||
friend.client.send({
|
||||
type: 'STATUS',
|
||||
username: session.username,
|
||||
status: status
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandler.prototype._disconnect = function(client, SESSION_TIMEOUT) {
|
||||
var threshold = +new Date - SESSION_TIMEOUT,
|
||||
session = this.session_store.get('client', client);
|
||||
|
||||
if(session && session.lastAccess < threshold) {
|
||||
if(session.status != 'offline')
|
||||
this._status(session.username, 'offline');
|
||||
|
||||
this.session_store.remove(session.username);
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandler.prototype.message = function(client, message) {
|
||||
switch(message.type) {
|
||||
case 'AUTH':
|
||||
this._auth(client, message);
|
||||
break;
|
||||
|
||||
case 'IM':
|
||||
this._im(client, message.to, message.message);
|
||||
break;
|
||||
|
||||
case 'STATUS':
|
||||
this._status(client, message.status, message.status_msg);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
MessageHandler.prototype.disconnect = function(client, SESSION_TIMEOUT) {
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
self._disconnect(client, SESSION_TIMEOUT);
|
||||
}, SESSION_TIMEOUT);
|
||||
};
|
||||
|
||||
module.exports = function createInstance(auth_handler, session_store) {
|
||||
return new MessageHandler(auth_handler, session_store);
|
||||
};
|
||||
@@ -1,67 +0,0 @@
|
||||
var url = require('url'),
|
||||
Hub = require('./im/hub');
|
||||
|
||||
module.exports = function setupHub(options) {
|
||||
options = options || {};
|
||||
|
||||
store = new Hub(options);
|
||||
|
||||
return function session(req, res, next) {
|
||||
req.sessionStore = store;
|
||||
req.sessionID = req.cookies[options.authentication.cookie];
|
||||
|
||||
if(!req.cookies) {
|
||||
next(new Error('session requires cookieDecoder to work properly'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(req.dev) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
if(req.sessionID) {
|
||||
store.get(req, function(err, sess) {
|
||||
if(err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!sess) {
|
||||
next(new Error(JSON.stringify({
|
||||
type: 'error',
|
||||
error: 'not authenticated'})));
|
||||
return;
|
||||
}
|
||||
|
||||
sess.touch();
|
||||
if(url.parse(req.url).pathname === '/listen') {
|
||||
req.connection.setTimeout(5 * 60 * 1000);
|
||||
sess.listener(res);
|
||||
store.set(req.sessionID, sess);
|
||||
|
||||
if(msg = sess.message_queue.shift())
|
||||
sess._send.apply(sess, msg);
|
||||
} else {
|
||||
sess.connection = res;
|
||||
}
|
||||
|
||||
req.session = sess;
|
||||
res.find = store.find.bind(store);
|
||||
res.message = function(to, package) {
|
||||
store.message(req.session, to, package);
|
||||
};
|
||||
res.status = function(value, message) {
|
||||
req.session.status(value, message);
|
||||
};
|
||||
res.signOff = function() { store.signOff(req.sessionID); };
|
||||
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next(new Error(JSON.stringify({
|
||||
type: 'error',
|
||||
error: 'not authenticated'})));
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,126 +0,0 @@
|
||||
var events = require('events'),
|
||||
sys = require('sys'),
|
||||
packages = require('../../libs/packages'),
|
||||
o_ = require('../../libs/utils'),
|
||||
User = require('./user');
|
||||
|
||||
var Hub = module.exports = function Hub(options) {
|
||||
this.events = new events.EventEmitter();
|
||||
this.auth = options.authentication;
|
||||
this.sessions = {};
|
||||
|
||||
this.maxAge = options.maxAge || 4 * 60 * 60 * 1000;
|
||||
this.reapInterval = options.reapInterval || 60 * 1000;
|
||||
|
||||
if(this.reapInterval !== -1) {
|
||||
setInterval(function(self) {
|
||||
self.reap(self.maxAge);
|
||||
}, this.reapInterval, this);
|
||||
}
|
||||
|
||||
this.events.addListener('update', o_.bind(function(package) {
|
||||
var _package = package.toJSON();
|
||||
if(package.type == 'status' && package.status == 'offline') {
|
||||
var sids = Object.keys(this.sessions), sid, sess;
|
||||
for(sid in this.sessions) {
|
||||
sess = this.sessions[sid];
|
||||
if(sess.data('username') == package.username) {
|
||||
if(sess.listeners.length)
|
||||
sess.send(200, {type: 'goodbye'});
|
||||
delete this.sessions[sid];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, this));
|
||||
};
|
||||
|
||||
Hub.prototype.destroy = function(sid, fn) {
|
||||
this.set(sid, null, fn);
|
||||
};
|
||||
|
||||
Hub.prototype.reap = function(ms) {
|
||||
var threshold = +new Date - ms,
|
||||
sids = Object.keys(this.sessions);
|
||||
for(var i = 0, len = sids.length; i < len; ++i) {
|
||||
var sid = sids[i], sess = this.sessions[sid];
|
||||
if(sess.lastAccess < threshold) {
|
||||
this.events.emit('update', new packages.Offline(sess.data('username')));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Hub.prototype.get = function(req, fn) {
|
||||
if(this.sessions[req.sessionID]) {
|
||||
fn(null, this.sessions[req.sessionID]);
|
||||
} else {
|
||||
this.auth.authenticate(req, o_.bind(function(data) {
|
||||
if(data) {
|
||||
var session = new User(req.sessionID, data);
|
||||
this.set(req.sessionID, session);
|
||||
|
||||
this.auth.friends(req, data, o_.bind(function(friends) {
|
||||
var friends_copy = friends.slice();
|
||||
o_.values(this.sessions).filter(function(friend) {
|
||||
return ~friends.indexOf(friend.data('username'));
|
||||
}).forEach(function(friend) {
|
||||
var username = friend.data('username');
|
||||
friends_copy[friends_copy.indexOf(username)] =
|
||||
[username, friend.status()];
|
||||
}, this);
|
||||
|
||||
session._friends(friends_copy);
|
||||
session.events.addListener('status',
|
||||
o_.bind(function(value, message) {
|
||||
this.events.emit(
|
||||
'update',
|
||||
new packages.Status(session.data('username'),
|
||||
value,
|
||||
message)
|
||||
);
|
||||
}, this));
|
||||
this.events.addListener('update',
|
||||
o_.bind(session.receivedUpdate, session));
|
||||
this.set(req.sessionID, session);
|
||||
fn(null, session);
|
||||
}, this));
|
||||
} else {
|
||||
fn();
|
||||
}
|
||||
}, this));
|
||||
}
|
||||
};
|
||||
|
||||
Hub.prototype.set = function(sid, sess, fn) {
|
||||
this.sessions[sid] = sess;
|
||||
fn && fn();
|
||||
};
|
||||
|
||||
Hub.prototype.find = function(username, fn) {
|
||||
for(var sid in this.sessions) {
|
||||
var session = this.sessions[sid],
|
||||
sess_username = session.data('username');
|
||||
if(sess_username == username) {
|
||||
fn(session);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fn(false);
|
||||
};
|
||||
|
||||
Hub.prototype.message = function(from, to, package) {
|
||||
try {
|
||||
package.user = from;
|
||||
to.send(package);
|
||||
from.respond(new packages.Success('sent'));
|
||||
} catch(e) {
|
||||
from.respond(new packages.Error(e.description));
|
||||
}
|
||||
};
|
||||
|
||||
Hub.prototype.signOff = function(sid) {
|
||||
if(sid in this.sessions)
|
||||
this.events.emit('update',
|
||||
new packages.Offline(
|
||||
this.sessions[sid].data('username')));
|
||||
};
|
||||
@@ -1,114 +0,0 @@
|
||||
var events = require('events'),
|
||||
packages = require('../../libs/packages'),
|
||||
o_ = require('../../libs/utils');
|
||||
|
||||
var User = module.exports = function(id, data) {
|
||||
this.id = id;
|
||||
this.connection = null;
|
||||
this.listeners = [];
|
||||
this.message_queue = [];
|
||||
this.convos = {};
|
||||
this._data = data;
|
||||
|
||||
this.events = new events.EventEmitter();
|
||||
this.status(packages.STATUSES[0], '');
|
||||
|
||||
setInterval(o_.bind(this._expireConns, this), 500);
|
||||
};
|
||||
|
||||
User.prototype.receivedUpdate = function(package) {
|
||||
if(this.friends.indexOf(package.username))
|
||||
this.send(package);
|
||||
};
|
||||
|
||||
User.prototype._friends = function(friends) {
|
||||
this.friends = friends;
|
||||
this.send(JSON.stringify({
|
||||
type: 'hello',
|
||||
username: this.data('username'),
|
||||
friends: friends
|
||||
}));
|
||||
};
|
||||
|
||||
User.prototype._expireConns = function() {
|
||||
var conn,
|
||||
noop = JSON.stringify({type: 'noop'}),
|
||||
noop_headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': noop.length
|
||||
};
|
||||
for(var i = 0; i < this.listeners.length; i++) {
|
||||
conn = this.listeners[i].connection;
|
||||
if((Date.now() - conn._idleStart) >= conn._idleTimeout - 2000) {
|
||||
this.listeners[i].writeHead(200, noop_headers);
|
||||
this.listeners[i].end(noop);
|
||||
this.listeners.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.listener = function(conn) {
|
||||
this.listeners.push(conn);
|
||||
};
|
||||
|
||||
User.prototype.respond = function(code, message, callback) {
|
||||
this._send('connection', code, message, callback);
|
||||
};
|
||||
|
||||
User.prototype.send = function(code, message, callback) {
|
||||
this._send('listener', code, message, callback);
|
||||
};
|
||||
|
||||
User.prototype._send = function(type, code, message, callback) {
|
||||
if(!message && typeof code != 'number') {
|
||||
callback = message;
|
||||
message = code;
|
||||
code = 200;
|
||||
}
|
||||
|
||||
if(typeof message != 'string')
|
||||
message = JSON.stringify(message);
|
||||
|
||||
if(type == 'connection' && this.connection) {
|
||||
this.connection.writeHead(code || 200, {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': message.length
|
||||
});
|
||||
this.connection.end(message);
|
||||
} else {
|
||||
if(!this.listeners.length)
|
||||
return this.message_queue.push(arguments);
|
||||
|
||||
var cx = this.listeners.slice(), conn;
|
||||
this.listeners = [];
|
||||
while(conn = cx.shift()) {
|
||||
conn.writeHead(code || 200, {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': message.length
|
||||
});
|
||||
conn.end(message);
|
||||
}
|
||||
if(callback) callback();
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.data = function(key, def) {
|
||||
if(key == 'id') return this.id;
|
||||
return this._data[key] || this['_' + key] ||
|
||||
(typeof this[key] != 'function' && this[key]) ||
|
||||
def || false;
|
||||
};
|
||||
|
||||
User.prototype.touch = function() {
|
||||
this.lastAccess = +new Date;
|
||||
};
|
||||
|
||||
User.prototype.status = function(value, message) {
|
||||
if(!value)
|
||||
return this._status;
|
||||
|
||||
this._status = value;
|
||||
this._status_message = message;
|
||||
this.events.emit('status', value, message);
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
var crypto = require('crypto');
|
||||
|
||||
var Session = function(username) {
|
||||
this.username = username;
|
||||
this.authenticated = false;
|
||||
this.lastAccess = new Date().getTime();
|
||||
this.client = -1;
|
||||
this.identifier = -1;
|
||||
this.friends = [];
|
||||
this.status = 'online';
|
||||
};
|
||||
|
||||
var MemorySessionStore = function() {
|
||||
this.sessions = {};
|
||||
this.sessionClientMap = {};
|
||||
this.sessionIdentifierMap = {};
|
||||
};
|
||||
|
||||
MemorySessionStore.prototype.create = function(username, client, friends) {
|
||||
var session = new Session(username);
|
||||
session.client = client;
|
||||
|
||||
if(friends) {
|
||||
for(var i = 0, fl = friends.length; i < fl; i++)
|
||||
session.push(friends[i])
|
||||
}
|
||||
|
||||
this.sessions[username] = session;
|
||||
this.sessionClientMap[client.sessionId] = username;
|
||||
|
||||
// create a re-authentication identifier
|
||||
var md5 = crypto.createHash('md5'),
|
||||
identifier = md5.update(username + client.sessionId).digest('hex');
|
||||
this.sessionIdentifierMap[identifier] = username;
|
||||
session.identifier = identifier;
|
||||
|
||||
return identifier;
|
||||
};
|
||||
|
||||
MemorySessionStore.prototype.set = function(username, session) {
|
||||
this.sessions[username] = session;
|
||||
this.sessionClientMap[session.client.sessionId] = username;
|
||||
this.sessionIdentifierMap[session.identifier] = username;
|
||||
};
|
||||
|
||||
MemorySessionStore.prototype.touch = function(session, client) {
|
||||
var new_session = session;
|
||||
new_session.lastAccess = new Date().getTime();
|
||||
new_session.client = client;
|
||||
|
||||
this.remove(new_session.username);
|
||||
this.set(new_session.username, new_session);
|
||||
};
|
||||
|
||||
MemorySessionStore.prototype.get = function(key, val) {
|
||||
switch(key) {
|
||||
case 'client':
|
||||
return this.sessions[this.sessionClientMap[val]];
|
||||
break;
|
||||
|
||||
case 'username':
|
||||
return this.sessions[val];
|
||||
break;
|
||||
|
||||
case 'identifier':
|
||||
return this.sessions[this.sessionIdentifierMap[val]];
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
MemorySessionStore.prototype.all = function() {
|
||||
return this.sessions;
|
||||
};
|
||||
|
||||
MemorySessionStore.prototype.remove = function(username) {
|
||||
if(this.session.username) {
|
||||
var clientid = this.sessions[username].client.sessionId,
|
||||
identifier = this.sessions[username].identifier;
|
||||
delete this.sessionClientMap[clientid];
|
||||
delete this.sessionIdentifierMap[identifier];
|
||||
delete this.sessions[username];
|
||||
}
|
||||
};
|
||||
|
||||
var instance = new MemorySessionStore();
|
||||
module.exports = function getInstance() {
|
||||
return instance;
|
||||
};
|
||||
+10
-6
@@ -7,18 +7,22 @@
|
||||
// === Host and Port ===
|
||||
//
|
||||
// Define the host and port that Ajax IM will run on.
|
||||
//
|
||||
// Note: Setting APP_HOST to null will run the server on port 8000 for any
|
||||
// hostname!
|
||||
APP_HOST = 'localhost';
|
||||
APP_PORT = 8000;
|
||||
|
||||
// === Authentication Library ===
|
||||
//
|
||||
// This is the library (from libs/authenticate/) that we will use to
|
||||
// authenticate a user signing in. The value should be the name of the file
|
||||
// without the '.js' part. 'index' is the default library.
|
||||
// Document me!
|
||||
AUTH_LIBRARY = 'default';
|
||||
SESSION_STORE = 'memory';
|
||||
MESSAGE_HANDLER = 'default';
|
||||
|
||||
// === Daemon ===
|
||||
//
|
||||
// Define where the PID and log files will be deposited when run as a daemon.
|
||||
/*
|
||||
// Broken! Removed for the time being.
|
||||
PID_FILE = '/tmp/ajaxim.pid';
|
||||
LOG_FILE = '/var/run/ajaxim.log';
|
||||
LOG_FILE = '/var/run/ajaxim.log';
|
||||
*/
|
||||
Referência em uma Nova Issue
Bloquear um usuário