Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 53 additions & 8 deletions api/basic/helper/multiaddr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,43 @@ import { Multiaddr } from 'multiaddr'
* Convert a comma-separated list of origins into an array of
* multiaddr strings that we could possibly connect to.
*
* Filters out:
* - malformed multiaddrs and ones with transports we don't recognise
* - private or reserved ip address that we wouldn't be able to connect to.
*/
* Picks the first 10 non-ip based multiaddr,
* or ip based multiaddrs with a public (non-bogon) IP address
* or a /p2p/:peerId addr from a bogon ip based multiaddr.
**/
export function findUsableMultiaddrs (input = ''): string[] {
if (input === '' || input === null) return []
return input
.split(',')
.filter(isMultiaddr)
.filter(hasPublicIpAddress)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more usage of this function. Looks like we can remove it

const specificAddrs: Set<string> = new Set()
const p2pAddrs: Set<string> = new Set()
for (const str of input.split(',')) {
const input = str.trim()
const ma = asMultiaddr(input)
if (ma === undefined) continue
// where we've got a ma with an ip we can't connect to,
// try to extract the /p2p/:peerId addr where available
if (hasBogonIpAddress(input)) {
const addr = getP2pAddr(input)
if (addr !== undefined) {
p2pAddrs.add(addr)
}
} else {
// either an ip based multiaddr with public ip, or a non-ip based multiaddr
specificAddrs.add(input)
}
}
return Array
.from(specificAddrs)
.concat(Array.from(p2pAddrs))
.slice(1, 10) // don't return an unbounded number of multiaddrs.
}

export function asMultiaddr (input = ''): Multiaddr | undefined {
if (input === '' || input === null) return undefined
try {
return new Multiaddr(input) // eslint-disable-line no-new
} catch (e) {
return undefined
}
}

export function isMultiaddr (input = ''): boolean {
Expand All @@ -37,3 +64,21 @@ export function hasPublicIpAddress (input = ''): boolean {
// not a IP based multiaddr, so we allow it.
return true
}

export function hasBogonIpAddress (input = ''): boolean {
if (input === '' || input === null) return false
if (input.startsWith('/ip6/') || input.startsWith('/ip4/')) {
const ip = input.split('/').at(2)
if (ip === undefined) return false
return bogon(ip)
}
return false
}

export function getP2pAddr (input = ''): string | undefined {
if (input === '' || input === null) return undefined
const match = input.match(/\/p2p\/\w+$/)
if (match != null) {
return match.at(0)
}
}
42 changes: 42 additions & 0 deletions api/test/multiaddrs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import test from 'ava'
import { findUsableMultiaddrs } from '../basic/helper/multiaddr.js'

const fixture = [
'/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a dns4 address just to make sure everything is working as expected for non hasBogonIpAddress?

'/ip4/127.0.0.1/udp/4001/quic-v1/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/127.0.0.1/udp/4001/quic-v1/webtransport/certhash/uEiAcyORkzbKPHpd2Rq8px1APBfdnTJ1jzH10u92mYJAOMA/certhash/uEiBFkYB7Q0cp49VFSMY9ae8ffHaRJf7N0WXCGBkGp4KCIQ/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/127.0.0.1/udp/4001/quic/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/192.168.1.113/tcp/4001/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/192.168.1.113/udp/4001/quic-v1/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/192.168.1.113/udp/4001/quic-v1/webtransport/certhash/uEiAcyORkzbKPHpd2Rq8px1APBfdnTJ1jzH10u92mYJAOMA/certhash/uEiBFkYB7Q0cp49VFSMY9ae8ffHaRJf7N0WXCGBkGp4KCIQ/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/192.168.1.113/udp/4001/quic/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/45.76.79.40/udp/4001/quic-v1/p2p/12D3KooWGFLFZ9uYAqD8WschDcPDT4PgmsGzgvwrTdDmV4LD5kSe/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/45.76.79.40/udp/4001/quic/p2p/12D3KooWGFLFZ9uYAqD8WschDcPDT4PgmsGzgvwrTdDmV4LD5kSe/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/5.161.44.89/tcp/4001/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/5.161.44.89/udp/4001/quic/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/2a01:4ff:f0:ab6::1/tcp/4001/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/2a01:4ff:f0:ab6::1/udp/4001/quic/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/::1/tcp/4001/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/::1/udp/4001/quic-v1/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/::1/udp/4001/quic-v1/webtransport/certhash/uEiAcyORkzbKPHpd2Rq8px1APBfdnTJ1jzH10u92mYJAOMA/certhash/uEiBFkYB7Q0cp49VFSMY9ae8ffHaRJf7N0WXCGBkGp4KCIQ/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/::1/udp/4001/quic/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN'
]

const expected = [
'/ip4/5.161.44.89/tcp/4001/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip4/5.161.44.89/udp/4001/quic/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/2a01:4ff:f0:ab6::1/tcp/4001/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/ip6/2a01:4ff:f0:ab6::1/udp/4001/quic/p2p/12D3KooWSvYbdaYZmZucbkEHKDDoHNqCtkEMWdSm1z4udww6fyUM/p2p-circuit/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN',
'/p2p/12D3KooWADjHf2kyANQodg9z5sSdX4bGEMbWg7ojwu6SCyDAMtzN'
]

test('findUsableMultiaddrs', t => {
const input = fixture.join(',')
const res = findUsableMultiaddrs(input)
t.is(res.length, 5)
let i = 0
for (const ma of expected) {
t.is(res[i], ma)
i++
}
})