@libp2p/utils 6.7.2 → 7.0.0-55b7e5fea
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 +16 -1
- package/dist/index.min.js +7 -1
- package/dist/index.min.js.map +4 -4
- package/dist/src/abstract-message-stream.d.ts +129 -0
- package/dist/src/abstract-message-stream.d.ts.map +1 -0
- package/dist/src/abstract-message-stream.js +393 -0
- package/dist/src/abstract-message-stream.js.map +1 -0
- package/dist/src/abstract-multiaddr-connection.d.ts +26 -0
- package/dist/src/abstract-multiaddr-connection.d.ts.map +1 -0
- package/dist/src/abstract-multiaddr-connection.js +66 -0
- package/dist/src/abstract-multiaddr-connection.js.map +1 -0
- package/dist/src/abstract-stream-muxer.d.ts +53 -0
- package/dist/src/abstract-stream-muxer.d.ts.map +1 -0
- package/dist/src/abstract-stream-muxer.js +169 -0
- package/dist/src/abstract-stream-muxer.js.map +1 -0
- package/dist/src/abstract-stream.d.ts +14 -130
- package/dist/src/abstract-stream.d.ts.map +1 -1
- package/dist/src/abstract-stream.js +39 -321
- package/dist/src/abstract-stream.js.map +1 -1
- package/dist/src/errors.d.ts +8 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +8 -0
- 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 +4 -3
- 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 +7 -9
- package/dist/src/get-thin-waist-addresses.js.map +1 -1
- package/dist/src/index.d.ts +31 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +31 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/length-prefixed-decoder.d.ts +37 -0
- package/dist/src/length-prefixed-decoder.d.ts.map +1 -0
- package/dist/src/length-prefixed-decoder.js +64 -0
- package/dist/src/length-prefixed-decoder.js.map +1 -0
- package/dist/src/message-queue.d.ts +61 -0
- package/dist/src/message-queue.d.ts.map +1 -0
- package/dist/src/message-queue.js +93 -0
- package/dist/src/message-queue.js.map +1 -0
- package/dist/src/mock-muxer.d.ts +57 -0
- package/dist/src/mock-muxer.d.ts.map +1 -0
- package/dist/src/mock-muxer.js +204 -0
- package/dist/src/mock-muxer.js.map +1 -0
- package/dist/src/mock-stream.d.ts +31 -0
- package/dist/src/mock-stream.d.ts.map +1 -0
- package/dist/src/mock-stream.js +69 -0
- package/dist/src/mock-stream.js.map +1 -0
- package/dist/src/multiaddr/get-net-config.d.ts +55 -0
- package/dist/src/multiaddr/get-net-config.d.ts.map +1 -0
- package/dist/src/multiaddr/get-net-config.js +54 -0
- package/dist/src/multiaddr/get-net-config.js.map +1 -0
- package/dist/src/multiaddr/index.d.ts +7 -0
- package/dist/src/multiaddr/index.d.ts.map +1 -0
- package/dist/src/multiaddr/index.js +7 -0
- package/dist/src/multiaddr/index.js.map +1 -0
- package/dist/src/multiaddr/is-global-unicast.d.ts.map +1 -1
- package/dist/src/multiaddr/is-global-unicast.js +8 -9
- package/dist/src/multiaddr/is-global-unicast.js.map +1 -1
- package/dist/src/multiaddr/is-link-local.d.ts.map +1 -1
- package/dist/src/multiaddr/is-link-local.js +11 -16
- 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 +12 -5
- 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 +4 -16
- 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 +9 -10
- package/dist/src/multiaddr/is-private.js.map +1 -1
- package/dist/src/multiaddr/utils.d.ts +5 -0
- package/dist/src/multiaddr/utils.d.ts.map +1 -0
- package/dist/src/multiaddr/utils.js +32 -0
- package/dist/src/multiaddr/utils.js.map +1 -0
- package/dist/src/multiaddr-connection-pair.d.ts +25 -0
- package/dist/src/multiaddr-connection-pair.d.ts.map +1 -0
- package/dist/src/multiaddr-connection-pair.js +103 -0
- package/dist/src/multiaddr-connection-pair.js.map +1 -0
- package/dist/src/queue/index.d.ts +3 -6
- package/dist/src/queue/index.d.ts.map +1 -1
- package/dist/src/queue/index.js +20 -4
- package/dist/src/queue/index.js.map +1 -1
- package/dist/src/rate-limiter.d.ts +1 -15
- package/dist/src/rate-limiter.d.ts.map +1 -1
- package/dist/src/rate-limiter.js +1 -14
- package/dist/src/rate-limiter.js.map +1 -1
- package/dist/src/stream-pair.d.ts +42 -0
- package/dist/src/stream-pair.d.ts.map +1 -0
- package/dist/src/stream-pair.js +40 -0
- package/dist/src/stream-pair.js.map +1 -0
- package/dist/src/stream-utils.d.ts +191 -0
- package/dist/src/stream-utils.d.ts.map +1 -0
- package/dist/src/stream-utils.js +371 -0
- package/dist/src/stream-utils.js.map +1 -0
- package/package.json +15 -162
- package/src/abstract-message-stream.ts +553 -0
- package/src/abstract-multiaddr-connection.ts +93 -0
- package/src/abstract-stream-muxer.ts +239 -0
- package/src/abstract-stream.ts +51 -464
- package/src/errors.ts +10 -0
- package/src/get-thin-waist-addresses.browser.ts +5 -4
- package/src/get-thin-waist-addresses.ts +8 -12
- package/src/index.ts +31 -1
- package/src/length-prefixed-decoder.ts +98 -0
- package/src/message-queue.ts +156 -0
- package/src/mock-muxer.ts +304 -0
- package/src/mock-stream.ts +101 -0
- package/src/multiaddr/get-net-config.ts +112 -0
- package/src/multiaddr/index.ts +6 -0
- package/src/multiaddr/is-global-unicast.ts +8 -11
- package/src/multiaddr/is-link-local.ts +11 -20
- package/src/multiaddr/is-loopback.ts +12 -7
- package/src/multiaddr/is-network-address.ts +4 -19
- package/src/multiaddr/is-private.ts +9 -14
- package/src/multiaddr/utils.ts +46 -0
- package/src/multiaddr-connection-pair.ts +147 -0
- package/src/queue/index.ts +24 -11
- package/src/rate-limiter.ts +3 -30
- package/src/stream-pair.ts +90 -0
- package/src/stream-utils.ts +866 -0
- package/dist/src/abort-options.d.ts +0 -7
- package/dist/src/abort-options.d.ts.map +0 -1
- package/dist/src/abort-options.js +0 -14
- package/dist/src/abort-options.js.map +0 -1
- package/dist/src/array-equals.d.ts +0 -24
- package/dist/src/array-equals.d.ts.map +0 -1
- package/dist/src/array-equals.js +0 -31
- package/dist/src/array-equals.js.map +0 -1
- package/dist/src/close-source.d.ts +0 -4
- package/dist/src/close-source.d.ts.map +0 -1
- package/dist/src/close-source.js +0 -11
- package/dist/src/close-source.js.map +0 -1
- package/dist/src/close.d.ts +0 -21
- package/dist/src/close.d.ts.map +0 -1
- package/dist/src/close.js +0 -49
- package/dist/src/close.js.map +0 -1
- package/dist/src/merge-options.d.ts +0 -7
- package/dist/src/merge-options.d.ts.map +0 -1
- package/dist/src/merge-options.js +0 -128
- package/dist/src/merge-options.js.map +0 -1
- package/dist/src/multiaddr/is-ip-based.d.ts +0 -6
- package/dist/src/multiaddr/is-ip-based.d.ts.map +0 -1
- package/dist/src/multiaddr/is-ip-based.js +0 -18
- package/dist/src/multiaddr/is-ip-based.js.map +0 -1
- package/dist/src/stream-to-ma-conn.d.ts +0 -23
- package/dist/src/stream-to-ma-conn.d.ts.map +0 -1
- package/dist/src/stream-to-ma-conn.js +0 -75
- package/dist/src/stream-to-ma-conn.js.map +0 -1
- package/dist/typedoc-urls.json +0 -147
- package/src/abort-options.ts +0 -20
- package/src/array-equals.ts +0 -34
- package/src/close-source.ts +0 -14
- package/src/close.ts +0 -65
- package/src/merge-options.ts +0 -161
- package/src/multiaddr/is-ip-based.ts +0 -21
- package/src/stream-to-ma-conn.ts +0 -106
package/src/abstract-stream.ts
CHANGED
|
@@ -1,515 +1,102 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import { Uint8ArrayList } from 'uint8arraylist'
|
|
6
|
-
import { closeSource } from './close-source.js'
|
|
7
|
-
import type { AbortOptions, Direction, ReadStatus, Stream, StreamStatus, StreamTimeline, WriteStatus } from '@libp2p/interface'
|
|
8
|
-
import type { Logger } from '@libp2p/logger'
|
|
9
|
-
import type { Pushable } from 'it-pushable'
|
|
10
|
-
import type { Source } from 'it-stream-types'
|
|
11
|
-
import type { DeferredPromise } from 'p-defer'
|
|
1
|
+
import { pEvent } from 'p-event'
|
|
2
|
+
import { AbstractMessageStream } from './abstract-message-stream.js'
|
|
3
|
+
import type { MessageStreamInit } from './abstract-message-stream.js'
|
|
4
|
+
import type { AbortOptions, Stream } from '@libp2p/interface'
|
|
12
5
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export interface AbstractStreamInit {
|
|
6
|
+
export interface AbstractStreamInit extends MessageStreamInit {
|
|
16
7
|
/**
|
|
17
8
|
* A unique identifier for this stream
|
|
18
9
|
*/
|
|
19
10
|
id: string
|
|
20
11
|
|
|
21
12
|
/**
|
|
22
|
-
* The stream
|
|
23
|
-
*/
|
|
24
|
-
direction: Direction
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* A Logger implementation used to log stream-specific information
|
|
28
|
-
*/
|
|
29
|
-
log: Logger
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* User specific stream metadata
|
|
33
|
-
*/
|
|
34
|
-
metadata?: Record<string, unknown>
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Invoked when the stream ends
|
|
38
|
-
*/
|
|
39
|
-
onEnd?(err?: Error): void
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Invoked when the readable end of the stream is closed
|
|
43
|
-
*/
|
|
44
|
-
onCloseRead?(): void
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Invoked when the writable end of the stream is closed
|
|
48
|
-
*/
|
|
49
|
-
onCloseWrite?(): void
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Invoked when the stream has been reset by the remote
|
|
53
|
-
*/
|
|
54
|
-
onReset?(): void
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Invoked when the stream has errored
|
|
13
|
+
* The protocol name for the stream, if it is known
|
|
58
14
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* How long to wait in ms for stream data to be written to the underlying
|
|
63
|
-
* connection when closing the writable end of the stream.
|
|
64
|
-
*
|
|
65
|
-
* @default 500
|
|
66
|
-
*/
|
|
67
|
-
closeTimeout?: number
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* After the stream sink has closed, a limit on how long it takes to send
|
|
71
|
-
* a close-write message to the remote peer.
|
|
72
|
-
*/
|
|
73
|
-
sendCloseWriteTimeout?: number
|
|
15
|
+
protocol?: string
|
|
74
16
|
}
|
|
75
17
|
|
|
76
|
-
|
|
77
|
-
if (thing == null) {
|
|
78
|
-
return false
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return typeof thing.then === 'function' &&
|
|
82
|
-
typeof thing.catch === 'function' &&
|
|
83
|
-
typeof thing.finally === 'function'
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export abstract class AbstractStream implements Stream {
|
|
18
|
+
export abstract class AbstractStream extends AbstractMessageStream implements Stream {
|
|
87
19
|
public id: string
|
|
88
|
-
public
|
|
89
|
-
public timeline: StreamTimeline
|
|
90
|
-
public protocol?: string
|
|
91
|
-
public metadata: Record<string, unknown>
|
|
92
|
-
public source: AsyncGenerator<Uint8ArrayList, void, unknown>
|
|
93
|
-
public status: StreamStatus
|
|
94
|
-
public readStatus: ReadStatus
|
|
95
|
-
public writeStatus: WriteStatus
|
|
96
|
-
public readonly log: Logger
|
|
97
|
-
|
|
98
|
-
private readonly sinkController: AbortController
|
|
99
|
-
private readonly sinkEnd: DeferredPromise<void>
|
|
100
|
-
private readonly closed: DeferredPromise<void>
|
|
101
|
-
private endErr: Error | undefined
|
|
102
|
-
private readonly streamSource: Pushable<Uint8ArrayList>
|
|
103
|
-
private readonly onEnd?: (err?: Error) => void
|
|
104
|
-
private readonly onCloseRead?: () => void
|
|
105
|
-
private readonly onCloseWrite?: () => void
|
|
106
|
-
private readonly onReset?: () => void
|
|
107
|
-
private readonly onAbort?: (err: Error) => void
|
|
108
|
-
private readonly sendCloseWriteTimeout: number
|
|
109
|
-
private sendingData?: DeferredPromise<void>
|
|
20
|
+
public protocol: string
|
|
110
21
|
|
|
111
22
|
constructor (init: AbstractStreamInit) {
|
|
112
|
-
|
|
113
|
-
this.sinkEnd = defer()
|
|
114
|
-
this.closed = defer()
|
|
115
|
-
this.log = init.log
|
|
116
|
-
|
|
117
|
-
// stream status
|
|
118
|
-
this.status = 'open'
|
|
119
|
-
this.readStatus = 'ready'
|
|
120
|
-
this.writeStatus = 'ready'
|
|
23
|
+
super(init)
|
|
121
24
|
|
|
122
25
|
this.id = init.id
|
|
123
|
-
this.
|
|
124
|
-
this.direction = init.direction
|
|
125
|
-
this.timeline = {
|
|
126
|
-
open: Date.now()
|
|
127
|
-
}
|
|
128
|
-
this.sendCloseWriteTimeout = init.sendCloseWriteTimeout ?? DEFAULT_SEND_CLOSE_WRITE_TIMEOUT
|
|
129
|
-
|
|
130
|
-
this.onEnd = init.onEnd
|
|
131
|
-
this.onCloseRead = init.onCloseRead
|
|
132
|
-
this.onCloseWrite = init.onCloseWrite
|
|
133
|
-
this.onReset = init.onReset
|
|
134
|
-
this.onAbort = init.onAbort
|
|
135
|
-
|
|
136
|
-
this.source = this.streamSource = pushable<Uint8ArrayList>({
|
|
137
|
-
onEnd: (err) => {
|
|
138
|
-
if (err != null) {
|
|
139
|
-
this.log.trace('source ended with error', err)
|
|
140
|
-
} else {
|
|
141
|
-
this.log.trace('source ended')
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
this.onSourceEnd(err)
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
// necessary because the libp2p upgrader wraps the sink function
|
|
149
|
-
this.sink = this.sink.bind(this)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async sink (source: Source<Uint8ArrayList | Uint8Array>): Promise<void> {
|
|
153
|
-
if (this.writeStatus !== 'ready') {
|
|
154
|
-
throw new StreamStateError(`writable end state is "${this.writeStatus}" not "ready"`)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
this.writeStatus = 'writing'
|
|
159
|
-
|
|
160
|
-
const options: AbortOptions = {
|
|
161
|
-
signal: this.sinkController.signal
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (this.direction === 'outbound') { // If initiator, open a new stream
|
|
165
|
-
const res = this.sendNewStream(options)
|
|
166
|
-
|
|
167
|
-
if (isPromise(res)) {
|
|
168
|
-
await res
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const abortListener = (): void => {
|
|
173
|
-
closeSource(source, this.log)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
try {
|
|
177
|
-
this.sinkController.signal.addEventListener('abort', abortListener)
|
|
178
|
-
|
|
179
|
-
this.log.trace('sink reading from source')
|
|
180
|
-
|
|
181
|
-
for await (let data of source) {
|
|
182
|
-
data = data instanceof Uint8Array ? new Uint8ArrayList(data) : data
|
|
183
|
-
|
|
184
|
-
const res = this.sendData(data, options)
|
|
185
|
-
|
|
186
|
-
if (isPromise(res)) {
|
|
187
|
-
this.sendingData = defer()
|
|
188
|
-
await res
|
|
189
|
-
this.sendingData.resolve()
|
|
190
|
-
this.sendingData = undefined
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
} finally {
|
|
194
|
-
this.sinkController.signal.removeEventListener('abort', abortListener)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
this.log.trace('sink finished reading from source, write status is "%s"', this.writeStatus)
|
|
198
|
-
|
|
199
|
-
if (this.writeStatus === 'writing') {
|
|
200
|
-
this.writeStatus = 'closing'
|
|
201
|
-
|
|
202
|
-
this.log.trace('send close write to remote')
|
|
203
|
-
await this.sendCloseWrite({
|
|
204
|
-
signal: AbortSignal.timeout(this.sendCloseWriteTimeout)
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
this.writeStatus = 'closed'
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
this.onSinkEnd()
|
|
211
|
-
} catch (err: any) {
|
|
212
|
-
this.log.trace('sink ended with error, calling abort with error', err)
|
|
213
|
-
this.abort(err)
|
|
214
|
-
|
|
215
|
-
throw err
|
|
216
|
-
} finally {
|
|
217
|
-
this.log.trace('resolve sink end')
|
|
218
|
-
this.sinkEnd.resolve()
|
|
219
|
-
}
|
|
26
|
+
this.protocol = init.protocol ?? ''
|
|
220
27
|
}
|
|
221
28
|
|
|
222
|
-
protected onSourceEnd (err?: Error): void {
|
|
223
|
-
if (this.timeline.closeRead != null) {
|
|
224
|
-
return
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
this.timeline.closeRead = Date.now()
|
|
228
|
-
this.readStatus = 'closed'
|
|
229
|
-
|
|
230
|
-
if (err != null && this.endErr == null) {
|
|
231
|
-
this.endErr = err
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
this.onCloseRead?.()
|
|
235
|
-
|
|
236
|
-
if (this.timeline.closeWrite != null) {
|
|
237
|
-
this.log.trace('source and sink ended')
|
|
238
|
-
this.timeline.close = Date.now()
|
|
239
|
-
|
|
240
|
-
if (this.status !== 'aborted' && this.status !== 'reset') {
|
|
241
|
-
this.status = 'closed'
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (this.onEnd != null) {
|
|
245
|
-
this.onEnd(this.endErr)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
this.closed.resolve()
|
|
249
|
-
} else {
|
|
250
|
-
this.log.trace('source ended, waiting for sink to end')
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
protected onSinkEnd (err?: Error): void {
|
|
255
|
-
if (this.timeline.closeWrite != null) {
|
|
256
|
-
return
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
this.timeline.closeWrite = Date.now()
|
|
260
|
-
this.writeStatus = 'closed'
|
|
261
|
-
|
|
262
|
-
if (err != null && this.endErr == null) {
|
|
263
|
-
this.endErr = err
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
this.onCloseWrite?.()
|
|
267
|
-
|
|
268
|
-
if (this.timeline.closeRead != null) {
|
|
269
|
-
this.log.trace('sink and source ended')
|
|
270
|
-
this.timeline.close = Date.now()
|
|
271
|
-
|
|
272
|
-
if (this.status !== 'aborted' && this.status !== 'reset') {
|
|
273
|
-
this.status = 'closed'
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (this.onEnd != null) {
|
|
277
|
-
this.onEnd(this.endErr)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
this.closed.resolve()
|
|
281
|
-
} else {
|
|
282
|
-
this.log.trace('sink ended, waiting for source to end')
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Close for both Reading and Writing
|
|
287
29
|
async close (options?: AbortOptions): Promise<void> {
|
|
288
|
-
if (this.status !== 'open') {
|
|
289
|
-
return
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
this.log.trace('closing gracefully')
|
|
293
|
-
|
|
294
|
-
this.status = 'closing'
|
|
295
|
-
|
|
296
|
-
// wait for read and write ends to close
|
|
297
|
-
await raceSignal(Promise.all([
|
|
298
|
-
this.closeWrite(options),
|
|
299
|
-
this.closeRead(options),
|
|
300
|
-
this.closed.promise
|
|
301
|
-
]), options?.signal)
|
|
302
|
-
|
|
303
|
-
this.status = 'closed'
|
|
304
|
-
|
|
305
|
-
this.log.trace('closed gracefully')
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
async closeRead (options: AbortOptions = {}): Promise<void> {
|
|
309
|
-
if (this.readStatus === 'closing' || this.readStatus === 'closed') {
|
|
310
|
-
return
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
this.log.trace('closing readable end of stream with starting read status "%s"', this.readStatus)
|
|
314
|
-
|
|
315
|
-
const readStatus = this.readStatus
|
|
316
|
-
this.readStatus = 'closing'
|
|
317
|
-
|
|
318
|
-
if (this.status !== 'reset' && this.status !== 'aborted' && this.timeline.closeRead == null) {
|
|
319
|
-
this.log.trace('send close read to remote')
|
|
320
|
-
await this.sendCloseRead(options)
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (readStatus === 'ready') {
|
|
324
|
-
this.log.trace('ending internal source queue with %d queued bytes', this.streamSource.readableLength)
|
|
325
|
-
this.streamSource.end()
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
this.log.trace('closed readable end of stream')
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
async closeWrite (options: AbortOptions = {}): Promise<void> {
|
|
332
30
|
if (this.writeStatus === 'closing' || this.writeStatus === 'closed') {
|
|
333
31
|
return
|
|
334
32
|
}
|
|
335
33
|
|
|
336
|
-
this.
|
|
337
|
-
|
|
338
|
-
if (this.writeStatus === 'ready') {
|
|
339
|
-
this.log.trace('sink was never sunk, sink an empty array')
|
|
340
|
-
|
|
341
|
-
await raceSignal(this.sink([]), options.signal)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (this.writeStatus === 'writing') {
|
|
345
|
-
// try to let sending outgoing data succeed
|
|
346
|
-
if (this.sendingData != null) {
|
|
347
|
-
await raceSignal(this.sendingData.promise, options.signal)
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// stop reading from the source passed to `.sink`
|
|
351
|
-
this.log.trace('aborting source passed to .sink')
|
|
352
|
-
this.sinkController.abort()
|
|
353
|
-
await raceSignal(this.sinkEnd.promise, options.signal)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
this.writeStatus = 'closed'
|
|
357
|
-
|
|
358
|
-
this.log.trace('closed writable end of stream')
|
|
359
|
-
}
|
|
34
|
+
this.writeStatus = 'closing'
|
|
360
35
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
this.log('abort with error', err)
|
|
371
|
-
|
|
372
|
-
// try to send a reset message
|
|
373
|
-
this.log('try to send reset to remote')
|
|
374
|
-
const res = this.sendReset()
|
|
375
|
-
|
|
376
|
-
if (isPromise(res)) {
|
|
377
|
-
res.catch((err) => {
|
|
378
|
-
this.log.error('error sending reset message', err)
|
|
36
|
+
// if we are currently sending data, wait for all the data to be written
|
|
37
|
+
// into the underlying transport
|
|
38
|
+
if (this.sendingData || this.writeBuffer.byteLength > 0) {
|
|
39
|
+
this.log('waiting for write queue to become idle before closing writable end of stream, %d unsent bytes', this.writeBuffer.byteLength)
|
|
40
|
+
await pEvent(this, 'idle', {
|
|
41
|
+
...options,
|
|
42
|
+
rejectionEvents: [
|
|
43
|
+
'close'
|
|
44
|
+
]
|
|
379
45
|
})
|
|
380
46
|
}
|
|
381
47
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
this.
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if (this.status === 'closed' || this.status === 'aborted' || this.status === 'reset') {
|
|
394
|
-
return
|
|
48
|
+
// now that the underlying transport has all the data, if the buffer is full
|
|
49
|
+
// wait for it to be emptied
|
|
50
|
+
if (this.writableNeedsDrain) {
|
|
51
|
+
this.log('waiting for write queue to drain before closing writable end of stream, %d unsent bytes, sending %s', this.writeBuffer.byteLength, this.sendingData)
|
|
52
|
+
await pEvent(this, 'drain', {
|
|
53
|
+
...options,
|
|
54
|
+
rejectionEvents: [
|
|
55
|
+
'close'
|
|
56
|
+
]
|
|
57
|
+
})
|
|
58
|
+
this.log('write queue drained, closing writable end of stream, %d unsent bytes, sending %s', this.writeBuffer.byteLength, this.sendingData)
|
|
395
59
|
}
|
|
396
60
|
|
|
397
|
-
|
|
61
|
+
await this.sendCloseWrite(options)
|
|
398
62
|
|
|
399
|
-
this.
|
|
400
|
-
this.timeline.reset = Date.now()
|
|
401
|
-
this._closeSinkAndSource(err)
|
|
402
|
-
this.onReset?.()
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
_closeSinkAndSource (err?: Error): void {
|
|
406
|
-
this._closeSink(err)
|
|
407
|
-
this._closeSource(err)
|
|
408
|
-
}
|
|
63
|
+
this.writeStatus = 'closed'
|
|
409
64
|
|
|
410
|
-
|
|
411
|
-
// if the sink function is running, cause it to end
|
|
412
|
-
if (this.writeStatus === 'writing') {
|
|
413
|
-
this.log.trace('end sink source')
|
|
414
|
-
this.sinkController.abort()
|
|
415
|
-
}
|
|
65
|
+
this.log('closed writable end gracefully')
|
|
416
66
|
|
|
417
|
-
this.
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
_closeSource (err?: Error): void {
|
|
421
|
-
// if the source is not ending, end it
|
|
422
|
-
if (this.readStatus !== 'closing' && this.readStatus !== 'closed') {
|
|
423
|
-
this.log.trace('ending source with %d bytes to be read by consumer', this.streamSource.readableLength)
|
|
424
|
-
this.readStatus = 'closing'
|
|
425
|
-
this.streamSource.end(err)
|
|
67
|
+
if (this.remoteWriteStatus === 'closed') {
|
|
68
|
+
this.onTransportClosed()
|
|
426
69
|
}
|
|
427
70
|
}
|
|
428
71
|
|
|
429
|
-
|
|
430
|
-
* The remote closed for writing so we should expect to receive no more
|
|
431
|
-
* messages
|
|
432
|
-
*/
|
|
433
|
-
remoteCloseWrite (): void {
|
|
72
|
+
async closeRead (options?: AbortOptions): Promise<void> {
|
|
434
73
|
if (this.readStatus === 'closing' || this.readStatus === 'closed') {
|
|
435
|
-
this.log('received remote close write but local source is already closed')
|
|
436
|
-
return
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
this.log.trace('remote close write')
|
|
440
|
-
this._closeSource()
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* The remote closed for reading so we should not send any more
|
|
445
|
-
* messages
|
|
446
|
-
*/
|
|
447
|
-
remoteCloseRead (): void {
|
|
448
|
-
if (this.writeStatus === 'closing' || this.writeStatus === 'closed') {
|
|
449
|
-
this.log('received remote close read but local sink is already closed')
|
|
450
74
|
return
|
|
451
75
|
}
|
|
452
76
|
|
|
453
|
-
|
|
454
|
-
this.
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* The underlying muxer has closed, no more messages can be sent or will
|
|
459
|
-
* be received, close immediately to free up resources
|
|
460
|
-
*/
|
|
461
|
-
destroy (): void {
|
|
462
|
-
if (this.status === 'closed' || this.status === 'aborted' || this.status === 'reset') {
|
|
463
|
-
this.log('received destroy but we are already closed')
|
|
464
|
-
return
|
|
77
|
+
// throw away any unread data
|
|
78
|
+
if (this.readBuffer.byteLength > 0) {
|
|
79
|
+
this.readBuffer.consume(this.readBuffer.byteLength)
|
|
465
80
|
}
|
|
466
81
|
|
|
467
|
-
this.
|
|
82
|
+
this.readStatus = 'closing'
|
|
468
83
|
|
|
469
|
-
this.
|
|
470
|
-
}
|
|
84
|
+
await this.sendCloseRead(options)
|
|
471
85
|
|
|
472
|
-
|
|
473
|
-
* When an extending class reads data from it's implementation-specific source,
|
|
474
|
-
* call this method to allow the stream consumer to read the data.
|
|
475
|
-
*/
|
|
476
|
-
sourcePush (data: Uint8ArrayList): void {
|
|
477
|
-
this.streamSource.push(data)
|
|
478
|
-
}
|
|
86
|
+
this.readStatus = 'closed'
|
|
479
87
|
|
|
480
|
-
|
|
481
|
-
* Returns the amount of unread data - can be used to prevent large amounts of
|
|
482
|
-
* data building up when the stream consumer is too slow.
|
|
483
|
-
*/
|
|
484
|
-
sourceReadableLength (): number {
|
|
485
|
-
return this.streamSource.readableLength
|
|
88
|
+
this.log('closed readable end gracefully')
|
|
486
89
|
}
|
|
487
90
|
|
|
488
91
|
/**
|
|
489
|
-
* Send a message to the remote
|
|
490
|
-
*
|
|
491
|
-
*/
|
|
492
|
-
abstract sendNewStream (options?: AbortOptions): void | Promise<void>
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Send a data message to the remote muxer
|
|
496
|
-
*/
|
|
497
|
-
abstract sendData (buf: Uint8ArrayList, options?: AbortOptions): void | Promise<void>
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Send a reset message to the remote muxer
|
|
501
|
-
*/
|
|
502
|
-
abstract sendReset (options?: AbortOptions): void | Promise<void>
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Send a message to the remote muxer, informing them no more data messages
|
|
506
|
-
* will be sent by this end of the stream
|
|
92
|
+
* Send a message to the remote end of the stream, informing them that we will
|
|
93
|
+
* send no more data messages.
|
|
507
94
|
*/
|
|
508
|
-
abstract sendCloseWrite (options?: AbortOptions):
|
|
95
|
+
abstract sendCloseWrite (options?: AbortOptions): Promise<void>
|
|
509
96
|
|
|
510
97
|
/**
|
|
511
|
-
*
|
|
512
|
-
*
|
|
98
|
+
* If supported, send a message to the remote end of the stream, informing
|
|
99
|
+
* them that we will read no more data messages.
|
|
513
100
|
*/
|
|
514
|
-
abstract sendCloseRead (options?: AbortOptions):
|
|
101
|
+
abstract sendCloseRead (options?: AbortOptions): Promise<void>
|
|
515
102
|
}
|
package/src/errors.ts
CHANGED
|
@@ -27,3 +27,13 @@ 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,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getNetConfig } from './multiaddr/get-net-config.ts'
|
|
2
|
+
import { netConfigToMultiaddr } from './multiaddr/utils.ts'
|
|
2
3
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -7,14 +8,14 @@ import type { Multiaddr } from '@multiformats/multiaddr'
|
|
|
7
8
|
*
|
|
8
9
|
* Wildcard IP4/6 addresses will be expanded into all available interfaces.
|
|
9
10
|
*/
|
|
10
|
-
export function getThinWaistAddresses (ma?: Multiaddr, port?: number): Multiaddr[] {
|
|
11
|
+
export function getThinWaistAddresses (ma?: Multiaddr, port?: number | string): Multiaddr[] {
|
|
11
12
|
if (ma == null) {
|
|
12
13
|
return []
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
+
const config = getNetConfig(ma)
|
|
16
17
|
|
|
17
18
|
return [
|
|
18
|
-
|
|
19
|
+
netConfigToMultiaddr(config, port)
|
|
19
20
|
]
|
|
20
21
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os from 'node:os'
|
|
2
|
-
import { multiaddr } from '@multiformats/multiaddr'
|
|
3
2
|
import { isLinkLocalIp } from './link-local-ip.js'
|
|
3
|
+
import { getNetConfig } from './multiaddr/get-net-config.ts'
|
|
4
|
+
import { netConfigToMultiaddr } from './multiaddr/utils.ts'
|
|
4
5
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
5
6
|
|
|
6
7
|
const FAMILIES = { 4: 'IPv4', 6: 'IPv6' }
|
|
@@ -36,24 +37,19 @@ function getNetworkAddrs (family: 4 | 6): string[] {
|
|
|
36
37
|
*
|
|
37
38
|
* Wildcard IP4/6 addresses will be expanded into all available interfaces.
|
|
38
39
|
*/
|
|
39
|
-
export function getThinWaistAddresses (ma?: Multiaddr, port?: number): Multiaddr[] {
|
|
40
|
+
export function getThinWaistAddresses (ma?: Multiaddr, port?: number | string): Multiaddr[] {
|
|
40
41
|
if (ma == null) {
|
|
41
42
|
return []
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
const
|
|
45
|
+
const config = getNetConfig(ma)
|
|
45
46
|
|
|
46
|
-
if (isWildcard(
|
|
47
|
-
|
|
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
|
|
47
|
+
if ((config.type === 'ip4' || config.type === 'ip6') && isWildcard(config.host)) {
|
|
48
|
+
return getNetworkAddrs(config.type === 'ip4' ? 4 : 6)
|
|
49
|
+
.map(host => netConfigToMultiaddr(config, port, host))
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
return [
|
|
57
|
-
|
|
53
|
+
netConfigToMultiaddr(config, port)
|
|
58
54
|
]
|
|
59
55
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,4 +4,34 @@
|
|
|
4
4
|
* This module contains utility functions used by libp2p modules.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export
|
|
7
|
+
export * from './filters/index.js'
|
|
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 './mock-muxer.js'
|
|
26
|
+
export * from './mock-stream.js'
|
|
27
|
+
export * from './moving-average.js'
|
|
28
|
+
export * from './multiaddr-connection-pair.js'
|
|
29
|
+
export * from './peer-queue.js'
|
|
30
|
+
export * from './priority-queue.js'
|
|
31
|
+
export * from './private-ip.js'
|
|
32
|
+
export * from './rate-limiter.js'
|
|
33
|
+
export * from './repeating-task.js'
|
|
34
|
+
export * from './stream-pair.js'
|
|
35
|
+
export * from './stream-utils.js'
|
|
36
|
+
export * from './tracked-list.js'
|
|
37
|
+
export * from './tracked-map.js'
|