@libp2p/interface-compliance-tests 2.0.2 → 3.0.1

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