main.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. "use strict"
  2. require([ "bacon"
  3. , "lib/helper"
  4. , "lib/streams"
  5. , "lib/gui"
  6. ], function(Bacon, Helper, Streams, GUI) {
  7. var mgmtBus = new Bacon.Bus()
  8. mgmtBus.pushEvent = function (key, a) {
  9. var v = [key].concat(a)
  10. return this.push(v)
  11. }
  12. mgmtBus.onEvent = function (events) {
  13. return this.onValue(function (e) {
  14. var d = e.slice() // shallow copy so calling shift doesn't change it
  15. var ev = d.shift()
  16. if (ev in events)
  17. events[ev].apply(this, d)
  18. })
  19. }
  20. var nodesBusIn = new Bacon.Bus()
  21. var nodesBus = nodesBusIn.scan({ "nodes": {}
  22. , "macs": {}
  23. }, scanNodeInfo)
  24. new GUI(mgmtBus, nodesBus)
  25. mgmtBus.onEvent({ "goto": gotoNode
  26. , "nodeinfo": function (d) { nodesBusIn.push(d) }
  27. })
  28. function tryIp(ip) {
  29. return Helper.request(ip, "nodeinfo").map(function () { return ip })
  30. }
  31. var gotoEpoch = 0
  32. function onEpoch(epoch, f) {
  33. return function (d) {
  34. if (epoch === gotoEpoch)
  35. return f(d)
  36. }
  37. }
  38. function gotoNode(nodeInfo) {
  39. gotoEpoch++
  40. var addresses = nodeInfo.network.addresses.filter(function (d) { return !/^fe80:/.test(d) })
  41. var race = Bacon.fromArray(addresses).flatMap(tryIp).withStateMachine([], function (acc, ev) {
  42. if (ev.isError())
  43. return [acc.concat(ev.error), []]
  44. else if (ev.isEnd() && acc.length > 0)
  45. return [undefined, [new Bacon.Error(acc), ev]]
  46. else if (ev.hasValue())
  47. return [[], [ev, new Bacon.End()]]
  48. })
  49. race.onValue(onEpoch(gotoEpoch, function (d) {
  50. mgmtBus.pushEvent("arrived", [nodeInfo, d])
  51. }))
  52. race.onError(onEpoch(gotoEpoch, function () {
  53. mgmtBus.pushEvent("gotoFailed", nodeInfo)
  54. }))
  55. }
  56. function scanNodeInfo(a, nodeInfo) {
  57. a.nodes[nodeInfo.node_id] = nodeInfo
  58. var mesh = Helper.dictGet(nodeInfo, ["network", "mesh"])
  59. if (mesh)
  60. for (var m in mesh)
  61. for (var ifname in mesh[m].interfaces)
  62. mesh[m].interfaces[ifname].forEach( function (d) {
  63. a.macs[d] = nodeInfo
  64. })
  65. return a
  66. }
  67. if (localStorage.nodes)
  68. JSON.parse(localStorage.nodes).forEach(nodesBusIn.push)
  69. nodesBus.map(".nodes").onValue(function (nodes) {
  70. var out = []
  71. for (var k in nodes)
  72. out.push(nodes[k])
  73. localStorage.nodes = JSON.stringify(out)
  74. })
  75. var bootstrap = Helper.getJSON(bootstrapUrl)
  76. bootstrap.onError(function () {
  77. console.log("FIXME bootstrapping failed")
  78. })
  79. bootstrap.onValue(function (d) {
  80. mgmtBus.pushEvent("nodeinfo", d)
  81. mgmtBus.pushEvent("goto", d)
  82. })
  83. })