multicast.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
  2. Gun.on('create', function(root){
  3. this.to.next(root);
  4. var opt = root.opt;
  5. if(false === opt.multicast){ return }
  6. if((typeof process !== "undefined") && 'false' === ''+(process.env||{}).MULTICAST){ return }
  7. //if(true !== opt.multicast){ return } // disable multicast by default for now.
  8. var udp = opt.multicast = opt.multicast || {};
  9. udp.address = udp.address || '233.255.255.255';
  10. udp.pack = udp.pack || 50000; // UDP messages limited to 65KB.
  11. udp.port = udp.port || 8765;
  12. var noop = function(){}, u;
  13. var pid = '2'+Math.random().toString().slice(-8);
  14. var mesh = opt.mesh = opt.mesh || Gun.Mesh(root);
  15. var dgram;
  16. try{ dgram = require("dgram") }catch(e){ return }
  17. var socket = dgram.createSocket({type: "udp4", reuseAddr: true});
  18. socket.bind({port: udp.port, exclusive: true}, function(){
  19. socket.setBroadcast(true);
  20. socket.setMulticastTTL(128);
  21. });
  22. socket.on("listening", function(){
  23. try { socket.addMembership(udp.address) }catch(e){ console.error(e); return; }
  24. udp.peer = {id: udp.address + ':' + udp.port, wire: socket};
  25. udp.peer.say = function(raw){
  26. var buf = Buffer.from(raw, 'utf8');
  27. if(udp.pack <= buf.length){ // message too big!!!
  28. return;
  29. }
  30. socket.send(buf, 0, buf.length, udp.port, udp.address, noop);
  31. }
  32. console.log('Multicast on', udp.peer.id);
  33. return; // below code only needed for when WebSocket connections desired!
  34. setInterval(function broadcast(){
  35. port = port || (opt.web && opt.web.address()||{}).port;
  36. if(!port){ return }
  37. udp.peer.say(JSON.stringify({id: opt.pid || (opt.pid = Math.random().toString(36).slice(2)), port: port}));
  38. }, 1000);
  39. });
  40. socket.on("message", function(raw, info) { try {
  41. if(!raw){ return }
  42. raw = raw.toString('utf8');
  43. if('2'===raw[0]){ return check(raw, info) }
  44. opt.mesh.hear(raw, udp.peer);
  45. return; // below code only needed for when WebSocket connections desired!
  46. var message;
  47. message = JSON.parse(raw.toString('utf8'));
  48. if(opt.pid === message.id){ return } // ignore self
  49. var url = 'http://' + info.address + ':' + (port || (opt.web && opt.web.address()||{}).port) + '/gun';
  50. if(root.opt.peers[url]){ return }
  51. //console.log('discovered', url, message, info);
  52. root.$.opt(url);
  53. } catch(e){
  54. //console.log('multicast error', e, raw);
  55. return;
  56. } });
  57. function say(msg){
  58. this.to.next(msg);
  59. if(!udp.peer){ return }
  60. mesh.say(msg, udp.peer);
  61. }
  62. function check(id, info){ var tmp;
  63. if(!udp.peer){ return }
  64. if(!id){
  65. id = check.id = check.id || Buffer.from(pid, 'utf8');
  66. socket.send(id, 0, id.length, udp.port, udp.address, noop);
  67. return;
  68. }
  69. if((tmp = root.stats) && (tmp = tmp.gap) && info){ (tmp.near || (tmp.near = {}))[info.address] = info.port || 1 } // STATS!
  70. if(check.on || id === pid){ return }
  71. root.on('out', check.on = say); // TODO: MULTICAST NEEDS TO BE CHECKED FOR NEW CODE SYSTEM!!!!!!!!!!
  72. }
  73. setInterval(check, 1000 * 1);
  74. });