Commit 23519237 authored by Jeffrey I. Schiller's avatar Jeffrey I. Schiller

Add node.js version of Rendezvous server.

Add node.js version of Rendezvous server. This version uses memcache
for storing rendezvous data. It logs information from phones to a
CouchDB Database.

Change-Id: I2b76750681e20b8aea56c507a7727c33ca3c2987
parent c110a912
node.js version of MIT App Inventor Rendezvous Server
===
This codebase provides the basic functions of the Rendezvous
Server. It also logs to a CouchDB instance the POST's received from
the phone. This database can then be mined for statistics.
### To Run:
Prerequisites:
* Node.js (tested with version v0.8.21)
* CouchDB -- for stats
* npm install memcache
* npm install nano
Setup a user named "appinv" (should be a system account, but doesn't have to be).
The "appinv" userid's home directory should be in /home/appinv
- Put rendezvous.js in /home/appinv.
- Put rendezvous.conf in /etc/init for upstart (Ubuntu 12.04LTS).
- Put the database URI in /home/appinv/uri.
\ No newline at end of file
description "Rendezvous node.js server"
author "jis"
start on (local-filesystems and net-device-up IFACE=eth0)
stop on shutdown
respawn
script
touch /home/appinv/rendezvous.log
chown appinv /home/appinv/rendezvous.log
su -s /bin/sh -c 'exec "$0" "$@"' appinv -- /usr/local/bin/node /home/appinv/rendezvous.js >> /home/appinv/rendezvous.log 2>&1
end script
var http = require('http');
var requestHandler = http.IncomingMessage.prototype;
var memcache = require('memcache');
var mc = new memcache.Client();
mc.connect();
var querystring = require('querystring');
var fs = require('fs')
/*
* Database Handler
*
*/
var db = { 'connection' : null,
'insert' : function(key, ua, ip) {
var entry;
try {
var data = { 'key' : key, 'ip' : ip, 'ua' : ua,
'ts' : (new Date()).toISOString()};
this.queue.push(data);
if (!this.connection) {
console.log('Opening a new connection.');
if (!this.uri) {
console.log("Do not have URI yet, queuing.");
} else {
var nano = require('nano')(this.uri);
this.connection = nano.use('companion');
}
}
while (entry = this.queue.pop())
this.connection.insert(data);
} catch (err) {
console.log(err);
console.log(err.stack);
this.connection = null; // Force reconnect next time
}
},
'queue' : []
}
fs.readFile('/home/appinv/uri', function(err, data) {
if (err)
throw err;
db.uri = data.toString();
});
/**
* Add a uniform interface for remote address in Node.js
*
* From: https://gist.github.com/3rd-Eden/1740741
* @api private
*/
requestHandler.__defineGetter__('remote', function remote () {
var connection = this.connection
, headers = this.headers
, socket = connection.socket;
// return early if we are behind a reverse proxy
if (headers['x-forwarded-for']) {
return {
ip: headers['x-forwarded-for']
, port: headers['x-forwarded-port']
}
}
// regular HTTP servers
if (connection.remoteAddress) {
return {
ip: connection.remoteAddress
, port: connection.remotePort
};
}
// in node 0.4 the remote address for https servers was in a different
// location
if (socket.remoteAddress) {
return {
ip: socket.remoteAddress
, port: socket.remotePort
};
}
// last possible location..
return {
ip: this.socket.remoteAddress || '0.0.0.0'
, port: this.socket.remotePort || 0
}
});
var server = function(request, response) {
var data = "";
if (request.method == 'POST') { // A phone checking in
request.on('data', function(chunk) {
data += chunk.toString();
});
request.on('end', function() {
data = querystring.parse(data);
var key = data['key'];
if (key) {
var json = JSON.stringify(data);
mc.set('rr-' + key, json, 120); // Save for two minutes.
}
db.insert(key, request.headers['user-agent'], request.remote.ip);
response.writeHead(200, "OK", { "Content-Type" : "text/plain",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Headers" : "origin, content-type"});
response.end("OK\n");
});
} else if (request.method == 'OPTIONS') {
response.writeHead(200, "OK", { "Content-Type" : "text/html",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Headers" : "origin, content-type"});
response.end("");
} else {
var url = request.url.split('/');
var key = url[url.length-1];
if (key) {
mc.get('rr-' + key, function(err, result) {
response.writeHead(200, "OK", { "Content-Type" : "application/json",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Headers" : "origin, content-type"});
// console.log(request.remote);
response.end(result);
});
} else { // Not found
response.writeHead(200, "OK", { "Content-Type" : "application/json",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Headers" : "origin, content-type"});
response.end("");
}
}
}
http.createServer(server).listen(3000);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment