Skip to content

Commit 0efce94

Browse files
authored
fix: solve circular import (#424)
1 parent 67a7ede commit 0efce94

File tree

5 files changed

+339
-332
lines changed

5 files changed

+339
-332
lines changed

src/convert.ts

Lines changed: 0 additions & 237 deletions
Original file line numberDiff line numberDiff line change
@@ -1,245 +1,8 @@
1-
import { isIPv4 } from '@chainsafe/is-ip'
21
import { IpNet } from '@chainsafe/netmask'
3-
import { base32 } from 'multiformats/bases/base32'
4-
import { bases } from 'multiformats/basics'
5-
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
62
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
73
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
8-
import { InvalidMultiaddrError } from './errors.ts'
94
import { registry } from './registry.js'
105
import type { Multiaddr } from './index.ts'
11-
import type { MultibaseCodec } from 'multiformats'
12-
import type { SupportedEncodings } from 'uint8arrays/to-string'
13-
14-
export function bytesToString (base: SupportedEncodings): (buf: Uint8Array) => string {
15-
return (buf) => {
16-
return uint8ArrayToString(buf, base)
17-
}
18-
}
19-
20-
export function stringToBytes (base: SupportedEncodings): (value: string) => Uint8Array {
21-
return (buf) => {
22-
return uint8ArrayFromString(buf, base)
23-
}
24-
}
25-
26-
export function bytes2port (buf: Uint8Array): string {
27-
const view = new DataView(buf.buffer)
28-
return view.getUint16(buf.byteOffset).toString()
29-
}
30-
31-
export function port2bytes (port: string | number): Uint8Array {
32-
const buf = new ArrayBuffer(2)
33-
const view = new DataView(buf)
34-
view.setUint16(0, typeof port === 'string' ? parseInt(port) : port)
35-
36-
return new Uint8Array(buf)
37-
}
38-
39-
export function onion2bytes (str: string): Uint8Array {
40-
const addr = str.split(':')
41-
42-
if (addr.length !== 2) {
43-
throw new Error(`failed to parse onion addr: ["'${addr.join('", "')}'"]' does not contain a port number`)
44-
}
45-
46-
if (addr[0].length !== 16) {
47-
throw new Error(`failed to parse onion addr: ${addr[0]} not a Tor onion address.`)
48-
}
49-
50-
// onion addresses do not include the multibase prefix, add it before decoding
51-
const buf = uint8ArrayFromString(addr[0], 'base32')
52-
53-
// onion port number
54-
const port = parseInt(addr[1], 10)
55-
56-
if (port < 1 || port > 65536) {
57-
throw new Error('Port number is not in range(1, 65536)')
58-
}
59-
60-
const portBuf = port2bytes(port)
61-
62-
return uint8ArrayConcat([buf, portBuf], buf.length + portBuf.length)
63-
}
64-
65-
export function onion32bytes (str: string): Uint8Array {
66-
const addr = str.split(':')
67-
68-
if (addr.length !== 2) {
69-
throw new Error(`failed to parse onion addr: ["'${addr.join('", "')}'"]' does not contain a port number`)
70-
}
71-
72-
if (addr[0].length !== 56) {
73-
throw new Error(`failed to parse onion addr: ${addr[0]} not a Tor onion3 address.`)
74-
}
75-
76-
// onion addresses do not include the multibase prefix, add it before decoding
77-
const buf = base32.decode(`b${addr[0]}`)
78-
79-
// onion port number
80-
const port = parseInt(addr[1], 10)
81-
82-
if (port < 1 || port > 65536) {
83-
throw new Error('Port number is not in range(1, 65536)')
84-
}
85-
86-
const portBuf = port2bytes(port)
87-
88-
return uint8ArrayConcat([buf, portBuf], buf.length + portBuf.length)
89-
}
90-
91-
export function bytes2onion (buf: Uint8Array): string {
92-
const addrBytes = buf.subarray(0, buf.length - 2)
93-
const portBytes = buf.subarray(buf.length - 2)
94-
const addr = uint8ArrayToString(addrBytes, 'base32')
95-
const port = bytes2port(portBytes)
96-
return `${addr}:${port}`
97-
}
98-
99-
// Copied from https://github.com/indutny/node-ip/blob/master/lib/ip.js#L7
100-
// but with buf/offset args removed because we don't use them
101-
export const ip4ToBytes = function (ip: string): Uint8Array {
102-
ip = ip.toString().trim()
103-
104-
const bytes = new Uint8Array(4)
105-
106-
ip.split(/\./g).forEach((byte, index) => {
107-
const value = parseInt(byte, 10)
108-
109-
if (isNaN(value) || value < 0 || value > 0xff) {
110-
throw new InvalidMultiaddrError('Invalid byte value in IP address')
111-
}
112-
113-
bytes[index] = value
114-
})
115-
116-
return bytes
117-
}
118-
119-
// Copied from https://github.com/indutny/node-ip/blob/master/lib/ip.js#L7
120-
// but with buf/offset args removed because we don't use them
121-
export const ip6ToBytes = function (ip: string): Uint8Array {
122-
let offset = 0
123-
ip = ip.toString().trim()
124-
125-
const sections = ip.split(':', 8)
126-
127-
let i
128-
for (i = 0; i < sections.length; i++) {
129-
const isv4 = isIPv4(sections[i])
130-
let v4Buffer: Uint8Array | undefined
131-
132-
if (isv4) {
133-
v4Buffer = ip4ToBytes(sections[i])
134-
sections[i] = uint8ArrayToString(v4Buffer.subarray(0, 2), 'base16')
135-
}
136-
137-
if (v4Buffer != null && ++i < 8) {
138-
sections.splice(i, 0, uint8ArrayToString(v4Buffer.subarray(2, 4), 'base16'))
139-
}
140-
}
141-
142-
if (sections[0] === '') {
143-
while (sections.length < 8) { sections.unshift('0') }
144-
} else if (sections[sections.length - 1] === '') {
145-
while (sections.length < 8) { sections.push('0') }
146-
} else if (sections.length < 8) {
147-
for (i = 0; i < sections.length && sections[i] !== ''; i++) { }
148-
const argv: [number, number, ...string[]] = [i, 1]
149-
for (i = 9 - sections.length; i > 0; i--) {
150-
argv.push('0')
151-
}
152-
sections.splice.apply(sections, argv)
153-
}
154-
155-
const bytes = new Uint8Array(offset + 16)
156-
157-
for (i = 0; i < sections.length; i++) {
158-
if (sections[i] === '') {
159-
sections[i] = '0'
160-
}
161-
162-
const word = parseInt(sections[i], 16)
163-
164-
if (isNaN(word) || word < 0 || word > 0xffff) {
165-
throw new InvalidMultiaddrError('Invalid byte value in IP address')
166-
}
167-
168-
bytes[offset++] = (word >> 8) & 0xff
169-
bytes[offset++] = word & 0xff
170-
}
171-
172-
return bytes
173-
}
174-
175-
// Copied from https://github.com/indutny/node-ip/blob/master/lib/ip.js#L63
176-
export const ip4ToString = function (buf: Uint8Array): string {
177-
if (buf.byteLength !== 4) {
178-
throw new InvalidMultiaddrError('IPv4 address was incorrect length')
179-
}
180-
181-
const result = []
182-
183-
for (let i = 0; i < buf.byteLength; i++) {
184-
result.push(buf[i])
185-
}
186-
187-
return result.join('.')
188-
}
189-
190-
export const ip6ToString = function (buf: Uint8Array): string {
191-
if (buf.byteLength !== 16) {
192-
throw new InvalidMultiaddrError('IPv6 address was incorrect length')
193-
}
194-
195-
const result: string[] = []
196-
197-
for (let i = 0; i < buf.byteLength; i += 2) {
198-
const byte1 = buf[i]
199-
const byte2 = buf[i + 1]
200-
201-
const tuple = `${byte1.toString(16).padStart(2, '0')}${byte2.toString(16).padStart(2, '0')}`
202-
203-
result.push(tuple)
204-
}
205-
206-
const ip = result.join(':')
207-
208-
try {
209-
const url = new URL(`http://[${ip}]`)
210-
211-
return url.hostname.substring(1, url.hostname.length - 1)
212-
} catch {
213-
throw new InvalidMultiaddrError(`Invalid IPv6 address "${ip}"`)
214-
}
215-
}
216-
217-
export function ip6StringToValue (str: string): string {
218-
try {
219-
const url = new URL(`http://[${str}]`)
220-
221-
return url.hostname.substring(1, url.hostname.length - 1)
222-
} catch {
223-
throw new InvalidMultiaddrError(`Invalid IPv6 address "${str}"`)
224-
}
225-
}
226-
227-
const decoders = Object.values(bases).map((c) => c.decoder)
228-
const anybaseDecoder = (function () {
229-
let acc = decoders[0].or(decoders[1])
230-
decoders.slice(2).forEach((d) => (acc = acc.or(d)))
231-
return acc
232-
})()
233-
234-
export function mb2bytes (mbstr: string): Uint8Array {
235-
return anybaseDecoder.decode(mbstr)
236-
}
237-
238-
export function bytes2mb (base: MultibaseCodec<any>): (buf: Uint8Array) => string {
239-
return (buf) => {
240-
return base.encoder.encode(buf)
241-
}
242-
}
2436

2447
export function convertToIpNet (multiaddr: Multiaddr): IpNet {
2458
let mask: string | undefined

src/registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { isIPv4, isIPv6 } from '@chainsafe/is-ip'
22
import { CID } from 'multiformats'
33
import { base64url } from 'multiformats/bases/base64'
44
import { CODE_CERTHASH, CODE_DCCP, CODE_DNS, CODE_DNS4, CODE_DNS6, CODE_DNSADDR, CODE_GARLIC32, CODE_GARLIC64, CODE_HTTP, CODE_HTTP_PATH, CODE_HTTPS, CODE_IP4, CODE_IP6, CODE_IP6ZONE, CODE_IPCIDR, CODE_MEMORY, CODE_NOISE, CODE_ONION, CODE_ONION3, CODE_P2P, CODE_P2P_CIRCUIT, CODE_P2P_STARDUST, CODE_P2P_WEBRTC_DIRECT, CODE_P2P_WEBRTC_STAR, CODE_P2P_WEBSOCKET_STAR, CODE_QUIC, CODE_QUIC_V1, CODE_SCTP, CODE_SNI, CODE_TCP, CODE_TLS, CODE_UDP, CODE_UDT, CODE_UNIX, CODE_UTP, CODE_WEBRTC, CODE_WEBRTC_DIRECT, CODE_WEBTRANSPORT, CODE_WS, CODE_WSS } from './constants.ts'
5-
import { bytes2mb, bytes2onion, bytes2port, bytesToString, ip4ToBytes, ip4ToString, ip6StringToValue, ip6ToBytes, ip6ToString, mb2bytes, onion2bytes, onion32bytes, port2bytes, stringToBytes } from './convert.ts'
65
import { InvalidProtocolError, ValidationError } from './errors.ts'
6+
import { bytes2mb, bytes2onion, bytes2port, bytesToString, ip4ToBytes, ip4ToString, ip6StringToValue, ip6ToBytes, ip6ToString, mb2bytes, onion2bytes, onion32bytes, port2bytes, stringToBytes } from './utils.ts'
77
import { validatePort } from './validation.ts'
88

99
export const V = -1

0 commit comments

Comments
 (0)