ddat interop with dat js cable interop with cabal js ddat's frontend = dat-thang cable fe = cable-thang dillo support based on cel's dillo-dat bootstrap node xplatform support Signed-off-by: divo <418@cryspace.space>
100 lines
4.8 KiB
JavaScript
100 lines
4.8 KiB
JavaScript
'use strict'
|
|
|
|
// Narrow diagnostic: validates the installed Hyperswarm/HyperDHT package and
|
|
// the local bootstrap node independently of Cabal's Hypercore replication.
|
|
const assert = require('assert')
|
|
const crypto = require('crypto')
|
|
const dgram = require('dgram')
|
|
const { loadCabalCore } = require('./cable_hyperswarm')
|
|
|
|
const { requireCabal } = loadCabalCore()
|
|
const DHT = requireCabal('hyperdht')
|
|
const Swarm = requireCabal('hyperswarm')
|
|
|
|
function freePort () {
|
|
return new Promise((resolve, reject) => {
|
|
const socket = dgram.createSocket('udp4')
|
|
socket.once('error', reject)
|
|
socket.bind(0, '127.0.0.1', () => {
|
|
const port = socket.address().port
|
|
socket.close(err => err ? reject(err) : resolve(port))
|
|
})
|
|
})
|
|
}
|
|
|
|
async function main () {
|
|
const portA = await freePort()
|
|
const portB = await freePort()
|
|
const relayPort = await freePort()
|
|
const useBuiltin = process.env.HYPERSWARM_TEST_BUILTIN === '1'
|
|
const bootstrapPort = useBuiltin ? 0 : await freePort()
|
|
const bootstrap = useBuiltin ? null : DHT.bootstrapper(bootstrapPort, '127.0.0.1', { host: '127.0.0.1' })
|
|
const relay = useBuiltin ? null : new DHT({
|
|
bootstrap: ['127.0.0.1:' + bootstrapPort], host: '127.0.0.1', port: relayPort,
|
|
ephemeral: false, firewalled: false
|
|
})
|
|
const swarms = []
|
|
try {
|
|
if (bootstrap) await bootstrap.ready()
|
|
if (relay) await relay.ready()
|
|
if (bootstrap) console.log('bootstrap state', { id: Boolean(bootstrap.id), ephemeral: bootstrap.ephemeral, storage: Boolean(bootstrap._persistent) })
|
|
if (relay) console.log('relay state', { id: Boolean(relay.id), ephemeral: relay.ephemeral, storage: Boolean(relay._persistent) })
|
|
const endpoint = useBuiltin ? undefined : '127.0.0.1:' + relayPort
|
|
for (const port of [portA, portB]) {
|
|
const dht = new DHT({ ...(useBuiltin ? {} : { bootstrap: [endpoint] }), host: '127.0.0.1', port,
|
|
ephemeral: false, firewalled: false })
|
|
dht._nat.add('127.0.0.1', port)
|
|
const swarm = new Swarm({ dht })
|
|
dht.on('error', err => console.error('DHT error:', err.message))
|
|
swarm.on('error', err => console.error('swarm error:', err.message))
|
|
swarms.push(swarm)
|
|
}
|
|
const [a, b] = swarms
|
|
const topic = crypto.randomBytes(32)
|
|
let connected = 0
|
|
const onConnection = socket => { connected++; socket.on('error', () => {}) }
|
|
a.on('connection', onConnection)
|
|
b.on('connection', onConnection)
|
|
const onDiscoveryError = (label) => err => console.error(label + ' discovery error:', err && (err.stack || err))
|
|
const discoveryA = a.join(topic, { server: true, client: false, onerror: onDiscoveryError('A') })
|
|
const aFlushed = await discoveryA.flushed()
|
|
const discoveryB = b.join(topic, { server: false, client: true, onerror: onDiscoveryError('B') })
|
|
const bFlushed = await discoveryB.flushed()
|
|
console.log('Hyperswarm discovery flush:', aFlushed + '/' + bFlushed)
|
|
console.log('DHT node tables:', {
|
|
a: a.dht.toArray(), b: b.dht.toArray(),
|
|
relay: relay && relay.table.toArray().map(node => ({ host: node.host, port: node.port }))
|
|
})
|
|
if (relay) console.log('relay stored topic peers:', relay._persistent.records.get(topic.toString('hex'), 20).length)
|
|
const lookup = b.dht.lookup(topic)
|
|
const lookupResults = []
|
|
lookup.on('data', result => lookupResults.push(result.peers.length))
|
|
await lookup.finished()
|
|
console.log('explicit topic lookup peer counts:', lookupResults)
|
|
const deadline = Date.now() + 20000
|
|
while (connected < 2 && Date.now() < deadline) await new Promise(resolve => setTimeout(resolve, 100))
|
|
const discovered = connected >= 2
|
|
console.log('Hyperswarm state:', { connections: [a.connections.size, b.connections.size],
|
|
queued: [a.connecting, b.connecting], peerEntries: [a.peers.size, b.peers.size] })
|
|
if (!discovered) {
|
|
console.log('DHT discovery did not connect both local nodes; trying direct Hyperswarm peers to isolate transport')
|
|
a.joinPeer(b.keyPair.publicKey)
|
|
b.joinPeer(a.keyPair.publicKey)
|
|
const directDeadline = Date.now() + 10000
|
|
while (connected < 2 && Date.now() < directDeadline) await new Promise(resolve => setTimeout(resolve, 100))
|
|
}
|
|
assert(connected >= 2, 'local Hyperswarm peers failed direct transport too')
|
|
console.log('local Hyperswarm transport: PASS')
|
|
if (!discovered) {
|
|
console.error('local DHT discovery: FAIL (the bootstrap node did not yield peer addresses)')
|
|
process.exitCode = 1
|
|
} else console.log('local Hyperswarm DHT discovery: PASS')
|
|
} finally {
|
|
for (const swarm of swarms) { try { await swarm.destroy() } catch (_) {} }
|
|
if (relay) { try { await relay.destroy() } catch (_) {} }
|
|
if (bootstrap) { try { await bootstrap.destroy() } catch (_) {} }
|
|
}
|
|
}
|
|
|
|
main().catch(err => { console.error(err.stack || err); process.exitCode = 1 })
|