@libp2p/floodsub 11.0.1 → 11.0.2-334f91bdc

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.
@@ -1,22 +1,15 @@
1
- import { AbortError } from '@libp2p/interface'
2
- import { pipe } from '@libp2p/utils'
3
- import * as lp from 'it-length-prefixed'
4
- import { pushable } from 'it-pushable'
1
+ import { pbStream } from '@libp2p/utils'
5
2
  import { TypedEventEmitter } from 'main-event'
6
- import { pEvent } from 'p-event'
7
- import { Uint8ArrayList } from 'uint8arraylist'
8
- import type { PeerStreamEvents } from './index.ts'
9
- import type { ComponentLogger, Logger, Stream, PeerId } from '@libp2p/interface'
3
+ import { RPC } from './message/rpc.ts'
4
+ import type { PubSubRPC } from './floodsub.ts'
5
+ import type { PeerStreamsEvents } from './index.ts'
6
+ import type { Stream, PeerId } from '@libp2p/interface'
7
+ import type { ProtobufMessageStream, ProtobufStreamOpts } from '@libp2p/utils'
10
8
  import type { DecoderOptions as LpDecoderOptions } from 'it-length-prefixed'
11
- import type { Pushable } from 'it-pushable'
12
9
 
13
- export interface PeerStreamsInit {
14
- id: PeerId
15
- protocol: string
16
- }
17
-
18
- export interface PeerStreamsComponents {
19
- logger: ComponentLogger
10
+ export interface PeerStreamInit {
11
+ peerId: PeerId
12
+ stream: Stream
20
13
  }
21
14
 
22
15
  export interface DecoderOptions extends LpDecoderOptions {
@@ -26,175 +19,86 @@ export interface DecoderOptions extends LpDecoderOptions {
26
19
  /**
27
20
  * Thin wrapper around a peer's inbound / outbound pubsub streams
28
21
  */
29
- export class PeerStreams extends TypedEventEmitter<PeerStreamEvents> {
30
- public readonly id: PeerId
31
- public readonly protocol: string
32
- /**
33
- * Write stream - it's preferable to use the write method
34
- */
35
- public outboundStream?: Pushable<Uint8ArrayList>
36
- /**
37
- * Read stream
38
- */
39
- public inboundStream?: AsyncIterable<Uint8ArrayList>
40
- /**
41
- * The raw outbound stream, as retrieved from conn.newStream
42
- */
43
- private _rawOutboundStream?: Stream
44
- /**
45
- * The raw inbound stream, as retrieved from the callback from libp2p.handle
46
- */
47
- private _rawInboundStream?: Stream
22
+ export class PeerStreams extends TypedEventEmitter<PeerStreamsEvents> {
23
+ public readonly peerId: PeerId
24
+
48
25
  /**
49
26
  * An AbortController for controlled shutdown of the inbound stream
50
27
  */
51
- private readonly _inboundAbortController: AbortController
52
- private closed: boolean
53
- private readonly log: Logger
28
+ private readonly shutDownController: AbortController
29
+ // messages sent by the remote
30
+ private inboundPb?: ProtobufMessageStream<RPC>
31
+ // messages we send
32
+ private outboundPb?: ProtobufMessageStream<RPC>
54
33
 
55
- constructor (components: PeerStreamsComponents, init: PeerStreamsInit) {
34
+ constructor (peerId: PeerId) {
56
35
  super()
57
36
 
58
- this.log = components.logger.forComponent('libp2p-pubsub:peer-streams')
59
- this.id = init.id
60
- this.protocol = init.protocol
61
-
62
- this._inboundAbortController = new AbortController()
63
- this.closed = false
37
+ this.peerId = peerId
38
+ this.shutDownController = new AbortController()
64
39
  }
65
40
 
66
- /**
67
- * Do we have a connection to read from?
68
- */
69
- get isReadable (): boolean {
70
- return Boolean(this.inboundStream)
71
- }
72
-
73
- /**
74
- * Do we have a connection to write on?
75
- */
76
- get isWritable (): boolean {
77
- return Boolean(this.outboundStream)
78
- }
41
+ attachInboundStream (stream: Stream, streamOpts?: Partial<ProtobufStreamOpts>): void {
42
+ this.inboundPb = pbStream(stream, streamOpts).pb(RPC)
79
43
 
80
- /**
81
- * Send a message to this peer.
82
- * Throws if there is no `stream` to write to available.
83
- */
84
- write (data: Uint8Array | Uint8ArrayList): void {
85
- if (this.outboundStream == null) {
86
- const id = this.id.toString()
87
- throw new Error('No writable connection to ' + id)
88
- }
89
-
90
- this.outboundStream.push(data instanceof Uint8Array ? new Uint8ArrayList(data) : data)
91
- }
44
+ Promise.resolve().then(async () => {
45
+ while (true) {
46
+ if (this.inboundPb == null) {
47
+ return
48
+ }
92
49
 
93
- /**
94
- * Attach a raw inbound stream and setup a read stream
95
- */
96
- attachInboundStream (stream: Stream, decoderOptions?: DecoderOptions): AsyncIterable<Uint8ArrayList> {
97
- const abortListener = (): void => {
98
- stream.abort(new AbortError())
99
- }
50
+ const message = await this.inboundPb.read({
51
+ signal: this.shutDownController.signal
52
+ })
100
53
 
101
- this._inboundAbortController.signal.addEventListener('abort', abortListener, {
102
- once: true
54
+ this.safeDispatchEvent('message', {
55
+ detail: message
56
+ })
57
+ }
103
58
  })
59
+ .catch(err => {
60
+ this.inboundPb?.unwrap().unwrap().abort(err)
61
+ })
62
+ }
104
63
 
105
- // Create and attach a new inbound stream
106
- // The inbound stream is:
107
- // - abortable, set to only return on abort, rather than throw
108
- // - transformed with length-prefix transform
109
- this._rawInboundStream = stream
110
- this.inboundStream = pipe(
111
- this._rawInboundStream,
112
- (source) => lp.decode(source, decoderOptions)
113
- )
114
-
115
- this.dispatchEvent(new CustomEvent('stream:inbound'))
116
- return this.inboundStream
64
+ attachOutboundStream (stream: Stream, streamOpts?: Partial<ProtobufStreamOpts>): void {
65
+ this.outboundPb = pbStream(stream, streamOpts).pb(RPC)
117
66
  }
118
67
 
119
68
  /**
120
- * Attach a raw outbound stream and setup a write stream
69
+ * Send a message to this peer
121
70
  */
122
- async attachOutboundStream (stream: Stream): Promise<Pushable<Uint8ArrayList>> {
123
- // If an outbound stream already exists, gently close it
124
- const _prevStream = this.outboundStream
125
- if (this.outboundStream != null) {
126
- // End the stream without emitting a close event
127
- this.outboundStream.end()
71
+ write (message: PubSubRPC): void {
72
+ if (this.outboundPb == null) {
73
+ return
128
74
  }
129
75
 
130
- this._rawOutboundStream = stream
131
- this.outboundStream = pushable<Uint8ArrayList>({
132
- onEnd: (shouldEmit) => {
133
- // close writable side of the stream if it exists
134
- this._rawOutboundStream?.close()
135
- .catch(err => {
136
- this.log('error closing outbound stream', err)
137
- })
138
-
139
- this._rawOutboundStream = undefined
140
- this.outboundStream = undefined
141
- if (shouldEmit != null) {
142
- this.dispatchEvent(new CustomEvent('close'))
143
- }
144
- }
76
+ this.outboundPb.write(message, {
77
+ signal: this.shutDownController.signal
145
78
  })
146
-
147
- pipe(
148
- this.outboundStream,
149
- (source) => lp.encode(source),
150
- async (source) => {
151
- for await (const buf of source) {
152
- const sendMore = stream.send(buf)
153
-
154
- if (sendMore === false) {
155
- await pEvent(stream, 'drain', {
156
- rejectionEvents: [
157
- 'close'
158
- ]
159
- })
160
- }
161
- }
162
- }
163
- ).catch((err: Error) => {
164
- this.log.error(err)
165
- })
166
-
167
- // Only emit if the connection is new
168
- if (_prevStream == null) {
169
- this.dispatchEvent(new CustomEvent('stream:outbound'))
170
- }
171
-
172
- return this.outboundStream
79
+ .catch(err => {
80
+ this.outboundPb?.unwrap().unwrap().abort(err)
81
+ })
173
82
  }
174
83
 
175
84
  /**
176
85
  * Closes the open connection to peer
177
86
  */
178
87
  close (): void {
179
- if (this.closed) {
180
- return
181
- }
182
-
183
- this.closed = true
184
-
185
- // End the outbound stream
186
- if (this.outboundStream != null) {
187
- this.outboundStream.end()
188
- }
189
- // End the inbound stream
190
- if (this.inboundStream != null) {
191
- this._inboundAbortController.abort()
192
- }
193
-
194
- this._rawOutboundStream = undefined
195
- this.outboundStream = undefined
196
- this._rawInboundStream = undefined
197
- this.inboundStream = undefined
198
- this.dispatchEvent(new CustomEvent('close'))
88
+ this.shutDownController.abort()
89
+
90
+ Promise.all([
91
+ this.inboundPb?.unwrap().unwrap().close()
92
+ .catch(err => {
93
+ this.inboundPb?.unwrap().unwrap().abort(err)
94
+ }),
95
+ this.outboundPb?.unwrap().unwrap().close()
96
+ .catch(err => {
97
+ this.inboundPb?.unwrap().unwrap().abort(err)
98
+ })
99
+ ])
100
+ .finally(() => {
101
+ this.safeDispatchEvent('close')
102
+ })
199
103
  }
200
104
  }
package/src/utils.ts CHANGED
@@ -59,17 +59,6 @@ export const anyMatch = (a: Set<number> | number[], b: Set<number> | number[]):
59
59
  return false
60
60
  }
61
61
 
62
- /**
63
- * Make everything an array
64
- */
65
- export const ensureArray = function <T> (maybeArray: T | T[]): T[] {
66
- if (!Array.isArray(maybeArray)) {
67
- return [maybeArray]
68
- }
69
-
70
- return maybeArray
71
- }
72
-
73
62
  const isSigned = async (message: PubSubRPCMessage): Promise<boolean> => {
74
63
  if ((message.sequenceNumber == null) || (message.from == null) || (message.signature == null)) {
75
64
  return false
@@ -1,41 +0,0 @@
1
- {
2
- "TopicValidatorResult": "https://libp2p.github.io/js-libp2p/enums/_libp2p_floodsub.TopicValidatorResult.html",
3
- ".:TopicValidatorResult": "https://libp2p.github.io/js-libp2p/enums/_libp2p_floodsub.TopicValidatorResult.html",
4
- "FloodSub": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSub.html",
5
- ".:FloodSub": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSub.html",
6
- "FloodSubComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSubComponents.html",
7
- ".:FloodSubComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSubComponents.html",
8
- "FloodSubEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSubEvents.html",
9
- ".:FloodSubEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSubEvents.html",
10
- "FloodSubInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSubInit.html",
11
- ".:FloodSubInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.FloodSubInit.html",
12
- "PeerStreamEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.PeerStreamEvents.html",
13
- ".:PeerStreamEvents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.PeerStreamEvents.html",
14
- "PublishResult": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.PublishResult.html",
15
- ".:PublishResult": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.PublishResult.html",
16
- "SignedMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.SignedMessage.html",
17
- ".:SignedMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.SignedMessage.html",
18
- "Subscription": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.Subscription.html",
19
- ".:Subscription": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.Subscription.html",
20
- "SubscriptionChangeData": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.SubscriptionChangeData.html",
21
- ".:SubscriptionChangeData": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.SubscriptionChangeData.html",
22
- "TopicValidatorFn": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.TopicValidatorFn.html",
23
- ".:TopicValidatorFn": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.TopicValidatorFn.html",
24
- "UnsignedMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.UnsignedMessage.html",
25
- ".:UnsignedMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_floodsub.UnsignedMessage.html",
26
- "Message": "https://libp2p.github.io/js-libp2p/types/_libp2p_floodsub.Message.html",
27
- ".:Message": "https://libp2p.github.io/js-libp2p/types/_libp2p_floodsub.Message.html",
28
- "SignaturePolicy": "https://libp2p.github.io/js-libp2p/types/_libp2p_floodsub.SignaturePolicy.html",
29
- ".:SignaturePolicy": "https://libp2p.github.io/js-libp2p/types/_libp2p_floodsub.SignaturePolicy.html",
30
- "protocol": "https://libp2p.github.io/js-libp2p/variables/_libp2p_floodsub.protocol.html",
31
- ".:protocol": "https://libp2p.github.io/js-libp2p/variables/_libp2p_floodsub.protocol.html",
32
- "pubSubSymbol": "https://libp2p.github.io/js-libp2p/variables/_libp2p_floodsub.pubSubSymbol.html",
33
- "StrictNoSign": "https://libp2p.github.io/js-libp2p/variables/_libp2p_floodsub.StrictNoSign.html",
34
- ".:StrictNoSign": "https://libp2p.github.io/js-libp2p/variables/_libp2p_floodsub.StrictNoSign.html",
35
- "StrictSign": "https://libp2p.github.io/js-libp2p/variables/_libp2p_floodsub.StrictSign.html",
36
- ".:StrictSign": "https://libp2p.github.io/js-libp2p/variables/_libp2p_floodsub.StrictSign.html",
37
- "floodsub": "https://libp2p.github.io/js-libp2p/functions/_libp2p_floodsub.floodsub.html",
38
- ".:floodsub": "https://libp2p.github.io/js-libp2p/functions/_libp2p_floodsub.floodsub.html",
39
- "isPubSub": "https://libp2p.github.io/js-libp2p/functions/_libp2p_floodsub.isPubSub.html",
40
- ".:isPubSub": "https://libp2p.github.io/js-libp2p/functions/_libp2p_floodsub.isPubSub.html"
41
- }