mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-04-03 08:11:04 +00:00
When the node is shutting down, new connections can still be received. If this happens we can end up writing into the datastore when it's been closed which throws an error. Instead, if we're not running, have the connection manager close new incoming connections.
181 lines
6.2 KiB
JavaScript
181 lines
6.2 KiB
JavaScript
'use strict'
|
|
/* eslint-env mocha */
|
|
|
|
const { expect } = require('aegir/utils/chai')
|
|
const sinon = require('sinon')
|
|
|
|
const { Multiaddr } = require('multiaddr')
|
|
const Resolver = require('multiaddr/src/resolvers/dns')
|
|
|
|
const { codes: ErrorCodes } = require('../../src/errors')
|
|
|
|
const peerUtils = require('../utils/creators/peer')
|
|
const baseOptions = require('../utils/base-options.browser')
|
|
|
|
const { MULTIADDRS_WEBSOCKETS } = require('../fixtures/browser')
|
|
const relayAddr = MULTIADDRS_WEBSOCKETS[0]
|
|
|
|
const getDnsaddrStub = (peerId) => [
|
|
[`dnsaddr=/dnsaddr/ams-1.bootstrap.libp2p.io/p2p/${peerId}`],
|
|
[`dnsaddr=/dnsaddr/ams-2.bootstrap.libp2p.io/p2p/${peerId}`],
|
|
[`dnsaddr=/dnsaddr/lon-1.bootstrap.libp2p.io/p2p/${peerId}`],
|
|
[`dnsaddr=/dnsaddr/nrt-1.bootstrap.libp2p.io/p2p/${peerId}`],
|
|
[`dnsaddr=/dnsaddr/nyc-1.bootstrap.libp2p.io/p2p/${peerId}`],
|
|
[`dnsaddr=/dnsaddr/sfo-2.bootstrap.libp2p.io/p2p/${peerId}`]
|
|
]
|
|
|
|
const relayedAddr = (peerId) => `${relayAddr}/p2p-circuit/p2p/${peerId}`
|
|
|
|
const getDnsRelayedAddrStub = (peerId) => [
|
|
[`dnsaddr=${relayedAddr(peerId)}`]
|
|
]
|
|
|
|
describe('Dialing (resolvable addresses)', () => {
|
|
let libp2p, remoteLibp2p
|
|
|
|
beforeEach(async () => {
|
|
[libp2p, remoteLibp2p] = await peerUtils.createPeer({
|
|
number: 2,
|
|
config: {
|
|
...baseOptions,
|
|
addresses: {
|
|
listen: [new Multiaddr(`${relayAddr}/p2p-circuit`)]
|
|
},
|
|
config: {
|
|
...baseOptions.config,
|
|
peerDiscovery: {
|
|
autoDial: false
|
|
}
|
|
}
|
|
},
|
|
started: true,
|
|
populateAddressBooks: false
|
|
})
|
|
|
|
await libp2p.start()
|
|
await remoteLibp2p.start()
|
|
})
|
|
|
|
afterEach(async () => {
|
|
sinon.restore()
|
|
await Promise.all([libp2p, remoteLibp2p].map(n => n.stop()))
|
|
})
|
|
|
|
it('resolves dnsaddr to ws local address', async () => {
|
|
const remoteId = remoteLibp2p.peerId.toB58String()
|
|
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
|
|
const relayedAddrFetched = new Multiaddr(relayedAddr(remoteId))
|
|
|
|
// Transport spy
|
|
const transport = libp2p.transportManager._transports.get('Circuit')
|
|
sinon.spy(transport, 'dial')
|
|
|
|
// Resolver stub
|
|
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
|
|
stub.onCall(0).returns(Promise.resolve(getDnsRelayedAddrStub(remoteId)))
|
|
|
|
// Dial with address resolve
|
|
const connection = await libp2p.dial(dialAddr)
|
|
expect(connection).to.exist()
|
|
expect(connection.remoteAddr.equals(relayedAddrFetched))
|
|
|
|
const dialArgs = transport.dial.firstCall.args
|
|
expect(dialArgs[0].equals(relayedAddrFetched)).to.eql(true)
|
|
})
|
|
|
|
it('resolves a dnsaddr recursively', async () => {
|
|
const remoteId = remoteLibp2p.peerId.toB58String()
|
|
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
|
|
const relayedAddrFetched = new Multiaddr(relayedAddr(remoteId))
|
|
|
|
// Transport spy
|
|
const transport = libp2p.transportManager._transports.get('Circuit')
|
|
sinon.spy(transport, 'dial')
|
|
|
|
// Resolver stub
|
|
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
|
|
let firstCall = false
|
|
stub.callsFake(() => {
|
|
if (!firstCall) {
|
|
firstCall = true
|
|
// Return an array of dnsaddr
|
|
return Promise.resolve(getDnsaddrStub(remoteId))
|
|
}
|
|
return Promise.resolve(getDnsRelayedAddrStub(remoteId))
|
|
})
|
|
|
|
// Dial with address resolve
|
|
const connection = await libp2p.dial(dialAddr)
|
|
expect(connection).to.exist()
|
|
expect(connection.remoteAddr.equals(relayedAddrFetched))
|
|
|
|
const dialArgs = transport.dial.firstCall.args
|
|
expect(dialArgs[0].equals(relayedAddrFetched)).to.eql(true)
|
|
})
|
|
|
|
// TODO: Temporary solution does not resolve dns4/dns6
|
|
// Resolver just returns the received multiaddrs
|
|
it('stops recursive resolve if finds dns4/dns6 and dials it', async () => {
|
|
const remoteId = remoteLibp2p.peerId.toB58String()
|
|
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
|
|
|
|
// Stub resolver
|
|
const dnsMa = new Multiaddr(`/dns4/ams-1.remote.libp2p.io/tcp/443/wss/p2p/${remoteId}`)
|
|
const stubResolve = sinon.stub(Resolver.prototype, 'resolveTxt')
|
|
stubResolve.returns(Promise.resolve([
|
|
[`dnsaddr=${dnsMa}`]
|
|
]))
|
|
|
|
// Stub transport
|
|
const transport = libp2p.transportManager._transports.get('WebSockets')
|
|
const stubTransport = sinon.stub(transport, 'dial')
|
|
stubTransport.callsFake((multiaddr) => {
|
|
expect(multiaddr.equals(dnsMa)).to.eql(true)
|
|
})
|
|
|
|
await libp2p.dial(dialAddr)
|
|
})
|
|
|
|
it('resolves a dnsaddr recursively not failing if one address fails to resolve', async () => {
|
|
const remoteId = remoteLibp2p.peerId.toB58String()
|
|
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
|
|
const relayedAddrFetched = new Multiaddr(relayedAddr(remoteId))
|
|
|
|
// Transport spy
|
|
const transport = libp2p.transportManager._transports.get('Circuit')
|
|
sinon.spy(transport, 'dial')
|
|
|
|
// Resolver stub
|
|
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
|
|
stub.onCall(0).callsFake(() => Promise.resolve(getDnsaddrStub(remoteId)))
|
|
stub.onCall(1).callsFake(() => Promise.reject(new Error()))
|
|
stub.callsFake(() => Promise.resolve(getDnsRelayedAddrStub(remoteId)))
|
|
|
|
// Dial with address resolve
|
|
const connection = await libp2p.dial(dialAddr)
|
|
expect(connection).to.exist()
|
|
expect(connection.remoteAddr.equals(relayedAddrFetched))
|
|
|
|
const dialArgs = transport.dial.firstCall.args
|
|
expect(dialArgs[0].equals(relayedAddrFetched)).to.eql(true)
|
|
})
|
|
|
|
it('fails to dial if resolve fails and there are no addresses to dial', async () => {
|
|
const remoteId = remoteLibp2p.peerId.toB58String()
|
|
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
|
|
|
|
// Stub resolver
|
|
const stubResolve = sinon.stub(Resolver.prototype, 'resolveTxt')
|
|
stubResolve.returns(Promise.reject(new Error()))
|
|
|
|
// Stub transport
|
|
const transport = libp2p.transportManager._transports.get('WebSockets')
|
|
const spy = sinon.spy(transport, 'dial')
|
|
|
|
await expect(libp2p.dial(dialAddr))
|
|
.to.eventually.be.rejectedWith(Error)
|
|
.and.to.have.nested.property('.code', ErrorCodes.ERR_NO_VALID_ADDRESSES)
|
|
expect(spy.callCount).to.eql(0)
|
|
})
|
|
})
|