diff --git a/.gitignore b/.gitignore index 6780e0b9..1a9d6b63 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ test/test-data/go-ipfs-repo/LOG.old # while testing npm5 package-lock.json +yarn.lock \ No newline at end of file diff --git a/package.json b/package.json index 475bc334..d0b505a5 100644 --- a/package.json +++ b/package.json @@ -32,12 +32,11 @@ "bugs": "https://github.com/multiformats/js-multiaddr/issues", "homepage": "https://github.com/multiformats/js-multiaddr", "dependencies": { - "bs58": "^4.0.1", + "buffer": "^5.5.0", "cids": "~0.7.1", "class-is": "^1.1.0", - "hi-base32": "~0.5.0", - "ip": "^1.1.5", "is-ip": "^3.1.0", + "multibase": "^0.6.0", "varint": "^5.0.0" }, "devDependencies": { diff --git a/src/codec.js b/src/codec.js index 0a4a8d6f..7abe09ad 100644 --- a/src/codec.js +++ b/src/codec.js @@ -1,5 +1,6 @@ 'use strict' +const { Buffer } = require('buffer') const convert = require('./convert') const protocols = require('./protocols-table') const varint = require('varint') diff --git a/src/convert.js b/src/convert.js index 5a9b4031..34731dd8 100644 --- a/src/convert.js +++ b/src/convert.js @@ -1,11 +1,10 @@ 'use strict' -const ip = require('ip') -const isIp = require('is-ip') +const { Buffer } = require('buffer') +const ip = require('./ip') const protocols = require('./protocols-table') -const bs58 = require('bs58') const CID = require('cids') -const base32 = require('hi-base32') +const multibase = require('multibase') const varint = require('varint') module.exports = Convert @@ -83,7 +82,7 @@ Convert.toBuffer = function convertToBuffer (proto, str) { } function ip2buf (ipString) { - if (!isIp(ipString)) { + if (!ip.isIP(ipString)) { throw new Error('invalid ip address') } return ip.toBuffer(ipString) @@ -91,7 +90,7 @@ function ip2buf (ipString) { function buf2ip (ipBuff) { const ipString = ip.toString(ipBuff) - if (!isIp(ipString)) { + if (!ip.isIP(ipString)) { throw new Error('invalid ip address') } return ipString @@ -138,8 +137,7 @@ function buf2mh (buf) { if (address.length !== size) { throw new Error('inconsistent lengths') } - - return bs58.encode(address) + return multibase.encode('base58btc', address).toString().slice(1) } function onion2buf (str) { @@ -150,7 +148,9 @@ function onion2buf (str) { if (addr[0].length !== 16) { throw new Error('failed to parse onion addr: ' + addr[0] + ' not a Tor onion address.') } - const buf = Buffer.from(base32.decode.asBytes(addr[0].toUpperCase())) + + // onion addresses do not include the multibase prefix, add it before decoding + const buf = multibase.decode('b' + addr[0]) // onion port number const port = parseInt(addr[1], 10) @@ -169,7 +169,8 @@ function onion32buf (str) { if (addr[0].length !== 56) { throw new Error('failed to parse onion addr: ' + addr[0] + ' not a Tor onion3 address.') } - const buf = Buffer.from(base32.decode.asBytes(addr[0].toUpperCase())) + // onion addresses do not include the multibase prefix, add it before decoding + const buf = multibase.decode('b' + addr[0]) // onion port number const port = parseInt(addr[1], 10) @@ -183,7 +184,7 @@ function onion32buf (str) { function buf2onion (buf) { const addrBytes = buf.slice(0, buf.length - 2) const portBytes = buf.slice(buf.length - 2) - const addr = base32.encode(addrBytes).toLowerCase() + const addr = multibase.encode('base32', addrBytes).toString().slice(1) const port = buf2port(portBytes) return addr + ':' + port } diff --git a/src/index.js b/src/index.js index c0c61006..023faefd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,10 @@ 'use strict' const codec = require('./codec') +const { Buffer } = require('buffer') const protocols = require('./protocols-table') const varint = require('varint') -const bs58 = require('bs58') +const multibase = require('multibase') const CID = require('cids') const withIs = require('class-is') const inspect = Symbol.for('nodejs.util.inspect.custom') @@ -308,7 +309,7 @@ Multiaddr.prototype.getPeerId = function getPeerId () { // Get the last id b58str = tuples.pop()[1] // Get multihash, unwrap from CID if needed - b58str = bs58.encode(new CID(b58str).multihash) + b58str = multibase.encode('base58btc', new CID(b58str).multihash).toString().slice(1) } catch (e) { b58str = null } diff --git a/src/ip.js b/src/ip.js new file mode 100644 index 00000000..99d9c265 --- /dev/null +++ b/src/ip.js @@ -0,0 +1,97 @@ +'use strict' + +const isIp = require('is-ip') + +const isIP = isIp +const isV4 = isIp.v4 +const isV6 = isIp.v6 + +// Copied from https://github.com/indutny/node-ip/blob/master/lib/ip.js#L7 +const toBuffer = function (ip, buff, offset) { + offset = ~~offset + + var result + + if (isV4(ip)) { + result = buff || Buffer.alloc(offset + 4) + ip.split(/\./g).map(function (byte) { + result[offset++] = parseInt(byte, 10) & 0xff + }) + } else if (isV6(ip)) { + var sections = ip.split(':', 8) + + var i + for (i = 0; i < sections.length; i++) { + var isv4 = isV4(sections[i]) + var v4Buffer + + if (isv4) { + v4Buffer = toBuffer(sections[i]) + sections[i] = v4Buffer.slice(0, 2).toString('hex') + } + + if (v4Buffer && ++i < 8) { + sections.splice(i, 0, v4Buffer.slice(2, 4).toString('hex')) + } + } + + if (sections[0] === '') { + while (sections.length < 8) sections.unshift('0') + } else if (sections[sections.length - 1] === '') { + while (sections.length < 8) sections.push('0') + } else if (sections.length < 8) { + for (i = 0; i < sections.length && sections[i] !== ''; i++); + var argv = [i, 1] + for (i = 9 - sections.length; i > 0; i--) { + argv.push('0') + } + sections.splice.apply(sections, argv) + } + + result = buff || Buffer.alloc(offset + 16) + for (i = 0; i < sections.length; i++) { + var word = parseInt(sections[i], 16) + result[offset++] = (word >> 8) & 0xff + result[offset++] = word & 0xff + } + } + + if (!result) { + throw Error('Invalid ip address: ' + ip) + } + + return result +} + +// Copied from https://github.com/indutny/node-ip/blob/master/lib/ip.js#L63 +const toString = function (buff, offset, length) { + offset = ~~offset + length = length || (buff.length - offset) + + var result = [] + if (length === 4) { + // IPv4 + for (let i = 0; i < length; i++) { + result.push(buff[offset + i]) + } + result = result.join('.') + } else if (length === 16) { + // IPv6 + for (let i = 0; i < length; i += 2) { + result.push(buff.readUInt16BE(offset + i).toString(16)) + } + result = result.join(':') + result = result.replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3') + result = result.replace(/:{3,4}/, '::') + } + + return result +} + +module.exports = { + isIP, + isV4, + isV6, + toBuffer, + toString +}