zeronet-swarm
Version:
libp2p based ZeroNet swarm
127 lines (107 loc) • 3.4 kB
JavaScript
// basics
const Libp2p = require('libp2p')
const series = require('async/series')
const LProtocol = require('zeronet-protocol').Lp2p
const debug = require('debug')
const log = debug('zeronet:swarm:libp2p')
// multiformats
const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr')
// libp2p connection
const SPDY = require('libp2p-spdy')
const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
// websocket-star
const WebsocketStarMulti = require('libp2p-websocket-star-multi')
// discovery
const Railing = require('libp2p-railing')
const MulticastDNS = require('libp2p-mdns')
// dht
const DHT = require('libp2p-kad-dht')
function Libp2pSwarm (opt, protocol, zeronet) {
const self = this
log('creating libp2p swarm')
const peerInfo = new PeerInfo(opt.id)
self.idB58 = opt.id.toB58String()
let listen = opt.listen || []
listen.forEach(addr => peerInfo.multiaddrs.add(multiaddr(addr)))
self.adv = []
let dht
let discovery = []
let transport = opt.transports || []
if (opt.bootstrap && opt.bootstrap.length) {
discovery.push(new Railing(opt.bootstrap))
log('enabled bootstrap with %s peer(s)', opt.bootstrap.length)
}
if (opt.mdns) {
discovery.push(new MulticastDNS(peerInfo, 'zeronet'))
log('enabled multicast-dns')
}
if (opt.dht) dht = DHT
if (opt.custom_dht) dht = opt.custom_dht
if (dht) log('enabled dht')
if (opt.wstar) { // wstar is an array with servers for wstar multi
const wsm = new WebsocketStarMulti({
servers: opt.wstar,
ignore_no_online: opt.wstar_ignore,
id: opt.id
})
peerInfo.multiaddrs.add(multiaddr('/p2p-websocket-star'))
transport.push(wsm)
discovery.push(wsm.discovery)
log('enabled websocket-star-multi with %s server(s) (ignore if unreachable %s)', opt.wstar.length, opt.wstar_ignore || false)
}
const modules = {
transport,
connection: {
muxer: [
MPLEX,
SPDY
],
crypto: [SECIO]
},
discovery: (opt.discover || []).concat(discovery),
dht
}
const options = {
/* relay: {
enabled: true,
hop: {
enabled: true,
active: false // passive relay
}
} */
}
const lp2p = self.lp2p = self.libp2p = new Libp2p(modules, peerInfo, /* peerBook */ null, options)
const swarm = lp2p
swarm.on('peer:discovery', pi => {
if (pi.id.toB58String() === peerInfo.id.toB58String()) return
const next = () => swarm.dial(pi, () => {})
if (swarm.isStarted()) next()
else swarm.once('start', () => process.nextTick(next))
})
swarm.on('peer:connect', peer => {
if (peer.id.toB58String() === peerInfo.id.toB58String()) return
const npeer = zeronet.peerPool.add(peer)
if (!npeer) return
const next = () => npeer.dial(() => {})
if (swarm.isStarted()) next()
else swarm.once('start', () => process.nextTick(next))
})
self.start = cb => series([
cb => lp2p.start(cb),
cb => {
self.adv = []
peerInfo.multiaddrs.forEach(ma => self.adv.push(ma.toString()))
cb()
}
], cb)
self.stop = cb => {
delete lp2p.switch.muxedConns['']
lp2p.stop(cb)
}
self.dial = (peer, proto, cb) => typeof proto === 'function' ? lp2p.dial(peer, cb) : lp2p.dialProtocol(peer, proto, cb)
self.proto = self.protocol = new LProtocol({}, self)
}
module.exports = Libp2pSwarm