@libp2p/interface 0.0.1-6fdaa7dc

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 (129) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +45 -0
  3. package/dist/index.min.js +3 -0
  4. package/dist/src/connection/index.d.ts +188 -0
  5. package/dist/src/connection/index.d.ts.map +1 -0
  6. package/dist/src/connection/index.js +5 -0
  7. package/dist/src/connection/index.js.map +1 -0
  8. package/dist/src/connection/status.d.ts +4 -0
  9. package/dist/src/connection/status.d.ts.map +1 -0
  10. package/dist/src/connection/status.js +4 -0
  11. package/dist/src/connection/status.js.map +1 -0
  12. package/dist/src/connection-encrypter/index.d.ts +27 -0
  13. package/dist/src/connection-encrypter/index.d.ts.map +1 -0
  14. package/dist/src/connection-encrypter/index.js +2 -0
  15. package/dist/src/connection-encrypter/index.js.map +1 -0
  16. package/dist/src/connection-gater/index.d.ts +117 -0
  17. package/dist/src/connection-gater/index.d.ts.map +1 -0
  18. package/dist/src/connection-gater/index.js +2 -0
  19. package/dist/src/connection-gater/index.js.map +1 -0
  20. package/dist/src/content-routing/index.d.ts +79 -0
  21. package/dist/src/content-routing/index.d.ts.map +1 -0
  22. package/dist/src/content-routing/index.js +21 -0
  23. package/dist/src/content-routing/index.js.map +1 -0
  24. package/dist/src/errors.d.ts +33 -0
  25. package/dist/src/errors.d.ts.map +1 -0
  26. package/dist/src/errors.js +51 -0
  27. package/dist/src/errors.js.map +1 -0
  28. package/dist/src/events.d.ts +28 -0
  29. package/dist/src/events.d.ts.map +1 -0
  30. package/dist/src/events.js +70 -0
  31. package/dist/src/events.js.map +1 -0
  32. package/dist/src/index.d.ts +575 -0
  33. package/dist/src/index.d.ts.map +1 -0
  34. package/dist/src/index.js +17 -0
  35. package/dist/src/index.js.map +1 -0
  36. package/dist/src/keychain/index.d.ts +154 -0
  37. package/dist/src/keychain/index.d.ts.map +1 -0
  38. package/dist/src/keychain/index.js +23 -0
  39. package/dist/src/keychain/index.js.map +1 -0
  40. package/dist/src/keys/index.d.ts +35 -0
  41. package/dist/src/keys/index.d.ts.map +1 -0
  42. package/dist/src/keys/index.js +4 -0
  43. package/dist/src/keys/index.js.map +1 -0
  44. package/dist/src/metrics/index.d.ts +165 -0
  45. package/dist/src/metrics/index.d.ts.map +1 -0
  46. package/dist/src/metrics/index.js +2 -0
  47. package/dist/src/metrics/index.js.map +1 -0
  48. package/dist/src/metrics/tracked-map.d.ts +17 -0
  49. package/dist/src/metrics/tracked-map.d.ts.map +1 -0
  50. package/dist/src/metrics/tracked-map.js +38 -0
  51. package/dist/src/metrics/tracked-map.js.map +1 -0
  52. package/dist/src/peer-discovery/index.d.ts +28 -0
  53. package/dist/src/peer-discovery/index.d.ts.map +1 -0
  54. package/dist/src/peer-discovery/index.js +21 -0
  55. package/dist/src/peer-discovery/index.js.map +1 -0
  56. package/dist/src/peer-id/index.d.ts +30 -0
  57. package/dist/src/peer-id/index.d.ts.map +1 -0
  58. package/dist/src/peer-id/index.js +5 -0
  59. package/dist/src/peer-id/index.js.map +1 -0
  60. package/dist/src/peer-info/index.d.ts +8 -0
  61. package/dist/src/peer-info/index.d.ts.map +1 -0
  62. package/dist/src/peer-info/index.js +2 -0
  63. package/dist/src/peer-info/index.js.map +1 -0
  64. package/dist/src/peer-routing/index.d.ts +51 -0
  65. package/dist/src/peer-routing/index.d.ts.map +1 -0
  66. package/dist/src/peer-routing/index.js +21 -0
  67. package/dist/src/peer-routing/index.js.map +1 -0
  68. package/dist/src/peer-store/index.d.ts +247 -0
  69. package/dist/src/peer-store/index.d.ts.map +1 -0
  70. package/dist/src/peer-store/index.js +2 -0
  71. package/dist/src/peer-store/index.js.map +1 -0
  72. package/dist/src/peer-store/tags.d.ts +2 -0
  73. package/dist/src/peer-store/tags.d.ts.map +1 -0
  74. package/dist/src/peer-store/tags.js +2 -0
  75. package/dist/src/peer-store/tags.js.map +1 -0
  76. package/dist/src/record/index.d.ts +33 -0
  77. package/dist/src/record/index.d.ts.map +1 -0
  78. package/dist/src/record/index.js +2 -0
  79. package/dist/src/record/index.js.map +1 -0
  80. package/dist/src/startable.d.ts +46 -0
  81. package/dist/src/startable.d.ts.map +1 -0
  82. package/dist/src/startable.js +46 -0
  83. package/dist/src/startable.js.map +1 -0
  84. package/dist/src/stream-handler/index.d.ts +23 -0
  85. package/dist/src/stream-handler/index.d.ts.map +1 -0
  86. package/dist/src/stream-handler/index.js +2 -0
  87. package/dist/src/stream-handler/index.js.map +1 -0
  88. package/dist/src/stream-muxer/index.d.ts +51 -0
  89. package/dist/src/stream-muxer/index.d.ts.map +1 -0
  90. package/dist/src/stream-muxer/index.js +2 -0
  91. package/dist/src/stream-muxer/index.js.map +1 -0
  92. package/dist/src/stream-muxer/stream.d.ts +85 -0
  93. package/dist/src/stream-muxer/stream.d.ts.map +1 -0
  94. package/dist/src/stream-muxer/stream.js +255 -0
  95. package/dist/src/stream-muxer/stream.js.map +1 -0
  96. package/dist/src/topology/index.d.ts +9 -0
  97. package/dist/src/topology/index.d.ts.map +1 -0
  98. package/dist/src/topology/index.js +2 -0
  99. package/dist/src/topology/index.js.map +1 -0
  100. package/dist/src/transport/index.d.ts +96 -0
  101. package/dist/src/transport/index.d.ts.map +1 -0
  102. package/dist/src/transport/index.js +19 -0
  103. package/dist/src/transport/index.js.map +1 -0
  104. package/package.json +177 -0
  105. package/src/connection/index.ts +221 -0
  106. package/src/connection/status.ts +4 -0
  107. package/src/connection-encrypter/index.ts +30 -0
  108. package/src/connection-gater/index.ts +128 -0
  109. package/src/content-routing/index.ts +83 -0
  110. package/src/errors.ts +68 -0
  111. package/src/events.ts +100 -0
  112. package/src/index.ts +627 -0
  113. package/src/keychain/index.ts +167 -0
  114. package/src/keys/index.ts +38 -0
  115. package/src/metrics/index.ts +187 -0
  116. package/src/metrics/tracked-map.ts +65 -0
  117. package/src/peer-discovery/index.ts +29 -0
  118. package/src/peer-id/index.ts +39 -0
  119. package/src/peer-info/index.ts +8 -0
  120. package/src/peer-routing/index.ts +53 -0
  121. package/src/peer-store/index.ts +272 -0
  122. package/src/peer-store/tags.ts +2 -0
  123. package/src/record/index.ts +35 -0
  124. package/src/startable.ts +117 -0
  125. package/src/stream-handler/index.ts +27 -0
  126. package/src/stream-muxer/index.ts +58 -0
  127. package/src/stream-muxer/stream.ts +365 -0
  128. package/src/topology/index.ts +10 -0
  129. package/src/transport/index.ts +111 -0
