@libp2p/interface-compliance-tests 1.1.6 → 1.1.10
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/mocks/connection.d.ts +13 -2
- package/dist/src/mocks/connection.d.ts.map +1 -1
- package/dist/src/mocks/connection.js +56 -24
- package/dist/src/mocks/connection.js.map +1 -1
- package/dist/src/mocks/multiaddr-connection.d.ts +2 -1
- package/dist/src/mocks/multiaddr-connection.d.ts.map +1 -1
- package/dist/src/mocks/multiaddr-connection.js +2 -2
- package/dist/src/mocks/multiaddr-connection.js.map +1 -1
- package/dist/src/mocks/muxer.d.ts +2 -2
- package/dist/src/mocks/muxer.d.ts.map +1 -1
- package/dist/src/mocks/muxer.js +175 -26
- package/dist/src/mocks/muxer.js.map +1 -1
- package/dist/src/mocks/registrar.d.ts +11 -2
- package/dist/src/mocks/registrar.d.ts.map +1 -1
- package/dist/src/mocks/registrar.js +47 -5
- package/dist/src/mocks/registrar.js.map +1 -1
- package/dist/src/mocks/upgrader.d.ts.map +1 -1
- package/dist/src/mocks/upgrader.js +8 -4
- package/dist/src/mocks/upgrader.js.map +1 -1
- package/dist/src/pubsub/api.d.ts +3 -2
- package/dist/src/pubsub/api.d.ts.map +1 -1
- package/dist/src/pubsub/api.js +23 -13
- package/dist/src/pubsub/api.js.map +1 -1
- package/dist/src/pubsub/connection-handlers.d.ts +3 -2
- package/dist/src/pubsub/connection-handlers.d.ts.map +1 -1
- package/dist/src/pubsub/connection-handlers.js +165 -69
- package/dist/src/pubsub/connection-handlers.js.map +1 -1
- package/dist/src/pubsub/emit-self.d.ts +3 -2
- package/dist/src/pubsub/emit-self.d.ts.map +1 -1
- package/dist/src/pubsub/emit-self.js +15 -4
- package/dist/src/pubsub/emit-self.js.map +1 -1
- package/dist/src/pubsub/index.d.ts +6 -3
- package/dist/src/pubsub/index.d.ts.map +1 -1
- package/dist/src/pubsub/index.js.map +1 -1
- package/dist/src/pubsub/messages.d.ts +3 -2
- package/dist/src/pubsub/messages.d.ts.map +1 -1
- package/dist/src/pubsub/messages.js +42 -39
- package/dist/src/pubsub/messages.js.map +1 -1
- package/dist/src/pubsub/multiple-nodes.d.ts +3 -2
- package/dist/src/pubsub/multiple-nodes.d.ts.map +1 -1
- package/dist/src/pubsub/multiple-nodes.js +163 -65
- package/dist/src/pubsub/multiple-nodes.js.map +1 -1
- package/dist/src/pubsub/two-nodes.d.ts +3 -2
- package/dist/src/pubsub/two-nodes.d.ts.map +1 -1
- package/dist/src/pubsub/two-nodes.js +80 -38
- package/dist/src/pubsub/two-nodes.js.map +1 -1
- package/dist/src/stream-muxer/base-test.js +1 -1
- package/dist/src/stream-muxer/base-test.js.map +1 -1
- package/dist/src/stream-muxer/close-test.d.ts.map +1 -1
- package/dist/src/stream-muxer/close-test.js +12 -10
- package/dist/src/stream-muxer/close-test.js.map +1 -1
- package/dist/src/transport/dial-test.d.ts.map +1 -1
- package/dist/src/transport/dial-test.js +2 -1
- package/dist/src/transport/dial-test.js.map +1 -1
- package/dist/src/transport/filter-test.js +1 -1
- package/dist/src/transport/filter-test.js.map +1 -1
- package/dist/src/transport/listen-test.d.ts.map +1 -1
- package/dist/src/transport/listen-test.js +2 -1
- package/dist/src/transport/listen-test.js.map +1 -1
- package/dist/src/utils/is-valid-tick.d.ts +6 -0
- package/dist/src/utils/is-valid-tick.d.ts.map +1 -0
- package/dist/src/utils/is-valid-tick.js +15 -0
- package/dist/src/utils/is-valid-tick.js.map +1 -0
- package/package.json +7 -5
- package/src/mocks/connection.ts +80 -24
- package/src/mocks/multiaddr-connection.ts +3 -2
- package/src/mocks/muxer.ts +230 -28
- package/src/mocks/registrar.ts +65 -7
- package/src/mocks/upgrader.ts +8 -5
- package/src/pubsub/api.ts +29 -15
- package/src/pubsub/connection-handlers.ts +186 -75
- package/src/pubsub/emit-self.ts +19 -7
- package/src/pubsub/index.ts +6 -3
- package/src/pubsub/messages.ts +59 -44
- package/src/pubsub/multiple-nodes.ts +189 -76
- package/src/pubsub/two-nodes.ts +94 -46
- package/src/stream-muxer/base-test.ts +1 -1
- package/src/stream-muxer/close-test.ts +13 -12
- package/src/transport/dial-test.ts +2 -1
- package/src/transport/filter-test.ts +1 -1
- package/src/transport/listen-test.ts +2 -1
- package/src/utils/is-valid-tick.ts +18 -0
- package/dist/src/pubsub/utils.d.ts +0 -3
- package/dist/src/pubsub/utils.d.ts.map +0 -1
- package/dist/src/pubsub/utils.js +0 -11
- package/dist/src/pubsub/utils.js.map +0 -1
- package/dist/src/transport/utils/index.d.ts +0 -15
- package/dist/src/transport/utils/index.d.ts.map +0 -1
- package/dist/src/transport/utils/index.js +0 -137
- package/dist/src/transport/utils/index.js.map +0 -1
- package/src/pubsub/utils.ts +0 -13
- package/src/transport/utils/index.ts +0 -172
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/interface-compliance-tests",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.10",
|
|
4
4
|
"description": "Compliance tests for JS libp2p interfaces",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interface-compliance-tests#readme",
|
|
@@ -56,6 +56,10 @@
|
|
|
56
56
|
"import": "./dist/src/crypto/index.js",
|
|
57
57
|
"types": "./dist/src/crypto/index.d.ts"
|
|
58
58
|
},
|
|
59
|
+
"./mocks": {
|
|
60
|
+
"import": "./dist/src/mocks/index.js",
|
|
61
|
+
"types": "./dist/src/mocks/index.d.ts"
|
|
62
|
+
},
|
|
59
63
|
"./peer-discovery": {
|
|
60
64
|
"import": "./dist/src/peer-discovery/index.js",
|
|
61
65
|
"types": "./dist/src/peer-discovery/index.d.ts"
|
|
@@ -88,10 +92,6 @@
|
|
|
88
92
|
"import": "./dist/src/transport/utils/index.js",
|
|
89
93
|
"types": "./dist/src/transport/utils/index.d.ts"
|
|
90
94
|
},
|
|
91
|
-
"./mocks": {
|
|
92
|
-
"import": "./dist/src/mocks/index.js",
|
|
93
|
-
"types": "./dist/src/mocks/index.d.ts"
|
|
94
|
-
},
|
|
95
95
|
"./utils/peers": {
|
|
96
96
|
"import": "./dist/src/utils/peers.js",
|
|
97
97
|
"types": "./dist/src/utils/peers.d.ts"
|
|
@@ -200,6 +200,8 @@
|
|
|
200
200
|
"dependencies": {
|
|
201
201
|
"@libp2p/crypto": "^0.22.2",
|
|
202
202
|
"@libp2p/interfaces": "^1.0.0",
|
|
203
|
+
"@libp2p/logger": "^1.0.3",
|
|
204
|
+
"@libp2p/multistream-select": "^1.0.0",
|
|
203
205
|
"@libp2p/peer-id": "^1.0.0",
|
|
204
206
|
"@libp2p/peer-id-factory": "^1.0.0",
|
|
205
207
|
"@libp2p/pubsub": "^1.1.0",
|
package/src/mocks/connection.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { peerIdFromString } from '@libp2p/peer-id'
|
|
2
|
-
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
|
|
3
2
|
import { pipe } from 'it-pipe'
|
|
4
3
|
import { duplexPair } from 'it-pair/duplex'
|
|
5
4
|
import type { MultiaddrConnection } from '@libp2p/interfaces/transport'
|
|
@@ -7,20 +6,68 @@ import type { Connection, Stream, Metadata, ProtocolStream } from '@libp2p/inter
|
|
|
7
6
|
import type { Muxer } from '@libp2p/interfaces/stream-muxer'
|
|
8
7
|
import type { Duplex } from 'it-stream-types'
|
|
9
8
|
import { mockMuxer } from './muxer.js'
|
|
9
|
+
import type { PeerId } from '@libp2p/interfaces/src/peer-id'
|
|
10
|
+
import { mockMultiaddrConnection } from './multiaddr-connection.js'
|
|
11
|
+
import type { Registrar } from '@libp2p/interfaces/registrar'
|
|
12
|
+
import { mockRegistrar } from './registrar.js'
|
|
13
|
+
import { Dialer, Listener } from '@libp2p/multistream-select'
|
|
14
|
+
import { logger } from '@libp2p/logger'
|
|
15
|
+
import { CustomEvent } from '@libp2p/interfaces'
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
const log = logger('libp2p:mock-connection')
|
|
18
|
+
|
|
19
|
+
export interface MockConnectionOptions {
|
|
20
|
+
direction?: 'inbound' | 'outbound'
|
|
21
|
+
muxer?: Muxer
|
|
22
|
+
registrar?: Registrar
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectionOptions = {}): Connection {
|
|
12
26
|
const remoteAddr = maConn.remoteAddr
|
|
13
27
|
const remotePeerIdStr = remoteAddr.getPeerId()
|
|
14
|
-
|
|
28
|
+
|
|
29
|
+
if (remotePeerIdStr == null) {
|
|
30
|
+
throw new Error('Remote multiaddr must contain a peer id')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const remotePeer = peerIdFromString(remotePeerIdStr)
|
|
15
34
|
const registry = new Map()
|
|
16
35
|
const streams: Stream[] = []
|
|
17
|
-
|
|
36
|
+
const direction = opts.direction ?? 'inbound'
|
|
37
|
+
const registrar = opts.registrar ?? mockRegistrar()
|
|
38
|
+
|
|
39
|
+
const muxer = opts.muxer ?? mockMuxer({
|
|
40
|
+
onStream: (muxedStream) => {
|
|
41
|
+
const mss = new Listener(muxedStream)
|
|
42
|
+
try {
|
|
43
|
+
mss.handle(registrar.getProtocols())
|
|
44
|
+
.then(({ stream, protocol }) => {
|
|
45
|
+
log('%s: incoming stream opened on %s', direction, protocol)
|
|
46
|
+
muxedStream = { ...muxedStream, ...stream }
|
|
47
|
+
|
|
48
|
+
connection.addStream(muxedStream, { protocol, metadata: {} })
|
|
49
|
+
const handler = registrar.getHandler(protocol)
|
|
50
|
+
|
|
51
|
+
handler(new CustomEvent('incomingStream', {
|
|
52
|
+
detail: { connection, stream: muxedStream, protocol }
|
|
53
|
+
}))
|
|
54
|
+
}).catch(err => {
|
|
55
|
+
log.error(err)
|
|
56
|
+
})
|
|
57
|
+
} catch (err: any) {
|
|
58
|
+
log.error(err)
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
onStreamEnd: (stream) => {
|
|
62
|
+
connection.removeStream(stream.id)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
18
65
|
|
|
19
66
|
void pipe(
|
|
20
67
|
maConn, muxer, maConn
|
|
21
68
|
)
|
|
22
69
|
|
|
23
|
-
|
|
70
|
+
const connection: Connection = {
|
|
24
71
|
id: 'mock-connection',
|
|
25
72
|
remoteAddr,
|
|
26
73
|
remotePeer,
|
|
@@ -43,11 +90,17 @@ export async function mockConnection (maConn: MultiaddrConnection, direction: 'i
|
|
|
43
90
|
throw new Error('protocols must have a length')
|
|
44
91
|
}
|
|
45
92
|
|
|
46
|
-
const id = `${
|
|
93
|
+
const id = `${Math.random()}`
|
|
47
94
|
const stream: Stream = muxer.newStream(id)
|
|
95
|
+
const mss = new Dialer(stream)
|
|
96
|
+
const result = await mss.select(protocols)
|
|
97
|
+
|
|
48
98
|
const streamData: ProtocolStream = {
|
|
49
|
-
protocol:
|
|
50
|
-
stream
|
|
99
|
+
protocol: result.protocol,
|
|
100
|
+
stream: {
|
|
101
|
+
...stream,
|
|
102
|
+
...result.stream
|
|
103
|
+
}
|
|
51
104
|
}
|
|
52
105
|
|
|
53
106
|
registry.set(id, streamData)
|
|
@@ -64,6 +117,8 @@ export async function mockConnection (maConn: MultiaddrConnection, direction: 'i
|
|
|
64
117
|
await maConn.close()
|
|
65
118
|
}
|
|
66
119
|
}
|
|
120
|
+
|
|
121
|
+
return connection
|
|
67
122
|
}
|
|
68
123
|
|
|
69
124
|
export function mockStream (stream: Duplex<Uint8Array>): Stream {
|
|
@@ -79,23 +134,24 @@ export function mockStream (stream: Duplex<Uint8Array>): Stream {
|
|
|
79
134
|
}
|
|
80
135
|
}
|
|
81
136
|
|
|
82
|
-
export
|
|
83
|
-
|
|
137
|
+
export interface Peer {
|
|
138
|
+
peerId: PeerId
|
|
139
|
+
registrar: Registrar
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function connectionPair (a: Peer, b: Peer): [ Connection, Connection ] {
|
|
143
|
+
const [peerBtoPeerA, peerAtoPeerB] = duplexPair<Uint8Array>()
|
|
84
144
|
|
|
85
145
|
return [
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
stream: mockStream(d1),
|
|
97
|
-
protocol: multicodecs[0]
|
|
98
|
-
})
|
|
99
|
-
}
|
|
146
|
+
mockConnection(
|
|
147
|
+
mockMultiaddrConnection(peerAtoPeerB, b.peerId), {
|
|
148
|
+
registrar: a.registrar
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
mockConnection(
|
|
152
|
+
mockMultiaddrConnection(peerBtoPeerA, a.peerId), {
|
|
153
|
+
registrar: b.registrar
|
|
154
|
+
}
|
|
155
|
+
)
|
|
100
156
|
]
|
|
101
157
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Multiaddr } from '@multiformats/multiaddr'
|
|
2
2
|
import type { MultiaddrConnection } from '@libp2p/interfaces/transport'
|
|
3
3
|
import type { Duplex } from 'it-stream-types'
|
|
4
|
+
import type { PeerId } from '@libp2p/interfaces/peer-id'
|
|
4
5
|
|
|
5
|
-
export function mockMultiaddrConnection (source: Duplex<Uint8Array> & Partial<MultiaddrConnection
|
|
6
|
+
export function mockMultiaddrConnection (source: Duplex<Uint8Array> & Partial<MultiaddrConnection>, peerId: PeerId): MultiaddrConnection {
|
|
6
7
|
const maConn: MultiaddrConnection = {
|
|
7
8
|
async close () {
|
|
8
9
|
|
|
@@ -10,7 +11,7 @@ export function mockMultiaddrConnection (source: Duplex<Uint8Array> & Partial<Mu
|
|
|
10
11
|
timeline: {
|
|
11
12
|
open: Date.now()
|
|
12
13
|
},
|
|
13
|
-
remoteAddr: new Multiaddr(
|
|
14
|
+
remoteAddr: new Multiaddr(`/ip4/127.0.0.1/tcp/4001/p2p/${peerId.toString()}`),
|
|
14
15
|
...source
|
|
15
16
|
}
|
|
16
17
|
|
package/src/mocks/muxer.ts
CHANGED
|
@@ -1,41 +1,243 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { Pushable, pushable } from 'it-pushable'
|
|
2
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
3
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
4
|
+
import { abortableSource } from 'abortable-iterator'
|
|
4
5
|
import type { Stream } from '@libp2p/interfaces/connection'
|
|
5
|
-
import type { Muxer } from '@libp2p/interfaces/stream-muxer'
|
|
6
|
+
import type { Muxer, MuxerOptions } from '@libp2p/interfaces/stream-muxer'
|
|
7
|
+
import type { Source } from 'it-stream-types'
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
interface DataMessage {
|
|
10
|
+
id: string
|
|
11
|
+
type: 'data'
|
|
12
|
+
chunk: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ResetMessage {
|
|
16
|
+
id: string
|
|
17
|
+
type: 'reset'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface CloseMessage {
|
|
21
|
+
id: string
|
|
22
|
+
type: 'close'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type StreamMessage = DataMessage | ResetMessage | CloseMessage
|
|
26
|
+
|
|
27
|
+
class MuxedStream {
|
|
28
|
+
public id: string
|
|
29
|
+
public input: Pushable<Uint8Array>
|
|
30
|
+
public stream: Stream
|
|
31
|
+
|
|
32
|
+
private sourceClosed: boolean
|
|
33
|
+
private sinkClosed: boolean
|
|
34
|
+
private readonly controller: AbortController
|
|
35
|
+
private readonly onEnd: () => void
|
|
36
|
+
|
|
37
|
+
constructor (opts: { id: string, push: Pushable<StreamMessage>, onEnd: () => void }) {
|
|
38
|
+
const { id, push, onEnd } = opts
|
|
39
|
+
|
|
40
|
+
this.id = id
|
|
41
|
+
this.controller = new AbortController()
|
|
42
|
+
this.onEnd = onEnd
|
|
43
|
+
this.sourceClosed = false
|
|
44
|
+
this.sinkClosed = false
|
|
45
|
+
this.input = pushable<Uint8Array>({
|
|
46
|
+
onEnd: () => {
|
|
47
|
+
this.sourceClosed = true
|
|
48
|
+
this.maybeEndStream()
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
this.stream = {
|
|
52
|
+
id,
|
|
53
|
+
sink: async (source) => {
|
|
54
|
+
source = abortableSource(source, this.controller.signal)
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
for await (const chunk of source) {
|
|
58
|
+
const dataMsg: DataMessage = {
|
|
59
|
+
id,
|
|
60
|
+
type: 'data',
|
|
61
|
+
chunk: uint8ArrayToString(chunk, 'base64')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
push.push(dataMsg)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const closeMsg: CloseMessage = {
|
|
68
|
+
id,
|
|
69
|
+
type: 'close'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
push.push(closeMsg)
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (!this.controller.signal.aborted) {
|
|
75
|
+
throw err
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.closeSink()
|
|
80
|
+
},
|
|
81
|
+
source: this.input,
|
|
82
|
+
close: () => {
|
|
83
|
+
const closeMsg: CloseMessage = {
|
|
84
|
+
id,
|
|
85
|
+
type: 'close'
|
|
86
|
+
}
|
|
87
|
+
push.push(closeMsg)
|
|
88
|
+
|
|
89
|
+
this.closeSink()
|
|
90
|
+
this.closeSource()
|
|
91
|
+
},
|
|
92
|
+
abort: () => {
|
|
93
|
+
const resetMsg: ResetMessage = {
|
|
94
|
+
id,
|
|
95
|
+
type: 'reset'
|
|
96
|
+
}
|
|
97
|
+
push.push(resetMsg)
|
|
98
|
+
|
|
99
|
+
this.closeSink()
|
|
100
|
+
this.closeSource()
|
|
101
|
+
},
|
|
102
|
+
reset: () => {
|
|
103
|
+
const resetMsg: ResetMessage = {
|
|
104
|
+
id,
|
|
105
|
+
type: 'reset'
|
|
106
|
+
}
|
|
107
|
+
push.push(resetMsg)
|
|
108
|
+
|
|
109
|
+
this.closeSink()
|
|
110
|
+
this.closeSource()
|
|
111
|
+
},
|
|
112
|
+
timeline: {
|
|
113
|
+
open: Date.now()
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
maybeEndStream () {
|
|
119
|
+
if (this.stream.timeline.close != null) {
|
|
120
|
+
// already ended
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (this.sinkClosed && this.sourceClosed) {
|
|
125
|
+
this.stream.timeline.close = Date.now()
|
|
126
|
+
this.onEnd()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
closeSource () {
|
|
131
|
+
this.sourceClosed = true
|
|
132
|
+
this.input.end()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
closeSink () {
|
|
136
|
+
this.sinkClosed = true
|
|
137
|
+
this.controller.abort()
|
|
138
|
+
this.maybeEndStream()
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function mockMuxer (options?: MuxerOptions): Muxer {
|
|
8
143
|
let streamId = 0
|
|
9
|
-
|
|
10
|
-
|
|
144
|
+
const streams = new Map<string, MuxedStream>()
|
|
145
|
+
|
|
146
|
+
// process incoming messages from the other muxer
|
|
147
|
+
const muxerSource = pushable<Uint8Array>({
|
|
148
|
+
onEnd: () => {
|
|
149
|
+
for (const muxedStream of streams.values()) {
|
|
150
|
+
muxedStream.stream.close()
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// receives messages from all of the muxed streams
|
|
156
|
+
const push = pushable<StreamMessage>()
|
|
157
|
+
void Promise.resolve().then(async () => {
|
|
158
|
+
for await (const message of push) {
|
|
159
|
+
if (message.type === 'data') {
|
|
160
|
+
muxerSource.push(uint8ArrayFromString(JSON.stringify({
|
|
161
|
+
id: message.id,
|
|
162
|
+
type: message.type,
|
|
163
|
+
chunk: message.chunk
|
|
164
|
+
})))
|
|
165
|
+
} else {
|
|
166
|
+
muxerSource.push(uint8ArrayFromString(JSON.stringify({
|
|
167
|
+
id: message.id,
|
|
168
|
+
type: message.type
|
|
169
|
+
})))
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
function createStream (name?: string): MuxedStream {
|
|
175
|
+
const id = name ?? `${streamId++}`
|
|
176
|
+
|
|
177
|
+
const muxedStream: MuxedStream = new MuxedStream({
|
|
178
|
+
id,
|
|
179
|
+
push,
|
|
180
|
+
onEnd: () => {
|
|
181
|
+
streams.delete(id)
|
|
182
|
+
|
|
183
|
+
if (options?.onStreamEnd != null) {
|
|
184
|
+
options?.onStreamEnd(muxedStream.stream)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
return muxedStream
|
|
190
|
+
}
|
|
11
191
|
|
|
12
192
|
const muxer: Muxer = {
|
|
13
|
-
|
|
14
|
-
sink
|
|
15
|
-
await
|
|
193
|
+
// receive incoming messages
|
|
194
|
+
async sink (source: Source<Uint8Array>) {
|
|
195
|
+
for await (const buf of source) {
|
|
196
|
+
const message: StreamMessage = JSON.parse(uint8ArrayToString(buf))
|
|
197
|
+
let muxedStream = streams.get(message.id)
|
|
198
|
+
|
|
199
|
+
if (muxedStream == null) {
|
|
200
|
+
muxedStream = createStream(message.id)
|
|
201
|
+
streams.set(muxedStream.stream.id, muxedStream)
|
|
202
|
+
|
|
203
|
+
if (options?.onStream != null) {
|
|
204
|
+
options.onStream(muxedStream.stream)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (message.type === 'data') {
|
|
209
|
+
muxedStream.input.push(uint8ArrayFromString(message.chunk, 'base64'))
|
|
210
|
+
} else if (message.type === 'reset') {
|
|
211
|
+
muxedStream.closeSink()
|
|
212
|
+
muxedStream.closeSource()
|
|
213
|
+
} else if (message.type === 'close') {
|
|
214
|
+
muxedStream.closeSource()
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for (const muxedStream of streams.values()) {
|
|
219
|
+
muxedStream.stream.close()
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
muxerSource.end()
|
|
16
223
|
},
|
|
224
|
+
|
|
225
|
+
source: muxerSource,
|
|
226
|
+
|
|
17
227
|
get streams () {
|
|
18
|
-
return streams
|
|
228
|
+
return Array.from(streams.values()).map(({ stream }) => stream)
|
|
19
229
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
close: () => {
|
|
29
|
-
streams = streams.filter(s => s !== stream)
|
|
30
|
-
},
|
|
31
|
-
abort: () => {},
|
|
32
|
-
reset: () => {},
|
|
33
|
-
timeline: {
|
|
34
|
-
open: 0
|
|
35
|
-
}
|
|
230
|
+
|
|
231
|
+
newStream (name?: string) {
|
|
232
|
+
const storedStream = createStream(name)
|
|
233
|
+
|
|
234
|
+
streams.set(storedStream.stream.id, storedStream)
|
|
235
|
+
|
|
236
|
+
if (options?.onStream != null) {
|
|
237
|
+
options.onStream(storedStream.stream)
|
|
36
238
|
}
|
|
37
239
|
|
|
38
|
-
return stream
|
|
240
|
+
return storedStream.stream
|
|
39
241
|
}
|
|
40
242
|
}
|
|
41
243
|
|
package/src/mocks/registrar.ts
CHANGED
|
@@ -1,15 +1,41 @@
|
|
|
1
|
-
import type { Registrar, StreamHandler } from '@libp2p/interfaces/registrar'
|
|
1
|
+
import type { IncomingStreamData, Registrar, StreamHandler } from '@libp2p/interfaces/registrar'
|
|
2
|
+
import type { Connection } from '@libp2p/interfaces/src/connection'
|
|
3
|
+
import type { PeerId } from '@libp2p/interfaces/src/peer-id'
|
|
2
4
|
import type { Topology } from '@libp2p/interfaces/topology'
|
|
5
|
+
import { connectionPair } from './connection.js'
|
|
6
|
+
import { CustomEvent } from '@libp2p/interfaces'
|
|
3
7
|
|
|
4
8
|
export class MockRegistrar implements Registrar {
|
|
5
9
|
private readonly topologies: Map<string, { topology: Topology, protocols: string[] }> = new Map()
|
|
6
10
|
private readonly handlers: Map<string, { handler: StreamHandler, protocols: string[] }> = new Map()
|
|
7
11
|
|
|
12
|
+
getProtocols () {
|
|
13
|
+
const protocols = new Set<string>()
|
|
14
|
+
|
|
15
|
+
for (const topology of this.topologies.values()) {
|
|
16
|
+
topology.protocols.forEach(protocol => protocols.add(protocol))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
for (const handler of this.handlers.values()) {
|
|
20
|
+
handler.protocols.forEach(protocol => protocols.add(protocol))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return Array.from(protocols).sort()
|
|
24
|
+
}
|
|
25
|
+
|
|
8
26
|
async handle (protocols: string | string[], handler: StreamHandler) {
|
|
9
27
|
if (!Array.isArray(protocols)) {
|
|
10
28
|
protocols = [protocols]
|
|
11
29
|
}
|
|
12
30
|
|
|
31
|
+
for (const protocol of protocols) {
|
|
32
|
+
for (const { protocols } of this.handlers.values()) {
|
|
33
|
+
if (protocols.includes(protocol)) {
|
|
34
|
+
throw new Error(`Handler already registered for protocol ${protocol}`)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
13
39
|
const id = `handler-id-${Math.random()}`
|
|
14
40
|
|
|
15
41
|
this.handlers.set(id, {
|
|
@@ -24,16 +50,14 @@ export class MockRegistrar implements Registrar {
|
|
|
24
50
|
this.handlers.delete(id)
|
|
25
51
|
}
|
|
26
52
|
|
|
27
|
-
|
|
28
|
-
const output: StreamHandler[] = []
|
|
29
|
-
|
|
53
|
+
getHandler (protocol: string) {
|
|
30
54
|
for (const { handler, protocols } of this.handlers.values()) {
|
|
31
55
|
if (protocols.includes(protocol)) {
|
|
32
|
-
|
|
56
|
+
return handler
|
|
33
57
|
}
|
|
34
58
|
}
|
|
35
59
|
|
|
36
|
-
|
|
60
|
+
throw new Error(`No handler registered for protocol ${protocol}`)
|
|
37
61
|
}
|
|
38
62
|
|
|
39
63
|
register (protocols: string | string[], topology: Topology) {
|
|
@@ -68,10 +92,44 @@ export class MockRegistrar implements Registrar {
|
|
|
68
92
|
}
|
|
69
93
|
}
|
|
70
94
|
|
|
71
|
-
|
|
95
|
+
if (output.length > 0) {
|
|
96
|
+
return output
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
throw new Error(`No topologies registered for protocol ${protocol}`)
|
|
72
100
|
}
|
|
73
101
|
}
|
|
74
102
|
|
|
75
103
|
export function mockRegistrar () {
|
|
76
104
|
return new MockRegistrar()
|
|
77
105
|
}
|
|
106
|
+
|
|
107
|
+
export async function mockIncomingStreamEvent (protocol: string, conn: Connection, remotePeer: PeerId): Promise<CustomEvent<IncomingStreamData>> {
|
|
108
|
+
// @ts-expect-error incomplete implementation
|
|
109
|
+
return new CustomEvent('incomingStream', {
|
|
110
|
+
detail: {
|
|
111
|
+
...await conn.newStream([protocol]),
|
|
112
|
+
connection: {
|
|
113
|
+
remotePeer
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface Peer {
|
|
120
|
+
peerId: PeerId
|
|
121
|
+
registrar: Registrar
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function connectPeers (protocol: string, a: Peer, b: Peer) {
|
|
125
|
+
// Notify peers of connection
|
|
126
|
+
const [aToB, bToA] = connectionPair(a, b)
|
|
127
|
+
|
|
128
|
+
for (const topology of a.registrar.getTopologies(protocol)) {
|
|
129
|
+
await topology.onConnect(b.peerId, aToB)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (const topology of b.registrar.getTopologies(protocol)) {
|
|
133
|
+
await topology.onConnect(a.peerId, bToA)
|
|
134
|
+
}
|
|
135
|
+
}
|
package/src/mocks/upgrader.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { expect } from 'aegir/utils/chai.js'
|
|
2
|
-
import { mockMuxer } from './muxer.js'
|
|
3
2
|
import { mockConnection } from './connection.js'
|
|
4
3
|
import type { Upgrader, MultiaddrConnection } from '@libp2p/interfaces/transport'
|
|
5
4
|
import type { Muxer } from '@libp2p/interfaces/stream-muxer'
|
|
@@ -16,16 +15,20 @@ export function mockUpgrader (options: MockUpgraderOptions = {}) {
|
|
|
16
15
|
return multiaddrConnection
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
const muxer = options.muxer ?? mockMuxer()
|
|
20
|
-
|
|
21
18
|
const upgrader: Upgrader = {
|
|
22
19
|
async upgradeOutbound (multiaddrConnection) {
|
|
23
20
|
ensureProps(multiaddrConnection)
|
|
24
|
-
return
|
|
21
|
+
return mockConnection(multiaddrConnection, {
|
|
22
|
+
direction: 'outbound',
|
|
23
|
+
muxer: options.muxer
|
|
24
|
+
})
|
|
25
25
|
},
|
|
26
26
|
async upgradeInbound (multiaddrConnection) {
|
|
27
27
|
ensureProps(multiaddrConnection)
|
|
28
|
-
return
|
|
28
|
+
return mockConnection(multiaddrConnection, {
|
|
29
|
+
direction: 'inbound',
|
|
30
|
+
muxer: options.muxer
|
|
31
|
+
})
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
|