summaryrefslogtreecommitdiff
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
parent978b056a0134edd9598a3edb219b31c61405c3b4 (diff)
downloadinfinitytier-25a84e30fc7cedf2cc45970ecbe0df64886394e0.tar.gz
infinitytier-25a84e30fc7cedf2cc45970ecbe0df64886394e0.zip
Code for cluster-geo service.
-rwxr-xr-x.gitignore14
-rw-r--r--cluster-geo/config.js.sample7
-rw-r--r--cluster-geo/index.js94
-rw-r--r--cluster-geo/package.json16
4 files changed, 121 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index 2dbec1e5..d314b3fc 100755
--- a/.gitignore
+++ b/.gitignore
@@ -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/
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"
+ }
+}