Code for cluster-geo service.

This commit is contained in:
Adam Ierymenko 2015-10-21 12:41:46 -07:00
parent 978b056a01
commit 25a84e30fc
4 changed files with 121 additions and 10 deletions

14
.gitignore vendored
View file

@ -49,23 +49,17 @@ Thumbs.db
*.rpm
*.autosave
*.tmp
node_modules
# Root topology build files, temporaries, and never check in secrets
/root-topology/bin2c
/root-topology/mktopology
/root-topology/*.secret
/root-topology/test/supernodes
/root-topology/test/test-root-topology
# cluster-geo stuff
cluster-geo/config.js
cluster-geo/cache.*
# MacGap wrapper build files
/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/*
/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/xcuserdata/*
/ext/mac-ui-macgap1-wrapper/src/build
# Web UI dev temporaries
/ui/.module-cache
node_modules
# Java/Android/JNI build droppings
java/obj/
java/libs/

View file

@ -0,0 +1,7 @@
// MaxMind GeoIP2 config
module.exports.maxmind = {
userId: 1234,
licenseKey: 'asdf',
service: 'city',
requestTimeout: 1000
};

94
cluster-geo/index.js Normal file
View file

@ -0,0 +1,94 @@
//
// GeoIP lookup service
//
// GeoIP cache TTL in ms
var CACHE_TTL = (60 * 60 * 24 * 60 * 1000); // 60 days
var config = require(__dirname + '/config.js');
if (!config.maxmind) {
console.error('FATAL: only MaxMind GeoIP2 is currently supported and is not configured in config.js');
process.exit(1);
}
var geo = require('geoip2ws')(config.maxmind);
var cache = require('levelup')(__dirname + '/cache.leveldb');
function lookup(ip,callback)
{
cache.get(ip,function(err,cachedEntryJson) {
if ((!err)&&(cachedEntryJson)) {
try {
var cachedEntry = JSON.parse(cachedEntryJson.toString());
if (cachedEntry) {
var ts = cachedEntry.ts;
var r = cachedEntry.r;
if ((ts)&&(r)) {
if ((Date.now() - ts) < CACHE_TTL) {
r._cached = true;
return callback(null,r);
}
}
}
} catch (e) {}
}
geo(ip,function(err,result) {
if (err)
return callback(err,null);
if ((!result)||(!result.location))
return callback(new Error('null result'),null);
cache.put(ip,JSON.stringify({
ts: Date.now(),
r: result
}),function(err) {
if (err)
console.error('Error saving to cache: '+err);
return callback(null,result);
});
});
});
};
var linebuf = '';
process.stdin.on('readable',function() {
var chunk;
while (null !== (chunk = process.stdin.read())) {
for(var i=0;i<chunk.length;++i) {
var c = chunk[i];
if ((c == 0x0d)||(c == 0x0a)) {
if (linebuf.length > 0) {
var ip = linebuf;
lookup(ip,function(err,result) {
if ((err)||(!result)||(!result.location)) {
return process.stdout.write(ip+',0,0,0,0,0,0\n');
} else {
var lat = parseFloat(result.location.latitude);
var lon = parseFloat(result.location.longitude);
// Convert to X,Y,Z coordinates from Earth's origin, Earth-as-sphere approximation.
var latRadians = lat * 0.01745329251994; // PI / 180
var lonRadians = lon * 0.01745329251994; // PI / 180
var cosLat = Math.cos(latRadians);
var x = Math.round((-6371.0) * cosLat * Math.cos(lonRadians)); // 6371 == Earth's approximate radius in kilometers
var y = Math.round(6371.0 * Math.sin(latRadians));
var z = Math.round(6371.0 * cosLat * Math.sin(lonRadians));
return process.stdout.write(ip+',1,'+lat+','+lon+','+x+','+y+','+z+'\n');
}
});
}
linebuf = '';
} else {
linebuf += String.fromCharCode(c);
}
}
}
});
process.stdin.on('end',function() {
cache.close();
process.exit(0);
});

16
cluster-geo/package.json Normal file
View file

@ -0,0 +1,16 @@
{
"name": "cluster-geo",
"version": "1.0.0",
"description": "Cluster GEO-IP Query Service",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "ZeroTier, Inc.",
"license": "GPL-3.0",
"dependencies": {
"geoip2ws": "^1.7.1",
"leveldown": "^1.4.2",
"levelup": "^1.2.1"
}
}