@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
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import { MuxerClosedError, TypedEventEmitter } from '@libp2p/interface'
|
|
2
|
-
import { raceSignal } from 'race-signal'
|
|
3
|
-
import { MaxEarlyStreamsError } from './errors.ts'
|
|
4
|
-
import { isPromise } from './is-promise.ts'
|
|
5
|
-
import type { AbstractStream } from './abstract-stream.ts'
|
|
6
|
-
import type { AbortOptions, CounterGroup, CreateStreamOptions, EventHandler, Logger, MessageStream, Stream, StreamCloseEvent, StreamMessageEvent, StreamMuxer, StreamMuxerEvents, StreamMuxerOptions, StreamMuxerStatus, StreamOptions } from '@libp2p/interface'
|
|
7
|
-
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
8
|
-
|
|
9
|
-
export interface AbstractStreamMuxerInit extends StreamMuxerOptions {
|
|
10
|
-
/**
|
|
11
|
-
* The protocol name for the muxer
|
|
12
|
-
*/
|
|
13
|
-
protocol: string
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The name of the muxer, used to create a new logging scope from the passed
|
|
17
|
-
* connection's logger
|
|
18
|
-
*/
|
|
19
|
-
name: string
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* A counter for muxer metrics
|
|
23
|
-
*/
|
|
24
|
-
metrics?: CounterGroup
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export abstract class AbstractStreamMuxer <MuxedStream extends AbstractStream = AbstractStream> extends TypedEventEmitter<StreamMuxerEvents<MuxedStream>> implements StreamMuxer<MuxedStream> {
|
|
28
|
-
public streams: MuxedStream[]
|
|
29
|
-
public protocol: string
|
|
30
|
-
public status: StreamMuxerStatus
|
|
31
|
-
|
|
32
|
-
protected log: Logger
|
|
33
|
-
protected maConn: MessageStream
|
|
34
|
-
protected streamOptions?: StreamOptions
|
|
35
|
-
protected earlyStreams: MuxedStream[]
|
|
36
|
-
protected maxEarlyStreams: number
|
|
37
|
-
|
|
38
|
-
private readonly metrics?: CounterGroup
|
|
39
|
-
|
|
40
|
-
constructor (maConn: MessageStream, init: AbstractStreamMuxerInit) {
|
|
41
|
-
super()
|
|
42
|
-
|
|
43
|
-
this.maConn = maConn
|
|
44
|
-
this.protocol = init.protocol
|
|
45
|
-
this.streams = []
|
|
46
|
-
this.earlyStreams = []
|
|
47
|
-
this.status = 'open'
|
|
48
|
-
this.log = maConn.log.newScope(init.name)
|
|
49
|
-
this.streamOptions = init.streamOptions
|
|
50
|
-
this.maxEarlyStreams = init.maxEarlyStreams ?? 10
|
|
51
|
-
this.metrics = init.metrics
|
|
52
|
-
|
|
53
|
-
// read/write all data from/to underlying maConn
|
|
54
|
-
const muxerMaConnOnMessage = (evt: StreamMessageEvent): void => {
|
|
55
|
-
try {
|
|
56
|
-
this.onData(evt.data)
|
|
57
|
-
} catch (err: any) {
|
|
58
|
-
this.abort(err)
|
|
59
|
-
this.maConn.abort(err)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
this.maConn.addEventListener('message', muxerMaConnOnMessage)
|
|
63
|
-
|
|
64
|
-
// signal stream writers when the underlying connection can accept more data
|
|
65
|
-
const muxerMaConnOnDrain = (): void => {
|
|
66
|
-
this.log('underlying stream drained, signal %d streams to continue writing', this.streams.length)
|
|
67
|
-
|
|
68
|
-
this.streams.forEach(stream => {
|
|
69
|
-
stream.onMuxerDrain()
|
|
70
|
-
})
|
|
71
|
-
}
|
|
72
|
-
this.maConn.addEventListener('drain', muxerMaConnOnDrain)
|
|
73
|
-
|
|
74
|
-
const muxerOnMaConnClose = (): void => {
|
|
75
|
-
this.log('underlying stream closed with status %s and %d streams', this.status, this.streams.length)
|
|
76
|
-
this.onTransportClosed()
|
|
77
|
-
}
|
|
78
|
-
this.maConn.addEventListener('close', muxerOnMaConnClose)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
send (data: Uint8Array | Uint8ArrayList): boolean {
|
|
82
|
-
const result = this.maConn.send(data)
|
|
83
|
-
|
|
84
|
-
if (result === false) {
|
|
85
|
-
this.log('underlying stream saturated, signal %d streams to pause writing', this.streams.length)
|
|
86
|
-
|
|
87
|
-
this.streams.forEach(stream => {
|
|
88
|
-
stream.onMuxerNeedsDrain()
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return result
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async close (options?: AbortOptions): Promise<void> {
|
|
96
|
-
if (this.status === 'closed' || this.status === 'closing') {
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
this.status = 'closing'
|
|
101
|
-
|
|
102
|
-
await raceSignal(Promise.all(
|
|
103
|
-
[...this.streams].map(async s => {
|
|
104
|
-
await s.close(options)
|
|
105
|
-
})
|
|
106
|
-
), options?.signal)
|
|
107
|
-
|
|
108
|
-
this.status = 'closed'
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
abort (err: Error): void {
|
|
112
|
-
if (this.status === 'closed') {
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
this.status = 'closing'
|
|
117
|
-
|
|
118
|
-
;[...this.streams].forEach(s => {
|
|
119
|
-
s.abort(err)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
this.status = 'closed'
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
onTransportClosed (err?: Error): void {
|
|
126
|
-
this.status = 'closing'
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
[...this.streams].forEach(stream => {
|
|
130
|
-
stream.onTransportClosed(err)
|
|
131
|
-
})
|
|
132
|
-
} catch (err: any) {
|
|
133
|
-
this.abort(err)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
this.status = 'closed'
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async createStream (options?: CreateStreamOptions): Promise<MuxedStream> {
|
|
140
|
-
if (this.status !== 'open') {
|
|
141
|
-
throw new MuxerClosedError()
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
let stream = this.onCreateStream({
|
|
145
|
-
...this.streamOptions,
|
|
146
|
-
...options
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
if (isPromise(stream)) {
|
|
150
|
-
stream = await stream
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
this.streams.push(stream)
|
|
154
|
-
this.cleanUpStream(stream)
|
|
155
|
-
|
|
156
|
-
return stream
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Extending classes should invoke this method when a new stream was created
|
|
161
|
-
* by the remote muxer
|
|
162
|
-
*/
|
|
163
|
-
onRemoteStream (stream: MuxedStream): void {
|
|
164
|
-
this.streams.push(stream)
|
|
165
|
-
this.cleanUpStream(stream)
|
|
166
|
-
|
|
167
|
-
if (this.listenerCount('stream') === 0) {
|
|
168
|
-
// no listener has been added for the stream event yet, store the stream
|
|
169
|
-
// to emit it later
|
|
170
|
-
this.earlyStreams.push(stream)
|
|
171
|
-
|
|
172
|
-
if (this.earlyStreams.length > this.maxEarlyStreams) {
|
|
173
|
-
this.abort(new MaxEarlyStreamsError(`Too many early streams were opened - ${this.earlyStreams.length}/${this.maxEarlyStreams}`))
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
this.safeDispatchEvent('stream', {
|
|
180
|
-
detail: stream
|
|
181
|
-
})
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
private cleanUpStream (stream: Stream): void {
|
|
185
|
-
const muxerOnStreamEnd = (evt: StreamCloseEvent): void => {
|
|
186
|
-
const index = this.streams.findIndex(s => s === stream)
|
|
187
|
-
|
|
188
|
-
if (index !== -1) {
|
|
189
|
-
this.streams.splice(index, 1)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (evt.error != null) {
|
|
193
|
-
if (evt.local) {
|
|
194
|
-
this.metrics?.increment({ [`${stream.direction}_stream_reset`]: true })
|
|
195
|
-
} else {
|
|
196
|
-
this.metrics?.increment({ [`${stream.direction}_stream_abort`]: true })
|
|
197
|
-
}
|
|
198
|
-
} else {
|
|
199
|
-
this.metrics?.increment({ [`${stream.direction}_stream_end`]: true })
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
stream.addEventListener('close', muxerOnStreamEnd)
|
|
203
|
-
|
|
204
|
-
this.metrics?.increment({ [`${stream.direction}_stream`]: true })
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
addEventListener<K extends keyof StreamMuxerEvents<MuxedStream>>(type: K, listener: EventHandler<StreamMuxerEvents<MuxedStream>[K]> | null, options?: boolean | AddEventListenerOptions): void
|
|
208
|
-
addEventListener (type: string, listener: EventHandler<Event>, options?: boolean | AddEventListenerOptions): void
|
|
209
|
-
addEventListener (...args: any[]): void {
|
|
210
|
-
// @ts-expect-error cannot ensure args has enough members
|
|
211
|
-
super.addEventListener.apply(this, args)
|
|
212
|
-
|
|
213
|
-
// if a 'stream' listener is being added and we have early streams, emit
|
|
214
|
-
// them
|
|
215
|
-
if (args[0] === 'stream' && this.earlyStreams.length > 0) {
|
|
216
|
-
// event listeners can be added in constructors and often use object
|
|
217
|
-
// properties - if this the case we can access a class member before it
|
|
218
|
-
// has been initialized so dispatch the message in the microtask queue
|
|
219
|
-
queueMicrotask(() => {
|
|
220
|
-
this.earlyStreams.forEach(stream => {
|
|
221
|
-
this.safeDispatchEvent('stream', {
|
|
222
|
-
detail: stream
|
|
223
|
-
})
|
|
224
|
-
})
|
|
225
|
-
this.earlyStreams = []
|
|
226
|
-
})
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* A new outgoing stream needs to be created
|
|
232
|
-
*/
|
|
233
|
-
abstract onCreateStream (options: CreateStreamOptions): MuxedStream | Promise<MuxedStream>
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Multiplexed data was received from the remote muxer
|
|
237
|
-
*/
|
|
238
|
-
abstract onData (data: Uint8Array | Uint8ArrayList): void
|
|
239
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { InvalidParametersError } from '@libp2p/interface'
|
|
2
|
-
import * as varint from 'uint8-varint'
|
|
3
|
-
import { Uint8ArrayList } from 'uint8arraylist'
|
|
4
|
-
import { InvalidMessageLengthError } from './stream-utils.ts'
|
|
5
|
-
|
|
6
|
-
const DEFAULT_MAX_BUFFER_SIZE = 1024 * 1024 * 4
|
|
7
|
-
const DEFAULT_MAX_DATA_LENGTH = 1024 * 1024 * 4
|
|
8
|
-
|
|
9
|
-
export interface LengthPrefixedDecoderInit {
|
|
10
|
-
/**
|
|
11
|
-
* How large the internal buffer is allowed to grow - attempting to store more
|
|
12
|
-
* data than this will throw
|
|
13
|
-
*/
|
|
14
|
-
maxBufferSize?: number
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Throw an error if the message that would be read from the buffer is larger
|
|
18
|
-
* than this value
|
|
19
|
-
*/
|
|
20
|
-
maxDataLength?: number
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Read a varint from the buffer
|
|
24
|
-
*/
|
|
25
|
-
lengthDecoder?(data: Uint8ArrayList | Uint8Array): number
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Return how many bytes it takes to encode the passed value
|
|
29
|
-
*/
|
|
30
|
-
encodingLength?(length: number): number
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Decode length-prefixed data from a buffer
|
|
35
|
-
*/
|
|
36
|
-
export class LengthPrefixedDecoder {
|
|
37
|
-
private readonly buffer: Uint8ArrayList
|
|
38
|
-
private readonly maxBufferSize: number
|
|
39
|
-
private readonly lengthDecoder: (data: Uint8ArrayList | Uint8Array) => number
|
|
40
|
-
private readonly maxDataLength: number
|
|
41
|
-
private readonly encodingLength: (length: number) => number
|
|
42
|
-
|
|
43
|
-
constructor (init: LengthPrefixedDecoderInit = {}) {
|
|
44
|
-
this.buffer = new Uint8ArrayList()
|
|
45
|
-
this.maxBufferSize = init.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE
|
|
46
|
-
this.maxDataLength = init.maxDataLength ?? DEFAULT_MAX_DATA_LENGTH
|
|
47
|
-
this.lengthDecoder = init.lengthDecoder ?? varint.decode
|
|
48
|
-
this.encodingLength = init.encodingLength ?? varint.encodingLength
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Decodes length-prefixed data
|
|
53
|
-
*/
|
|
54
|
-
* decode (buf: Uint8Array | Uint8ArrayList): Generator<Uint8ArrayList> {
|
|
55
|
-
this.buffer.append(buf)
|
|
56
|
-
|
|
57
|
-
if (this.buffer.byteLength > this.maxBufferSize) {
|
|
58
|
-
throw new InvalidParametersError(`Buffer length limit exceeded - ${this.buffer.byteLength}/${this.maxBufferSize}`)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Loop to consume as many bytes from the buffer as possible
|
|
62
|
-
// Eg: when a single chunk contains several frames
|
|
63
|
-
while (true) {
|
|
64
|
-
let dataLength: number
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
dataLength = this.lengthDecoder(this.buffer)
|
|
68
|
-
} catch (err) {
|
|
69
|
-
if (err instanceof RangeError) {
|
|
70
|
-
// ignore errors where we don't have enough data to read the length
|
|
71
|
-
// prefix
|
|
72
|
-
break
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
throw err
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (dataLength < 0 || dataLength > this.maxDataLength) {
|
|
79
|
-
throw new InvalidMessageLengthError('Invalid message length')
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const lengthLength = this.encodingLength(dataLength)
|
|
83
|
-
const chunkLength = lengthLength + dataLength
|
|
84
|
-
|
|
85
|
-
if (this.buffer.byteLength >= chunkLength) {
|
|
86
|
-
const buf = this.buffer.sublist(lengthLength, chunkLength)
|
|
87
|
-
|
|
88
|
-
this.buffer.consume(chunkLength)
|
|
89
|
-
|
|
90
|
-
if (buf.byteLength > 0) {
|
|
91
|
-
yield buf
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
break
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
package/src/message-queue.ts
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { StreamMessageEvent } from '@libp2p/interface'
|
|
2
|
-
import delay from 'delay'
|
|
3
|
-
import { TypedEventEmitter } from 'main-event'
|
|
4
|
-
import { raceSignal } from 'race-signal'
|
|
5
|
-
import { isUint8ArrayList, Uint8ArrayList } from 'uint8arraylist'
|
|
6
|
-
import { Queue } from './queue/index.js'
|
|
7
|
-
import type { AbortOptions, Logger } from '@libp2p/interface'
|
|
8
|
-
|
|
9
|
-
const DEFAULT_CHUNK_SIZE = 1024 * 64
|
|
10
|
-
|
|
11
|
-
export interface MessageQueueEvents {
|
|
12
|
-
/**
|
|
13
|
-
* Message data
|
|
14
|
-
*/
|
|
15
|
-
message: StreamMessageEvent
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Emitted when the queue is empty
|
|
19
|
-
*/
|
|
20
|
-
drain: Event
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The remote closed the connection abruptly
|
|
24
|
-
*/
|
|
25
|
-
reset: Event
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface MessageQueueInit {
|
|
29
|
-
/**
|
|
30
|
-
* How much delay there should be between each message send in ms (note that
|
|
31
|
-
* even 0 introduces a small delay)
|
|
32
|
-
*
|
|
33
|
-
* @default 0
|
|
34
|
-
*/
|
|
35
|
-
delay?: number
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* How many messages to hold in the send queue before applying backpressure to
|
|
39
|
-
* the sender
|
|
40
|
-
*/
|
|
41
|
-
capacity?: number
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Data messages larger than this size will be chunked into smaller messages.
|
|
45
|
-
*
|
|
46
|
-
* Defaults to the maximum TCP package size.
|
|
47
|
-
*
|
|
48
|
-
* @default 65_536
|
|
49
|
-
*/
|
|
50
|
-
chunkSize?: number
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
interface MessageQueueJobOptions extends AbortOptions {
|
|
54
|
-
evt: Event
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Accepts events to emit after a short delay, and with a configurable maximum
|
|
59
|
-
* queue capacity after which the send method will return false to let us
|
|
60
|
-
* simulate write backpressure.
|
|
61
|
-
*/
|
|
62
|
-
export class MessageQueue<Events> extends TypedEventEmitter<Events & MessageQueueEvents> {
|
|
63
|
-
public needsDrain: boolean
|
|
64
|
-
|
|
65
|
-
private queue: Queue<void, MessageQueueJobOptions>
|
|
66
|
-
private capacity: number
|
|
67
|
-
private delay: number
|
|
68
|
-
private log: Logger
|
|
69
|
-
private chunkSize: number
|
|
70
|
-
|
|
71
|
-
constructor (init: MessageQueueInit & { log: Logger }) {
|
|
72
|
-
super()
|
|
73
|
-
|
|
74
|
-
this.needsDrain = false
|
|
75
|
-
this.queue = new Queue({
|
|
76
|
-
concurrency: 1
|
|
77
|
-
})
|
|
78
|
-
this.capacity = init.capacity ?? 5
|
|
79
|
-
this.delay = init.delay ?? 0
|
|
80
|
-
this.log = init.log
|
|
81
|
-
this.chunkSize = init.chunkSize ?? DEFAULT_CHUNK_SIZE
|
|
82
|
-
|
|
83
|
-
this.queue.addEventListener('idle', () => {
|
|
84
|
-
if (this.needsDrain) {
|
|
85
|
-
this.log('network send queue drained')
|
|
86
|
-
this.needsDrain = false
|
|
87
|
-
this.safeDispatchEvent('drain')
|
|
88
|
-
} else {
|
|
89
|
-
this.log('network send queue idle')
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
send (evt: Event): boolean {
|
|
95
|
-
if (isMessageEvent(evt)) {
|
|
96
|
-
// chunk outgoing messages to match TCP packet sizes
|
|
97
|
-
const data = new Uint8ArrayList(evt.data)
|
|
98
|
-
|
|
99
|
-
while (data.byteLength > 0) {
|
|
100
|
-
const end = Math.min(this.chunkSize, data.byteLength)
|
|
101
|
-
const chunk = data.sublist(0, end)
|
|
102
|
-
data.consume(chunk.byteLength)
|
|
103
|
-
|
|
104
|
-
const chunkEvent = new StreamMessageEvent(chunk)
|
|
105
|
-
|
|
106
|
-
this.queue.add(async (opts) => {
|
|
107
|
-
if (this.delay > 0) {
|
|
108
|
-
await raceSignal(delay(this.delay), opts.signal)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
this.dispatchEvent(opts.evt)
|
|
112
|
-
}, {
|
|
113
|
-
evt: chunkEvent
|
|
114
|
-
})
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
this.queue.add(async (opts) => {
|
|
118
|
-
if (this.delay > 0) {
|
|
119
|
-
await raceSignal(delay(this.delay), opts.signal)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this.dispatchEvent(opts.evt)
|
|
123
|
-
}, {
|
|
124
|
-
evt
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (this.queue.size >= this.capacity) {
|
|
129
|
-
this.log('network send queue full')
|
|
130
|
-
this.needsDrain = true
|
|
131
|
-
return false
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return true
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
pause (): void {
|
|
138
|
-
this.queue.pause()
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
resume (): void {
|
|
142
|
-
this.queue.resume()
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
onIdle (): Promise<void> {
|
|
146
|
-
return this.queue.onIdle()
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
size (): number {
|
|
150
|
-
return this.queue.size
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function isMessageEvent (evt?: any): evt is StreamMessageEvent {
|
|
155
|
-
return evt?.data instanceof Uint8Array || isUint8ArrayList(evt?.data)
|
|
156
|
-
}
|