Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contrib/nodejs/dynamic-peers/lib/cjdns
92 changes: 92 additions & 0 deletions contrib/nodejs/dynamic-peers/lib/dynamic-peers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
var path = require('path');
var os = require('os');
var fs = require('fs');
var dns = require('dns');
var Promise = require('./promise');

var Cjdns = require('./cjdns/cjdnsadmin/cjdnsadmin');

var readFile = Promise.wrap(fs.readFile);
var resolve = Promise.wrap(dns.resolve);

var conf_name = process.env.conf;
if(!conf_name) conf_name = "cjdns_dynamic.conf";

readFile
(path.join(os.homedir(),".config",conf_name))
.then(JSON.parse)
.then(function (nodes) {
console.log("got nodes");
Cjdns.connectWithAdminInfo(function(cjdns) {
console.log("connected");
const peerStats =
Promise.wrap(cjdns.InterfaceController_peerStats);

function link_up(node) {
// can't attach port until the DNS lookup
var address = node.address + ":" + node.port;
console.log("link up", address, node.publicKey);
cjdns.UDPInterface_beginConnection(node.publicKey,
address,
node.password,
function() {
}
);
}
function lookup(node) {
if(node.name) {
resolve(node.name)
.then(function (addresses) {
node.address = addresses[0];
link_up(node);
// no need to wait for callback?
},function(err) {
print(err);
link_up(node)
});
} else {
link_up(node);
}
}

function collectPeers(then) {
var peers = {};
var count = 0;
function again(i) {
peerStats(i).then(function(ret) {
ret.peers.forEach(function (peer) {
if(peer.state != 'UNRESPONSIVE') {
if(!(peer.publicKey in peers))
++count;
peers[peer.publicKey] = peer;
}
});
if (typeof(ret.more) !== 'undefined') {
again(i+1);
} else {
then(peers,count);
setTimeout(function() {
collectPeers(then);
},10000);
}
});
}
again(0);
}

for(var key in nodes) {
var node = nodes[key];
node.publicKey = key;
}
collectPeers(function(peers,npeers) {
console.log("checking",npeers,"peers")
for(var key in nodes) {
if(key in peers) continue;
console.log("Peer not found",key,"poking.");
lookup(nodes[key]);
}
});
});
});


120 changes: 120 additions & 0 deletions contrib/nodejs/dynamic-peers/lib/promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// because depending on acorn is dumb

var sentinel = "unset";

const ACCEPT = true;
const REJECT = false;

var Promise = function(callback) {
var result = sentinel;
var err = sentinel;
var stages = [];
function doit(res,mode) {
if(result !== sentinel) {
throw new Error("Don't call this twice");
}
// don't you love tail recursion?
if(mode === ACCEPT) {
result = res;
} else {
err = res;
}
while(stages.length > 0) {
var stage = stages[0];
try {
if(mode === ACCEPT) {
res = stage.ok(res);
stages.shift();
} else {
while(!stage.err) {
if(stages.length == 0)
throw err;
stage = stages.shift();
}
res = stage.err(err,res);
mode = ACCEPT;
stages.shift();
}
} catch(e) {
mode = REJECT;
err = e;
stages.shift();
if(!stages.length)
throw e;
}
}
}
function accept(res) {
return doit(res,ACCEPT);
}
function reject(e) {
return doit(e,REJECT);
}
callback(accept,reject);
return {
then: function(ok,notok) {
// if already set, don't bother with stages
if(err !== sentinel && notok) {
notok(err,result);
return this;
}
if(result !== sentinel) {
ok(result);
return this;
}
var stage = {
ok: ok,
err: notok
};
stages.push(stage);
return this;
},
catch: function(notok) {
return this.then(undefined,notok);
}
}
}

module.exports = Promise;

Promise.wrap = function(fn) {
return function() {
var that = this;
var args = Array.prototype.slice.call(arguments);
return new Promise(function(accept,reject) {
args.push(function(err, res) {
if(err) reject(err);
else accept(res);
});
try { fn.apply(that, args); }
catch(e) {
reject(e);
}
});
}
}

Promise.all = function(promises) {
return new Promise(function(accept,reject) {
var results = new Array(promises.length);
var i = 0;
var count = 0;
for(var promise of promises) {
++count;
promise.then(function(res) {
results[i] = res;
if(count == 0) {
accept(results);
} else {
--count;
}
},function(err) {
reject(err);
});
}
});
}

Promise.success = new Promise(function(accept,reject) {
accept(true);
});
42 changes: 42 additions & 0 deletions contrib/nodejs/dynamic-peers/lib/test-promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
var Promise = require('./promise');
var fs = require('fs');

function dummyPromise() {
return new Promise(function(accept, reject) {
setTimeout(function() {
accept(0);
},1);
});
}
var p = dummyPromise();

p.then(function herp(i) {
return i + 19;
}).then(function derp(i) {
return i + 23;
}).then(function done(i) {
if(i != 42) {
throw new Error("Fail");
}
dummyPromise()
.then(function(i) {
throw new Error("failure");
},function(e) {
console.log("should never get here!");
})
.then(function(i) {
console.log("or here!");
},function(e) {
//console.log("got error",e);
throw new Error("something else went wrong");
})
.catch(function(e) {
//console.log("we caught e",e);
return 42;
})
.then(function(res) {
if(42 != res) throw new Error("fail...");
});
});


7 changes: 7 additions & 0 deletions contrib/nodejs/dynamic-peers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "cjdns-dynamic-peers",
"version": "0.1.1",
"dependencies": {
"cjdns": "~0.17.2"
}
}
Loading