@libp2p/interface-compliance-tests 2.0.1 → 3.0.0

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 (192) hide show
  1. package/README.md +19 -11
  2. package/dist/src/{utils/is-valid-tick.d.ts → is-valid-tick.d.ts} +0 -0
  3. package/dist/src/is-valid-tick.d.ts.map +1 -0
  4. package/dist/src/{utils/is-valid-tick.js → is-valid-tick.js} +0 -0
  5. package/dist/src/is-valid-tick.js.map +1 -0
  6. package/dist/src/{utils/peers.d.ts → peers.d.ts} +0 -0
  7. package/dist/src/peers.d.ts.map +1 -0
  8. package/dist/src/{utils/peers.js → peers.js} +0 -0
  9. package/dist/src/peers.js.map +1 -0
  10. package/package.json +11 -88
  11. package/src/{utils/is-valid-tick.ts → is-valid-tick.ts} +0 -0
  12. package/src/{utils/peers.ts → peers.ts} +0 -0
  13. package/dist/src/connection/connection.d.ts +0 -5
  14. package/dist/src/connection/connection.d.ts.map +0 -1
  15. package/dist/src/connection/connection.js +0 -146
  16. package/dist/src/connection/connection.js.map +0 -1
  17. package/dist/src/connection/index.d.ts +0 -5
  18. package/dist/src/connection/index.d.ts.map +0 -1
  19. package/dist/src/connection/index.js +0 -5
  20. package/dist/src/connection/index.js.map +0 -1
  21. package/dist/src/connection-encrypter/index.d.ts +0 -5
  22. package/dist/src/connection-encrypter/index.d.ts.map +0 -1
  23. package/dist/src/connection-encrypter/index.js +0 -77
  24. package/dist/src/connection-encrypter/index.js.map +0 -1
  25. package/dist/src/connection-encrypter/utils/index.d.ts +0 -3
  26. package/dist/src/connection-encrypter/utils/index.d.ts.map +0 -1
  27. package/dist/src/connection-encrypter/utils/index.js +0 -18
  28. package/dist/src/connection-encrypter/utils/index.js.map +0 -1
  29. package/dist/src/mocks/connection-encrypter.d.ts +0 -3
  30. package/dist/src/mocks/connection-encrypter.d.ts.map +0 -1
  31. package/dist/src/mocks/connection-encrypter.js +0 -93
  32. package/dist/src/mocks/connection-encrypter.js.map +0 -1
  33. package/dist/src/mocks/connection-gater.d.ts +0 -12
  34. package/dist/src/mocks/connection-gater.d.ts.map +0 -1
  35. package/dist/src/mocks/connection-gater.js +0 -14
  36. package/dist/src/mocks/connection-gater.js.map +0 -1
  37. package/dist/src/mocks/connection-manager.d.ts +0 -28
  38. package/dist/src/mocks/connection-manager.d.ts.map +0 -1
  39. package/dist/src/mocks/connection-manager.js +0 -107
  40. package/dist/src/mocks/connection-manager.js.map +0 -1
  41. package/dist/src/mocks/connection.d.ts +0 -18
  42. package/dist/src/mocks/connection.d.ts.map +0 -1
  43. package/dist/src/mocks/connection.js +0 -138
  44. package/dist/src/mocks/connection.js.map +0 -1
  45. package/dist/src/mocks/duplex.d.ts +0 -3
  46. package/dist/src/mocks/duplex.d.ts.map +0 -1
  47. package/dist/src/mocks/duplex.js +0 -7
  48. package/dist/src/mocks/duplex.js.map +0 -1
  49. package/dist/src/mocks/index.d.ts +0 -10
  50. package/dist/src/mocks/index.d.ts.map +0 -1
  51. package/dist/src/mocks/index.js +0 -9
  52. package/dist/src/mocks/index.js.map +0 -1
  53. package/dist/src/mocks/multiaddr-connection.d.ts +0 -17
  54. package/dist/src/mocks/multiaddr-connection.d.ts.map +0 -1
  55. package/dist/src/mocks/multiaddr-connection.js +0 -51
  56. package/dist/src/mocks/multiaddr-connection.js.map +0 -1
  57. package/dist/src/mocks/muxer.d.ts +0 -9
  58. package/dist/src/mocks/muxer.d.ts.map +0 -1
  59. package/dist/src/mocks/muxer.js +0 -277
  60. package/dist/src/mocks/muxer.js.map +0 -1
  61. package/dist/src/mocks/registrar.d.ts +0 -18
  62. package/dist/src/mocks/registrar.d.ts.map +0 -1
  63. package/dist/src/mocks/registrar.js +0 -73
  64. package/dist/src/mocks/registrar.js.map +0 -1
  65. package/dist/src/mocks/upgrader.d.ts +0 -15
  66. package/dist/src/mocks/upgrader.d.ts.map +0 -1
  67. package/dist/src/mocks/upgrader.js +0 -33
  68. package/dist/src/mocks/upgrader.js.map +0 -1
  69. package/dist/src/peer-discovery/index.d.ts +0 -6
  70. package/dist/src/peer-discovery/index.d.ts.map +0 -1
  71. package/dist/src/peer-discovery/index.js +0 -64
  72. package/dist/src/peer-discovery/index.js.map +0 -1
  73. package/dist/src/pubsub/api.d.ts +0 -6
  74. package/dist/src/pubsub/api.d.ts.map +0 -1
  75. package/dist/src/pubsub/api.js +0 -87
  76. package/dist/src/pubsub/api.js.map +0 -1
  77. package/dist/src/pubsub/connection-handlers.d.ts +0 -6
  78. package/dist/src/pubsub/connection-handlers.d.ts.map +0 -1
  79. package/dist/src/pubsub/connection-handlers.js +0 -329
  80. package/dist/src/pubsub/connection-handlers.js.map +0 -1
  81. package/dist/src/pubsub/emit-self.d.ts +0 -6
  82. package/dist/src/pubsub/emit-self.d.ts.map +0 -1
  83. package/dist/src/pubsub/emit-self.js +0 -86
  84. package/dist/src/pubsub/emit-self.js.map +0 -1
  85. package/dist/src/pubsub/index.d.ts +0 -10
  86. package/dist/src/pubsub/index.d.ts.map +0 -1
  87. package/dist/src/pubsub/index.js +0 -17
  88. package/dist/src/pubsub/index.js.map +0 -1
  89. package/dist/src/pubsub/messages.d.ts +0 -6
  90. package/dist/src/pubsub/messages.d.ts.map +0 -1
  91. package/dist/src/pubsub/messages.js +0 -46
  92. package/dist/src/pubsub/messages.js.map +0 -1
  93. package/dist/src/pubsub/multiple-nodes.d.ts +0 -6
  94. package/dist/src/pubsub/multiple-nodes.d.ts.map +0 -1
  95. package/dist/src/pubsub/multiple-nodes.js +0 -350
  96. package/dist/src/pubsub/multiple-nodes.js.map +0 -1
  97. package/dist/src/pubsub/two-nodes.d.ts +0 -6
  98. package/dist/src/pubsub/two-nodes.d.ts.map +0 -1
  99. package/dist/src/pubsub/two-nodes.js +0 -185
  100. package/dist/src/pubsub/two-nodes.js.map +0 -1
  101. package/dist/src/pubsub/utils.d.ts +0 -6
  102. package/dist/src/pubsub/utils.d.ts.map +0 -1
  103. package/dist/src/pubsub/utils.js +0 -22
  104. package/dist/src/pubsub/utils.js.map +0 -1
  105. package/dist/src/record/index.d.ts +0 -5
  106. package/dist/src/record/index.d.ts.map +0 -1
  107. package/dist/src/record/index.js +0 -25
  108. package/dist/src/record/index.js.map +0 -1
  109. package/dist/src/stream-muxer/base-test.d.ts +0 -5
  110. package/dist/src/stream-muxer/base-test.d.ts.map +0 -1
  111. package/dist/src/stream-muxer/base-test.js +0 -147
  112. package/dist/src/stream-muxer/base-test.js.map +0 -1
  113. package/dist/src/stream-muxer/close-test.d.ts +0 -5
  114. package/dist/src/stream-muxer/close-test.d.ts.map +0 -1
  115. package/dist/src/stream-muxer/close-test.js +0 -180
  116. package/dist/src/stream-muxer/close-test.js.map +0 -1
  117. package/dist/src/stream-muxer/index.d.ts +0 -5
  118. package/dist/src/stream-muxer/index.d.ts.map +0 -1
  119. package/dist/src/stream-muxer/index.js +0 -13
  120. package/dist/src/stream-muxer/index.js.map +0 -1
  121. package/dist/src/stream-muxer/mega-stress-test.d.ts +0 -5
  122. package/dist/src/stream-muxer/mega-stress-test.d.ts.map +0 -1
  123. package/dist/src/stream-muxer/mega-stress-test.js +0 -12
  124. package/dist/src/stream-muxer/mega-stress-test.js.map +0 -1
  125. package/dist/src/stream-muxer/spawner.d.ts +0 -4
  126. package/dist/src/stream-muxer/spawner.d.ts.map +0 -1
  127. package/dist/src/stream-muxer/spawner.js +0 -32
  128. package/dist/src/stream-muxer/spawner.js.map +0 -1
  129. package/dist/src/stream-muxer/stress-test.d.ts +0 -5
  130. package/dist/src/stream-muxer/stress-test.d.ts.map +0 -1
  131. package/dist/src/stream-muxer/stress-test.js +0 -26
  132. package/dist/src/stream-muxer/stress-test.js.map +0 -1
  133. package/dist/src/topology/topology.d.ts +0 -5
  134. package/dist/src/topology/topology.d.ts.map +0 -1
  135. package/dist/src/topology/topology.js +0 -20
  136. package/dist/src/topology/topology.js.map +0 -1
  137. package/dist/src/transport/dial-test.d.ts +0 -5
  138. package/dist/src/transport/dial-test.d.ts.map +0 -1
  139. package/dist/src/transport/dial-test.js +0 -97
  140. package/dist/src/transport/dial-test.js.map +0 -1
  141. package/dist/src/transport/filter-test.d.ts +0 -5
  142. package/dist/src/transport/filter-test.d.ts.map +0 -1
  143. package/dist/src/transport/filter-test.js +0 -18
  144. package/dist/src/transport/filter-test.js.map +0 -1
  145. package/dist/src/transport/index.d.ts +0 -15
  146. package/dist/src/transport/index.d.ts.map +0 -1
  147. package/dist/src/transport/index.js +0 -11
  148. package/dist/src/transport/index.js.map +0 -1
  149. package/dist/src/transport/listen-test.d.ts +0 -5
  150. package/dist/src/transport/listen-test.d.ts.map +0 -1
  151. package/dist/src/transport/listen-test.js +0 -152
  152. package/dist/src/transport/listen-test.js.map +0 -1
  153. package/dist/src/utils/is-valid-tick.d.ts.map +0 -1
  154. package/dist/src/utils/is-valid-tick.js.map +0 -1
  155. package/dist/src/utils/peers.d.ts.map +0 -1
  156. package/dist/src/utils/peers.js.map +0 -1
  157. package/src/connection/README.md +0 -256
  158. package/src/connection/connection.ts +0 -176
  159. package/src/connection/index.ts +0 -7
  160. package/src/connection-encrypter/index.ts +0 -104
  161. package/src/connection-encrypter/utils/index.ts +0 -23
  162. package/src/mocks/connection-encrypter.ts +0 -110
  163. package/src/mocks/connection-gater.ts +0 -14
  164. package/src/mocks/connection-manager.ts +0 -141
  165. package/src/mocks/connection.ts +0 -204
  166. package/src/mocks/duplex.ts +0 -8
  167. package/src/mocks/index.ts +0 -10
  168. package/src/mocks/multiaddr-connection.ts +0 -66
  169. package/src/mocks/muxer.ts +0 -393
  170. package/src/mocks/registrar.ts +0 -96
  171. package/src/mocks/upgrader.ts +0 -46
  172. package/src/peer-discovery/index.ts +0 -89
  173. package/src/pubsub/api.ts +0 -115
  174. package/src/pubsub/connection-handlers.ts +0 -413
  175. package/src/pubsub/emit-self.ts +0 -105
  176. package/src/pubsub/index.ts +0 -25
  177. package/src/pubsub/messages.ts +0 -58
  178. package/src/pubsub/multiple-nodes.ts +0 -429
  179. package/src/pubsub/two-nodes.ts +0 -235
  180. package/src/pubsub/utils.ts +0 -28
  181. package/src/record/index.ts +0 -32
  182. package/src/stream-muxer/base-test.ts +0 -190
  183. package/src/stream-muxer/close-test.ts +0 -227
  184. package/src/stream-muxer/index.ts +0 -15
  185. package/src/stream-muxer/mega-stress-test.ts +0 -15
  186. package/src/stream-muxer/spawner.ts +0 -50
  187. package/src/stream-muxer/stress-test.ts +0 -29
  188. package/src/topology/topology.ts +0 -25
  189. package/src/transport/dial-test.ts +0 -123
  190. package/src/transport/filter-test.ts +0 -25
  191. package/src/transport/index.ts +0 -25
  192. package/src/transport/listen-test.ts +0 -191
