@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.
Files changed (160) hide show
  1. package/README.md +16 -1
  2. package/dist/index.min.js +7 -1
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/abstract-message-stream.d.ts +129 -0
  5. package/dist/src/abstract-message-stream.d.ts.map +1 -0
  6. package/dist/src/abstract-message-stream.js +393 -0
  7. package/dist/src/abstract-message-stream.js.map +1 -0
  8. package/dist/src/abstract-multiaddr-connection.d.ts +26 -0
  9. package/dist/src/abstract-multiaddr-connection.d.ts.map +1 -0
  10. package/dist/src/abstract-multiaddr-connection.js +66 -0
  11. package/dist/src/abstract-multiaddr-connection.js.map +1 -0
  12. package/dist/src/abstract-stream-muxer.d.ts +53 -0
  13. package/dist/src/abstract-stream-muxer.d.ts.map +1 -0
  14. package/dist/src/abstract-stream-muxer.js +169 -0
  15. package/dist/src/abstract-stream-muxer.js.map +1 -0
  16. package/dist/src/abstract-stream.d.ts +14 -130
  17. package/dist/src/abstract-stream.d.ts.map +1 -1
  18. package/dist/src/abstract-stream.js +39 -321
  19. package/dist/src/abstract-stream.js.map +1 -1
  20. package/dist/src/errors.d.ts +8 -0
  21. package/dist/src/errors.d.ts.map +1 -1
  22. package/dist/src/errors.js +8 -0
  23. package/dist/src/errors.js.map +1 -1
  24. package/dist/src/get-thin-waist-addresses.browser.d.ts +1 -1
  25. package/dist/src/get-thin-waist-addresses.browser.d.ts.map +1 -1
  26. package/dist/src/get-thin-waist-addresses.browser.js +4 -3
  27. package/dist/src/get-thin-waist-addresses.browser.js.map +1 -1
  28. package/dist/src/get-thin-waist-addresses.d.ts +1 -1
  29. package/dist/src/get-thin-waist-addresses.d.ts.map +1 -1
  30. package/dist/src/get-thin-waist-addresses.js +7 -9
  31. package/dist/src/get-thin-waist-addresses.js.map +1 -1
  32. package/dist/src/index.d.ts +31 -1
  33. package/dist/src/index.d.ts.map +1 -1
  34. package/dist/src/index.js +31 -1
  35. package/dist/src/index.js.map +1 -1
  36. package/dist/src/length-prefixed-decoder.d.ts +37 -0
  37. package/dist/src/length-prefixed-decoder.d.ts.map +1 -0
  38. package/dist/src/length-prefixed-decoder.js +64 -0
  39. package/dist/src/length-prefixed-decoder.js.map +1 -0
  40. package/dist/src/message-queue.d.ts +61 -0
  41. package/dist/src/message-queue.d.ts.map +1 -0
  42. package/dist/src/message-queue.js +93 -0
  43. package/dist/src/message-queue.js.map +1 -0
  44. package/dist/src/mock-muxer.d.ts +57 -0
  45. package/dist/src/mock-muxer.d.ts.map +1 -0
  46. package/dist/src/mock-muxer.js +204 -0
  47. package/dist/src/mock-muxer.js.map +1 -0
  48. package/dist/src/mock-stream.d.ts +31 -0
  49. package/dist/src/mock-stream.d.ts.map +1 -0
  50. package/dist/src/mock-stream.js +69 -0
  51. package/dist/src/mock-stream.js.map +1 -0
  52. package/dist/src/multiaddr/get-net-config.d.ts +55 -0
  53. package/dist/src/multiaddr/get-net-config.d.ts.map +1 -0
  54. package/dist/src/multiaddr/get-net-config.js +54 -0
  55. package/dist/src/multiaddr/get-net-config.js.map +1 -0
  56. package/dist/src/multiaddr/index.d.ts +7 -0
  57. package/dist/src/multiaddr/index.d.ts.map +1 -0
  58. package/dist/src/multiaddr/index.js +7 -0
  59. package/dist/src/multiaddr/index.js.map +1 -0
  60. package/dist/src/multiaddr/is-global-unicast.d.ts.map +1 -1
  61. package/dist/src/multiaddr/is-global-unicast.js +8 -9
  62. package/dist/src/multiaddr/is-global-unicast.js.map +1 -1
  63. package/dist/src/multiaddr/is-link-local.d.ts.map +1 -1
  64. package/dist/src/multiaddr/is-link-local.js +11 -16
  65. package/dist/src/multiaddr/is-link-local.js.map +1 -1
  66. package/dist/src/multiaddr/is-loopback.d.ts.map +1 -1
  67. package/dist/src/multiaddr/is-loopback.js +12 -5
  68. package/dist/src/multiaddr/is-loopback.js.map +1 -1
  69. package/dist/src/multiaddr/is-network-address.d.ts.map +1 -1
  70. package/dist/src/multiaddr/is-network-address.js +4 -16
  71. package/dist/src/multiaddr/is-network-address.js.map +1 -1
  72. package/dist/src/multiaddr/is-private.d.ts.map +1 -1
  73. package/dist/src/multiaddr/is-private.js +9 -10
  74. package/dist/src/multiaddr/is-private.js.map +1 -1
  75. package/dist/src/multiaddr/utils.d.ts +5 -0
  76. package/dist/src/multiaddr/utils.d.ts.map +1 -0
  77. package/dist/src/multiaddr/utils.js +32 -0
  78. package/dist/src/multiaddr/utils.js.map +1 -0
  79. package/dist/src/multiaddr-connection-pair.d.ts +25 -0
  80. package/dist/src/multiaddr-connection-pair.d.ts.map +1 -0
  81. package/dist/src/multiaddr-connection-pair.js +103 -0
  82. package/dist/src/multiaddr-connection-pair.js.map +1 -0
  83. package/dist/src/queue/index.d.ts +3 -6
  84. package/dist/src/queue/index.d.ts.map +1 -1
  85. package/dist/src/queue/index.js +20 -4
  86. package/dist/src/queue/index.js.map +1 -1
  87. package/dist/src/rate-limiter.d.ts +1 -15
  88. package/dist/src/rate-limiter.d.ts.map +1 -1
  89. package/dist/src/rate-limiter.js +1 -14
  90. package/dist/src/rate-limiter.js.map +1 -1
  91. package/dist/src/stream-pair.d.ts +42 -0
  92. package/dist/src/stream-pair.d.ts.map +1 -0
  93. package/dist/src/stream-pair.js +40 -0
  94. package/dist/src/stream-pair.js.map +1 -0
  95. package/dist/src/stream-utils.d.ts +191 -0
  96. package/dist/src/stream-utils.d.ts.map +1 -0
  97. package/dist/src/stream-utils.js +371 -0
  98. package/dist/src/stream-utils.js.map +1 -0
  99. package/package.json +15 -162
  100. package/src/abstract-message-stream.ts +553 -0
  101. package/src/abstract-multiaddr-connection.ts +93 -0
  102. package/src/abstract-stream-muxer.ts +239 -0
  103. package/src/abstract-stream.ts +51 -464
  104. package/src/errors.ts +10 -0
  105. package/src/get-thin-waist-addresses.browser.ts +5 -4
  106. package/src/get-thin-waist-addresses.ts +8 -12
  107. package/src/index.ts +31 -1
  108. package/src/length-prefixed-decoder.ts +98 -0
  109. package/src/message-queue.ts +156 -0
  110. package/src/mock-muxer.ts +304 -0
  111. package/src/mock-stream.ts +101 -0
  112. package/src/multiaddr/get-net-config.ts +112 -0
  113. package/src/multiaddr/index.ts +6 -0
  114. package/src/multiaddr/is-global-unicast.ts +8 -11
  115. package/src/multiaddr/is-link-local.ts +11 -20
  116. package/src/multiaddr/is-loopback.ts +12 -7
  117. package/src/multiaddr/is-network-address.ts +4 -19
  118. package/src/multiaddr/is-private.ts +9 -14
  119. package/src/multiaddr/utils.ts +46 -0
  120. package/src/multiaddr-connection-pair.ts +147 -0
  121. package/src/queue/index.ts +24 -11
  122. package/src/rate-limiter.ts +3 -30
  123. package/src/stream-pair.ts +90 -0
  124. package/src/stream-utils.ts +866 -0
  125. package/dist/src/abort-options.d.ts +0 -7
  126. package/dist/src/abort-options.d.ts.map +0 -1
  127. package/dist/src/abort-options.js +0 -14
  128. package/dist/src/abort-options.js.map +0 -1
  129. package/dist/src/array-equals.d.ts +0 -24
  130. package/dist/src/array-equals.d.ts.map +0 -1
  131. package/dist/src/array-equals.js +0 -31
  132. package/dist/src/array-equals.js.map +0 -1
  133. package/dist/src/close-source.d.ts +0 -4
  134. package/dist/src/close-source.d.ts.map +0 -1
  135. package/dist/src/close-source.js +0 -11
  136. package/dist/src/close-source.js.map +0 -1
  137. package/dist/src/close.d.ts +0 -21
  138. package/dist/src/close.d.ts.map +0 -1
  139. package/dist/src/close.js +0 -49
  140. package/dist/src/close.js.map +0 -1
  141. package/dist/src/merge-options.d.ts +0 -7
  142. package/dist/src/merge-options.d.ts.map +0 -1
  143. package/dist/src/merge-options.js +0 -128
  144. package/dist/src/merge-options.js.map +0 -1
  145. package/dist/src/multiaddr/is-ip-based.d.ts +0 -6
  146. package/dist/src/multiaddr/is-ip-based.d.ts.map +0 -1
  147. package/dist/src/multiaddr/is-ip-based.js +0 -18
  148. package/dist/src/multiaddr/is-ip-based.js.map +0 -1
  149. package/dist/src/stream-to-ma-conn.d.ts +0 -23
  150. package/dist/src/stream-to-ma-conn.d.ts.map +0 -1
  151. package/dist/src/stream-to-ma-conn.js +0 -75
  152. package/dist/src/stream-to-ma-conn.js.map +0 -1
  153. package/dist/typedoc-urls.json +0 -147
  154. package/src/abort-options.ts +0 -20
  155. package/src/array-equals.ts +0 -34
  156. package/src/close-source.ts +0 -14
  157. package/src/close.ts +0 -65
  158. package/src/merge-options.ts +0 -161
  159. package/src/multiaddr/is-ip-based.ts +0 -21
  160. package/src/stream-to-ma-conn.ts +0 -106
