@libp2p/utils 6.7.2-8484de8a2 → 6.7.2-87bc8d4fb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.min.js +1 -6
- package/dist/index.min.js.map +4 -4
- package/dist/src/abort-options.d.ts +7 -0
- package/dist/src/abort-options.d.ts.map +1 -0
- package/dist/src/abort-options.js +14 -0
- package/dist/src/abort-options.js.map +1 -0
- package/dist/src/abstract-stream.d.ts +130 -14
- package/dist/src/abstract-stream.d.ts.map +1 -1
- package/dist/src/abstract-stream.js +321 -39
- package/dist/src/abstract-stream.js.map +1 -1
- package/dist/src/array-equals.d.ts +24 -0
- package/dist/src/array-equals.d.ts.map +1 -0
- package/dist/src/array-equals.js +31 -0
- package/dist/src/array-equals.js.map +1 -0
- package/dist/src/close-source.d.ts +4 -0
- package/dist/src/close-source.d.ts.map +1 -0
- package/dist/src/close-source.js +11 -0
- package/dist/src/close-source.js.map +1 -0
- package/dist/src/close.d.ts +21 -0
- package/dist/src/close.d.ts.map +1 -0
- package/dist/src/close.js +49 -0
- package/dist/src/close.js.map +1 -0
- package/dist/src/errors.d.ts +0 -8
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +0 -8
- package/dist/src/errors.js.map +1 -1
- package/dist/src/get-thin-waist-addresses.browser.d.ts +1 -1
- package/dist/src/get-thin-waist-addresses.browser.d.ts.map +1 -1
- package/dist/src/get-thin-waist-addresses.browser.js +3 -4
- package/dist/src/get-thin-waist-addresses.browser.js.map +1 -1
- package/dist/src/get-thin-waist-addresses.d.ts +1 -1
- package/dist/src/get-thin-waist-addresses.d.ts.map +1 -1
- package/dist/src/get-thin-waist-addresses.js +9 -7
- package/dist/src/get-thin-waist-addresses.js.map +1 -1
- package/dist/src/index.d.ts +1 -33
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -33
- package/dist/src/index.js.map +1 -1
- package/dist/src/multiaddr/is-global-unicast.d.ts.map +1 -1
- package/dist/src/multiaddr/is-global-unicast.js +9 -8
- package/dist/src/multiaddr/is-global-unicast.js.map +1 -1
- package/dist/src/multiaddr/is-ip-based.d.ts +6 -0
- package/dist/src/multiaddr/is-ip-based.d.ts.map +1 -0
- package/dist/src/multiaddr/is-ip-based.js +18 -0
- package/dist/src/multiaddr/is-ip-based.js.map +1 -0
- package/dist/src/multiaddr/is-link-local.d.ts.map +1 -1
- package/dist/src/multiaddr/is-link-local.js +16 -11
- package/dist/src/multiaddr/is-link-local.js.map +1 -1
- package/dist/src/multiaddr/is-loopback.d.ts.map +1 -1
- package/dist/src/multiaddr/is-loopback.js +5 -12
- package/dist/src/multiaddr/is-loopback.js.map +1 -1
- package/dist/src/multiaddr/is-network-address.d.ts.map +1 -1
- package/dist/src/multiaddr/is-network-address.js +16 -4
- package/dist/src/multiaddr/is-network-address.js.map +1 -1
- package/dist/src/multiaddr/is-private.d.ts.map +1 -1
- package/dist/src/multiaddr/is-private.js +10 -9
- package/dist/src/multiaddr/is-private.js.map +1 -1
- package/dist/src/queue/index.d.ts +0 -3
- package/dist/src/queue/index.d.ts.map +1 -1
- package/dist/src/queue/index.js +4 -20
- package/dist/src/queue/index.js.map +1 -1
- package/dist/src/rate-limiter.d.ts +15 -1
- package/dist/src/rate-limiter.d.ts.map +1 -1
- package/dist/src/rate-limiter.js +14 -1
- package/dist/src/rate-limiter.js.map +1 -1
- package/dist/src/stream-to-ma-conn.d.ts +23 -0
- package/dist/src/stream-to-ma-conn.d.ts.map +1 -0
- package/dist/src/stream-to-ma-conn.js +75 -0
- package/dist/src/stream-to-ma-conn.js.map +1 -0
- package/package.json +163 -19
- package/src/abort-options.ts +20 -0
- package/src/abstract-stream.ts +464 -51
- package/src/array-equals.ts +34 -0
- package/src/close-source.ts +14 -0
- package/src/close.ts +65 -0
- package/src/errors.ts +0 -10
- package/src/get-thin-waist-addresses.browser.ts +4 -5
- package/src/get-thin-waist-addresses.ts +12 -8
- package/src/index.ts +1 -33
- package/src/multiaddr/is-global-unicast.ts +11 -8
- package/src/multiaddr/is-ip-based.ts +21 -0
- package/src/multiaddr/is-link-local.ts +20 -11
- package/src/multiaddr/is-loopback.ts +7 -12
- package/src/multiaddr/is-network-address.ts +19 -4
- package/src/multiaddr/is-private.ts +14 -9
- package/src/queue/index.ts +4 -24
- package/src/rate-limiter.ts +30 -3
- package/src/stream-to-ma-conn.ts +106 -0
- package/dist/src/abstract-message-stream.d.ts +0 -129
- package/dist/src/abstract-message-stream.d.ts.map +0 -1
- package/dist/src/abstract-message-stream.js +0 -389
- package/dist/src/abstract-message-stream.js.map +0 -1
- package/dist/src/abstract-multiaddr-connection.d.ts +0 -26
- package/dist/src/abstract-multiaddr-connection.d.ts.map +0 -1
- package/dist/src/abstract-multiaddr-connection.js +0 -66
- package/dist/src/abstract-multiaddr-connection.js.map +0 -1
- package/dist/src/abstract-stream-muxer.d.ts +0 -53
- package/dist/src/abstract-stream-muxer.d.ts.map +0 -1
- package/dist/src/abstract-stream-muxer.js +0 -169
- package/dist/src/abstract-stream-muxer.js.map +0 -1
- package/dist/src/length-prefixed-decoder.d.ts +0 -37
- package/dist/src/length-prefixed-decoder.d.ts.map +0 -1
- package/dist/src/length-prefixed-decoder.js +0 -64
- package/dist/src/length-prefixed-decoder.js.map +0 -1
- package/dist/src/message-queue.d.ts +0 -61
- package/dist/src/message-queue.d.ts.map +0 -1
- package/dist/src/message-queue.js +0 -93
- package/dist/src/message-queue.js.map +0 -1
- package/dist/src/mock-muxer.d.ts +0 -57
- package/dist/src/mock-muxer.d.ts.map +0 -1
- package/dist/src/mock-muxer.js +0 -204
- package/dist/src/mock-muxer.js.map +0 -1
- package/dist/src/mock-stream.d.ts +0 -31
- package/dist/src/mock-stream.d.ts.map +0 -1
- package/dist/src/mock-stream.js +0 -69
- package/dist/src/mock-stream.js.map +0 -1
- package/dist/src/multiaddr/get-net-config.d.ts +0 -55
- package/dist/src/multiaddr/get-net-config.d.ts.map +0 -1
- package/dist/src/multiaddr/get-net-config.js +0 -54
- package/dist/src/multiaddr/get-net-config.js.map +0 -1
- package/dist/src/multiaddr/index.d.ts +0 -7
- package/dist/src/multiaddr/index.d.ts.map +0 -1
- package/dist/src/multiaddr/index.js +0 -7
- package/dist/src/multiaddr/index.js.map +0 -1
- package/dist/src/multiaddr/utils.d.ts +0 -5
- package/dist/src/multiaddr/utils.d.ts.map +0 -1
- package/dist/src/multiaddr/utils.js +0 -32
- package/dist/src/multiaddr/utils.js.map +0 -1
- package/dist/src/multiaddr-connection-pair.d.ts +0 -25
- package/dist/src/multiaddr-connection-pair.d.ts.map +0 -1
- package/dist/src/multiaddr-connection-pair.js +0 -103
- package/dist/src/multiaddr-connection-pair.js.map +0 -1
- package/dist/src/socket-writer.browser.d.ts +0 -2
- package/dist/src/socket-writer.browser.d.ts.map +0 -1
- package/dist/src/socket-writer.browser.js +0 -4
- package/dist/src/socket-writer.browser.js.map +0 -1
- package/dist/src/socket-writer.d.ts +0 -19
- package/dist/src/socket-writer.d.ts.map +0 -1
- package/dist/src/socket-writer.js +0 -43
- package/dist/src/socket-writer.js.map +0 -1
- package/dist/src/stream-pair.d.ts +0 -42
- package/dist/src/stream-pair.d.ts.map +0 -1
- package/dist/src/stream-pair.js +0 -40
- package/dist/src/stream-pair.js.map +0 -1
- package/dist/src/stream-utils.d.ts +0 -198
- package/dist/src/stream-utils.d.ts.map +0 -1
- package/dist/src/stream-utils.js +0 -369
- package/dist/src/stream-utils.js.map +0 -1
- package/src/abstract-message-stream.ts +0 -549
- package/src/abstract-multiaddr-connection.ts +0 -93
- package/src/abstract-stream-muxer.ts +0 -239
- package/src/length-prefixed-decoder.ts +0 -98
- package/src/message-queue.ts +0 -156
- package/src/mock-muxer.ts +0 -304
- package/src/mock-stream.ts +0 -101
- package/src/multiaddr/get-net-config.ts +0 -112
- package/src/multiaddr/index.ts +0 -6
- package/src/multiaddr/utils.ts +0 -46
- package/src/multiaddr-connection-pair.ts +0 -147
- package/src/socket-writer.browser.ts +0 -3
- package/src/socket-writer.ts +0 -64
- package/src/stream-pair.ts +0 -90
- package/src/stream-utils.ts +0 -873
package/src/close.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Connection, Stream, AbortOptions } from '@libp2p/interface'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Close the passed stream, falling back to aborting the stream if closing
|
|
5
|
+
* cleanly fails.
|
|
6
|
+
*/
|
|
7
|
+
export async function safelyCloseStream (stream?: Stream, options?: AbortOptions): Promise<void> {
|
|
8
|
+
try {
|
|
9
|
+
await stream?.close(options)
|
|
10
|
+
} catch (err: any) {
|
|
11
|
+
stream?.abort(err)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* These are speculative protocols that are run automatically on connection open
|
|
17
|
+
* so are usually not the reason the connection was opened.
|
|
18
|
+
*
|
|
19
|
+
* Consequently when requested it should be safe to close connections that only
|
|
20
|
+
* have these protocol streams open.
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_CLOSABLE_PROTOCOLS = [
|
|
23
|
+
// identify
|
|
24
|
+
'/ipfs/id/1.0.0',
|
|
25
|
+
|
|
26
|
+
// identify-push
|
|
27
|
+
'/ipfs/id/push/1.0.0',
|
|
28
|
+
|
|
29
|
+
// autonat
|
|
30
|
+
'/libp2p/autonat/1.0.0',
|
|
31
|
+
|
|
32
|
+
// dcutr
|
|
33
|
+
'/libp2p/dcutr'
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
export interface SafelyCloseConnectionOptions extends AbortOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Only close the stream if it either has no protocol streams open or only
|
|
39
|
+
* ones in this list.
|
|
40
|
+
*
|
|
41
|
+
* @default ['/ipfs/id/1.0.0']
|
|
42
|
+
*/
|
|
43
|
+
closableProtocols?: string[]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Close the passed connection if it has no streams, or only closable protocol
|
|
48
|
+
* streams, falling back to aborting the connection if closing it cleanly fails.
|
|
49
|
+
*/
|
|
50
|
+
export async function safelyCloseConnectionIfUnused (connection?: Connection, options?: SafelyCloseConnectionOptions): Promise<void> {
|
|
51
|
+
const streamProtocols = connection?.streams?.map(stream => stream.protocol) ?? []
|
|
52
|
+
const closableProtocols = options?.closableProtocols ?? DEFAULT_CLOSABLE_PROTOCOLS
|
|
53
|
+
|
|
54
|
+
// if the connection has protocols not in the closable protocols list, do not
|
|
55
|
+
// close the connection
|
|
56
|
+
if (streamProtocols.filter(proto => proto != null && !closableProtocols.includes(proto)).length > 0) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
await connection?.close(options)
|
|
62
|
+
} catch (err: any) {
|
|
63
|
+
connection?.abort(err)
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/errors.ts
CHANGED
|
@@ -27,13 +27,3 @@ export class QueueFullError extends Error {
|
|
|
27
27
|
this.name = 'QueueFullError'
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
export class UnexpectedEOFError extends Error {
|
|
32
|
-
static name = 'UnexpectedEOFError'
|
|
33
|
-
name = 'UnexpectedEOFError'
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class MaxEarlyStreamsError extends Error {
|
|
37
|
-
static name = 'MaxEarlyStreamsError'
|
|
38
|
-
name = 'MaxEarlyStreamsError'
|
|
39
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { netConfigToMultiaddr } from './multiaddr/utils.ts'
|
|
1
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
3
2
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
4
3
|
|
|
5
4
|
/**
|
|
@@ -8,14 +7,14 @@ import type { Multiaddr } from '@multiformats/multiaddr'
|
|
|
8
7
|
*
|
|
9
8
|
* Wildcard IP4/6 addresses will be expanded into all available interfaces.
|
|
10
9
|
*/
|
|
11
|
-
export function getThinWaistAddresses (ma?: Multiaddr, port?: number
|
|
10
|
+
export function getThinWaistAddresses (ma?: Multiaddr, port?: number): Multiaddr[] {
|
|
12
11
|
if (ma == null) {
|
|
13
12
|
return []
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
const
|
|
15
|
+
const options = ma.toOptions()
|
|
17
16
|
|
|
18
17
|
return [
|
|
19
|
-
|
|
18
|
+
multiaddr(`/ip${options.family}/${options.host}/${options.transport}/${port ?? options.port}`)
|
|
20
19
|
]
|
|
21
20
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import os from 'node:os'
|
|
2
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
2
3
|
import { isLinkLocalIp } from './link-local-ip.js'
|
|
3
|
-
import { getNetConfig } from './multiaddr/get-net-config.ts'
|
|
4
|
-
import { netConfigToMultiaddr } from './multiaddr/utils.ts'
|
|
5
4
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
6
5
|
|
|
7
6
|
const FAMILIES = { 4: 'IPv4', 6: 'IPv6' }
|
|
@@ -37,19 +36,24 @@ function getNetworkAddrs (family: 4 | 6): string[] {
|
|
|
37
36
|
*
|
|
38
37
|
* Wildcard IP4/6 addresses will be expanded into all available interfaces.
|
|
39
38
|
*/
|
|
40
|
-
export function getThinWaistAddresses (ma?: Multiaddr, port?: number
|
|
39
|
+
export function getThinWaistAddresses (ma?: Multiaddr, port?: number): Multiaddr[] {
|
|
41
40
|
if (ma == null) {
|
|
42
41
|
return []
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
const
|
|
44
|
+
const options = ma.toOptions()
|
|
46
45
|
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
if (isWildcard(options.host)) {
|
|
47
|
+
const addrs = []
|
|
48
|
+
|
|
49
|
+
for (const host of getNetworkAddrs(options.family)) {
|
|
50
|
+
addrs.push(multiaddr(`/ip${options.family}/${host}/${options.transport}/${port ?? options.port}`))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return addrs
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
return [
|
|
53
|
-
|
|
57
|
+
multiaddr(`/ip${options.family}/${options.host}/${options.transport}/${port ?? options.port}`)
|
|
54
58
|
]
|
|
55
59
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,36 +4,4 @@
|
|
|
4
4
|
* This module contains utility functions used by libp2p modules.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
export * from './multiaddr/index.js'
|
|
9
|
-
export * from './queue/index.js'
|
|
10
|
-
export * from './abstract-message-stream.js'
|
|
11
|
-
export * from './abstract-multiaddr-connection.js'
|
|
12
|
-
export * from './abstract-stream-muxer.js'
|
|
13
|
-
export * from './abstract-stream.js'
|
|
14
|
-
export * from './adaptive-timeout.js'
|
|
15
|
-
export * from './debounce.js'
|
|
16
|
-
export * from './errors.js'
|
|
17
|
-
export * from './get-thin-waist-addresses.js'
|
|
18
|
-
export * from './global-unicast-ip.js'
|
|
19
|
-
export * from './ip-port-to-multiaddr.js'
|
|
20
|
-
export * from './is-async-generator.js'
|
|
21
|
-
export * from './is-generator.js'
|
|
22
|
-
export * from './is-promise.js'
|
|
23
|
-
export * from './length-prefixed-decoder.js'
|
|
24
|
-
export * from './link-local-ip.js'
|
|
25
|
-
export * from './merge-options.js'
|
|
26
|
-
export * from './mock-muxer.js'
|
|
27
|
-
export * from './mock-stream.js'
|
|
28
|
-
export * from './moving-average.js'
|
|
29
|
-
export * from './multiaddr-connection-pair.js'
|
|
30
|
-
export * from './peer-queue.js'
|
|
31
|
-
export * from './priority-queue.js'
|
|
32
|
-
export * from './private-ip.js'
|
|
33
|
-
export * from './rate-limiter.js'
|
|
34
|
-
export * from './repeating-task.js'
|
|
35
|
-
export * from './stream-pair.js'
|
|
36
|
-
export * from './stream-utils.js'
|
|
37
|
-
export * from './socket-writer.js'
|
|
38
|
-
export * from './tracked-list.js'
|
|
39
|
-
export * from './tracked-map.js'
|
|
7
|
+
export {}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cidrContains } from '@chainsafe/netmask'
|
|
2
|
-
import {
|
|
2
|
+
import { CODE_IP6 } from '@multiformats/multiaddr'
|
|
3
3
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -7,15 +7,18 @@ import type { Multiaddr } from '@multiformats/multiaddr'
|
|
|
7
7
|
*/
|
|
8
8
|
export function isGlobalUnicast (ma: Multiaddr): boolean {
|
|
9
9
|
try {
|
|
10
|
-
const
|
|
10
|
+
for (const { code, value } of ma.getComponents()) {
|
|
11
|
+
if (value == null) {
|
|
12
|
+
continue
|
|
13
|
+
}
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
default:
|
|
16
|
-
return false
|
|
15
|
+
if (code === CODE_IP6) {
|
|
16
|
+
return cidrContains('2000::/3', value)
|
|
17
|
+
}
|
|
17
18
|
}
|
|
18
19
|
} catch {
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
}
|
|
22
|
+
|
|
23
|
+
return false
|
|
21
24
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CODE_IP4, CODE_IP6, CODE_IP6ZONE } from '@multiformats/multiaddr'
|
|
2
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Check if a given multiaddr is IP-based
|
|
6
|
+
*/
|
|
7
|
+
export function isIpBased (ma: Multiaddr): boolean {
|
|
8
|
+
try {
|
|
9
|
+
for (const { code } of ma.getComponents()) {
|
|
10
|
+
if (code === CODE_IP6ZONE) {
|
|
11
|
+
continue
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return code === CODE_IP4 || code === CODE_IP6
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CODE_IP4, CODE_IP6, CODE_IP6ZONE } from '@multiformats/multiaddr'
|
|
2
2
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -6,17 +6,26 @@ import type { Multiaddr } from '@multiformats/multiaddr'
|
|
|
6
6
|
*/
|
|
7
7
|
export function isLinkLocal (ma: Multiaddr): boolean {
|
|
8
8
|
try {
|
|
9
|
-
const
|
|
9
|
+
for (const { code, value } of ma.getComponents()) {
|
|
10
|
+
if (code === CODE_IP6ZONE) {
|
|
11
|
+
continue
|
|
12
|
+
}
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if (value == null) {
|
|
15
|
+
continue
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (code === CODE_IP4) {
|
|
19
|
+
return value.startsWith('169.254.')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (code === CODE_IP6) {
|
|
23
|
+
return value.toLowerCase().startsWith('fe80')
|
|
24
|
+
}
|
|
18
25
|
}
|
|
19
|
-
} catch
|
|
20
|
-
|
|
26
|
+
} catch {
|
|
27
|
+
|
|
21
28
|
}
|
|
29
|
+
|
|
30
|
+
return false
|
|
22
31
|
}
|
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
import { isLoopbackAddr } from 'is-loopback-addr'
|
|
2
|
-
import {
|
|
2
|
+
import { isIpBased } from './is-ip-based.js'
|
|
3
3
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Check if a given multiaddr is a loopback address.
|
|
7
7
|
*/
|
|
8
8
|
export function isLoopback (ma: Multiaddr): boolean {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
switch (config.type) {
|
|
13
|
-
case 'ip4':
|
|
14
|
-
case 'ip6':
|
|
15
|
-
return isLoopbackAddr(config.host)
|
|
16
|
-
default:
|
|
17
|
-
return false
|
|
18
|
-
}
|
|
19
|
-
} catch {
|
|
9
|
+
if (!isIpBased(ma)) {
|
|
10
|
+
// not an IP based multiaddr, cannot be private
|
|
20
11
|
return false
|
|
21
12
|
}
|
|
13
|
+
|
|
14
|
+
const { address } = ma.nodeAddress()
|
|
15
|
+
|
|
16
|
+
return isLoopbackAddr(address)
|
|
22
17
|
}
|
|
@@ -1,15 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CODE_IP4, CODE_IP6, CODE_IP6ZONE, CODE_DNS, CODE_DNS4, CODE_DNS6, CODE_DNSADDR } from '@multiformats/multiaddr'
|
|
2
2
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
3
3
|
|
|
4
|
+
const NETWORK_CODECS = [
|
|
5
|
+
CODE_IP4,
|
|
6
|
+
CODE_IP6,
|
|
7
|
+
CODE_DNS,
|
|
8
|
+
CODE_DNS4,
|
|
9
|
+
CODE_DNS6,
|
|
10
|
+
CODE_DNSADDR
|
|
11
|
+
]
|
|
12
|
+
|
|
4
13
|
/**
|
|
5
14
|
* Check if a given multiaddr is a network address
|
|
6
15
|
*/
|
|
7
16
|
export function isNetworkAddress (ma: Multiaddr): boolean {
|
|
8
17
|
try {
|
|
9
|
-
|
|
18
|
+
for (const { code } of ma.getComponents()) {
|
|
19
|
+
if (code === CODE_IP6ZONE) {
|
|
20
|
+
continue
|
|
21
|
+
}
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
return NETWORK_CODECS.includes(code)
|
|
24
|
+
}
|
|
12
25
|
} catch {
|
|
13
|
-
|
|
26
|
+
|
|
14
27
|
}
|
|
28
|
+
|
|
29
|
+
return false
|
|
15
30
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isPrivateIp } from '../private-ip.js'
|
|
2
|
-
import {
|
|
2
|
+
import { isIpBased } from './is-ip-based.js'
|
|
3
3
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -7,16 +7,21 @@ import type { Multiaddr } from '@multiformats/multiaddr'
|
|
|
7
7
|
*/
|
|
8
8
|
export function isPrivate (ma: Multiaddr): boolean {
|
|
9
9
|
try {
|
|
10
|
-
|
|
10
|
+
if (!isIpBased(ma)) {
|
|
11
|
+
// not an IP based multiaddr, cannot be private
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const [[, value]] = ma.stringTuples()
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
case 'ip6':
|
|
15
|
-
return isPrivateIp(config.host) ?? false
|
|
16
|
-
default:
|
|
17
|
-
return config.host === 'localhost'
|
|
17
|
+
if (value == null) {
|
|
18
|
+
return false
|
|
18
19
|
}
|
|
20
|
+
|
|
21
|
+
return isPrivateIp(value) ?? false
|
|
19
22
|
} catch {
|
|
20
|
-
|
|
23
|
+
|
|
21
24
|
}
|
|
25
|
+
|
|
26
|
+
return true
|
|
22
27
|
}
|
package/src/queue/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AbortError } from '@libp2p/interface'
|
|
2
2
|
import { pushable } from 'it-pushable'
|
|
3
3
|
import { TypedEventEmitter } from 'main-event'
|
|
4
|
-
import {
|
|
4
|
+
import { raceEvent } from 'race-event'
|
|
5
5
|
import { debounce } from '../debounce.js'
|
|
6
6
|
import { QueueFullError } from '../errors.js'
|
|
7
7
|
import { Job } from './job.js'
|
|
@@ -131,7 +131,6 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
131
131
|
public queue: Array<Job<JobOptions, JobReturnType>>
|
|
132
132
|
private pending: number
|
|
133
133
|
private readonly sort?: Comparator<Job<JobOptions, JobReturnType>>
|
|
134
|
-
private paused: boolean
|
|
135
134
|
|
|
136
135
|
constructor (init: QueueInit<JobReturnType, JobOptions> = {}) {
|
|
137
136
|
super()
|
|
@@ -139,7 +138,6 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
139
138
|
this.concurrency = init.concurrency ?? Number.POSITIVE_INFINITY
|
|
140
139
|
this.maxSize = init.maxSize ?? Number.POSITIVE_INFINITY
|
|
141
140
|
this.pending = 0
|
|
142
|
-
this.paused = false
|
|
143
141
|
|
|
144
142
|
if (init.metricName != null) {
|
|
145
143
|
init.metrics?.registerMetricGroup(init.metricName, {
|
|
@@ -176,24 +174,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
176
174
|
this.safeDispatchEvent('idle')
|
|
177
175
|
}
|
|
178
176
|
|
|
179
|
-
pause (): void {
|
|
180
|
-
this.paused = true
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
resume (): void {
|
|
184
|
-
if (!this.paused) {
|
|
185
|
-
return
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
this.paused = false
|
|
189
|
-
this.tryToStartAnother()
|
|
190
|
-
}
|
|
191
|
-
|
|
192
177
|
private tryToStartAnother (): boolean {
|
|
193
|
-
if (this.paused) {
|
|
194
|
-
return false
|
|
195
|
-
}
|
|
196
|
-
|
|
197
178
|
if (this.size === 0) {
|
|
198
179
|
this.emitEmpty()
|
|
199
180
|
|
|
@@ -319,7 +300,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
319
300
|
return
|
|
320
301
|
}
|
|
321
302
|
|
|
322
|
-
await
|
|
303
|
+
await raceEvent(this, 'empty', options?.signal)
|
|
323
304
|
}
|
|
324
305
|
|
|
325
306
|
/**
|
|
@@ -339,8 +320,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
339
320
|
return
|
|
340
321
|
}
|
|
341
322
|
|
|
342
|
-
await
|
|
343
|
-
...options,
|
|
323
|
+
await raceEvent(this, 'next', options?.signal, {
|
|
344
324
|
filter: () => this.size < limit
|
|
345
325
|
})
|
|
346
326
|
}
|
|
@@ -359,7 +339,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
359
339
|
return
|
|
360
340
|
}
|
|
361
341
|
|
|
362
|
-
await
|
|
342
|
+
await raceEvent(this, 'idle', options?.signal)
|
|
363
343
|
}
|
|
364
344
|
|
|
365
345
|
/**
|
package/src/rate-limiter.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import delay from 'delay'
|
|
1
2
|
import { RateLimitError } from './errors.js'
|
|
2
3
|
|
|
3
4
|
export interface RateLimiterInit {
|
|
@@ -22,6 +23,20 @@ export interface RateLimiterInit {
|
|
|
22
23
|
*/
|
|
23
24
|
blockDuration?: number
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Execute allowed actions evenly over duration
|
|
28
|
+
*
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
execEvenly?: boolean
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* ms, works with execEvenly=true option
|
|
35
|
+
*
|
|
36
|
+
* @default duration * 1000 / points
|
|
37
|
+
*/
|
|
38
|
+
execEvenlyMinDelayMs?: number
|
|
39
|
+
|
|
25
40
|
/**
|
|
26
41
|
* @default "rlflx"
|
|
27
42
|
*/
|
|
@@ -50,17 +65,21 @@ export class RateLimiter {
|
|
|
50
65
|
protected points: number
|
|
51
66
|
protected duration: number
|
|
52
67
|
protected blockDuration: number
|
|
68
|
+
protected execEvenly: boolean
|
|
69
|
+
protected execEvenlyMinDelayMs: number
|
|
53
70
|
protected keyPrefix: string
|
|
54
71
|
|
|
55
72
|
constructor (opts: RateLimiterInit = {}) {
|
|
56
73
|
this.points = opts.points ?? 4
|
|
57
74
|
this.duration = opts.duration ?? 1
|
|
58
75
|
this.blockDuration = opts.blockDuration ?? 0
|
|
76
|
+
this.execEvenly = opts.execEvenly ?? false
|
|
77
|
+
this.execEvenlyMinDelayMs = opts.execEvenlyMinDelayMs ?? (this.duration * 1000 / this.points)
|
|
59
78
|
this.keyPrefix = opts.keyPrefix ?? 'rlflx'
|
|
60
79
|
this.memoryStorage = new MemoryStorage()
|
|
61
80
|
}
|
|
62
81
|
|
|
63
|
-
consume (key: string, pointsToConsume: number = 1, options: GetKeySecDurationOptions = {}): RateLimiterResult {
|
|
82
|
+
async consume (key: string, pointsToConsume: number = 1, options: GetKeySecDurationOptions = {}): Promise<RateLimiterResult> {
|
|
64
83
|
const rlKey = this.getKey(key)
|
|
65
84
|
const secDuration = this._getKeySecDuration(options)
|
|
66
85
|
let res = this.memoryStorage.incrby(rlKey, pointsToConsume, secDuration)
|
|
@@ -74,6 +93,14 @@ export class RateLimiter {
|
|
|
74
93
|
}
|
|
75
94
|
|
|
76
95
|
throw new RateLimitError('Rate limit exceeded', res)
|
|
96
|
+
} else if (this.execEvenly && res.msBeforeNext > 0 && !res.isFirstInDuration) {
|
|
97
|
+
// Execute evenly
|
|
98
|
+
let delayMs = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2))
|
|
99
|
+
if (delayMs < this.execEvenlyMinDelayMs) {
|
|
100
|
+
delayMs = res.consumedPoints * this.execEvenlyMinDelayMs
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
await delay(delayMs)
|
|
77
104
|
}
|
|
78
105
|
|
|
79
106
|
return res
|
|
@@ -214,8 +241,8 @@ export class MemoryStorage {
|
|
|
214
241
|
this.storage.delete(key)
|
|
215
242
|
}, durationMs)
|
|
216
243
|
|
|
217
|
-
if (
|
|
218
|
-
|
|
244
|
+
if (record.timeoutId.unref != null) {
|
|
245
|
+
record.timeoutId.unref()
|
|
219
246
|
}
|
|
220
247
|
}
|
|
221
248
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import forEach from 'it-foreach'
|
|
2
|
+
import { pipe } from 'it-pipe'
|
|
3
|
+
import type { Logger, MultiaddrConnection, Stream } from '@libp2p/interface'
|
|
4
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
5
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
6
|
+
|
|
7
|
+
export interface StreamProperties {
|
|
8
|
+
stream: Stream
|
|
9
|
+
remoteAddr: Multiaddr
|
|
10
|
+
localAddr: Multiaddr
|
|
11
|
+
log: Logger
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A callback invoked when data is read from the stream
|
|
15
|
+
*/
|
|
16
|
+
onDataRead?(buf: Uint8ArrayList | Uint8Array): void
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A callback invoked when data is written to the stream
|
|
20
|
+
*/
|
|
21
|
+
onDataWrite?(buf: Uint8ArrayList | Uint8Array): void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Convert a duplex iterable into a MultiaddrConnection.
|
|
26
|
+
* https://github.com/libp2p/interface-transport#multiaddrconnection
|
|
27
|
+
*/
|
|
28
|
+
export function streamToMaConnection (props: StreamProperties): MultiaddrConnection {
|
|
29
|
+
const { stream, remoteAddr, log, onDataRead, onDataWrite } = props
|
|
30
|
+
|
|
31
|
+
let closedRead = false
|
|
32
|
+
let closedWrite = false
|
|
33
|
+
|
|
34
|
+
// piggyback on `stream.close` invocations to close multiaddr connection
|
|
35
|
+
const streamClose = stream.close.bind(stream)
|
|
36
|
+
stream.close = async (options): Promise<void> => {
|
|
37
|
+
await streamClose(options)
|
|
38
|
+
close(true)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// piggyback on `stream.abort` invocations to close multiaddr connection
|
|
42
|
+
const streamAbort = stream.abort.bind(stream)
|
|
43
|
+
stream.abort = (err): void => {
|
|
44
|
+
streamAbort(err)
|
|
45
|
+
close(true)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// piggyback on `stream.sink` invocations to close multiaddr connection
|
|
49
|
+
const streamSink = stream.sink.bind(stream)
|
|
50
|
+
stream.sink = async (source): Promise<void> => {
|
|
51
|
+
try {
|
|
52
|
+
await streamSink(
|
|
53
|
+
pipe(
|
|
54
|
+
source,
|
|
55
|
+
(source) => forEach(source, buf => onDataWrite?.(buf))
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
} catch (err: any) {
|
|
59
|
+
maConn.log.error('errored - %e', err)
|
|
60
|
+
|
|
61
|
+
// If aborted we can safely ignore
|
|
62
|
+
if (err.type !== 'aborted') {
|
|
63
|
+
// If the source errored the socket will already have been destroyed by
|
|
64
|
+
// toIterable.duplex(). If the socket errored it will already be
|
|
65
|
+
// destroyed. There's nothing to do here except log the error & return.
|
|
66
|
+
maConn.log.error('%s error in sink - %e', remoteAddr, err)
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
closedWrite = true
|
|
70
|
+
close()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const maConn: MultiaddrConnection = {
|
|
75
|
+
log: log.newScope('stream-to-maconn'),
|
|
76
|
+
sink: stream.sink,
|
|
77
|
+
source: (async function * (): AsyncGenerator<Uint8ArrayList> {
|
|
78
|
+
try {
|
|
79
|
+
for await (const buf of stream.source) {
|
|
80
|
+
onDataRead?.(buf)
|
|
81
|
+
yield buf
|
|
82
|
+
}
|
|
83
|
+
} finally {
|
|
84
|
+
closedRead = true
|
|
85
|
+
close()
|
|
86
|
+
}
|
|
87
|
+
}()),
|
|
88
|
+
remoteAddr,
|
|
89
|
+
timeline: { open: Date.now(), close: undefined },
|
|
90
|
+
close: stream.close,
|
|
91
|
+
abort: stream.abort
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function close (force?: boolean): void {
|
|
95
|
+
if (force === true) {
|
|
96
|
+
closedRead = true
|
|
97
|
+
closedWrite = true
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (closedRead && closedWrite && maConn.timeline.close == null) {
|
|
101
|
+
maConn.timeline.close = Date.now()
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return maConn
|
|
106
|
+
}
|