@@ -1,204 +0,0 @@
1
- import { peerIdFromString } from '@libp2p/peer-id'
2
- import { pipe } from 'it-pipe'
3
- import { duplexPair } from 'it-pair/duplex'
4
- import type { MultiaddrConnection } from '@libp2p/interfaces/transport'
5
- import type { Connection, Stream, Metadata, ProtocolStream, ConnectionStat } from '@libp2p/interfaces/connection'
6
- import type { Duplex } from 'it-stream-types'
7
- import { mockMuxer } from './muxer.js'
8
- import type { PeerId } from '@libp2p/interfaces/peer-id'
9
- import { mockMultiaddrConnection } from './multiaddr-connection.js'
10
- import type { Registrar } from '@libp2p/interfaces/registrar'
11
- import { mockRegistrar } from './registrar.js'
12
- import { Dialer, Listener } from '@libp2p/multistream-select'
13
- import { logger } from '@libp2p/logger'
14
- import * as STATUS from '@libp2p/interfaces/connection/status'
15
- import type { Multiaddr } from '@multiformats/multiaddr'
16
- import type { StreamMuxer } from '@libp2p/interfaces/stream-muxer'
17
- import { Components } from '@libp2p/interfaces/components'
18
-
19
- const log = logger('libp2p:mock-connection')
20
-
21
- export interface MockConnectionOptions {
22
- direction?: 'inbound' | 'outbound'
23
- registrar?: Registrar
24
- }
25
-
26
- interface MockConnectionInit {
27
- remoteAddr: Multiaddr
28
- remotePeer: PeerId
29
- direction: 'inbound' | 'outbound'
30
- maConn: MultiaddrConnection
31
- muxer: StreamMuxer
32
- }
33
-
34
- class MockConnection implements Connection {
35
- public id: string
36
- public remoteAddr: Multiaddr
37
- public remotePeer: PeerId
38
- public direction: 'inbound' | 'outbound'
39
- public stat: ConnectionStat
40
- public registry: Map<string, Metadata>
41
- public streams: Stream[]
42
- public tags: string[]
43
-
44
- private readonly muxer: StreamMuxer
45
- private readonly maConn: MultiaddrConnection
46
-
47
- constructor (init: MockConnectionInit) {
48
- const { remoteAddr, remotePeer, direction, maConn, muxer } = init
49
-
50
- this.id = `mock-connection-${Math.random()}`
51
- this.remoteAddr = remoteAddr
52
- this.remotePeer = remotePeer
53
- this.direction = direction
54
- this.stat = {
55
- status: STATUS.OPEN,
56
- direction,
57
- timeline: maConn.timeline,
58
- multiplexer: 'test-multiplexer',
59
- encryption: 'yes-yes-very-secure'
60
- }
61
- this.registry = new Map()
62
- this.streams = []
63
- this.tags = []
64
- this.muxer = muxer
65
- this.maConn = maConn
66
- }
67
-
68
- async newStream (protocols: string | string[]) {
69
- if (!Array.isArray(protocols)) {
70
- protocols = [protocols]
71
- }
72
-
73
- if (protocols.length === 0) {
74
- throw new Error('protocols must have a length')
75
- }
76
-
77
- const id = `${Math.random()}`
78
- const stream: Stream = this.muxer.newStream(id)
79
- const mss = new Dialer(stream)
80
- const result = await mss.select(protocols)
81
-
82
- const streamData: ProtocolStream = {
83
- protocol: result.protocol,
84
- stream: {
85
- ...stream,
86
- ...result.stream
87
- }
88
- }
89
-
90
- this.addStream(stream, { protocol: result.protocol, metadata: {} })
91
-
92
- return streamData
93
- }
94
-
95
- addStream (stream: Stream, metadata: Partial<Metadata>) {
96
- this.registry.set(stream.id, {
97
- protocol: metadata.protocol ?? '',
98
- metadata: metadata.metadata ?? {}
99
- })
100
-
101
- this.streams.push(stream)
102
- }
103
-
104
- removeStream (id: string) {
105
- this.registry.delete(id)
106
- this.streams = this.streams.filter(stream => stream.id !== id)
107
- }
108
-
109
- async close () {
110
- this.stat.status = STATUS.CLOSING
111
- await this.maConn.close()
112
- this.stat.status = STATUS.CLOSED
113
- }
114
- }
115
-
116
- export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectionOptions = {}): Connection {
117
- const remoteAddr = maConn.remoteAddr
118
- const remotePeerIdStr = remoteAddr.getPeerId() ?? '12D3KooWCrhmFM1BCPGBkNzbPfDk4cjYmtAYSpZwUBC69Qg2kZyq'
119
-
120
- if (remotePeerIdStr == null) {
121
- throw new Error('Remote multiaddr must contain a peer id')
122
- }
123
-
124
- const remotePeer = peerIdFromString(remotePeerIdStr)
125
- const direction = opts.direction ?? 'inbound'
126
- const registrar = opts.registrar ?? mockRegistrar()
127
- const muxerFactory = mockMuxer()
128
-
129
- const muxer = muxerFactory.createStreamMuxer(new Components(), {
130
- onIncomingStream: (muxedStream) => {
131
- const mss = new Listener(muxedStream)
132
- try {
133
- mss.handle(registrar.getProtocols())
134
- .then(({ stream, protocol }) => {
135
- log('%s: incoming stream opened on %s', direction, protocol)
136
- muxedStream = { ...muxedStream, ...stream }
137
-
138
- connection.addStream(muxedStream, { protocol, metadata: {} })
139
- const handler = registrar.getHandler(protocol)
140
-
141
- handler({ connection, stream: muxedStream, protocol })
142
- }).catch(err => {
143
- log.error(err)
144
- })
145
- } catch (err: any) {
146
- log.error(err)
147
- }
148
- },
149
- onStreamEnd: (muxedStream) => {
150
- connection.removeStream(muxedStream.id)
151
- }
152
- })
153
-
154
- void pipe(
155
- maConn, muxer, maConn
156
- )
157
-
158
- const connection = new MockConnection({
159
- remoteAddr,
160
- remotePeer,
161
- direction,
162
- maConn,
163
- muxer
164
- })
165
-
166
- return connection
167
- }
168
-
169
- export function mockStream (stream: Duplex<Uint8Array>): Stream {
170
- return {
171
- ...stream,
172
- close: () => {},
173
- closeRead: () => {},
174
- closeWrite: () => {},
175
- abort: () => {},
176
- reset: () => {},
177
- timeline: {
178
- open: Date.now()
179
- },
180
- id: `stream-${Date.now()}`
181
- }
182
- }
183
-
184
- export interface Peer {
185
- peerId: PeerId
186
- registrar: Registrar
187
- }
188
-
189
- export function connectionPair (a: Components, b: Components): [ Connection, Connection ] {
190
- const [peerBtoPeerA, peerAtoPeerB] = duplexPair<Uint8Array>()
191
-
192
- return [
193
- mockConnection(
194
- mockMultiaddrConnection(peerAtoPeerB, b.getPeerId()), {
195
- registrar: a.getRegistrar()
196
- }
197
- ),
198
- mockConnection(
199
- mockMultiaddrConnection(peerBtoPeerA, a.getPeerId()), {
200
- registrar: b.getRegistrar()
201
- }
202
- )
203
- ]
204
- }
@@ -1,8 +0,0 @@
1
- import type { Duplex } from 'it-stream-types'
2
-
3
- export function mockDuplex (): Duplex<Uint8Array> {
4
- return {
5
- source: [],
6
- sink: async () => {}
7
- }
8
- }
@@ -1,10 +0,0 @@
1
-
2
- export { mockConnectionGater } from './connection-gater.js'
3
- export { mockConnectionManager, mockNetwork } from './connection-manager.js'
4
- export { mockConnection, mockStream, connectionPair } from './connection.js'
5
- export { mockMultiaddrConnection, mockMultiaddrConnPair } from './multiaddr-connection.js'
6
- export { mockMuxer } from './muxer.js'
7
- export { mockRegistrar } from './registrar.js'
8
- export { mockUpgrader } from './upgrader.js'
9
- export { mockDuplex } from './duplex.js'
10
- export type { MockUpgraderInit } from './upgrader.js'
@@ -1,66 +0,0 @@
1
- import { Multiaddr } from '@multiformats/multiaddr'
2
- import { duplexPair } from 'it-pair/duplex'
3
- import { abortableSource } from 'abortable-iterator'
4
- import type { MultiaddrConnection } from '@libp2p/interfaces/transport'
5
- import type { Duplex } from 'it-stream-types'
6
- import type { PeerId } from '@libp2p/interfaces/peer-id'
7
-
8
- export function mockMultiaddrConnection (source: Duplex<Uint8Array> & Partial<MultiaddrConnection>, peerId: PeerId): MultiaddrConnection {
9
- const maConn: MultiaddrConnection = {
10
- async close () {
11
-
12
- },
13
- timeline: {
14
- open: Date.now()
15
- },
16
- remoteAddr: new Multiaddr(`/ip4/127.0.0.1/tcp/4001/p2p/${peerId.toString()}`),
17
- ...source
18
- }
19
-
20
- return maConn
21
- }
22
-
23
- export interface MockMultiaddrConnPairOptions {
24
- addrs: Multiaddr[]
25
- remotePeer: PeerId
26
- }
27
-
28
- /**
29
- * Returns both sides of a mocked MultiaddrConnection
30
- */
31
- export function mockMultiaddrConnPair (opts: MockMultiaddrConnPairOptions): { inbound: MultiaddrConnection, outbound: MultiaddrConnection } {
32
- const { addrs, remotePeer } = opts
33
- const controller = new AbortController()
34
- const [localAddr, remoteAddr] = addrs
35
- const [inboundStream, outboundStream] = duplexPair<Uint8Array>()
36
-
37
- const outbound: MultiaddrConnection = {
38
- ...outboundStream,
39
- remoteAddr: remoteAddr.encapsulate(`/p2p/${remotePeer.toString()}`),
40
- timeline: {
41
- open: Date.now()
42
- },
43
- close: async () => {
44
- outbound.timeline.close = Date.now()
45
- controller.abort()
46
- }
47
- }
48
-
49
- const inbound: MultiaddrConnection = {
50
- ...inboundStream,
51
- remoteAddr: localAddr,
52
- timeline: {
53
- open: Date.now()
54
- },
55
- close: async () => {
56
- inbound.timeline.close = Date.now()
57
- controller.abort()
58
- }
59
- }
60
-
61
- // Make the sources abortable so we can close them easily
62
- inbound.source = abortableSource(inbound.source, controller.signal)
63
- outbound.source = abortableSource(outbound.source, controller.signal)
64
-
65
- return { inbound, outbound }
66
- }
@@ -1,393 +0,0 @@
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'
5
- import { anySignal } from 'any-signal'
6
- import errCode from 'err-code'
7
- import { Logger, logger } from '@libp2p/logger'
8
- import * as ndjson from 'it-ndjson'
9
- import type { Stream } from '@libp2p/interfaces/connection'
10
- import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer'
11
- import type { Source } from 'it-stream-types'
12
- import { pipe } from 'it-pipe'
13
- import map from 'it-map'
14
- import type { Components } from '@libp2p/interfaces/components'
15
-
16
- let muxers = 0
17
- let streams = 0
18
-
19
- interface DataMessage {
20
- id: string
21
- type: 'data'
22
- direction: 'initiator' | 'recipient'
23
- chunk: string
24
- }
25
-
26
- interface ResetMessage {
27
- id: string
28
- type: 'reset'
29
- direction: 'initiator' | 'recipient'
30
- }
31
-
32
- interface CloseMessage {
33
- id: string
34
- type: 'close'
35
- direction: 'initiator' | 'recipient'
36
- }
37
-
38
- interface CreateMessage {
39
- id: string
40
- type: 'create'
41
- direction: 'initiator'
42
- }
43
-
44
- type StreamMessage = DataMessage | ResetMessage | CloseMessage | CreateMessage
45
-
46
- class MuxedStream {
47
- public id: string
48
- public input: Pushable<Uint8Array>
49
- public stream: Stream
50
- public type: 'initiator' | 'recipient'
51
-
52
- private sinkEnded: boolean
53
- private sourceEnded: boolean
54
- private readonly abortController: AbortController
55
- private readonly resetController: AbortController
56
- private readonly log: Logger
57
-
58
- constructor (init: { id: string, type: 'initiator' | 'recipient', push: Pushable<StreamMessage>, onEnd: (err?: Error) => void }) {
59
- const { id, type, push, onEnd } = init
60
-
61
- this.log = logger(`libp2p:mock-muxer:stream:${id}:${type}`)
62
-
63
- this.id = id
64
- this.type = type
65
- this.abortController = new AbortController()
66
- this.resetController = new AbortController()
67
-
68
- this.sourceEnded = false
69
- this.sinkEnded = false
70
-
71
- let endErr: Error | undefined
72
-
73
- const onSourceEnd = (err?: Error) => {
74
- if (this.sourceEnded) {
75
- return
76
- }
77
-
78
- this.log('onSourceEnd sink ended? %s', this.sinkEnded)
79
-
80
- this.sourceEnded = true
81
-
82
- if (err != null && endErr == null) {
83
- endErr = err
84
- }
85
-
86
- if (this.sinkEnded) {
87
- this.stream.timeline.close = Date.now()
88
-
89
- if (onEnd != null) {
90
- onEnd(endErr)
91
- }
92
- }
93
- }
94
-
95
- const onSinkEnd = (err?: Error) => {
96
- if (this.sinkEnded) {
97
- return
98
- }
99
-
100
- this.log('onSinkEnd source ended? %s', this.sourceEnded)
101
-
102
- this.sinkEnded = true
103
-
104
- if (err != null && endErr == null) {
105
- endErr = err
106
- }
107
-
108
- if (this.sourceEnded) {
109
- this.stream.timeline.close = Date.now()
110
-
111
- if (onEnd != null) {
112
- onEnd(endErr)
113
- }
114
- }
115
- }
116
-
117
- this.input = pushable<Uint8Array>({
118
- onEnd: onSourceEnd
119
- })
120
-
121
- this.stream = {
122
- id,
123
- sink: async (source) => {
124
- source = abortableSource(source, anySignal([
125
- this.abortController.signal,
126
- this.resetController.signal
127
- ]))
128
-
129
- try {
130
- if (this.type === 'initiator') {
131
- // If initiator, open a new stream
132
- const createMsg: CreateMessage = {
133
- id: this.id,
134
- type: 'create',
135
- direction: this.type
136
- }
137
- push.push(createMsg)
138
- }
139
-
140
- for await (const chunk of source) {
141
- const dataMsg: DataMessage = {
142
- id,
143
- type: 'data',
144
- chunk: uint8ArrayToString(chunk, 'base64'),
145
- direction: this.type
146
- }
147
-
148
- push.push(dataMsg)
149
- }
150
- } catch (err: any) {
151
- if (err.type === 'aborted' && err.message === 'The operation was aborted') {
152
- if (this.resetController.signal.aborted) {
153
- err.message = 'stream reset'
154
- err.code = 'ERR_STREAM_RESET'
155
- }
156
-
157
- if (this.abortController.signal.aborted) {
158
- err.message = 'stream aborted'
159
- err.code = 'ERR_STREAM_ABORT'
160
- }
161
- }
162
-
163
- // Send no more data if this stream was remotely reset
164
- if (err.code !== 'ERR_STREAM_RESET') {
165
- const resetMsg: ResetMessage = {
166
- id,
167
- type: 'reset',
168
- direction: this.type
169
- }
170
- push.push(resetMsg)
171
- }
172
-
173
- this.log('sink erred', err)
174
-
175
- this.input.end(err)
176
- onSinkEnd(err)
177
- return
178
- }
179
-
180
- this.log('sink ended')
181
-
182
- onSinkEnd()
183
-
184
- const closeMsg: CloseMessage = {
185
- id,
186
- type: 'close',
187
- direction: this.type
188
- }
189
- push.push(closeMsg)
190
- },
191
- source: this.input,
192
-
193
- // Close for reading
194
- close: () => {
195
- this.input.end()
196
- },
197
-
198
- closeRead: () => {
199
- this.input.end()
200
- },
201
-
202
- closeWrite: () => {
203
- this.input.end()
204
- },
205
-
206
- // Close for reading and writing (local error)
207
- abort: (err?: Error) => {
208
- // End the source with the passed error
209
- this.input.end(err)
210
- this.abortController.abort()
211
- onSinkEnd(err)
212
- },
213
-
214
- // Close immediately for reading and writing (remote error)
215
- reset: () => {
216
- const err = errCode(new Error('stream reset'), 'ERR_STREAM_RESET')
217
- this.resetController.abort()
218
- this.input.end(err)
219
- onSinkEnd(err)
220
- },
221
- timeline: {
222
- open: Date.now()
223
- }
224
- }
225
- }
226
- }
227
-
228
- class MockMuxer implements StreamMuxer {
229
- public source: Source<Uint8Array>
230
- public input: Pushable<Uint8Array>
231
- public streamInput: Pushable<StreamMessage>
232
- public name: string
233
- public protocol: string = '/mock-muxer/1.0.0'
234
-
235
- private readonly registryInitiatorStreams: Map<string, MuxedStream>
236
- private readonly registryRecipientStreams: Map<string, MuxedStream>
237
- private readonly options: StreamMuxerInit
238
-
239
- private readonly log: Logger
240
-
241
- constructor (init?: StreamMuxerInit) {
242
- this.name = `muxer:${muxers++}`
243
- this.log = logger(`libp2p:mock-muxer:${this.name}`)
244
- this.registryInitiatorStreams = new Map()
245
- this.registryRecipientStreams = new Map()
246
- this.log('create muxer')
247
- this.options = init ?? {}
248
- // receives data from the muxer at the other end of the stream
249
- this.source = this.input = pushable<Uint8Array>({
250
- onEnd: (err) => {
251
- this.log('closing muxed streams')
252
- for (const stream of this.streams) {
253
- if (err == null) {
254
- stream.close()
255
- } else {
256
- stream.abort(err)
257
- }
258
- }
259
- }
260
- })
261
-
262
- // receives messages from all of the muxed streams
263
- this.streamInput = pushable<StreamMessage>()
264
- }
265
-
266
- // receive incoming messages
267
- async sink (source: Source<Uint8Array>) {
268
- try {
269
- await pipe(
270
- source,
271
- (source) => map(source, buf => uint8ArrayToString(buf)),
272
- ndjson.parse,
273
- async (source) => {
274
- for await (const message of source) {
275
- this.log.trace('-> %s %s %s', message.type, message.direction, message.id)
276
- this.handleMessage(message)
277
- }
278
- }
279
- )
280
-
281
- this.log('muxed stream ended')
282
- this.input.end()
283
- } catch (err: any) {
284
- this.log('muxed stream errored', err)
285
- this.input.end(err)
286
- }
287
- }
288
-
289
- handleMessage (message: StreamMessage) {
290
- let muxedStream: MuxedStream | undefined
291
-
292
- const registry = message.direction === 'initiator' ? this.registryRecipientStreams : this.registryInitiatorStreams
293
-
294
- if (message.type === 'create') {
295
- if (registry.has(message.id)) {
296
- throw new Error(`Already had stream for ${message.id}`)
297
- }
298
-
299
- muxedStream = this.createStream(message.id, 'recipient')
300
- registry.set(muxedStream.stream.id, muxedStream)
301
-
302
- if (this.options.onIncomingStream != null) {
303
- this.options.onIncomingStream(muxedStream.stream)
304
- }
305
- }
306
-
307
- muxedStream = registry.get(message.id)
308
-
309
- if (muxedStream == null) {
310
- this.log.error(`No stream found for ${message.id}`)
311
-
312
- return
313
- }
314
-
315
- if (message.type === 'data') {
316
- muxedStream.input.push(uint8ArrayFromString(message.chunk, 'base64'))
317
- } else if (message.type === 'reset') {
318
- this.log('-> reset stream %s %s', muxedStream.type, muxedStream.stream.id)
319
- muxedStream.stream.reset()
320
- } else if (message.type === 'close') {
321
- this.log('-> closing stream %s %s', muxedStream.type, muxedStream.stream.id)
322
- void muxedStream.stream.close()
323
- }
324
- }
325
-
326
- get streams () {
327
- return Array.from(this.registryRecipientStreams.values())
328
- .concat(Array.from(this.registryInitiatorStreams.values()))
329
- .map(({ stream }) => stream)
330
- }
331
-
332
- newStream (name?: string) {
333
- this.log('newStream %s', name)
334
- const storedStream = this.createStream(name, 'initiator')
335
- this.registryInitiatorStreams.set(storedStream.stream.id, storedStream)
336
-
337
- return storedStream.stream
338
- }
339
-
340
- createStream (name?: string, type: 'initiator' | 'recipient' = 'initiator'): MuxedStream {
341
- const id = name ?? `${this.name}:stream:${streams++}`
342
-
343
- this.log('createStream %s %s', type, id)
344
-
345
- const muxedStream: MuxedStream = new MuxedStream({
346
- id,
347
- type,
348
- push: this.streamInput,
349
- onEnd: () => {
350
- this.log('stream ended %s %s', type, id)
351
-
352
- if (type === 'initiator') {
353
- this.registryInitiatorStreams.delete(id)
354
- } else {
355
- this.registryRecipientStreams.delete(id)
356
- }
357
-
358
- if (this.options.onStreamEnd != null) {
359
- this.options.onStreamEnd(muxedStream.stream)
360
- }
361
- }
362
- })
363
-
364
- return muxedStream
365
- }
366
- }
367
-
368
- class MockMuxerFactory implements StreamMuxerFactory {
369
- public protocol: string = '/mock-muxer/1.0.0'
370
-
371
- createStreamMuxer (c: Components, init?: StreamMuxerInit): StreamMuxer {
372
- const mockMuxer = new MockMuxer(init)
373
-
374
- void Promise.resolve().then(async () => {
375
- void pipe(
376
- mockMuxer.streamInput,
377
- ndjson.stringify,
378
- (source) => map(source, str => uint8ArrayFromString(str)),
379
- async (source) => {
380
- for await (const buf of source) {
381
- mockMuxer.input.push(buf)
382
- }
383
- }
384
- )
385
- })
386
-
387
- return mockMuxer
388
- }
389
- }
390
-
391
- export function mockMuxer (): MockMuxerFactory {
392
- return new MockMuxerFactory()
393
- }