axe.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. ;(function(){
  2. /* UNBUILD */
  3. var root;
  4. if(typeof window !== "undefined"){ root = window }
  5. if(typeof global !== "undefined"){ root = global }
  6. root = root || {};
  7. var console = root.console || {log: function(){}};
  8. function USE(arg, req){
  9. return req? require(arg) : arg.slice? USE[R(arg)] : function(mod, path){
  10. arg(mod = {exports: {}});
  11. USE[R(path)] = mod.exports;
  12. }
  13. function R(p){
  14. return p.split('/').slice(-1).toString().replace('.js','');
  15. }
  16. }
  17. if(typeof module !== "undefined"){ var common = module }
  18. /* UNBUILD */
  19. ;USE(function(module){
  20. if(typeof window !== "undefined"){ module.window = window }
  21. var tmp = module.window || module;
  22. var AXE = tmp.AXE || function(){};
  23. if(AXE.window = module.window){ try{
  24. AXE.window.AXE = AXE;
  25. tmp = document.createEvent('CustomEvent');
  26. tmp.initCustomEvent('extension', false, false, {type: "AXE"});
  27. (window.dispatchEvent || window.fireEvent)(tmp);
  28. window.postMessage({type: "AXE"}, '*');
  29. } catch(e){} }
  30. try{ if(typeof common !== "undefined"){ common.exports = AXE } }catch(e){}
  31. module.exports = AXE;
  32. })(USE, './root');
  33. ;USE(function(module){
  34. var AXE = USE('./root'), Gun = (AXE.window||{}).Gun || USE('./gun', 1);
  35. (Gun.AXE = AXE).GUN = AXE.Gun = Gun;
  36. Gun.on('opt', function(at){
  37. if(!at.axe){
  38. at.axe = {};
  39. var peers = at.opt.peers, tmp;
  40. // 1. If any remembered peers or from last cache or extension
  41. // 2. Fallback to use hard coded peers from dApp
  42. // 3. Or any offered peers.
  43. //if(Gun.obj.empty(p)){
  44. // Gun.obj.map(['http://localhost:8765/gun'/*, 'https://guntest.herokuapp.com/gun'*/], function(url){
  45. // p[url] = {url: url, axe: {}};
  46. // });
  47. //}
  48. // Our current hypothesis is that it is most optimal
  49. // to take peers in a common network, and align
  50. // them in a line, where you only have left and right
  51. // peers, so messages propagate left and right in
  52. // a linear manner with reduced overlap, and
  53. // with one common superpeer (with ready failovers)
  54. // in case the p2p linear latency is high.
  55. // Or there could be plenty of other better options.
  56. console.log("axe");
  57. function verify(dht, msg, send, at) {
  58. var puts = Object.keys(msg.put);
  59. var soul = puts[0]; /// TODO: verify all souls in puts. Copy the msg only with subscribed souls?
  60. var subs = dht(soul);
  61. // console.log('[AXE] VERIFY soul: %s, subs: %s, Peers: %s, msg: ', soul, subs, Object.keys(peers), msg);
  62. if (!subs) { return; }
  63. var tmp = [];
  64. Gun.obj.map(subs.split(','), function(pid) {
  65. if (pid in peers) {
  66. tmp.push(pid);
  67. // console.log('[AXE] SEND TO >>>>> ', pid, msg.put.bob || msg.put);
  68. send(msg, peers[pid]);
  69. }
  70. });
  71. /// Only connected peers in the tmp array.
  72. if (at.on.opt.super) {
  73. dht(soul, tmp.join(','));
  74. }
  75. }
  76. var Rad = (Gun.window||{}).Radix || USE('./lib/radix', 1);
  77. at.opt.dht = Rad();
  78. at.on('in', input/*USE('./lib/super', 1)*/, at);
  79. // at.on('out', function(msg, a) {
  80. // this.to.next(msg);
  81. // console.log('[AXE] out:', msg, a);
  82. // }, at);
  83. if(at.opt.super){
  84. AXE.say = function(msg, send, at) {
  85. if (msg.rtc) {
  86. // console.log('[AXE] MSG WEBRTC: ', msg.rtc);
  87. if (msg.rtc.to) {
  88. /// Send announce to one peer only if the msg have 'to' attr
  89. var peer = (at.on.opt.peers) ? at.on.opt.peers[msg.rtc.to] : null;
  90. // if (peer) { at.on.opt.mesh.say(msg, peer); }
  91. if (peer) { send(msg, peer); }
  92. return;
  93. }
  94. }
  95. if (!msg.put) { send(msg); return; }
  96. //console.log('AXE HOOK!! ', msg);
  97. verify(at.on.opt.dht, msg, send, at);
  98. };
  99. } else {
  100. AXE.say = function(msg, send, at) {
  101. if (msg.rtc) {
  102. // console.log('[AXE] MSG WEBRTC: ', msg.rtc);
  103. }
  104. if (!msg.put) { send(msg); return; }
  105. verify(at.on.opt.dht, msg, send, at);
  106. /// Always send to superpeers?
  107. Gun.obj.map(at.on.opt.peers, function(peer) {
  108. if (peer.url) {
  109. // console.log('SEND TO SUPERPEER', msg);
  110. send(msg, peer);
  111. }
  112. });
  113. };
  114. var connections = 0;
  115. at.on('hi', function(opt) {
  116. this.to.next(opt);
  117. //console.log('AXE PEER [HI]', new Date(), opt);
  118. connections++;
  119. /// The first connection don't need to resubscribe the nodes.
  120. if (connections === 1) { return; }
  121. /// Resubscribe all nodes.
  122. setTimeout(function() {
  123. var souls = Object.keys(at.graph);
  124. for (var i=0; i < souls.length; ++i) {
  125. //at.gun.get(souls[i]).off();
  126. at.next[souls[i]].ack = 0;
  127. at.gun.get(souls[i]).once(function(){});
  128. }
  129. //location.reload();
  130. }, 500);
  131. }, at);
  132. }
  133. }
  134. this.to.next(at); // make sure to call the "next" middleware adapter.
  135. });
  136. function joindht(dht, soul, pids) {
  137. if (!pids || !soul || !dht) { return; }
  138. var subs = dht(soul);
  139. var tmp = subs ? subs.split(',') : [];
  140. Gun.obj.map(pids.split(','), function(pid) {
  141. if (pid && tmp.indexOf(pid) === -1) { tmp.push(pid); }
  142. });
  143. tmp = tmp.join(',');
  144. dht(soul, tmp);
  145. return tmp;
  146. }
  147. function input(msg){
  148. // console.log('[AXE] input: ', msg);
  149. var at = this.as, to = this.to, peer = (msg._||{}).via;
  150. var opt = at.opt;
  151. var dht = opt.dht;
  152. var get = msg.get, soul, key;
  153. if(peer && get){
  154. if(soul = get['#']){
  155. if(key = get['.']){
  156. } else {
  157. }
  158. if (!peer.id) {console.log('[*** WARN] no peer.id %s', soul);}
  159. var pids = joindht(dht, soul, peer.id);
  160. if (pids) {
  161. var dht = {};
  162. dht[soul] = pids;
  163. at.opt.mesh.say({dht:dht}, opt.peers[peer.id]);
  164. }
  165. }
  166. }
  167. to.next(msg);
  168. if (opt.rtc && msg.dht) {
  169. Gun.obj.map(msg.dht, function(pids, soul) {
  170. dht(soul, pids);
  171. Gun.obj.map(pids.split(','), function(pid) {
  172. /// TODO: here we can put an algorithm of who must connect?
  173. if (!pid || pid in opt.peers || pid === opt.pid || opt.announce[pid]) { return; }
  174. opt.announce[pid] = true; /// To try only one connection to the same peer.
  175. opt.announce(pid);
  176. });
  177. });
  178. }
  179. }
  180. module.exports = AXE;
  181. })(USE, './axe');
  182. }());