diff --git a/package.json b/package.json index 8bc6495..eca4b28 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "mafmt": "^8.0.1", "multiaddr": "^8.1.1", "multiaddr-to-uri": "^6.0.0", + "p-defer": "^3.0.0", "p-timeout": "^3.2.0" }, "devDependencies": { diff --git a/src/index.js b/src/index.js index 3d985ae..26c550c 100644 --- a/src/index.js +++ b/src/index.js @@ -4,8 +4,11 @@ const connect = require('it-ws/client') const withIs = require('class-is') const toUri = require('multiaddr-to-uri') const { AbortError } = require('abortable-iterator') +const pDefer = require('p-defer') -const log = require('debug')('libp2p:websockets') +const debug = require('debug') +const log = debug('libp2p:websockets') +log.error = debug('libp2p:websockets:error') const env = require('ipfs-utils/src/env') const createListener = require('./listener') @@ -63,10 +66,24 @@ class WebSockets { const cOpts = ma.toOptions() log('dialing %s:%s', cOpts.host, cOpts.port) + const errorPromise = pDefer() + const errfn = (err) => { + const msg = `connection error: ${err.message}` + log.error(msg) + + errorPromise.reject(err) + } + const rawSocket = connect(toUri(ma), Object.assign({ binary: true }, options)) + if (rawSocket.socket.on) { + rawSocket.socket.on('error', errfn) + } else { + rawSocket.socket.onerror = errfn + } + if (!options.signal) { - await rawSocket.connected() + await Promise.race([rawSocket.connected(), errorPromise.promise]) log('connected %s', ma) return rawSocket @@ -77,7 +94,10 @@ class WebSockets { const abort = new Promise((resolve, reject) => { onAbort = () => { reject(new AbortError()) - rawSocket.close() + // FIXME: https://github.com/libp2p/js-libp2p-websockets/issues/121 + setTimeout(() => { + rawSocket.close() + }) } // Already aborted? @@ -86,7 +106,7 @@ class WebSockets { }) try { - await Promise.race([abort, rawSocket.connected()]) + await Promise.race([abort, errorPromise.promise, rawSocket.connected()]) } finally { options.signal.removeEventListener('abort', onAbort) } diff --git a/test/node.js b/test/node.js index 83bcd8f..e7eadd9 100644 --- a/test/node.js +++ b/test/node.js @@ -5,6 +5,7 @@ const https = require('https') const fs = require('fs') +const AbortController = require('abort-controller').default const { expect } = require('aegir/utils/chai') const multiaddr = require('multiaddr') const goodbye = require('it-goodbye') @@ -224,6 +225,16 @@ describe('dial', () => { expect(result).to.be.eql([uint8ArrayFromString('hey')]) }) + it('dial should throw on immediate abort', async () => { + const ma = multiaddr('/ip4/127.0.0.1/tcp/0/ws') + const controller = new AbortController() + + const conn = ws.dial(ma, { signal: controller.signal }) + controller.abort() + + await expect(conn).to.eventually.be.rejected() + }) + it('should resolve port 0', async () => { const ma = multiaddr('/ip4/127.0.0.1/tcp/0/ws') const ws = new WS({ upgrader: mockUpgrader })