@@ -1,515 +1,102 @@
1
- import { StreamResetError, StreamStateError } from '@libp2p/interface'
2
- import { pushable } from 'it-pushable'
3
- import defer from 'p-defer'
4
- import { raceSignal } from 'race-signal'
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
- const DEFAULT_SEND_CLOSE_WRITE_TIMEOUT = 5000
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 direction
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
- onAbort?(err: Error): void
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
- function isPromise <T = unknown> (thing: any): thing is Promise<T> {
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 direction: Direction
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
- this.sinkController = new AbortController()
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.metadata = init.metadata ?? {}
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.log.trace('closing writable end of stream with starting write status "%s"', this.writeStatus)
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
- * Close immediately for reading and writing and send a reset message (local
363
- * error)
364
- */
365
- abort (err: Error): void {
366
- if (this.status === 'closed' || this.status === 'aborted' || this.status === 'reset') {
367
- return
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
- this.status = 'aborted'
383
- this.timeline.abort = Date.now()
384
- this._closeSinkAndSource(err)
385
- this.onAbort?.(err)
386
- }
387
-
388
- /**
389
- * Receive a reset message - close immediately for reading and writing (remote
390
- * error)
391
- */
392
- reset (): void {
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
- const err = new StreamResetError('stream reset')
61
+ await this.sendCloseWrite(options)
398
62
 
399
- this.status = 'reset'
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
- _closeSink (err?: Error): void {
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.onSinkEnd(err)
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
- this.log.trace('remote close read')
454
- this._closeSink()
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.log.trace('stream destroyed')
82
+ this.readStatus = 'closing'
468
83
 
469
- this._closeSinkAndSource()
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 muxer informing them a new stream is being
490
- * opened
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): void | Promise<void>
95
+ abstract sendCloseWrite (options?: AbortOptions): Promise<void>
509
96
 
510
97
  /**
511
- * Send a message to the remote muxer, informing them no more data messages
512
- * will be read by this end of the stream
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): void | Promise<void>
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 { multiaddr } from '@multiformats/multiaddr'
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 options = ma.toOptions()
16
+ const config = getNetConfig(ma)
16
17
 
17
18
  return [
18
- multiaddr(`/ip${options.family}/${options.host}/${options.transport}/${port ?? options.port}`)
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 options = ma.toOptions()
45
+ const config = getNetConfig(ma)
45
46
 
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
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
- multiaddr(`/ip${options.family}/${options.host}/${options.transport}/${port ?? options.port}`)
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'