diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-10-21 12:41:46 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-10-21 12:41:46 -0700 |
commit | 25a84e30fc7cedf2cc45970ecbe0df64886394e0 (patch) | |
tree | e23cbb35d1abf032cf4e7d7f8ed3e949592f84da /cluster-geo | |
parent | 978b056a0134edd9598a3edb219b31c61405c3b4 (diff) | |
download | infinitytier-25a84e30fc7cedf2cc45970ecbe0df64886394e0.tar.gz infinitytier-25a84e30fc7cedf2cc45970ecbe0df64886394e0.zip |
Code for cluster-geo service.
Diffstat (limited to 'cluster-geo')
-rw-r--r-- | cluster-geo/config.js.sample | 7 | ||||
-rw-r--r-- | cluster-geo/index.js | 94 | ||||
-rw-r--r-- | cluster-geo/package.json | 16 |
3 files changed, 117 insertions, 0 deletions
diff --git a/cluster-geo/config.js.sample b/cluster-geo/config.js.sample new file mode 100644 index 00000000..ec1ebfea --- /dev/null +++ b/cluster-geo/config.js.sample @@ -0,0 +1,7 @@ +// MaxMind GeoIP2 config +module.exports.maxmind = { + userId: 1234, + licenseKey: 'asdf', + service: 'city', + requestTimeout: 1000 +}; diff --git a/cluster-geo/index.js b/cluster-geo/index.js new file mode 100644 index 00000000..0e903ade --- /dev/null +++ b/cluster-geo/index.js @@ -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); +}); diff --git a/cluster-geo/package.json b/cluster-geo/package.json new file mode 100644 index 00000000..1927197e --- /dev/null +++ b/cluster-geo/package.json @@ -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" + } +} |