hyperswarm
Advanced tools
Comparing version 2.3.1 to 2.4.0
'use strict' | ||
const { EventEmitter } = require('events') | ||
module.exports = peer => new PeerInfo(peer) | ||
module.exports = (peer, queue) => new PeerInfo(peer, queue) | ||
@@ -17,3 +17,3 @@ const PROVEN = 0b1 | ||
class PeerInfo extends EventEmitter { | ||
constructor (peer = null) { | ||
constructor (peer = null, queue) { | ||
super() | ||
@@ -26,4 +26,6 @@ this.priority = (peer && peer.local) ? 3 : 2 | ||
this.stream = null | ||
this.duplicate = null | ||
this.topics = [] | ||
this._index = 0 | ||
this._queue = queue | ||
} | ||
@@ -43,2 +45,6 @@ | ||
deduplicate (remoteId, localId) { | ||
return this._queue.deduplicate(remoteId, localId, this) | ||
} | ||
backoff () { | ||
@@ -45,0 +51,0 @@ // server can not backoff: |
@@ -53,6 +53,56 @@ 'use strict' | ||
}) | ||
this._dedup = new Map() | ||
} | ||
deduplicate (localId, remoteId, peer) { | ||
const id = localId.toString('hex') + '\n' + remoteId.toString('hex') | ||
const other = this._dedup.get(id) | ||
if (!other) { | ||
this._dedup.set(id, peer) | ||
peer.stream.on('close', this._ondedupclose.bind(this, peer, id)) | ||
return false | ||
} | ||
const cmp = Buffer.compare(localId, remoteId) | ||
if (cmp === 0) { | ||
// destroy and ban connections to ourself | ||
other.destroy(new Error('Connected to self')) | ||
peer.destroy(new Error('Connected to self')) | ||
return true | ||
} | ||
if (cmp < 0 ? peer.client : !peer.client) { | ||
if (other.client && !other.banned) peer.duplicate = other | ||
other.destroy(new Error('Duplicate connection')) | ||
this._dedup.set(id, peer) | ||
peer.stream.on('close', this._ondedupclose.bind(this, peer, id)) | ||
return false | ||
} | ||
if (peer.client && !peer.banned) other.duplicate = peer | ||
peer.destroy(new Error('Duplicate connection')) | ||
return true | ||
} | ||
_ondedupclose (peer, id) { | ||
if (this._dedup.get(id) === peer) this._dedup.delete(id) | ||
if (!peer.duplicate || !peer.duplicate.client || !peer.duplicate.banned) return | ||
// double check that this is exactly the one we banned earlier | ||
if (this._infos === null || this._infos.get(toID(peer.duplicate.peer, this._multiplex)) !== peer.duplicate) return | ||
// remove and add to give it lowest possible prio | ||
this.remove(peer.duplicate.peer) | ||
this.add(peer.duplicate.peer) | ||
} | ||
_release (batch) { | ||
for (const info of batch) this.remove(info.peer) | ||
} | ||
_push (batch) { | ||
@@ -105,3 +155,3 @@ const empty = !this._queue.head() | ||
if (!info) { | ||
info = peerInfo(peer) | ||
info = peerInfo(peer, this) | ||
this._infos.set(id, info) | ||
@@ -123,3 +173,3 @@ } | ||
const id = toID(peer) | ||
const id = toID(peer, this._multiplex) | ||
const info = this._infos.get(id) | ||
@@ -126,0 +176,0 @@ |
{ | ||
"name": "hyperswarm", | ||
"version": "2.3.1", | ||
"version": "2.4.0", | ||
"description": "A distributed networking stack for connecting peers", | ||
@@ -5,0 +5,0 @@ "main": "swarm.js", |
@@ -61,3 +61,5 @@ # hyperswarm | ||
maxClientSockets: Infinity, | ||
// configure peer management behaviour | ||
// apply a filter before connecting to the peer | ||
validatePeer: (peer) => true, | ||
// configure peer management behaviour | ||
queue = { | ||
@@ -77,3 +79,3 @@ // an array of backoff times, in millieconds | ||
unresponsive: 7500, | ||
// how long to wait before fogetting that a peer | ||
// how long to wait before fogetting that a peer | ||
// has been banned | ||
@@ -124,3 +126,3 @@ banned: Infinity | ||
#### `swarm.on('connection', (socket, details) => {})` | ||
#### `swarm.on('connection', (socket, info) => {})` | ||
@@ -130,3 +132,3 @@ A new connection has been created. You should handle this event by using the socket. | ||
- `socket`. The established TCP or UTP socket. | ||
- `details`. Object describing the connection. | ||
- `info`. Object describing the connection. | ||
- `type`. String. Should be either `'tcp'` or `'utp'`. | ||
@@ -144,7 +146,29 @@ - `client`. Boolean. If true, the connection was initiated by this node. | ||
- `topic`. Buffer. The identifier which this peer was discovered under. | ||
The `details` argument is a `PeerInfo` object, which will emit events of the form `details.on('topic', topic => ...)` when the `multiplex` flag is `true`. | ||
#### `swarm.on('disconnection', (socket, details) => {})` | ||
#### `info.ban()` | ||
Call this to ban this peer. Makes the swarm stop connecting to it. | ||
#### `info.backoff()` | ||
Call this to make the swarm backoff reconnecting to this peer. | ||
Can be called multiple times to backoff more. | ||
#### `dropped = info.deduplicate(localIdBuffer, remoteIdBuffer)` | ||
Use this method to deduplicate connections. | ||
When two swarms both announce and do lookups on the same topic you'll get duplicate connections | ||
between them (one client connection and one server connection each). | ||
If you exchange some sort of peer id between them you can use this method to make Hyperswarm | ||
deduplicate those connection (ie drop one of them deterministically). | ||
If it returns true then this current connection was dropped due to deduplication and is auto removed. | ||
Only call this once per connection. | ||
#### `swarm.on('disconnection', (socket, info) => {})` | ||
A connection has been dropped. | ||
@@ -170,4 +194,18 @@ | ||
#### `swarm.on('peer-rejected', (peer) => {})` | ||
A peer has been rejected as a connection candidate. | ||
- `peer`. Object describing the peer. | ||
- `port`. Number. | ||
- `host`. String. The IP address of the peer. | ||
- `local`. Boolean. Is the peer on the LAN? | ||
- `referrer`. Object. The address of the node that informed us of the peer. | ||
- `port`. Number. | ||
- `host`. String. The IP address of the referrer. | ||
- `id`. Buffer. | ||
- `topic`. Buffer. The identifier which this peer was discovered under. | ||
#### `swarm.on('updated', ({ key }) => {})` | ||
Emitted once a discovery cycle for a particular topic has completed. The topic can be identified by the `key` property of the emitted object. After this event the peer will wait for period of between 5 and 10 minutes before looking for new peers on that topic again. |
@@ -32,2 +32,3 @@ 'use strict' | ||
ephemeral, | ||
validatePeer = () => true, | ||
queue = {} | ||
@@ -42,3 +43,3 @@ } = opts | ||
socket: (socket, isTCP) => { | ||
const info = peerInfo(null) | ||
const info = peerInfo(null, this[kQueue]) | ||
info.connected(socket, isTCP) | ||
@@ -73,2 +74,4 @@ this.emit('connection', socket, info) | ||
this.validatePeer = validatePeer | ||
this[kQueue] = peerQueue(queue) | ||
@@ -159,2 +162,6 @@ this[kQueue].on('readable', this[kDrain](this[kQueue])) | ||
topic.on('peer', (peer) => { | ||
if (!this.validatePeer(peer)) { | ||
this.emit('peer-rejected', peer) | ||
return | ||
} | ||
this.emit('peer', peer) | ||
@@ -161,0 +168,0 @@ this[kQueue].add(peer) |
@@ -94,5 +94,11 @@ 'use strict' | ||
const { peer: peer1 } = q.shift() | ||
const { peer: peer2 } = q.shift() | ||
let { peer: peer1 } = q.shift() | ||
let { peer: peer2 } = q.shift() | ||
if (peer1.topic.equals(Buffer.from('world'))) { | ||
const tmp = peer2 | ||
peer2 = peer1 | ||
peer1 = tmp | ||
} | ||
same(peer1, { port: 8000, host: '127.0.0.1', topic: Buffer.from('hello') }) | ||
@@ -99,0 +105,0 @@ same(peer2, { port: 8000, host: '127.0.0.1', topic: Buffer.from('world') }) |
@@ -5,3 +5,3 @@ 'use strict' | ||
const { NetworkResource } = require('@hyperswarm/network') | ||
const { test, skip, only } = require('tap') | ||
const { test } = require('tap') | ||
const { once, done, promisifyMethod, whenifyMethod } = require('nonsynchronous') | ||
@@ -13,3 +13,5 @@ const { dhtBootstrap, validSocket } = require('./util') | ||
test('default ephemerality', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ | ||
bootstrap: [] | ||
}) | ||
is(swarm.ephemeral, true) | ||
@@ -23,3 +25,5 @@ promisifyMethod(swarm, 'listen') | ||
test('destroyed property', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ | ||
bootstrap: [] | ||
}) | ||
swarm.listen() | ||
@@ -32,4 +36,7 @@ is(swarm.destroyed, false) | ||
test('network property', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ | ||
bootstrap: [] | ||
}) | ||
is(swarm.network instanceof NetworkResource, true) | ||
swarm.destroy() | ||
}) | ||
@@ -39,3 +46,4 @@ | ||
const swarm = hyperswarm({ | ||
ephemeral: false | ||
ephemeral: false, | ||
bootstrap: [] | ||
}) | ||
@@ -56,8 +64,7 @@ is(swarm.ephemeral, false) | ||
is(swarm.network.discovery.dht.bootstrapNodes[0].port, port) | ||
swarm.destroy() | ||
closeDht() | ||
closeDht(swarm) | ||
}) | ||
test('emits listening event when bound', async ({ pass }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
swarm.listen() | ||
@@ -70,3 +77,3 @@ await once(swarm, 'listening') | ||
test('emits close event when destroyed', async ({ pass }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
promisifyMethod(swarm, 'listen') | ||
@@ -80,3 +87,3 @@ await swarm.listen() | ||
test('join - missing key', async ({ throws }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
promisifyMethod(swarm, 'listen') | ||
@@ -90,3 +97,3 @@ await swarm.listen() | ||
test('join automatically binds', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
var bind = false | ||
@@ -100,3 +107,3 @@ swarm.network.bind = () => (bind = true) | ||
test('join – emits error event when failing to bind', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const fauxError = Error('problem binding') | ||
@@ -111,3 +118,3 @@ swarm.network.bind = (cb) => process.nextTick(cb, fauxError) | ||
test('join – default options', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
var lookupKey = null | ||
@@ -126,3 +133,3 @@ const key = Buffer.from('key') | ||
test('join - announce: false, lookup: true', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
var lookupKey = null | ||
@@ -141,3 +148,3 @@ const key = Buffer.from('key') | ||
test('join - announce: false, lookup: false', async ({ throws }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const key = Buffer.from('key') | ||
@@ -152,3 +159,3 @@ throws( | ||
test('join - emits update event when topic updates', async ({ pass }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const key = Buffer.from('key') | ||
@@ -165,4 +172,6 @@ const topic = new EventEmitter() | ||
test('join - emits peer event when topic recieves peer', async ({ pass, is }) => { | ||
const swarm = hyperswarm() | ||
test('join - emits peer event when topic recieves peer', async ({ plan, pass, is }) => { | ||
plan(2) | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const key = Buffer.from('key') | ||
@@ -174,13 +183,14 @@ const topic = new EventEmitter() | ||
await once(swarm, 'listening') | ||
process.nextTick(() => { | ||
topic.emit('peer', fauxPeer) | ||
swarm.once('peer', function (peer) { | ||
pass('event emitted') | ||
is(peer, fauxPeer) | ||
swarm.destroy() | ||
}) | ||
const [ peer ] = await once(swarm, 'peer') | ||
pass('event emitted') | ||
is(peer, fauxPeer) | ||
swarm.destroy() | ||
topic.emit('peer', fauxPeer) | ||
}) | ||
test('join - announce: true, lookup: false', async ({ is, fail }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
var announceKey = null | ||
@@ -206,4 +216,6 @@ const key = Buffer.from('key') | ||
test('join - announce: true, lookup: true', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
test('join - announce: true, lookup: true', async ({ plan, is }) => { | ||
plan(2) | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
var announceKey = null | ||
@@ -215,2 +227,3 @@ const key = Buffer.from('key') | ||
announceKey = key | ||
topic.key = key | ||
return topic | ||
@@ -220,13 +233,14 @@ } | ||
await once(swarm, 'listening') | ||
process.nextTick(() => { | ||
topic.emit('peer', fauxPeer) | ||
swarm.once('peer', function (peer) { | ||
is(peer, fauxPeer) | ||
is(announceKey, key) | ||
swarm.destroy() | ||
}) | ||
const [ peer ] = await once(swarm, 'peer') | ||
is(peer, fauxPeer) | ||
is(announceKey, key) | ||
swarm.destroy() | ||
topic.emit('peer', fauxPeer) | ||
}) | ||
test('leave - missing key', async ({ throws }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
promisifyMethod(swarm, 'listen') | ||
@@ -240,3 +254,3 @@ await swarm.listen() | ||
test('leave destroys the topic for a given pre-existing key', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const key = Buffer.concat([Buffer.alloc(28), Buffer.from('key1')]) | ||
@@ -265,3 +279,3 @@ const key2 = Buffer.concat([Buffer.alloc(28), Buffer.from('key2')]) | ||
test('leave does not throw when a given key was never joined', async ({ doesNotThrow }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const key = Buffer.from('key1') | ||
@@ -276,3 +290,3 @@ const key2 = Buffer.from('key2') | ||
test('joining the same topic twice will leave the topic before rejoining', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const key = Buffer.from('key') | ||
@@ -299,3 +313,3 @@ const { lookup } = swarm.network | ||
test('connect to a swarm with a plain TCP client', async ({ pass, same, is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
promisifyMethod(swarm, 'listen') | ||
@@ -324,4 +338,4 @@ await swarm.listen() | ||
test('connect two peers directly', async ({ is }) => { | ||
const swarm1 = hyperswarm() | ||
const swarm2 = hyperswarm() | ||
const swarm1 = hyperswarm({ bootstrap: [] }) | ||
const swarm2 = hyperswarm({ bootstrap: [] }) | ||
swarm1.listen() | ||
@@ -371,5 +385,3 @@ await once(swarm1, 'listening') | ||
peer2.leave(key) | ||
peer1.destroy() | ||
peer2.destroy() | ||
closeDht() | ||
closeDht(peer1, peer2) | ||
}) | ||
@@ -401,5 +413,3 @@ | ||
peer2.leave(key) | ||
peer1.destroy() | ||
peer2.destroy() | ||
closeDht() | ||
closeDht(peer1, peer2) | ||
}) | ||
@@ -431,5 +441,3 @@ | ||
peer2.leave(key) | ||
peer1.destroy() | ||
peer2.destroy() | ||
closeDht() | ||
closeDht(peer1, peer2) | ||
}) | ||
@@ -459,5 +467,3 @@ | ||
swarm2.leave(key) | ||
swarm1.destroy() | ||
swarm2.destroy() | ||
closeDht() | ||
closeDht(swarm1, swarm2) | ||
}) | ||
@@ -486,5 +492,3 @@ | ||
swarm2.leave(key) | ||
swarm1.destroy() | ||
swarm2.destroy() | ||
closeDht() | ||
closeDht(swarm1, swarm2) | ||
}) | ||
@@ -516,4 +520,3 @@ | ||
swarm2.leave(key) | ||
swarm2.destroy() | ||
closeDht() | ||
closeDht(swarm2) | ||
}) | ||
@@ -546,4 +549,3 @@ | ||
swarm1.leave(key) | ||
swarm1.destroy() | ||
closeDht() | ||
closeDht(swarm1) | ||
}) | ||
@@ -577,7 +579,6 @@ | ||
swarm2.leave(key) | ||
swarm2.destroy() | ||
closeDht() | ||
closeDht(swarm2) | ||
}) | ||
only('can multiplex 100 topics over the same connection', async ({ same }) => { | ||
test('can multiplex 100 topics over the same connection', async ({ same }) => { | ||
const { bootstrap, closeDht } = await dhtBootstrap() | ||
@@ -601,3 +602,3 @@ const swarm1 = hyperswarm({ bootstrap, maxPeers: 20, queue: { multiplex: true } }) | ||
// Start listening for new connections, and briefly wait to flush the DHT. | ||
const emittedTopicsPromise = listenForConnections(swarm2) | ||
const l = listenForConnections(swarm2) | ||
await new Promise(resolve => setTimeout(resolve, 100)) | ||
@@ -614,6 +615,2 @@ | ||
const topicSet = new Set(topics.map(t => t.toString('hex'))) | ||
const failTimer = setTimeout(() => { | ||
throw new Error('Did not establish connections in time.') | ||
}, 5000) | ||
const emittedTopics = await emittedTopicsPromise | ||
@@ -625,14 +622,14 @@ for (const topic of topics) { | ||
same(topicSet.size, 0) | ||
await l | ||
for (const topic of topics) { | ||
swarm1.leave(topic) | ||
swarm2.leave(topic) | ||
} | ||
swarm1.destroy() | ||
swarm2.destroy() | ||
closeDht() | ||
closeDht(swarm1, swarm2) | ||
function listenForConnections (swarm) { | ||
const emittedTopics = [] | ||
return new Promise(resolve => { | ||
return new Promise((resolve, reject) => { | ||
const failTimer = setTimeout(() => { | ||
reject(new Error('Did not establish connections in time.')) | ||
}, 5000) | ||
swarm.on('connection', (socket, info) => { | ||
@@ -642,8 +639,10 @@ for (let topic of info.topics) { | ||
} | ||
info.on('topic', topic => { | ||
pushTopic(topic) | ||
}) | ||
function pushTopic (topic) { | ||
emittedTopics.push(topic) | ||
if (topics.length === numTopics) { | ||
if (emittedTopics.length === numTopics) { | ||
clearTimeout(failTimer) | ||
@@ -658,1 +657,34 @@ info.removeAllListeners('topic') | ||
}) | ||
test('can dedup connections', async ({ same, end }) => { | ||
const { bootstrap, closeDht } = await dhtBootstrap() | ||
const swarm1 = hyperswarm({ bootstrap, maxPeers: 20, queue: { multiplex: true } }) | ||
const swarm2 = hyperswarm({ bootstrap, maxPeers: 20, queue: { multiplex: true } }) | ||
swarm1.on('connection', (socket, info) => { | ||
socket.write('b') | ||
socket.once('data', function (id) { | ||
info.deduplicate(Buffer.from('b'), id) | ||
}) | ||
socket.on('error', () => {}) | ||
}) | ||
swarm2.on('connection', (socket, info) => { | ||
socket.write('a') | ||
socket.once('data', function (id) { | ||
info.deduplicate(Buffer.from('a'), id) | ||
}) | ||
socket.on('error', () => {}) | ||
}) | ||
const topic = randomBytes(32) | ||
swarm1.join(topic, { announce: true, lookup: true }) | ||
swarm2.join(topic, { announce: true, lookup: true }) | ||
await new Promise(resolve => setTimeout(resolve, 100)) | ||
same(swarm1.connections.size, 1) | ||
same(swarm1.connections.size, 1) | ||
closeDht(swarm1, swarm2) | ||
}) |
@@ -9,3 +9,3 @@ 'use strict' | ||
test('maxClientSockets defaults to Infinity', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const { maxClientSockets } = swarm | ||
@@ -61,5 +61,4 @@ is(maxClientSockets, Infinity) | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(...swarms) | ||
}) | ||
@@ -112,5 +111,4 @@ | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(...swarms) | ||
}) |
@@ -9,3 +9,3 @@ 'use strict' | ||
test('maxPeers defaults to 24', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const { maxPeers } = swarm | ||
@@ -60,10 +60,7 @@ is(maxPeers, 24) | ||
is(swarm.open, false) | ||
swarm2.destroy() | ||
swarm.leave(key) | ||
swarm.destroy() | ||
for (const s of swarms) { | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(swarm, swarm2, ...swarms) | ||
}) | ||
@@ -112,10 +109,7 @@ | ||
is(swarm.open, false) | ||
swarm2.destroy() | ||
swarm.leave(key) | ||
swarm.destroy() | ||
for (const s of swarms) { | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(swarm, swarm2, ...swarms) | ||
}) | ||
@@ -186,10 +180,7 @@ | ||
is(swarm.open, false) | ||
swarm2.destroy() | ||
swarm.leave(key) | ||
swarm.destroy() | ||
for (const s of swarms) { | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(swarm, swarm2, ...swarms) | ||
}) | ||
@@ -263,10 +254,7 @@ | ||
swarm2.destroy() | ||
swarm.leave(key) | ||
swarm.destroy() | ||
for (const s of swarms) { | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(swarm, swarm2, ...swarms) | ||
}) |
@@ -89,5 +89,4 @@ 'use strict' | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(...swarms) | ||
}) |
'use strict' | ||
const { EventEmitter } = require('events') | ||
const { randomBytes } = require('crypto') | ||
@@ -11,3 +10,3 @@ const { test } = require('tap') | ||
test('maxServerSockets defaults to Infinity', async ({ is }) => { | ||
const swarm = hyperswarm() | ||
const swarm = hyperswarm({ bootstrap: [] }) | ||
const { maxServerSockets } = swarm | ||
@@ -49,10 +48,7 @@ is(maxServerSockets, Infinity) | ||
await timeout(150) // allow time for a potential connection event | ||
swarm2.destroy() | ||
swarm.leave(key) | ||
swarm.destroy() | ||
for (const s of swarms) { | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(swarm, swarm2, ...swarms) | ||
}) | ||
@@ -102,10 +98,7 @@ | ||
swarm2.destroy() | ||
swarm.leave(key) | ||
swarm.destroy() | ||
for (const s of swarms) { | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(swarm, swarm2, ...swarms) | ||
}) | ||
@@ -141,2 +134,3 @@ | ||
is(maxServerSockets, 4) | ||
swarm.on('connection', c => c.write('hi')) | ||
swarm.join(key, { | ||
@@ -159,24 +153,5 @@ announce: true, | ||
// fake utp connection | ||
s.network.utp.connect = (port, host) => { | ||
const ee = new EventEmitter() | ||
ee.destroy = (cb) => { | ||
if (cb) ee.once('close', cb) | ||
ee.emit('close') | ||
} | ||
// filter out multiple connect attempts | ||
if (host === '127.0.0.1') return ee | ||
process.nextTick(() => { | ||
ee.emit('connect') | ||
const conn = new EventEmitter() | ||
conn.destroy = (cb) => { | ||
if (cb) ee.once('close', cb) | ||
ee.emit('close') | ||
} | ||
swarm.network.utp.emit('connection', conn) | ||
}) | ||
return ee | ||
} | ||
await once(swarm, 'connection') | ||
} | ||
is(swarm.serverSockets, maxServerSockets) | ||
@@ -189,3 +164,2 @@ | ||
hyperswarm = require('../swarm') | ||
for (var c = 0; c < maxServerSockets; c++) { | ||
@@ -211,3 +185,4 @@ const s = hyperswarm({ bootstrap }) | ||
await once(swarm2, 'listening') | ||
swarm.once('connection', () => { | ||
swarm.once('connection', (_, info) => { | ||
fail('connection should not be emitted after double max server connections is reached') | ||
@@ -218,10 +193,9 @@ }) | ||
swarm2.leave(key) | ||
swarm2.destroy() | ||
swarm.leave(key) | ||
swarm.destroy() | ||
for (const s of swarms) { | ||
s.leave(key) | ||
s.destroy() | ||
} | ||
closeDht() | ||
closeDht(swarm, swarm2, ...swarms) | ||
setImmediate(() => process.exit(0)) // haxx exit the process so we don't have to wait for utp timeouts ... maybe something we can improve in utp? | ||
}) |
@@ -8,3 +8,7 @@ 'use strict' | ||
async function dhtBootstrap () { | ||
const node = dht() | ||
const node = dht({ | ||
bootstrap: [], | ||
ephemeral: true | ||
}) | ||
node.listen() | ||
await once(node, 'listening') | ||
@@ -15,3 +19,16 @@ const { port } = node.address() | ||
bootstrap: [`127.0.0.1:${port}`], | ||
closeDht: () => node.destroy() | ||
closeDht (...others) { | ||
let missing = 1 | ||
for (const n of others) { | ||
missing++ | ||
n.destroy(done) | ||
} | ||
done() | ||
function done () { | ||
if (--missing) return | ||
node.destroy() | ||
} | ||
} | ||
} | ||
@@ -18,0 +35,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
88499
21
2688
206