pzp-net/lib/multiaddr.js

100 lines
3.1 KiB
JavaScript

const IP = require('ip')
const Multiaddr = {
/**
* Converts (legacy) [multiserver](https://github.com/ssbc/multiserver-address)
* addresses to [multiaddr](https://multiformats.io/multiaddr/) (modern).
* @param {string} msaddr
* @returns {`/${string}`}
*/
fromMs(msaddr) {
const [msTransport, msTransform] = msaddr.split('~')
const [label1, ...pieces] = msTransport.split(':')
/**@type {string}*/
let soFar
if (label1 === 'tunnel') {
const [hubPubkey, targetPubkey] = pieces
soFar = `tunnel/${hubPubkey}.${targetPubkey}`
} else {
const transport = label1 === 'net' ? 'tcp' : label1 === 'ws' ? 'ws' : null
if (!transport) throw new Error(`Unknown transport "${label1}"`)
const [host, port] = pieces
const hostFormat = IP.isV4Format(host)
? 'ip4'
: IP.isV6Format('ipv6')
? 'ip6'
: 'dns'
soFar = `${hostFormat}/${host}/${transport}/${port}`
}
if (msTransform) {
const [label2, pubkey, token] = msTransform.split(':')
if (label2 !== 'shse') throw new Error(`Unknown transform "${label2}"`)
if (token) {
return `/${soFar}/shse/${pubkey}.${token}`
} else {
return `/${soFar}/shse/${pubkey}`
}
} else {
return `/${soFar}`
}
},
/**
* Converts [multiaddr](https://multiformats.io/multiaddr/) (modern) to
* [multiserver](https://github.com/ssbc/multiserver-address) address (legacy).
* @param {`/${string}`} multiaddr
* @returns {string}
*/
toMs(multiaddr) {
if (!multiaddr.startsWith('/')) {
// prettier-ignore
throw new Error(`Invalid multiaddr "${multiaddr}"`)
}
const pieces = multiaddr.split('/')
// Parse tunnel multiaddr
if (pieces[1] === 'tunnel') {
const [, , pubkeys, transform, cred] = pieces
const [hubPubkey, targetPubkey] = pubkeys.split('.')
// prettier-ignore
if (!hubPubkey || !targetPubkey) throw new Error(`Invalid tunnel multiaddr "${multiaddr}"`)
const soFar = `tunnel:${hubPubkey}:${targetPubkey}`
if (transform) {
// prettier-ignore
if (transform !== 'shse') throw new Error(`Unknown transform "${transform}"`)
const [pubkey, token] = cred.split('.')
if (token) {
return `${soFar}~shse:${pubkey}:${token}`
} else {
return `${soFar}~shse:${pubkey}`
}
} else {
return soFar
}
}
// Parse host+transport multiaddr
const [, , host, transport, port, transform, cred] = pieces
const label1 =
transport === 'tcp' ? 'net' : transport === 'ws' ? 'ws' : null
if (!label1) throw new Error(`Unknown transport "${transport}"`)
const soFar = `${label1}:${host}:${port}`
if (transform) {
// prettier-ignore
if (transform !== 'shse') throw new Error(`Unknown transform "${transform}"`)
const [pubkey, token] = cred.split('.')
if (token) {
return `${soFar}~shse:${pubkey}:${token}`
} else {
return `${soFar}~shse:${pubkey}`
}
} else {
return soFar
}
},
}
module.exports = Multiaddr