@libp2p/mplex 8.0.1 → 8.0.3
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/index.min.js +4 -4
- package/dist/src/decode.d.ts +1 -1
- package/dist/src/decode.d.ts.map +1 -1
- package/dist/src/decode.js +5 -1
- package/dist/src/decode.js.map +1 -1
- package/dist/src/encode.d.ts +1 -1
- package/dist/src/encode.d.ts.map +1 -1
- package/dist/src/encode.js +4 -2
- package/dist/src/encode.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mplex.d.ts +4 -4
- package/dist/src/mplex.d.ts.map +1 -1
- package/dist/src/mplex.js +16 -8
- package/dist/src/mplex.js.map +1 -1
- package/dist/src/stream.d.ts +20 -1
- package/dist/src/stream.d.ts.map +1 -1
- package/dist/src/stream.js +39 -191
- package/dist/src/stream.js.map +1 -1
- package/package.json +4 -5
- package/src/decode.ts +1 -1
- package/src/encode.ts +4 -4
- package/src/index.ts +1 -1
- package/src/mplex.ts +11 -11
- package/src/stream.ts +44 -226
package/src/stream.ts
CHANGED
@@ -1,23 +1,9 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import {
|
1
|
+
import { AbstractStream, type AbstractStreamInit } from '@libp2p/interface-stream-muxer/stream'
|
2
|
+
import { Uint8ArrayList } from 'uint8arraylist'
|
3
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
4
4
|
import { MAX_MSG_SIZE } from './decode.js'
|
5
|
-
import { anySignal } from 'any-signal'
|
6
5
|
import { InitiatorMessageTypes, ReceiverMessageTypes } from './message-types.js'
|
7
|
-
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
8
|
-
import { Uint8ArrayList } from 'uint8arraylist'
|
9
|
-
import { logger } from '@libp2p/logger'
|
10
6
|
import type { Message } from './message-types.js'
|
11
|
-
import type { StreamTimeline } from '@libp2p/interface-connection'
|
12
|
-
import type { Source } from 'it-stream-types'
|
13
|
-
import type { MplexStream } from './mplex.js'
|
14
|
-
|
15
|
-
const log = logger('libp2p:mplex:stream')
|
16
|
-
|
17
|
-
const ERR_STREAM_RESET = 'ERR_STREAM_RESET'
|
18
|
-
const ERR_STREAM_ABORT = 'ERR_STREAM_ABORT'
|
19
|
-
const ERR_SINK_ENDED = 'ERR_SINK_ENDED'
|
20
|
-
const ERR_DOUBLE_SINK = 'ERR_DOUBLE_SINK'
|
21
7
|
|
22
8
|
export interface Options {
|
23
9
|
id: number
|
@@ -28,226 +14,58 @@ export interface Options {
|
|
28
14
|
maxMsgSize?: number
|
29
15
|
}
|
30
16
|
|
31
|
-
|
32
|
-
|
17
|
+
interface MplexStreamInit extends AbstractStreamInit {
|
18
|
+
streamId: number
|
19
|
+
name: string
|
20
|
+
send: (msg: Message) => void
|
21
|
+
}
|
33
22
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
const streamName = `${name == null ? id : name}`
|
23
|
+
class MplexStream extends AbstractStream {
|
24
|
+
private readonly name: string
|
25
|
+
private readonly streamId: number
|
26
|
+
private readonly send: (msg: Message) => void
|
27
|
+
private readonly types: Record<string, number>
|
40
28
|
|
41
|
-
|
42
|
-
|
43
|
-
let sinkSunk = false
|
44
|
-
let endErr: Error | undefined
|
29
|
+
constructor (init: MplexStreamInit) {
|
30
|
+
super(init)
|
45
31
|
|
46
|
-
|
47
|
-
|
32
|
+
this.types = init.direction === 'outbound' ? InitiatorMessageTypes : ReceiverMessageTypes
|
33
|
+
this.send = init.send
|
34
|
+
this.name = init.name
|
35
|
+
this.streamId = init.streamId
|
48
36
|
}
|
49
37
|
|
50
|
-
|
51
|
-
|
52
|
-
return
|
53
|
-
}
|
54
|
-
|
55
|
-
sourceEnded = true
|
56
|
-
log.trace('%s stream %s source end - err: %o', type, streamName, err)
|
57
|
-
|
58
|
-
if (err != null && endErr == null) {
|
59
|
-
endErr = err
|
60
|
-
}
|
61
|
-
|
62
|
-
if (sinkEnded) {
|
63
|
-
stream.stat.timeline.close = Date.now()
|
64
|
-
|
65
|
-
if (onEnd != null) {
|
66
|
-
onEnd(endErr)
|
67
|
-
}
|
68
|
-
}
|
38
|
+
sendNewStream (): void {
|
39
|
+
this.send({ id: this.streamId, type: InitiatorMessageTypes.NEW_STREAM, data: new Uint8ArrayList(uint8ArrayFromString(this.name)) })
|
69
40
|
}
|
70
41
|
|
71
|
-
|
72
|
-
|
73
|
-
return
|
74
|
-
}
|
75
|
-
|
76
|
-
sinkEnded = true
|
77
|
-
log.trace('%s stream %s sink end - err: %o', type, streamName, err)
|
78
|
-
|
79
|
-
if (err != null && endErr == null) {
|
80
|
-
endErr = err
|
81
|
-
}
|
82
|
-
|
83
|
-
if (sourceEnded) {
|
84
|
-
timeline.close = Date.now()
|
85
|
-
|
86
|
-
if (onEnd != null) {
|
87
|
-
onEnd(endErr)
|
88
|
-
}
|
89
|
-
}
|
42
|
+
sendData (data: Uint8ArrayList): void {
|
43
|
+
this.send({ id: this.streamId, type: this.types.MESSAGE, data })
|
90
44
|
}
|
91
45
|
|
92
|
-
|
93
|
-
|
94
|
-
}
|
95
|
-
|
96
|
-
const stream: MplexStream = {
|
97
|
-
// Close for both Reading and Writing
|
98
|
-
close: () => {
|
99
|
-
log.trace('%s stream %s close', type, streamName)
|
100
|
-
|
101
|
-
stream.closeRead()
|
102
|
-
stream.closeWrite()
|
103
|
-
},
|
104
|
-
|
105
|
-
// Close for reading
|
106
|
-
closeRead: () => {
|
107
|
-
log.trace('%s stream %s closeRead', type, streamName)
|
108
|
-
|
109
|
-
if (sourceEnded) {
|
110
|
-
return
|
111
|
-
}
|
112
|
-
|
113
|
-
streamSource.end()
|
114
|
-
},
|
115
|
-
|
116
|
-
// Close for writing
|
117
|
-
closeWrite: () => {
|
118
|
-
log.trace('%s stream %s closeWrite', type, streamName)
|
119
|
-
|
120
|
-
if (sinkEnded) {
|
121
|
-
return
|
122
|
-
}
|
123
|
-
|
124
|
-
closeController.abort()
|
125
|
-
|
126
|
-
try {
|
127
|
-
send({ id, type: Types.CLOSE })
|
128
|
-
} catch (err) {
|
129
|
-
log.trace('%s stream %s error sending close', type, name, err)
|
130
|
-
}
|
131
|
-
|
132
|
-
onSinkEnd()
|
133
|
-
},
|
134
|
-
|
135
|
-
// Close for reading and writing (local error)
|
136
|
-
abort: (err: Error) => {
|
137
|
-
log.trace('%s stream %s abort', type, streamName, err)
|
138
|
-
// End the source with the passed error
|
139
|
-
streamSource.end(err)
|
140
|
-
abortController.abort()
|
141
|
-
onSinkEnd(err)
|
142
|
-
},
|
143
|
-
|
144
|
-
// Close immediately for reading and writing (remote error)
|
145
|
-
reset: () => {
|
146
|
-
const err = new CodeError('stream reset', ERR_STREAM_RESET)
|
147
|
-
resetController.abort()
|
148
|
-
streamSource.end(err)
|
149
|
-
onSinkEnd(err)
|
150
|
-
},
|
151
|
-
|
152
|
-
sink: async (source: Source<Uint8ArrayList | Uint8Array>) => {
|
153
|
-
if (sinkSunk) {
|
154
|
-
throw new CodeError('sink already called on stream', ERR_DOUBLE_SINK)
|
155
|
-
}
|
156
|
-
|
157
|
-
sinkSunk = true
|
158
|
-
|
159
|
-
if (sinkEnded) {
|
160
|
-
throw new CodeError('stream closed for writing', ERR_SINK_ENDED)
|
161
|
-
}
|
162
|
-
|
163
|
-
const signal = anySignal([
|
164
|
-
abortController.signal,
|
165
|
-
resetController.signal,
|
166
|
-
closeController.signal
|
167
|
-
])
|
168
|
-
|
169
|
-
try {
|
170
|
-
source = abortableSource(source, signal)
|
171
|
-
|
172
|
-
if (type === 'initiator') { // If initiator, open a new stream
|
173
|
-
send({ id, type: InitiatorMessageTypes.NEW_STREAM, data: new Uint8ArrayList(uint8ArrayFromString(streamName)) })
|
174
|
-
}
|
175
|
-
|
176
|
-
for await (let data of source) {
|
177
|
-
while (data.length > 0) {
|
178
|
-
if (data.length <= maxMsgSize) {
|
179
|
-
send({ id, type: Types.MESSAGE, data: data instanceof Uint8Array ? new Uint8ArrayList(data) : data })
|
180
|
-
break
|
181
|
-
}
|
182
|
-
data = data instanceof Uint8Array ? new Uint8ArrayList(data) : data
|
183
|
-
send({ id, type: Types.MESSAGE, data: data.sublist(0, maxMsgSize) })
|
184
|
-
data.consume(maxMsgSize)
|
185
|
-
}
|
186
|
-
}
|
187
|
-
} catch (err: any) {
|
188
|
-
if (err.type === 'aborted' && err.message === 'The operation was aborted') {
|
189
|
-
if (closeController.signal.aborted) {
|
190
|
-
return
|
191
|
-
}
|
192
|
-
|
193
|
-
if (resetController.signal.aborted) {
|
194
|
-
err.message = 'stream reset'
|
195
|
-
err.code = ERR_STREAM_RESET
|
196
|
-
}
|
197
|
-
|
198
|
-
if (abortController.signal.aborted) {
|
199
|
-
err.message = 'stream aborted'
|
200
|
-
err.code = ERR_STREAM_ABORT
|
201
|
-
}
|
202
|
-
}
|
203
|
-
|
204
|
-
// Send no more data if this stream was remotely reset
|
205
|
-
if (err.code === ERR_STREAM_RESET) {
|
206
|
-
log.trace('%s stream %s reset', type, name)
|
207
|
-
} else {
|
208
|
-
log.trace('%s stream %s error', type, name, err)
|
209
|
-
try {
|
210
|
-
send({ id, type: Types.RESET })
|
211
|
-
} catch (err) {
|
212
|
-
log.trace('%s stream %s error sending reset', type, name, err)
|
213
|
-
}
|
214
|
-
}
|
215
|
-
|
216
|
-
streamSource.end(err)
|
217
|
-
onSinkEnd(err)
|
218
|
-
return
|
219
|
-
} finally {
|
220
|
-
signal.clear()
|
221
|
-
}
|
222
|
-
|
223
|
-
try {
|
224
|
-
send({ id, type: Types.CLOSE })
|
225
|
-
} catch (err) {
|
226
|
-
log.trace('%s stream %s error sending close', type, name, err)
|
227
|
-
}
|
228
|
-
|
229
|
-
onSinkEnd()
|
230
|
-
},
|
231
|
-
|
232
|
-
source: streamSource,
|
233
|
-
|
234
|
-
sourcePush: (data: Uint8ArrayList) => {
|
235
|
-
streamSource.push(data)
|
236
|
-
},
|
237
|
-
|
238
|
-
sourceReadableLength () {
|
239
|
-
return streamSource.readableLength
|
240
|
-
},
|
241
|
-
|
242
|
-
stat: {
|
243
|
-
direction: type === 'initiator' ? 'outbound' : 'inbound',
|
244
|
-
timeline
|
245
|
-
},
|
46
|
+
sendReset (): void {
|
47
|
+
this.send({ id: this.streamId, type: this.types.RESET })
|
48
|
+
}
|
246
49
|
|
247
|
-
|
50
|
+
sendCloseWrite (): void {
|
51
|
+
this.send({ id: this.streamId, type: this.types.CLOSE })
|
52
|
+
}
|
248
53
|
|
249
|
-
|
54
|
+
sendCloseRead (): void {
|
55
|
+
// mplex does not support close read, only close write
|
250
56
|
}
|
57
|
+
}
|
58
|
+
|
59
|
+
export function createStream (options: Options): MplexStream {
|
60
|
+
const { id, name, send, onEnd, type = 'initiator', maxMsgSize = MAX_MSG_SIZE } = options
|
251
61
|
|
252
|
-
return
|
62
|
+
return new MplexStream({
|
63
|
+
id: type === 'initiator' ? (`i${id}`) : `r${id}`,
|
64
|
+
streamId: id,
|
65
|
+
name: `${name == null ? id : name}`,
|
66
|
+
direction: type === 'initiator' ? 'outbound' : 'inbound',
|
67
|
+
maxDataSize: maxMsgSize,
|
68
|
+
onEnd,
|
69
|
+
send
|
70
|
+
})
|
253
71
|
}
|