@@ -0,0 +1,365 @@
1
+ // import { logger } from '@libp2p/logger'
2
+ import { abortableSource } from 'abortable-iterator'
3
+ import { anySignal } from 'any-signal'
4
+ import { type Pushable, pushable } from 'it-pushable'
5
+ import { Uint8ArrayList } from 'uint8arraylist'
6
+ import { CodeError } from '../errors.js'
7
+ import type { Direction, Stream, StreamStat } from '../connection/index.js'
8
+ import type { Source } from 'it-stream-types'
9
+
10
+ // const log = logger('libp2p:stream')
11
+
12
+ const log: any = () => {}
13
+ log.trace = () => {}
14
+ log.error = () => {}
15
+
16
+ const ERR_STREAM_RESET = 'ERR_STREAM_RESET'
17
+ const ERR_STREAM_ABORT = 'ERR_STREAM_ABORT'
18
+ const ERR_SINK_ENDED = 'ERR_SINK_ENDED'
19
+ const ERR_DOUBLE_SINK = 'ERR_DOUBLE_SINK'
20
+
21
+ export interface AbstractStreamInit {
22
+ /**
23
+ * A unique identifier for this stream
24
+ */
25
+ id: string
26
+
27
+ /**
28
+ * The stream direction
29
+ */
30
+ direction: Direction
31
+
32
+ /**
33
+ * The maximum allowable data size, any data larger than this will be
34
+ * chunked and sent in multiple data messages
35
+ */
36
+ maxDataSize: number
37
+
38
+ /**
39
+ * User specific stream metadata
40
+ */
41
+ metadata?: Record<string, unknown>
42
+
43
+ /**
44
+ * Invoked when the stream ends
45
+ */
46
+ onEnd?: (err?: Error | undefined) => void
47
+ }
48
+
49
+ function isPromise (res?: any): res is Promise<void> {
50
+ return res != null && typeof res.then === 'function'
51
+ }
52
+
53
+ export abstract class AbstractStream implements Stream {
54
+ public id: string
55
+ public stat: StreamStat
56
+ public metadata: Record<string, unknown>
57
+ public source: AsyncGenerator<Uint8ArrayList, void, unknown>
58
+
59
+ private readonly abortController: AbortController
60
+ private readonly resetController: AbortController
61
+ private readonly closeController: AbortController
62
+ private sourceEnded: boolean
63
+ private sinkEnded: boolean
64
+ private sinkSunk: boolean
65
+ private endErr: Error | undefined
66
+ private readonly streamSource: Pushable<Uint8ArrayList>
67
+ private readonly onEnd?: (err?: Error | undefined) => void
68
+ private readonly maxDataSize: number
69
+
70
+ constructor (init: AbstractStreamInit) {
71
+ this.abortController = new AbortController()
72
+ this.resetController = new AbortController()
73
+ this.closeController = new AbortController()
74
+ this.sourceEnded = false
75
+ this.sinkEnded = false
76
+ this.sinkSunk = false
77
+
78
+ this.id = init.id
79
+ this.metadata = init.metadata ?? {}
80
+ this.stat = {
81
+ direction: init.direction,
82
+ timeline: {
83
+ open: Date.now()
84
+ }
85
+ }
86
+ this.maxDataSize = init.maxDataSize
87
+ this.onEnd = init.onEnd
88
+
89
+ this.source = this.streamSource = pushable<Uint8ArrayList>({
90
+ onEnd: () => {
91
+ // already sent a reset message
92
+ if (this.stat.timeline.reset !== null) {
93
+ const res = this.sendCloseRead()
94
+
95
+ if (isPromise(res)) {
96
+ res.catch(err => {
97
+ log.error('error while sending close read', err)
98
+ })
99
+ }
100
+ }
101
+
102
+ this.onSourceEnd()
103
+ }
104
+ })
105
+
106
+ // necessary because the libp2p upgrader wraps the sink function
107
+ this.sink = this.sink.bind(this)
108
+ }
109
+
110
+ protected onSourceEnd (err?: Error): void {
111
+ if (this.sourceEnded) {
112
+ return
113
+ }
114
+
115
+ this.stat.timeline.closeRead = Date.now()
116
+ this.sourceEnded = true
117
+ log.trace('%s stream %s source end - err: %o', this.stat.direction, this.id, err)
118
+
119
+ if (err != null && this.endErr == null) {
120
+ this.endErr = err
121
+ }
122
+
123
+ if (this.sinkEnded) {
124
+ this.stat.timeline.close = Date.now()
125
+
126
+ if (this.onEnd != null) {
127
+ this.onEnd(this.endErr)
128
+ }
129
+ }
130
+ }
131
+
132
+ protected onSinkEnd (err?: Error): void {
133
+ if (this.sinkEnded) {
134
+ return
135
+ }
136
+
137
+ this.stat.timeline.closeWrite = Date.now()
138
+ this.sinkEnded = true
139
+ log.trace('%s stream %s sink end - err: %o', this.stat.direction, this.id, err)
140
+
141
+ if (err != null && this.endErr == null) {
142
+ this.endErr = err
143
+ }
144
+
145
+ if (this.sourceEnded) {
146
+ this.stat.timeline.close = Date.now()
147
+
148
+ if (this.onEnd != null) {
149
+ this.onEnd(this.endErr)
150
+ }
151
+ }
152
+ }
153
+
154
+ // Close for both Reading and Writing
155
+ close (): void {
156
+ log.trace('%s stream %s close', this.stat.direction, this.id)
157
+
158
+ this.closeRead()
159
+ this.closeWrite()
160
+ }
161
+
162
+ // Close for reading
163
+ closeRead (): void {
164
+ log.trace('%s stream %s closeRead', this.stat.direction, this.id)
165
+
166
+ if (this.sourceEnded) {
167
+ return
168
+ }
169
+
170
+ this.streamSource.end()
171
+ }
172
+
173
+ // Close for writing
174
+ closeWrite (): void {
175
+ log.trace('%s stream %s closeWrite', this.stat.direction, this.id)
176
+
177
+ if (this.sinkEnded) {
178
+ return
179
+ }
180
+
181
+ this.closeController.abort()
182
+
183
+ try {
184
+ // need to call this here as the sink method returns in the catch block
185
+ // when the close controller is aborted
186
+ const res = this.sendCloseWrite()
187
+
188
+ if (isPromise(res)) {
189
+ res.catch(err => {
190
+ log.error('error while sending close write', err)
191
+ })
192
+ }
193
+ } catch (err) {
194
+ log.trace('%s stream %s error sending close', this.stat.direction, this.id, err)
195
+ }
196
+
197
+ this.onSinkEnd()
198
+ }
199
+
200
+ // Close for reading and writing (local error)
201
+ abort (err: Error): void {
202
+ log.trace('%s stream %s abort', this.stat.direction, this.id, err)
203
+ // End the source with the passed error
204
+ this.streamSource.end(err)
205
+ this.abortController.abort()
206
+ this.onSinkEnd(err)
207
+ }
208
+
209
+ // Close immediately for reading and writing (remote error)
210
+ reset (): void {
211
+ const err = new CodeError('stream reset', ERR_STREAM_RESET)
212
+ this.resetController.abort()
213
+ this.streamSource.end(err)
214
+ this.onSinkEnd(err)
215
+ }
216
+
217
+ async sink (source: Source<Uint8ArrayList | Uint8Array>): Promise<void> {
218
+ if (this.sinkSunk) {
219
+ throw new CodeError('sink already called on stream', ERR_DOUBLE_SINK)
220
+ }
221
+
222
+ this.sinkSunk = true
223
+
224
+ if (this.sinkEnded) {
225
+ throw new CodeError('stream closed for writing', ERR_SINK_ENDED)
226
+ }
227
+
228
+ const signal = anySignal([
229
+ this.abortController.signal,
230
+ this.resetController.signal,
231
+ this.closeController.signal
232
+ ])
233
+
234
+ try {
235
+ source = abortableSource(source, signal)
236
+
237
+ if (this.stat.direction === 'outbound') { // If initiator, open a new stream
238
+ const res = this.sendNewStream()
239
+
240
+ if (isPromise(res)) {
241
+ await res
242
+ }
243
+ }
244
+
245
+ for await (let data of source) {
246
+ while (data.length > 0) {
247
+ if (data.length <= this.maxDataSize) {
248
+ const res = this.sendData(data instanceof Uint8Array ? new Uint8ArrayList(data) : data)
249
+
250
+ if (isPromise(res)) { // eslint-disable-line max-depth
251
+ await res
252
+ }
253
+
254
+ break
255
+ }
256
+ data = data instanceof Uint8Array ? new Uint8ArrayList(data) : data
257
+ const res = this.sendData(data.sublist(0, this.maxDataSize))
258
+
259
+ if (isPromise(res)) {
260
+ await res
261
+ }
262
+
263
+ data.consume(this.maxDataSize)
264
+ }
265
+ }
266
+ } catch (err: any) {
267
+ if (err.type === 'aborted' && err.message === 'The operation was aborted') {
268
+ if (this.closeController.signal.aborted) {
269
+ return
270
+ }
271
+
272
+ if (this.resetController.signal.aborted) {
273
+ err.message = 'stream reset'
274
+ err.code = ERR_STREAM_RESET
275
+ }
276
+
277
+ if (this.abortController.signal.aborted) {
278
+ err.message = 'stream aborted'
279
+ err.code = ERR_STREAM_ABORT
280
+ }
281
+ }
282
+
283
+ // Send no more data if this stream was remotely reset
284
+ if (err.code === ERR_STREAM_RESET) {
285
+ log.trace('%s stream %s reset', this.stat.direction, this.id)
286
+ } else {
287
+ log.trace('%s stream %s error', this.stat.direction, this.id, err)
288
+ try {
289
+ const res = this.sendReset()
290
+
291
+ if (isPromise(res)) {
292
+ await res
293
+ }
294
+
295
+ this.stat.timeline.reset = Date.now()
296
+ } catch (err) {
297
+ log.trace('%s stream %s error sending reset', this.stat.direction, this.id, err)
298
+ }
299
+ }
300
+
301
+ this.streamSource.end(err)
302
+ this.onSinkEnd(err)
303
+
304
+ throw err
305
+ } finally {
306
+ signal.clear()
307
+ }
308
+
309
+ try {
310
+ const res = this.sendCloseWrite()
311
+
312
+ if (isPromise(res)) {
313
+ await res
314
+ }
315
+ } catch (err) {
316
+ log.trace('%s stream %s error sending close', this.stat.direction, this.id, err)
317
+ }
318
+
319
+ this.onSinkEnd()
320
+ }
321
+
322
+ /**
323
+ * When an extending class reads data from it's implementation-specific source,
324
+ * call this method to allow the stream consumer to read the data.
325
+ */
326
+ sourcePush (data: Uint8ArrayList): void {
327
+ this.streamSource.push(data)
328
+ }
329
+
330
+ /**
331
+ * Returns the amount of unread data - can be used to prevent large amounts of
332
+ * data building up when the stream consumer is too slow.
333
+ */
334
+ sourceReadableLength (): number {
335
+ return this.streamSource.readableLength
336
+ }
337
+
338
+ /**
339
+ * Send a message to the remote muxer informing them a new stream is being
340
+ * opened
341
+ */
342
+ abstract sendNewStream (): void | Promise<void>
343
+
344
+ /**
345
+ * Send a data message to the remote muxer
346
+ */
347
+ abstract sendData (buf: Uint8ArrayList): void | Promise<void>
348
+
349
+ /**
350
+ * Send a reset message to the remote muxer
351
+ */
352
+ abstract sendReset (): void | Promise<void>
353
+
354
+ /**
355
+ * Send a message to the remote muxer, informing them no more data messages
356
+ * will be sent by this end of the stream
357
+ */
358
+ abstract sendCloseWrite (): void | Promise<void>
359
+
360
+ /**
361
+ * Send a message to the remote muxer, informing them no more data messages
362
+ * will be read by this end of the stream
363
+ */
364
+ abstract sendCloseRead (): void | Promise<void>
365
+ }
@@ -0,0 +1,10 @@
1
+ import type { Connection } from '../connection/index.js'
2
+ import type { PeerId } from '../peer-id/index.js'
3
+
4
+ export interface Topology {
5
+ min?: number
6
+ max?: number
7
+
8
+ onConnect?: (peerId: PeerId, conn: Connection) => void
9
+ onDisconnect?: (peerId: PeerId) => void
10
+ }
@@ -0,0 +1,111 @@
1
+ import type { Connection, MultiaddrConnection } from '../connection/index.js'
2
+ import type { EventEmitter } from '../events.js'
3
+ import type { AbortOptions } from '../index.js'
4
+ import type { StreamMuxerFactory } from '../stream-muxer/index.js'
5
+ import type { Multiaddr } from '@multiformats/multiaddr'
6
+
7
+ export interface ListenerEvents {
8
+ 'connection': CustomEvent<Connection>
9
+ 'listening': CustomEvent
10
+ 'error': CustomEvent<Error>
11
+ 'close': CustomEvent
12
+ }
13
+
14
+ export interface Listener extends EventEmitter<ListenerEvents> {
15
+ /**
16
+ * Start a listener
17
+ */
18
+ listen: (multiaddr: Multiaddr) => Promise<void>
19
+ /**
20
+ * Get listen addresses
21
+ */
22
+ getAddrs: () => Multiaddr[]
23
+ /**
24
+ * Close listener
25
+ *
26
+ * @returns {Promise<void>}
27
+ */
28
+ close: () => Promise<void>
29
+ }
30
+
31
+ export const symbol = Symbol.for('@libp2p/transport')
32
+
33
+ export interface ConnectionHandler { (connection: Connection): void }
34
+
35
+ export interface MultiaddrFilter { (multiaddrs: Multiaddr[]): Multiaddr[] }
36
+
37
+ export interface CreateListenerOptions {
38
+ handler?: ConnectionHandler
39
+ upgrader: Upgrader
40
+ }
41
+
42
+ export interface DialOptions extends AbortOptions {
43
+ upgrader: Upgrader
44
+ }
45
+
46
+ /**
47
+ * A libp2p transport is understood as something that offers a dial and listen interface to establish connections.
48
+ */
49
+ export interface Transport {
50
+ /**
51
+ * Used to identify the transport
52
+ */
53
+ [Symbol.toStringTag]: string
54
+
55
+ /**
56
+ * Used by the isTransport function
57
+ */
58
+ [symbol]: true
59
+
60
+ /**
61
+ * Dial a given multiaddr.
62
+ */
63
+ dial: (ma: Multiaddr, options: DialOptions) => Promise<Connection>
64
+
65
+ /**
66
+ * Create transport listeners.
67
+ */
68
+ createListener: (options: CreateListenerOptions) => Listener
69
+
70
+ /**
71
+ * Takes a list of `Multiaddr`s and returns only valid addresses for the transport
72
+ */
73
+ filter: MultiaddrFilter
74
+ }
75
+
76
+ export function isTransport (other: any): other is Transport {
77
+ return other != null && Boolean(other[symbol])
78
+ }
79
+
80
+ /**
81
+ * Enum Transport Manager Fault Tolerance values
82
+ */
83
+ export enum FaultTolerance {
84
+ /**
85
+ * should be used for failing in any listen circumstance
86
+ */
87
+ FATAL_ALL = 0,
88
+
89
+ /**
90
+ * should be used for not failing when not listening
91
+ */
92
+ NO_FATAL
93
+ }
94
+
95
+ export interface UpgraderOptions {
96
+ skipEncryption?: boolean
97
+ skipProtection?: boolean
98
+ muxerFactory?: StreamMuxerFactory
99
+ }
100
+
101
+ export interface Upgrader {
102
+ /**
103
+ * Upgrades an outbound connection on `transport.dial`.
104
+ */
105
+ upgradeOutbound: (maConn: MultiaddrConnection, opts?: UpgraderOptions) => Promise<Connection>
106
+
107
+ /**
108
+ * Upgrades an inbound connection on transport listener.
109
+ */
110
+ upgradeInbound: (maConn: MultiaddrConnection, opts?: UpgraderOptions) => Promise<Connection>
111
+ }