summaryrefslogtreecommitdiff
path: root/cluster-geo
diff options
context:
space:
mode:
authorGrant Limberg <glimberg@gmail.com>2015-11-02 18:32:21 -0800
committerGrant Limberg <glimberg@gmail.com>2015-11-02 18:32:21 -0800
commit179b064b05460b706526a3249a25cd07232a42f5 (patch)
treed26dfeb2c02ce59c4a531142684695e45bb515ad /cluster-geo
parent75a191a8564030f4d5e99aca76b980e2d69abd20 (diff)
parent4e9d4304761f93a1764d3ec2d2b0c38140decad8 (diff)
downloadinfinitytier-179b064b05460b706526a3249a25cd07232a42f5.tar.gz
infinitytier-179b064b05460b706526a3249a25cd07232a42f5.zip
Merge branch 'edge' into android-jni-dev
Diffstat (limited to 'cluster-geo')
-rwxr-xr-xcluster-geo/cluster-geo.exe13
-rw-r--r--cluster-geo/cluster-geo/cluster-geo.js96
-rw-r--r--cluster-geo/cluster-geo/config.js.sample7
-rw-r--r--cluster-geo/cluster-geo/package.json16
4 files changed, 132 insertions, 0 deletions
diff --git a/cluster-geo/cluster-geo.exe b/cluster-geo/cluster-geo.exe
new file mode 100755
index 00000000..56b76e0d
--- /dev/null
+++ b/cluster-geo/cluster-geo.exe
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin
+
+cd `dirname $0`
+if [ ! -d cluster-geo -o ! -f cluster-geo/cluster-geo.js ]; then
+ echo 'Cannot find ./cluster-geo containing NodeJS script files.'
+ exit 1
+fi
+
+cd cluster-geo
+
+exec node --harmony cluster-geo.js
diff --git a/cluster-geo/cluster-geo/cluster-geo.js b/cluster-geo/cluster-geo/cluster-geo.js
new file mode 100644
index 00000000..44af8492
--- /dev/null
+++ b/cluster-geo/cluster-geo/cluster-geo.js
@@ -0,0 +1,96 @@
+"use strict";
+
+//
+// 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 {
+ let cachedEntry = JSON.parse(cachedEntryJson.toString());
+ if (cachedEntry) {
+ let ts = cachedEntry.ts;
+ let 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) {
+ let c = chunk[i];
+ if ((c == 0x0d)||(c == 0x0a)) {
+ if (linebuf.length > 0) {
+ let 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 {
+ let lat = parseFloat(result.location.latitude);
+ let lon = parseFloat(result.location.longitude);
+
+ // Convert to X,Y,Z coordinates from Earth's origin, Earth-as-sphere approximation.
+ let latRadians = lat * 0.01745329251994; // PI / 180
+ let lonRadians = lon * 0.01745329251994; // PI / 180
+ let cosLat = Math.cos(latRadians);
+ let x = Math.round((-6371.0) * cosLat * Math.cos(lonRadians)); // 6371 == Earth's approximate radius in kilometers
+ let y = Math.round(6371.0 * Math.sin(latRadians));
+ let 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/cluster-geo/config.js.sample b/cluster-geo/cluster-geo/config.js.sample
new file mode 100644
index 00000000..ec1ebfea
--- /dev/null
+++ b/cluster-geo/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/cluster-geo/package.json b/cluster-geo/cluster-geo/package.json
new file mode 100644
index 00000000..4cd1ce00
--- /dev/null
+++ b/cluster-geo/cluster-geo/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "cluster-geo",
+ "version": "1.0.0",
+ "description": "Cluster GEO-IP Query Service",
+ "main": "cluster-geo.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"
+ }
+}