summaryrefslogtreecommitdiff
path: root/cluster-geo
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2015-10-21 12:41:46 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2015-10-21 12:41:46 -0700
commit25a84e30fc7cedf2cc45970ecbe0df64886394e0 (patch)
treee23cbb35d1abf032cf4e7d7f8ed3e949592f84da /cluster-geo
parent978b056a0134edd9598a3edb219b31c61405c3b4 (diff)
downloadinfinitytier-25a84e30fc7cedf2cc45970ecbe0df64886394e0.tar.gz
infinitytier-25a84e30fc7cedf2cc45970ecbe0df64886394e0.zip
Code for cluster-geo service.
Diffstat (limited to 'cluster-geo')
-rw-r--r--cluster-geo/config.js.sample7
-rw-r--r--cluster-geo/index.js94
-rw-r--r--cluster-geo/package.json16
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"
+ }
+}