diff --git a/src/errors.js b/src/errors.js index 14752b2706..0b73b983db 100644 --- a/src/errors.js +++ b/src/errors.js @@ -11,6 +11,7 @@ exports.codes = { PUBSUB_NOT_STARTED: 'ERR_PUBSUB_NOT_STARTED', DHT_NOT_STARTED: 'ERR_DHT_NOT_STARTED', CONN_ENCRYPTION_REQUIRED: 'ERR_CONN_ENCRYPTION_REQUIRED', + ERR_INVALID_PROTOCOLS_FOR_STREAM: 'ERR_INVALID_PROTOCOLS_FOR_STREAM', ERR_CONNECTION_ENDED: 'ERR_CONNECTION_ENDED', ERR_CONNECTION_FAILED: 'ERR_CONNECTION_FAILED', ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED', diff --git a/src/index.js b/src/index.js index 02fa4f4ed5..fb961f0e77 100644 --- a/src/index.js +++ b/src/index.js @@ -462,26 +462,23 @@ class Libp2p extends EventEmitter { } /** - * Dials to the provided peer and handshakes with the given protocol. + * Dials to the provided peer and tries to handshake with the given protocols in order. * If successful, the known metadata of the peer will be added to the nodes `peerStore`, - * and the `Connection` will be returned + * and the `MuxedStream` will be returned together with the successful negotiated protocol. * * @async * @param {PeerId|Multiaddr|string} peer - The peer to dial * @param {string[]|string} protocols * @param {object} [options] * @param {AbortSignal} [options.signal] - * @returns {Promise} */ async dialProtocol (peer, protocols, options) { - const connection = await this._dial(peer, options) - - // If a protocol was provided, create a new stream - if (protocols && protocols.length) { - return connection.newStream(protocols) + if (!protocols || !protocols.length) { + throw errCode(new Error('no protocols were provided to open a stream'), codes.ERR_INVALID_PROTOCOLS_FOR_STREAM) } - return connection + const connection = await this._dial(peer, options) + return connection.newStream(protocols) } /** diff --git a/test/dialing/direct.node.js b/test/dialing/direct.node.js index 1f8a5dfee7..1a1b508929 100644 --- a/test/dialing/direct.node.js +++ b/test/dialing/direct.node.js @@ -352,6 +352,25 @@ describe('Dialing (direct, TCP)', () => { await pWaitFor(() => remoteConn.streams.length === 0) }) + it('should throw when using dialProtocol with no protocols', async () => { + libp2p = new Libp2p({ + peerId, + modules: { + transport: [Transport], + streamMuxer: [Muxer], + connEncryption: [Crypto] + } + }) + + await expect(libp2p.dialProtocol(remotePeerId)) + .to.eventually.be.rejectedWith(Error) + .and.to.have.property('code', ErrorCodes.ERR_INVALID_PROTOCOLS_FOR_STREAM) + + await expect(libp2p.dialProtocol(remotePeerId, [])) + .to.eventually.be.rejectedWith(Error) + .and.to.have.property('code', ErrorCodes.ERR_INVALID_PROTOCOLS_FOR_STREAM) + }) + it('should be able to use hangup to close connections', async () => { libp2p = new Libp2p({ peerId,