"use strict" require([ "bacon" , "lib/helper" , "lib/streams" , "lib/gui" ], function(Bacon, Helper, Streams, GUI) { var mgmtBus = new Bacon.Bus() mgmtBus.pushEvent = function (key, a) { var v = [key].concat(a) return this.push(v) } mgmtBus.onEvent = function (events) { return this.onValue(function (e) { var d = e.slice() // shallow copy so calling shift doesn't change it var ev = d.shift() if (ev in events) events[ev].apply(this, d) }) } var nodesBusIn = new Bacon.Bus() var nodesBus = nodesBusIn.scan({ "nodes": {} , "macs": {} }, scanNodeInfo) new GUI(mgmtBus, nodesBus) mgmtBus.onEvent({ "goto": gotoNode , "nodeinfo": function (d) { nodesBusIn.push(d) } }) function tryIp(ip) { return Helper.request(ip, "nodeinfo").map(function () { return ip }) } var gotoEpoch = 0 function onEpoch(epoch, f) { return function (d) { if (epoch === gotoEpoch) return f(d) } } function gotoNode(nodeInfo) { gotoEpoch++ var addresses = nodeInfo.network.addresses.filter(function (d) { return !/^fe80:/.test(d) }) var race = Bacon.fromArray(addresses).flatMap(tryIp).withStateMachine([], function (acc, ev) { if (ev.isError()) return [acc.concat(ev.error), []] else if (ev.isEnd() && acc.length > 0) return [undefined, [new Bacon.Error(acc), ev]] else if (ev.hasValue()) return [[], [ev, new Bacon.End()]] }) race.onValue(onEpoch(gotoEpoch, function (d) { mgmtBus.pushEvent("arrived", [nodeInfo, d]) })) race.onError(onEpoch(gotoEpoch, function () { mgmtBus.pushEvent("gotoFailed", nodeInfo) })) } function scanNodeInfo(a, nodeInfo) { a.nodes[nodeInfo.node_id] = nodeInfo var mesh = Helper.dictGet(nodeInfo, ["network", "mesh"]) if (mesh) for (var m in mesh) for (var ifname in mesh[m].interfaces) mesh[m].interfaces[ifname].forEach( function (d) { a.macs[d] = nodeInfo }) return a } if (localStorage.nodes) JSON.parse(localStorage.nodes).forEach(nodesBusIn.push) nodesBus.map(".nodes").onValue(function (nodes) { var out = [] for (var k in nodes) out.push(nodes[k]) localStorage.nodes = JSON.stringify(out) }) var bootstrap = Helper.getJSON(bootstrapUrl) bootstrap.onError(function () { console.log("FIXME bootstrapping failed") }) bootstrap.onValue(function (d) { mgmtBus.pushEvent("nodeinfo", d) mgmtBus.pushEvent("goto", d) }) })