gun/lib/multicast.js
2020-02-08 02:02:36 -08:00

92 lines
3.0 KiB
JavaScript

var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
Gun.on('create', function(root){
this.to.next(root);
var opt = root.opt;
if(false === opt.multicast){ return }
if((typeof process !== "undefined") && 'false' === ''+(process.env||{}).MULTICAST){ return }
//if(true !== opt.multicast){ return } // disable multicast by default for now.
var udp = opt.multicast = opt.multicast || {};
udp.address = udp.address || '233.255.255.255';
udp.pack = udp.pack || 50000; // UDP messages limited to 65KB.
udp.port = udp.port || 8765;
var noop = function(){}, u;
var pid = '2'+Math.random().toString().slice(-8);
var mesh = opt.mesh = opt.mesh || Gun.Mesh(root);
var dgram;
try{ dgram = require("dgram") }catch(e){ return }
var socket = dgram.createSocket({type: "udp4", reuseAddr: true});
socket.bind({port: udp.port, exclusive: true}, function(){
socket.setBroadcast(true);
socket.setMulticastTTL(128);
});
socket.on("listening", function(){
try { socket.addMembership(udp.address) }catch(e){ console.error(e); return; }
udp.peer = {id: udp.address + ':' + udp.port, wire: socket};
udp.peer.say = function(raw){
var buf = Buffer.from(raw, 'utf8');
if(udp.pack <= buf.length){ // message too big!!!
return;
}
socket.send(buf, 0, buf.length, udp.port, udp.address, noop);
}
console.log('Multicast on', udp.peer.id);
return; // below code only needed for when WebSocket connections desired!
setInterval(function broadcast(){
port = port || (opt.web && opt.web.address()||{}).port;
if(!port){ return }
udp.peer.say(JSON.stringify({id: opt.pid || (opt.pid = Math.random().toString(36).slice(2)), port: port}));
}, 1000);
});
socket.on("message", function(raw, info) { try {
if(!raw){ return }
raw = raw.toString('utf8');
if('2'===raw[0]){ return check(raw, info) }
opt.mesh.hear(raw, udp.peer);
return; // below code only needed for when WebSocket connections desired!
var message;
message = JSON.parse(raw.toString('utf8'));
if(opt.pid === message.id){ return } // ignore self
var url = 'http://' + info.address + ':' + (port || (opt.web && opt.web.address()||{}).port) + '/gun';
if(root.opt.peers[url]){ return }
//console.log('discovered', url, message, info);
root.$.opt(url);
} catch(e){
//console.log('multicast error', e, raw);
return;
} });
function say(msg){
this.to.next(msg);
if(!udp.peer){ return }
mesh.say(msg, udp.peer);
}
function check(id, info){ var tmp;
if(!udp.peer){ return }
if(!id){
id = check.id = check.id || Buffer.from(pid, 'utf8');
socket.send(id, 0, id.length, udp.port, udp.address, noop);
return;
}
if((tmp = root.stats) && (tmp = tmp.gap) && info){ (tmp.near || (tmp.near = {}))[info.address] = info.port || 1 } // STATS!
if(check.on || id === pid){ return }
root.on('out', check.on = say); // TODO: MULTICAST NEEDS TO BE CHECKED FOR NEW CODE SYSTEM!!!!!!!!!!
}
setInterval(check, 1000 * 1);
});