From d3f8b05436542560330140afa430dddc3a83f327 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 7 Jul 2022 16:23:04 +0200 Subject: [PATCH] fix: return correct family from toOptions with dns4 MultiAddr (#233) When calling toOptions with a dns4 multiaddress, a MultiaddrObject is returned where the ip family is 6 instead of 4. This causes an issue where libp2p is unable to resolve the domain and dial the peer. This only appears to be an issue on some systems. It works on Mac OS but fails on for example Alpine Linux. Example: ```javascript const {multiaddr} = require("multiaddr") console.log(multiaddr('/dns4/google.net/tcp/8000').toOptions())` ``` ```javascript Object {family: 6, host: "google.net", transport: "tcp", port: 8000} ``` Co-authored-by: achingbrain --- src/index.ts | 29 ++++++++++++++++++++++++----- test/index.spec.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index b8de0017..0ba8a868 100644 --- a/src/index.ts +++ b/src/index.ts @@ -141,13 +141,32 @@ export class Multiaddr { * ``` */ toOptions (): MultiaddrObject { - const parsed = this.toString().split('/') + const codes = this.protoCodes() + const parts = this.toString().split('/').slice(1) + let transport: string + let port: number + + if (parts.length > 2) { + // default to https when protocol & port are omitted from DNS addrs + if (DNS_CODES.includes(codes[0]) && P2P_CODES.includes(codes[1])) { + transport = getProtocol('tcp').name + port = 443 + } else { + transport = getProtocol(parts[2]).name + port = parseInt(parts[3]) + } + } else if (DNS_CODES.includes(codes[0])) { + transport = getProtocol('tcp').name + port = 443 + } else { + throw new Error('multiaddr must have a valid format: "/{ip4, ip6, dns4, dns6, dnsaddr}/{address}/{tcp, udp}/{port}".') + } const opts: MultiaddrObject = { - family: parsed[1] === 'ip4' ? 4 : 6, - host: parsed[2], - transport: parsed[3], - port: parseInt(parsed[4]) + family: (codes[0] === 41 || codes[0] === 55) ? 6 : 4, + host: parts[1], + transport, + port } return opts diff --git a/test/index.spec.ts b/test/index.spec.ts index e423d55a..225a89a0 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -486,6 +486,46 @@ describe('helpers', () => { port: 1234 }) }) + + it('returns an options object from a DNS addr', () => { + expect(new Multiaddr('/dns4/google.net/tcp/8000').toOptions()) + .to.eql({ + family: 4, + host: 'google.net', + transport: 'tcp', + port: 8000 + }) + }) + + it('returns an options object from a DNS6 addr', () => { + expect(new Multiaddr('/dns6/google.net/tcp/8000').toOptions()) + .to.eql({ + family: 6, + host: 'google.net', + transport: 'tcp', + port: 8000 + }) + }) + + it('returns an options object from a DNS addr defaulting to https', () => { + expect(new Multiaddr('/dnsaddr/google.net').toOptions()) + .to.eql({ + family: 4, + host: 'google.net', + transport: 'tcp', + port: 443 + }) + }) + + it('returns an options object from a DNS addr with a PeerID defaulting to https', () => { + expect(new Multiaddr('/dnsaddr/google.net/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC').toOptions()) + .to.eql({ + family: 4, + host: 'google.net', + transport: 'tcp', + port: 443 + }) + }) }) describe('.inspect', () => {