@libp2p/interface-compliance-tests 3.0.7-e9cafd3d → 3.0.7-eabf6f36
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/dist/src/connection/index.js +5 -5
- package/dist/src/connection/index.js.map +1 -1
- package/dist/src/connection-encryption/utils/index.d.ts.map +1 -1
- package/dist/src/connection-encryption/utils/index.js +1 -0
- package/dist/src/connection-encryption/utils/index.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/is-valid-tick.d.ts.map +1 -1
- package/dist/src/is-valid-tick.js.map +1 -1
- package/dist/src/mocks/connection-manager.d.ts.map +1 -1
- package/dist/src/mocks/connection.d.ts.map +1 -1
- package/dist/src/mocks/connection.js +30 -21
- package/dist/src/mocks/connection.js.map +1 -1
- package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -1
- package/dist/src/mocks/multiaddr-connection.js +9 -0
- package/dist/src/mocks/multiaddr-connection.js.map +1 -1
- package/dist/src/mocks/muxer.d.ts +28 -0
- package/dist/src/mocks/muxer.d.ts.map +1 -1
- package/dist/src/mocks/muxer.js +85 -211
- package/dist/src/mocks/muxer.js.map +1 -1
- package/dist/src/mocks/upgrader.d.ts +1 -1
- package/dist/src/mocks/upgrader.d.ts.map +1 -1
- package/dist/src/stream-muxer/close-test.d.ts.map +1 -1
- package/dist/src/stream-muxer/close-test.js +100 -12
- package/dist/src/stream-muxer/close-test.js.map +1 -1
- package/dist/src/stream-muxer/fixtures/pb/message.d.ts +13 -0
- package/dist/src/stream-muxer/fixtures/pb/message.d.ts.map +1 -0
- package/dist/src/stream-muxer/fixtures/pb/message.js +67 -0
- package/dist/src/stream-muxer/fixtures/pb/message.js.map +1 -0
- package/dist/src/stream-muxer/spawner.d.ts.map +1 -1
- package/dist/src/stream-muxer/spawner.js +4 -3
- package/dist/src/stream-muxer/spawner.js.map +1 -1
- package/dist/src/stream-muxer/stress-test.js +1 -1
- package/dist/src/stream-muxer/stress-test.js.map +1 -1
- package/dist/src/transport/listen-test.js +1 -1
- package/dist/src/transport/listen-test.js.map +1 -1
- package/package.json +15 -14
- package/src/connection/index.ts +5 -5
- package/src/connection-encryption/utils/index.ts +1 -0
- package/src/index.ts +0 -1
- package/src/is-valid-tick.ts +0 -1
- package/src/mocks/connection-manager.ts +2 -2
- package/src/mocks/connection.ts +35 -24
- package/src/mocks/multiaddr-connection.ts +9 -0
- package/src/mocks/muxer.ts +105 -247
- package/src/mocks/upgrader.ts +1 -1
- package/src/stream-muxer/close-test.ts +110 -14
- package/src/stream-muxer/fixtures/pb/message.proto +7 -0
- package/src/stream-muxer/fixtures/pb/message.ts +87 -0
- package/src/stream-muxer/spawner.ts +3 -2
- package/src/stream-muxer/stress-test.ts +1 -1
- package/src/transport/listen-test.ts +1 -1
package/src/mocks/muxer.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AbstractStream, type AbstractStreamInit } from '@libp2p/interface/stream-muxer/stream'
|
|
2
2
|
import { type Logger, logger } from '@libp2p/logger'
|
|
3
3
|
import { abortableSource } from 'abortable-iterator'
|
|
4
|
-
import { anySignal } from 'any-signal'
|
|
5
4
|
import map from 'it-map'
|
|
6
5
|
import * as ndjson from 'it-ndjson'
|
|
7
6
|
import { pipe } from 'it-pipe'
|
|
@@ -9,254 +8,94 @@ import { type Pushable, pushable } from 'it-pushable'
|
|
|
9
8
|
import { Uint8ArrayList } from 'uint8arraylist'
|
|
10
9
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
11
10
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
12
|
-
import type {
|
|
11
|
+
import type { AbortOptions } from '@libp2p/interface'
|
|
12
|
+
import type { Direction, Stream } from '@libp2p/interface/connection'
|
|
13
13
|
import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface/stream-muxer'
|
|
14
14
|
import type { Source } from 'it-stream-types'
|
|
15
15
|
|
|
16
16
|
let muxers = 0
|
|
17
17
|
let streams = 0
|
|
18
|
-
const MAX_MESSAGE_SIZE = 1024 * 1024
|
|
19
18
|
|
|
20
19
|
interface DataMessage {
|
|
21
20
|
id: string
|
|
22
21
|
type: 'data'
|
|
23
|
-
direction:
|
|
22
|
+
direction: Direction
|
|
24
23
|
chunk: string
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
interface ResetMessage {
|
|
28
27
|
id: string
|
|
29
28
|
type: 'reset'
|
|
30
|
-
direction:
|
|
29
|
+
direction: Direction
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
interface CloseMessage {
|
|
34
33
|
id: string
|
|
35
34
|
type: 'close'
|
|
36
|
-
direction:
|
|
35
|
+
direction: Direction
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
interface CreateMessage {
|
|
40
39
|
id: string
|
|
41
40
|
type: 'create'
|
|
42
|
-
direction: '
|
|
41
|
+
direction: 'outbound'
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
type StreamMessage = DataMessage | ResetMessage | CloseMessage | CreateMessage
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
public stream: Stream
|
|
51
|
-
public type: 'initiator' | 'recipient'
|
|
52
|
-
|
|
53
|
-
private sinkEnded: boolean
|
|
54
|
-
private sourceEnded: boolean
|
|
55
|
-
private readonly abortController: AbortController
|
|
56
|
-
private readonly resetController: AbortController
|
|
57
|
-
private readonly closeController: AbortController
|
|
58
|
-
private readonly log: Logger
|
|
59
|
-
|
|
60
|
-
constructor (init: { id: string, type: 'initiator' | 'recipient', push: Pushable<StreamMessage>, onEnd: (err?: Error) => void }) {
|
|
61
|
-
const { id, type, push, onEnd } = init
|
|
62
|
-
|
|
63
|
-
this.log = logger(`libp2p:mock-muxer:stream:${id}:${type}`)
|
|
64
|
-
|
|
65
|
-
this.id = id
|
|
66
|
-
this.type = type
|
|
67
|
-
this.abortController = new AbortController()
|
|
68
|
-
this.resetController = new AbortController()
|
|
69
|
-
this.closeController = new AbortController()
|
|
70
|
-
|
|
71
|
-
this.sourceEnded = false
|
|
72
|
-
this.sinkEnded = false
|
|
73
|
-
|
|
74
|
-
let endErr: Error | undefined
|
|
75
|
-
|
|
76
|
-
const onSourceEnd = (err?: Error): void => {
|
|
77
|
-
if (this.sourceEnded) {
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
this.log('onSourceEnd sink ended? %s', this.sinkEnded)
|
|
46
|
+
export interface MockMuxedStreamInit extends AbstractStreamInit {
|
|
47
|
+
push: Pushable<StreamMessage>
|
|
48
|
+
}
|
|
82
49
|
|
|
83
|
-
|
|
50
|
+
class MuxedStream extends AbstractStream {
|
|
51
|
+
private readonly push: Pushable<StreamMessage>
|
|
84
52
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
53
|
+
constructor (init: MockMuxedStreamInit) {
|
|
54
|
+
super(init)
|
|
88
55
|
|
|
89
|
-
|
|
90
|
-
|
|
56
|
+
this.push = init.push
|
|
57
|
+
}
|
|
91
58
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
59
|
+
sendNewStream (): void {
|
|
60
|
+
// If initiator, open a new stream
|
|
61
|
+
const createMsg: CreateMessage = {
|
|
62
|
+
id: this.id,
|
|
63
|
+
type: 'create',
|
|
64
|
+
direction: 'outbound'
|
|
96
65
|
}
|
|
66
|
+
this.push.push(createMsg)
|
|
67
|
+
}
|
|
97
68
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
this.sinkEnded = true
|
|
106
|
-
|
|
107
|
-
if (err != null && endErr == null) {
|
|
108
|
-
endErr = err
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (this.sourceEnded) {
|
|
112
|
-
this.stream.timeline.close = Date.now()
|
|
113
|
-
|
|
114
|
-
if (onEnd != null) {
|
|
115
|
-
onEnd(endErr)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
69
|
+
sendData (data: Uint8ArrayList): void {
|
|
70
|
+
const dataMsg: DataMessage = {
|
|
71
|
+
id: this.id,
|
|
72
|
+
type: 'data',
|
|
73
|
+
chunk: uint8ArrayToString(data.subarray(), 'base64pad'),
|
|
74
|
+
direction: this.direction
|
|
118
75
|
}
|
|
76
|
+
this.push.push(dataMsg)
|
|
77
|
+
}
|
|
119
78
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
throw new CodeError('stream closed for writing', 'ERR_SINK_ENDED')
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const signal = anySignal([
|
|
132
|
-
this.abortController.signal,
|
|
133
|
-
this.resetController.signal,
|
|
134
|
-
this.closeController.signal
|
|
135
|
-
])
|
|
136
|
-
|
|
137
|
-
source = abortableSource(source, signal)
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
if (this.type === 'initiator') {
|
|
141
|
-
// If initiator, open a new stream
|
|
142
|
-
const createMsg: CreateMessage = {
|
|
143
|
-
id: this.id,
|
|
144
|
-
type: 'create',
|
|
145
|
-
direction: this.type
|
|
146
|
-
}
|
|
147
|
-
push.push(createMsg)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const list = new Uint8ArrayList()
|
|
151
|
-
|
|
152
|
-
for await (const chunk of source) {
|
|
153
|
-
list.append(chunk)
|
|
154
|
-
|
|
155
|
-
while (list.length > 0) {
|
|
156
|
-
const available = Math.min(list.length, MAX_MESSAGE_SIZE)
|
|
157
|
-
const dataMsg: DataMessage = {
|
|
158
|
-
id,
|
|
159
|
-
type: 'data',
|
|
160
|
-
chunk: uint8ArrayToString(list.subarray(0, available), 'base64pad'),
|
|
161
|
-
direction: this.type
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
push.push(dataMsg)
|
|
165
|
-
list.consume(available)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
} catch (err: any) {
|
|
169
|
-
if (err.type === 'aborted' && err.message === 'The operation was aborted') {
|
|
170
|
-
if (this.closeController.signal.aborted) {
|
|
171
|
-
return
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (this.resetController.signal.aborted) {
|
|
175
|
-
err.message = 'stream reset'
|
|
176
|
-
err.code = 'ERR_STREAM_RESET'
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (this.abortController.signal.aborted) {
|
|
180
|
-
err.message = 'stream aborted'
|
|
181
|
-
err.code = 'ERR_STREAM_ABORT'
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Send no more data if this stream was remotely reset
|
|
186
|
-
if (err.code !== 'ERR_STREAM_RESET') {
|
|
187
|
-
const resetMsg: ResetMessage = {
|
|
188
|
-
id,
|
|
189
|
-
type: 'reset',
|
|
190
|
-
direction: this.type
|
|
191
|
-
}
|
|
192
|
-
push.push(resetMsg)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
this.log('sink erred', err)
|
|
196
|
-
|
|
197
|
-
this.input.end(err)
|
|
198
|
-
onSinkEnd(err)
|
|
199
|
-
return
|
|
200
|
-
} finally {
|
|
201
|
-
signal.clear()
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
this.log('sink ended')
|
|
205
|
-
|
|
206
|
-
onSinkEnd()
|
|
207
|
-
|
|
208
|
-
const closeMsg: CloseMessage = {
|
|
209
|
-
id,
|
|
210
|
-
type: 'close',
|
|
211
|
-
direction: this.type
|
|
212
|
-
}
|
|
213
|
-
push.push(closeMsg)
|
|
214
|
-
},
|
|
215
|
-
source: this.input,
|
|
216
|
-
|
|
217
|
-
// Close for reading
|
|
218
|
-
close: () => {
|
|
219
|
-
this.stream.closeRead()
|
|
220
|
-
this.stream.closeWrite()
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
closeRead: () => {
|
|
224
|
-
this.input.end()
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
closeWrite: () => {
|
|
228
|
-
this.closeController.abort()
|
|
229
|
-
|
|
230
|
-
const closeMsg: CloseMessage = {
|
|
231
|
-
id,
|
|
232
|
-
type: 'close',
|
|
233
|
-
direction: this.type
|
|
234
|
-
}
|
|
235
|
-
push.push(closeMsg)
|
|
236
|
-
onSinkEnd()
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
// Close for reading and writing (local error)
|
|
240
|
-
abort: (err: Error) => {
|
|
241
|
-
// End the source with the passed error
|
|
242
|
-
this.input.end(err)
|
|
243
|
-
this.abortController.abort()
|
|
244
|
-
onSinkEnd(err)
|
|
245
|
-
},
|
|
79
|
+
sendReset (): void {
|
|
80
|
+
const resetMsg: ResetMessage = {
|
|
81
|
+
id: this.id,
|
|
82
|
+
type: 'reset',
|
|
83
|
+
direction: this.direction
|
|
84
|
+
}
|
|
85
|
+
this.push.push(resetMsg)
|
|
86
|
+
}
|
|
246
87
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
onSinkEnd(err)
|
|
253
|
-
},
|
|
254
|
-
direction: type === 'initiator' ? 'outbound' : 'inbound',
|
|
255
|
-
timeline: {
|
|
256
|
-
open: Date.now()
|
|
257
|
-
},
|
|
258
|
-
metadata: {}
|
|
88
|
+
sendCloseWrite (): void {
|
|
89
|
+
const closeMsg: CloseMessage = {
|
|
90
|
+
id: this.id,
|
|
91
|
+
type: 'close',
|
|
92
|
+
direction: this.direction
|
|
259
93
|
}
|
|
94
|
+
this.push.push(closeMsg)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
sendCloseRead (): void {
|
|
98
|
+
// does not support close read, only close write
|
|
260
99
|
}
|
|
261
100
|
}
|
|
262
101
|
|
|
@@ -284,8 +123,14 @@ class MockMuxer implements StreamMuxer {
|
|
|
284
123
|
this.closeController = new AbortController()
|
|
285
124
|
// receives data from the muxer at the other end of the stream
|
|
286
125
|
this.source = this.input = pushable({
|
|
287
|
-
onEnd: (
|
|
288
|
-
this.
|
|
126
|
+
onEnd: () => {
|
|
127
|
+
for (const stream of this.registryInitiatorStreams.values()) {
|
|
128
|
+
stream.destroy()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const stream of this.registryRecipientStreams.values()) {
|
|
132
|
+
stream.destroy()
|
|
133
|
+
}
|
|
289
134
|
}
|
|
290
135
|
})
|
|
291
136
|
|
|
@@ -321,18 +166,18 @@ class MockMuxer implements StreamMuxer {
|
|
|
321
166
|
handleMessage (message: StreamMessage): void {
|
|
322
167
|
let muxedStream: MuxedStream | undefined
|
|
323
168
|
|
|
324
|
-
const registry = message.direction === '
|
|
169
|
+
const registry = message.direction === 'outbound' ? this.registryRecipientStreams : this.registryInitiatorStreams
|
|
325
170
|
|
|
326
171
|
if (message.type === 'create') {
|
|
327
172
|
if (registry.has(message.id)) {
|
|
328
173
|
throw new Error(`Already had stream for ${message.id}`)
|
|
329
174
|
}
|
|
330
175
|
|
|
331
|
-
muxedStream = this.createStream(message.id, '
|
|
332
|
-
registry.set(muxedStream.
|
|
176
|
+
muxedStream = this.createStream(message.id, 'inbound')
|
|
177
|
+
registry.set(muxedStream.id, muxedStream)
|
|
333
178
|
|
|
334
179
|
if (this.options.onIncomingStream != null) {
|
|
335
|
-
this.options.onIncomingStream(muxedStream
|
|
180
|
+
this.options.onIncomingStream(muxedStream)
|
|
336
181
|
}
|
|
337
182
|
}
|
|
338
183
|
|
|
@@ -345,20 +190,19 @@ class MockMuxer implements StreamMuxer {
|
|
|
345
190
|
}
|
|
346
191
|
|
|
347
192
|
if (message.type === 'data') {
|
|
348
|
-
muxedStream.
|
|
193
|
+
muxedStream.sourcePush(new Uint8ArrayList(uint8ArrayFromString(message.chunk, 'base64pad')))
|
|
349
194
|
} else if (message.type === 'reset') {
|
|
350
|
-
this.log('-> reset stream %s %s', muxedStream.
|
|
351
|
-
muxedStream.
|
|
195
|
+
this.log('-> reset stream %s %s', muxedStream.direction, muxedStream.id)
|
|
196
|
+
muxedStream.reset()
|
|
352
197
|
} else if (message.type === 'close') {
|
|
353
|
-
this.log('-> closing stream %s %s', muxedStream.
|
|
354
|
-
muxedStream.
|
|
198
|
+
this.log('-> closing stream %s %s', muxedStream.direction, muxedStream.id)
|
|
199
|
+
muxedStream.remoteCloseWrite()
|
|
355
200
|
}
|
|
356
201
|
}
|
|
357
202
|
|
|
358
203
|
get streams (): Stream[] {
|
|
359
204
|
return Array.from(this.registryRecipientStreams.values())
|
|
360
205
|
.concat(Array.from(this.registryInitiatorStreams.values()))
|
|
361
|
-
.map(({ stream }) => stream)
|
|
362
206
|
}
|
|
363
207
|
|
|
364
208
|
newStream (name?: string): Stream {
|
|
@@ -366,53 +210,67 @@ class MockMuxer implements StreamMuxer {
|
|
|
366
210
|
throw new Error('Muxer already closed')
|
|
367
211
|
}
|
|
368
212
|
this.log('newStream %s', name)
|
|
369
|
-
const storedStream = this.createStream(name, '
|
|
370
|
-
this.registryInitiatorStreams.set(storedStream.
|
|
213
|
+
const storedStream = this.createStream(name, 'outbound')
|
|
214
|
+
this.registryInitiatorStreams.set(storedStream.id, storedStream)
|
|
371
215
|
|
|
372
|
-
return storedStream
|
|
216
|
+
return storedStream
|
|
373
217
|
}
|
|
374
218
|
|
|
375
|
-
createStream (name?: string,
|
|
376
|
-
const id = name ?? `${
|
|
219
|
+
createStream (name?: string, direction: Direction = 'outbound'): MuxedStream {
|
|
220
|
+
const id = name ?? `${streams++}`
|
|
377
221
|
|
|
378
|
-
this.log('createStream %s %s',
|
|
222
|
+
this.log('createStream %s %s', direction, id)
|
|
379
223
|
|
|
380
224
|
const muxedStream: MuxedStream = new MuxedStream({
|
|
381
225
|
id,
|
|
382
|
-
|
|
226
|
+
direction,
|
|
383
227
|
push: this.streamInput,
|
|
384
228
|
onEnd: () => {
|
|
385
|
-
this.log('stream ended
|
|
229
|
+
this.log('stream ended')
|
|
386
230
|
|
|
387
|
-
if (
|
|
388
|
-
this.registryInitiatorStreams.delete(id)
|
|
231
|
+
if (direction === 'outbound') {
|
|
232
|
+
this.registryInitiatorStreams.delete(muxedStream.id)
|
|
389
233
|
} else {
|
|
390
|
-
this.registryRecipientStreams.delete(id)
|
|
234
|
+
this.registryRecipientStreams.delete(muxedStream.id)
|
|
391
235
|
}
|
|
392
236
|
|
|
393
237
|
if (this.options.onStreamEnd != null) {
|
|
394
|
-
this.options.onStreamEnd(muxedStream
|
|
238
|
+
this.options.onStreamEnd(muxedStream)
|
|
395
239
|
}
|
|
396
|
-
}
|
|
240
|
+
},
|
|
241
|
+
log: logger(`libp2p:mock-muxer:stream:${direction}:${id}`)
|
|
397
242
|
})
|
|
398
243
|
|
|
399
244
|
return muxedStream
|
|
400
245
|
}
|
|
401
246
|
|
|
402
|
-
close (
|
|
403
|
-
if (this.closeController.signal.aborted)
|
|
247
|
+
async close (options?: AbortOptions): Promise<void> {
|
|
248
|
+
if (this.closeController.signal.aborted) {
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
|
|
404
252
|
this.log('closing muxed streams')
|
|
405
253
|
|
|
406
|
-
|
|
407
|
-
this.streams.
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
} else {
|
|
411
|
-
this.streams.forEach(s => {
|
|
412
|
-
s.abort(err)
|
|
413
|
-
})
|
|
414
|
-
}
|
|
254
|
+
await Promise.all(
|
|
255
|
+
this.streams.map(async s => s.close())
|
|
256
|
+
)
|
|
257
|
+
|
|
415
258
|
this.closeController.abort()
|
|
259
|
+
this.input.end()
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
abort (err: Error): void {
|
|
263
|
+
if (this.closeController.signal.aborted) {
|
|
264
|
+
return
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
this.log('aborting muxed streams')
|
|
268
|
+
|
|
269
|
+
this.streams.forEach(s => {
|
|
270
|
+
s.abort(err)
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
this.closeController.abort(err)
|
|
416
274
|
this.input.end(err)
|
|
417
275
|
}
|
|
418
276
|
}
|
package/src/mocks/upgrader.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { mockConnection } from './connection.js'
|
|
|
2
2
|
import type { Libp2pEvents } from '@libp2p/interface'
|
|
3
3
|
import type { Connection, MultiaddrConnection } from '@libp2p/interface/connection'
|
|
4
4
|
import type { EventEmitter } from '@libp2p/interface/events'
|
|
5
|
+
import type { Upgrader, UpgraderOptions } from '@libp2p/interface/transport'
|
|
5
6
|
import type { Registrar } from '@libp2p/interface-internal/registrar'
|
|
6
|
-
import type { Upgrader, UpgraderOptions } from '@libp2p/interface-internal/upgrader'
|
|
7
7
|
|
|
8
8
|
export interface MockUpgraderInit {
|
|
9
9
|
registrar?: Registrar
|
|
@@ -6,9 +6,12 @@ import all from 'it-all'
|
|
|
6
6
|
import drain from 'it-drain'
|
|
7
7
|
import { duplexPair } from 'it-pair/duplex'
|
|
8
8
|
import { pipe } from 'it-pipe'
|
|
9
|
+
import { pbStream } from 'it-protobuf-stream'
|
|
10
|
+
import toBuffer from 'it-to-buffer'
|
|
9
11
|
import pDefer from 'p-defer'
|
|
10
12
|
import { Uint8ArrayList } from 'uint8arraylist'
|
|
11
13
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
14
|
+
import { Message } from './fixtures/pb/message.js'
|
|
12
15
|
import type { TestSetup } from '../index.js'
|
|
13
16
|
import type { StreamMuxerFactory } from '@libp2p/interface/stream-muxer'
|
|
14
17
|
|
|
@@ -61,9 +64,9 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
61
64
|
|
|
62
65
|
expect(dialer.streams).to.have.lengthOf(expectedStreams)
|
|
63
66
|
|
|
64
|
-
// Pause, and then
|
|
67
|
+
// Pause, and then close the dialer
|
|
65
68
|
await delay(50)
|
|
66
|
-
await pipe([
|
|
69
|
+
await pipe([], dialer, drain)
|
|
67
70
|
|
|
68
71
|
expect(openedStreams).to.have.equal(expectedStreams)
|
|
69
72
|
expect(dialer.streams).to.have.lengthOf(0)
|
|
@@ -106,7 +109,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
106
109
|
// Pause, and then close the dialer
|
|
107
110
|
await delay(50)
|
|
108
111
|
|
|
109
|
-
dialer.close()
|
|
112
|
+
await dialer.close()
|
|
110
113
|
|
|
111
114
|
expect(openedStreams, 'listener - number of opened streams should match number of calls to newStream').to.have.equal(expectedStreams)
|
|
112
115
|
expect(dialer.streams, 'all tracked streams should be deleted after the muxer has called close').to.have.lengthOf(0)
|
|
@@ -148,7 +151,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
148
151
|
await delay(50)
|
|
149
152
|
|
|
150
153
|
// close _with an error_
|
|
151
|
-
dialer.
|
|
154
|
+
dialer.abort(new Error('Oh no!'))
|
|
152
155
|
|
|
153
156
|
const timeoutError = new Error('timeout')
|
|
154
157
|
for (const pipe of streamPipes) {
|
|
@@ -173,7 +176,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
173
176
|
const dialerFactory = await common.setup()
|
|
174
177
|
const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
|
|
175
178
|
|
|
176
|
-
dialer.close()
|
|
179
|
+
await dialer.close()
|
|
177
180
|
|
|
178
181
|
try {
|
|
179
182
|
await dialer.newStream()
|
|
@@ -246,7 +249,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
246
249
|
onIncomingStream: (stream) => {
|
|
247
250
|
void Promise.resolve().then(async () => {
|
|
248
251
|
// Immediate close for write
|
|
249
|
-
stream.closeWrite()
|
|
252
|
+
await stream.closeWrite()
|
|
250
253
|
|
|
251
254
|
const results = await pipe(stream, async (source) => {
|
|
252
255
|
const data = []
|
|
@@ -275,16 +278,16 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
275
278
|
await stream.sink(data)
|
|
276
279
|
|
|
277
280
|
const err = await deferred.promise
|
|
278
|
-
expect(err).to.have.property('
|
|
281
|
+
expect(err).to.have.property('code', 'ERR_SINK_INVALID_STATE')
|
|
279
282
|
})
|
|
280
283
|
|
|
281
284
|
it('can close a stream for reading', async () => {
|
|
282
|
-
const deferred = pDefer<
|
|
283
|
-
|
|
285
|
+
const deferred = pDefer<Uint8ArrayList[]>()
|
|
284
286
|
const p = duplexPair<Uint8Array>()
|
|
285
287
|
const dialerFactory = await common.setup()
|
|
286
288
|
const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
|
|
287
289
|
const data = [randomBuffer(), randomBuffer()].map(d => new Uint8ArrayList(d))
|
|
290
|
+
const expected = toBuffer(data.map(d => d.subarray()))
|
|
288
291
|
|
|
289
292
|
const listenerFactory = await common.setup()
|
|
290
293
|
const listener = listenerFactory.createStreamMuxer({
|
|
@@ -298,7 +301,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
298
301
|
void pipe(p[1], listener, p[1])
|
|
299
302
|
|
|
300
303
|
const stream = await dialer.newStream()
|
|
301
|
-
stream.closeRead()
|
|
304
|
+
await stream.closeRead()
|
|
302
305
|
|
|
303
306
|
// Source should be done
|
|
304
307
|
void Promise.resolve().then(async () => {
|
|
@@ -307,7 +310,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
307
310
|
})
|
|
308
311
|
|
|
309
312
|
const results = await deferred.promise
|
|
310
|
-
expect(results).to.
|
|
313
|
+
expect(toBuffer(results.map(b => b.subarray()))).to.equalBytes(expected)
|
|
311
314
|
})
|
|
312
315
|
|
|
313
316
|
it('calls onStreamEnd for closed streams not previously written', async () => {
|
|
@@ -322,7 +325,7 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
322
325
|
|
|
323
326
|
const stream = await dialer.newStream()
|
|
324
327
|
|
|
325
|
-
stream.close()
|
|
328
|
+
await stream.close()
|
|
326
329
|
await deferred.promise
|
|
327
330
|
})
|
|
328
331
|
|
|
@@ -338,9 +341,102 @@ export default (common: TestSetup<StreamMuxerFactory>): void => {
|
|
|
338
341
|
|
|
339
342
|
const stream = await dialer.newStream()
|
|
340
343
|
|
|
341
|
-
stream.closeWrite()
|
|
342
|
-
stream.closeRead()
|
|
344
|
+
await stream.closeWrite()
|
|
345
|
+
await stream.closeRead()
|
|
346
|
+
await deferred.promise
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
it('should wait for all data to be sent when closing streams', async () => {
|
|
350
|
+
const deferred = pDefer<Message>()
|
|
351
|
+
|
|
352
|
+
const p = duplexPair<Uint8Array>()
|
|
353
|
+
const dialerFactory = await common.setup()
|
|
354
|
+
const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
|
|
355
|
+
|
|
356
|
+
const listenerFactory = await common.setup()
|
|
357
|
+
const listener = listenerFactory.createStreamMuxer({
|
|
358
|
+
direction: 'inbound',
|
|
359
|
+
onIncomingStream: (stream) => {
|
|
360
|
+
const pb = pbStream(stream)
|
|
361
|
+
|
|
362
|
+
void pb.read(Message)
|
|
363
|
+
.then(async message => {
|
|
364
|
+
deferred.resolve(message)
|
|
365
|
+
await pb.unwrap().close()
|
|
366
|
+
})
|
|
367
|
+
.catch(err => {
|
|
368
|
+
deferred.reject(err)
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
void pipe(p[0], dialer, p[0])
|
|
374
|
+
void pipe(p[1], listener, p[1])
|
|
375
|
+
|
|
376
|
+
const message = {
|
|
377
|
+
message: 'hello world',
|
|
378
|
+
value: 5,
|
|
379
|
+
flag: true
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const stream = await dialer.newStream()
|
|
383
|
+
|
|
384
|
+
const pb = pbStream(stream)
|
|
385
|
+
await pb.write(message, Message)
|
|
386
|
+
await pb.unwrap().close()
|
|
387
|
+
|
|
388
|
+
await expect(deferred.promise).to.eventually.deep.equal(message)
|
|
389
|
+
})
|
|
390
|
+
/*
|
|
391
|
+
it('should abort closing a stream with outstanding data to read', async () => {
|
|
392
|
+
const deferred = pDefer<Message>()
|
|
393
|
+
|
|
394
|
+
const p = duplexPair<Uint8Array>()
|
|
395
|
+
const dialerFactory = await common.setup()
|
|
396
|
+
const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' })
|
|
397
|
+
|
|
398
|
+
const listenerFactory = await common.setup()
|
|
399
|
+
const listener = listenerFactory.createStreamMuxer({
|
|
400
|
+
direction: 'inbound',
|
|
401
|
+
onIncomingStream: (stream) => {
|
|
402
|
+
const pb = pbStream(stream)
|
|
403
|
+
|
|
404
|
+
void pb.read(Message)
|
|
405
|
+
.then(async message => {
|
|
406
|
+
await pb.write(message, Message)
|
|
407
|
+
await pb.unwrap().close()
|
|
408
|
+
deferred.resolve(message)
|
|
409
|
+
})
|
|
410
|
+
.catch(err => {
|
|
411
|
+
deferred.reject(err)
|
|
412
|
+
})
|
|
413
|
+
}
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
void pipe(p[0], dialer, p[0])
|
|
417
|
+
void pipe(p[1], listener, p[1])
|
|
418
|
+
|
|
419
|
+
const message = {
|
|
420
|
+
message: 'hello world',
|
|
421
|
+
value: 5,
|
|
422
|
+
flag: true
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const stream = await dialer.newStream()
|
|
426
|
+
|
|
427
|
+
const pb = pbStream(stream)
|
|
428
|
+
await pb.write(message, Message)
|
|
429
|
+
|
|
430
|
+
console.info('await write back')
|
|
343
431
|
await deferred.promise
|
|
432
|
+
|
|
433
|
+
// let message arrive
|
|
434
|
+
await delay(100)
|
|
435
|
+
|
|
436
|
+
// close should time out as message is never read
|
|
437
|
+
await expect(pb.unwrap().close()).to.eventually.be.rejected
|
|
438
|
+
.with.property('code', 'ERR_CLOSE_READ_ABORTED')
|
|
344
439
|
})
|
|
440
|
+
*/
|
|
345
441
|
})
|
|
346
442
|
}
|