@libp2p/pubsub 1.2.6 → 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/errors.d.ts +4 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +4 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +24 -22
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +141 -99
- package/dist/src/index.js.map +1 -1
- package/dist/src/message/rpc.d.ts +586 -175
- package/dist/src/message/rpc.js +1238 -67
- package/dist/src/message/sign.d.ts +1 -1
- package/dist/src/message/sign.d.ts.map +1 -1
- package/dist/src/message/sign.js +4 -8
- package/dist/src/message/sign.js.map +1 -1
- package/dist/src/peer-streams.d.ts +2 -2
- package/dist/src/peer-streams.d.ts.map +1 -1
- package/dist/src/peer-streams.js +3 -3
- package/dist/src/peer-streams.js.map +1 -1
- package/dist/src/utils.d.ts +2 -6
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +10 -17
- package/dist/src/utils.js.map +1 -1
- package/package.json +14 -18
- package/src/errors.ts +4 -0
- package/src/index.ts +171 -106
- package/src/message/rpc.d.ts +586 -175
- package/src/message/rpc.js +1238 -67
- package/src/message/rpc.proto +38 -4
- package/src/message/sign.ts +6 -9
- package/src/peer-streams.ts +4 -4
- package/src/utils.ts +11 -20
package/dist/src/errors.d.ts
CHANGED
@@ -15,6 +15,10 @@ export declare const codes: {
|
|
15
15
|
* Message expected to have a `seqno`, but doesn't
|
16
16
|
*/
|
17
17
|
ERR_MISSING_SEQNO: string;
|
18
|
+
/**
|
19
|
+
* Message expected to have a `key`, but doesn't
|
20
|
+
*/
|
21
|
+
ERR_MISSING_KEY: string;
|
18
22
|
/**
|
19
23
|
* Message `signature` is invalid
|
20
24
|
*/
|
package/dist/src/errors.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,KAAK;IAChB;;OAEG;;IAEH;;OAEG;;IAKH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAKH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;CAEJ,CAAA"}
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,KAAK;IAChB;;OAEG;;IAEH;;OAEG;;IAKH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAKH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;CAEJ,CAAA"}
|
package/dist/src/errors.js
CHANGED
@@ -16,6 +16,10 @@ export const codes = {
|
|
16
16
|
* Message expected to have a `seqno`, but doesn't
|
17
17
|
*/
|
18
18
|
ERR_MISSING_SEQNO: 'ERR_MISSING_SEQNO',
|
19
|
+
/**
|
20
|
+
* Message expected to have a `key`, but doesn't
|
21
|
+
*/
|
22
|
+
ERR_MISSING_KEY: 'ERR_MISSING_KEY',
|
19
23
|
/**
|
20
24
|
* Message `signature` is invalid
|
21
25
|
*/
|
package/dist/src/errors.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB;;OAEG;IACH,4BAA4B,EAAE,8BAA8B;IAC5D;;OAEG;IACH,8BAA8B,EAAE,gCAAgC;IAEhE,uBAAuB;IAEvB;;OAEG;IACH,qBAAqB,EAAE,uBAAuB;IAC9C;;OAEG;IACH,iBAAiB,EAAE,mBAAmB;IACtC;;OAEG;IACH,qBAAqB,EAAE,uBAAuB;IAC9C;;OAEG;IACH,gBAAgB,EAAE,kBAAkB;IAEpC,0BAA0B;IAE1B;;OAEG;IACH,mBAAmB,EAAE,qBAAqB;IAC1C;;OAEG;IACH,wBAAwB,EAAE,0BAA0B;IACpD;;OAEG;IACH,kBAAkB,EAAE,oBAAoB;IACxC;;OAEG;IACH,oBAAoB,EAAE,sBAAsB;CAC7C,CAAA"}
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB;;OAEG;IACH,4BAA4B,EAAE,8BAA8B;IAC5D;;OAEG;IACH,8BAA8B,EAAE,gCAAgC;IAEhE,uBAAuB;IAEvB;;OAEG;IACH,qBAAqB,EAAE,uBAAuB;IAC9C;;OAEG;IACH,iBAAiB,EAAE,mBAAmB;IACtC;;OAEG;IACH,eAAe,EAAE,iBAAiB;IAClC;;OAEG;IACH,qBAAqB,EAAE,uBAAuB;IAC9C;;OAEG;IACH,gBAAgB,EAAE,kBAAkB;IAEpC,0BAA0B;IAE1B;;OAEG;IACH,mBAAmB,EAAE,qBAAqB;IAC1C;;OAEG;IACH,wBAAwB,EAAE,0BAA0B;IACpD;;OAEG;IACH,kBAAkB,EAAE,oBAAoB;IACxC;;OAEG;IACH,oBAAoB,EAAE,sBAAsB;CAC7C,CAAA"}
|
package/dist/src/index.d.ts
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
import { EventEmitter } from '@libp2p/interfaces';
|
1
|
+
import { EventEmitter, EventHandler } from '@libp2p/interfaces';
|
2
2
|
import Queue from 'p-queue';
|
3
3
|
import type { PeerId } from '@libp2p/interfaces/peer-id';
|
4
4
|
import type { Registrar, IncomingStreamData } from '@libp2p/interfaces/registrar';
|
5
5
|
import type { Connection } from '@libp2p/interfaces/connection';
|
6
|
-
import type { PubSub, Message, StrictNoSign, StrictSign, PubSubOptions, PubSubEvents,
|
6
|
+
import type { PubSub, Message, StrictNoSign, StrictSign, PubSubOptions, PubSubEvents, RPC, PeerStreams, RPCSubscription } from '@libp2p/interfaces/pubsub';
|
7
7
|
import type { Logger } from '@libp2p/logger';
|
8
8
|
import type { PeerMap } from '@libp2p/peer-map';
|
9
9
|
import type { IRPC } from './message/rpc.js';
|
@@ -15,7 +15,7 @@ export interface TopicValidator {
|
|
15
15
|
* PubsubBaseProtocol handles the peers and connections logic for pubsub routers
|
16
16
|
* and specifies the API that pubsub routers should have.
|
17
17
|
*/
|
18
|
-
export declare abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap & PubSubEvents> implements PubSub<EventMap & PubSubEvents> {
|
18
|
+
export declare abstract class PubsubBaseProtocol<EventMap extends PubSubEvents = PubSubEvents> extends EventEmitter<EventMap & PubSubEvents> implements PubSub<EventMap & PubSubEvents> {
|
19
19
|
peerId: PeerId;
|
20
20
|
started: boolean;
|
21
21
|
/**
|
@@ -83,7 +83,7 @@ export declare abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<
|
|
83
83
|
/**
|
84
84
|
* Notifies the router that a peer has been connected
|
85
85
|
*/
|
86
|
-
|
86
|
+
addPeer(peerId: PeerId, protocol: string): PeerStreams;
|
87
87
|
/**
|
88
88
|
* Notifies the router that a peer has been disconnected
|
89
89
|
*/
|
@@ -91,23 +91,19 @@ export declare abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<
|
|
91
91
|
/**
|
92
92
|
* Responsible for processing each RPC message received by other peers.
|
93
93
|
*/
|
94
|
-
|
94
|
+
processMessages(peerId: PeerId, stream: AsyncIterable<Uint8Array>, peerStreams: PeerStreams): Promise<void>;
|
95
95
|
/**
|
96
96
|
* Handles an rpc request from a peer
|
97
97
|
*/
|
98
|
-
processRpc(from: PeerId, peerStreams: PeerStreams, rpc: RPC): Promise<
|
98
|
+
processRpc(from: PeerId, peerStreams: PeerStreams, rpc: RPC): Promise<void>;
|
99
99
|
/**
|
100
100
|
* Handles a subscription change from a peer
|
101
101
|
*/
|
102
|
-
|
102
|
+
processRpcSubOpt(id: PeerId, subOpt: RPCSubscription): void;
|
103
103
|
/**
|
104
104
|
* Handles an message from a peer
|
105
105
|
*/
|
106
|
-
|
107
|
-
/**
|
108
|
-
* Emit a message from a peer
|
109
|
-
*/
|
110
|
-
emitMessage(message: Message): void;
|
106
|
+
processMessage(from: PeerId, msg: Message): Promise<void>;
|
111
107
|
/**
|
112
108
|
* The default msgID implementation
|
113
109
|
* Child class can override this.
|
@@ -117,25 +113,29 @@ export declare abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<
|
|
117
113
|
* Whether to accept a message from a peer
|
118
114
|
* Override to create a graylist
|
119
115
|
*/
|
120
|
-
|
116
|
+
acceptFrom(id: PeerId): boolean;
|
121
117
|
/**
|
122
118
|
* Decode Uint8Array into an RPC object.
|
123
119
|
* This can be override to use a custom router protobuf.
|
124
120
|
*/
|
125
|
-
|
121
|
+
decodeRpc(bytes: Uint8Array): RPCProto;
|
126
122
|
/**
|
127
123
|
* Encode RPC object into a Uint8Array.
|
128
124
|
* This can be override to use a custom router protobuf.
|
129
125
|
*/
|
130
|
-
|
126
|
+
encodeRpc(rpc: IRPC): Uint8Array;
|
131
127
|
/**
|
132
128
|
* Send an rpc object to a peer
|
133
129
|
*/
|
134
|
-
|
130
|
+
send(peer: PeerId, data: {
|
131
|
+
messages?: Message[];
|
132
|
+
subscriptions?: string[];
|
133
|
+
subscribe?: boolean;
|
134
|
+
}): void;
|
135
135
|
/**
|
136
|
-
* Send
|
136
|
+
* Send an rpc object to a peer
|
137
137
|
*/
|
138
|
-
|
138
|
+
sendRpc(peer: PeerId, rpc: IRPC): void;
|
139
139
|
/**
|
140
140
|
* Validates the given message. The signature will be checked for authenticity.
|
141
141
|
* Throws an error on invalid messages
|
@@ -145,7 +145,7 @@ export declare abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<
|
|
145
145
|
* Normalizes the message and signs it, if signing is enabled.
|
146
146
|
* Should be used by the routers to create the message to send.
|
147
147
|
*/
|
148
|
-
|
148
|
+
buildMessage(message: Message): Promise<Message>;
|
149
149
|
/**
|
150
150
|
* Get a list of the peer-ids that are subscribed to one topic.
|
151
151
|
*/
|
@@ -153,18 +153,18 @@ export declare abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<
|
|
153
153
|
/**
|
154
154
|
* Publishes messages to all subscribed peers
|
155
155
|
*/
|
156
|
-
|
156
|
+
dispatchEvent(event: CustomEvent): boolean;
|
157
157
|
/**
|
158
158
|
* Overriding the implementation of publish should handle the appropriate algorithms for the publish/subscriber implementation.
|
159
159
|
* For example, a Floodsub implementation might simply publish each message to each topic for every peer
|
160
160
|
*/
|
161
|
-
abstract
|
161
|
+
abstract publishMessage(peerId: PeerId, message: Message): Promise<void>;
|
162
162
|
/**
|
163
163
|
* Subscribes to a given topic.
|
164
164
|
*/
|
165
165
|
subscribe(topic: string): void;
|
166
166
|
/**
|
167
|
-
* Unsubscribe from the given topic
|
167
|
+
* Unsubscribe from the given topic
|
168
168
|
*/
|
169
169
|
unsubscribe(topic: string): void;
|
170
170
|
/**
|
@@ -172,5 +172,7 @@ export declare abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<
|
|
172
172
|
*/
|
173
173
|
getTopics(): string[];
|
174
174
|
getPeers(): PeerId[];
|
175
|
+
addEventListener<U extends keyof EventMap>(type: U, callback: EventHandler<EventMap[U]>, options?: AddEventListenerOptions | boolean): void;
|
176
|
+
removeEventListener<U extends keyof EventMap>(type: U, callback: EventHandler<EventMap[U]> | undefined, options?: EventListenerOptions | boolean): void;
|
175
177
|
}
|
176
178
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAe,MAAM,oBAAoB,CAAA;
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.js
CHANGED
@@ -3,10 +3,10 @@ import { EventEmitter, CustomEvent } from '@libp2p/interfaces';
|
|
3
3
|
import errcode from 'err-code';
|
4
4
|
import { pipe } from 'it-pipe';
|
5
5
|
import Queue from 'p-queue';
|
6
|
-
import {
|
6
|
+
import { createTopology } from '@libp2p/topology';
|
7
7
|
import { codes } from './errors.js';
|
8
8
|
import { PeerStreams as PeerStreamsImpl } from './peer-streams.js';
|
9
|
-
import {
|
9
|
+
import { toMessage, ensureArray, randomSeqno, noSignMsgId, msgId, toRpcMessage } from './utils.js';
|
10
10
|
import { signMessage, verifySignature } from './message/sign.js';
|
11
11
|
import { base58btc } from 'multiformats/bases/base58';
|
12
12
|
import { peerMap } from '@libp2p/peer-map';
|
@@ -53,7 +53,7 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
53
53
|
this._registrarHandlerId = await this.registrar.handle(this.multicodecs, this._onIncomingStream);
|
54
54
|
// register protocol with topology
|
55
55
|
// Topology callbacks called on connection manager changes
|
56
|
-
const topology =
|
56
|
+
const topology = createTopology({
|
57
57
|
onConnect: this._onPeerConnected,
|
58
58
|
onDisconnect: this._onPeerDisconnected
|
59
59
|
});
|
@@ -93,9 +93,9 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
93
93
|
_onIncomingStream(evt) {
|
94
94
|
const { protocol, stream, connection } = evt.detail;
|
95
95
|
const peerId = connection.remotePeer;
|
96
|
-
const peer = this.
|
96
|
+
const peer = this.addPeer(peerId, protocol);
|
97
97
|
const inboundStream = peer.attachInboundStream(stream);
|
98
|
-
this.
|
98
|
+
this.processMessages(peerId, inboundStream, peer)
|
99
99
|
.catch(err => this.log(err));
|
100
100
|
}
|
101
101
|
/**
|
@@ -105,14 +105,14 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
105
105
|
this.log('connected %p', peerId);
|
106
106
|
try {
|
107
107
|
const { stream, protocol } = await conn.newStream(this.multicodecs);
|
108
|
-
const peer = this.
|
108
|
+
const peer = this.addPeer(peerId, protocol);
|
109
109
|
await peer.attachOutboundStream(stream);
|
110
110
|
}
|
111
111
|
catch (err) {
|
112
112
|
this.log.error(err);
|
113
113
|
}
|
114
114
|
// Immediately send my own subscriptions to the newly established conn
|
115
|
-
this.
|
115
|
+
this.send(peerId, { subscriptions: Array.from(this.subscriptions).map(sub => sub.toString()), subscribe: true });
|
116
116
|
}
|
117
117
|
/**
|
118
118
|
* Registrar notifies a closing connection with pubsub protocol
|
@@ -125,7 +125,7 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
125
125
|
/**
|
126
126
|
* Notifies the router that a peer has been connected
|
127
127
|
*/
|
128
|
-
|
128
|
+
addPeer(peerId, protocol) {
|
129
129
|
const existing = this.peers.get(peerId);
|
130
130
|
// If peer streams already exists, do nothing
|
131
131
|
if (existing != null) {
|
@@ -167,28 +167,36 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
167
167
|
/**
|
168
168
|
* Responsible for processing each RPC message received by other peers.
|
169
169
|
*/
|
170
|
-
async
|
170
|
+
async processMessages(peerId, stream, peerStreams) {
|
171
171
|
try {
|
172
172
|
await pipe(stream, async (source) => {
|
173
173
|
for await (const data of source) {
|
174
|
-
const rpcMsg = this.
|
175
|
-
|
174
|
+
const rpcMsg = this.decodeRpc(data);
|
175
|
+
const messages = [];
|
176
|
+
for (const msg of (rpcMsg.messages ?? [])) {
|
177
|
+
if (msg.from == null || msg.data == null || msg.topic == null) {
|
178
|
+
this.log('message from %p was missing from, data or topic fields, dropping', peerId);
|
179
|
+
continue;
|
180
|
+
}
|
181
|
+
messages.push({
|
182
|
+
from: msg.from,
|
183
|
+
data: msg.data,
|
184
|
+
topic: msg.topic,
|
185
|
+
seqno: msg.seqno ?? undefined,
|
186
|
+
signature: msg.signature ?? undefined,
|
187
|
+
key: msg.key ?? undefined
|
188
|
+
});
|
189
|
+
}
|
190
|
+
// Since processRpc may be overridden entirely in unsafe ways,
|
176
191
|
// the simplest/safest option here is to wrap in a function and capture all errors
|
177
192
|
// to prevent a top-level unhandled exception
|
178
193
|
// This processing of rpc messages should happen without awaiting full validation/execution of prior messages
|
179
194
|
this.processRpc(peerId, peerStreams, {
|
180
195
|
subscriptions: (rpcMsg.subscriptions).map(sub => ({
|
181
196
|
subscribe: Boolean(sub.subscribe),
|
182
|
-
|
197
|
+
topic: sub.topic ?? ''
|
183
198
|
})),
|
184
|
-
|
185
|
-
from: msg.from ?? peerId.multihash.bytes,
|
186
|
-
data: msg.data ?? new Uint8Array(0),
|
187
|
-
topicIDs: msg.topicIDs ?? [],
|
188
|
-
seqno: msg.seqno ?? undefined,
|
189
|
-
signature: msg.signature ?? undefined,
|
190
|
-
key: msg.key ?? undefined
|
191
|
-
}))
|
199
|
+
messages
|
192
200
|
})
|
193
201
|
.catch(err => this.log(err));
|
194
202
|
}
|
@@ -202,36 +210,32 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
202
210
|
* Handles an rpc request from a peer
|
203
211
|
*/
|
204
212
|
async processRpc(from, peerStreams, rpc) {
|
213
|
+
if (!this.acceptFrom(from)) {
|
214
|
+
this.log('received message from unacceptable peer %p', from);
|
215
|
+
return;
|
216
|
+
}
|
205
217
|
this.log('rpc from %p', from);
|
206
|
-
const
|
207
|
-
|
208
|
-
|
218
|
+
const { subscriptions, messages } = rpc;
|
219
|
+
if (subscriptions.length > 0) {
|
220
|
+
this.log('subscription update from %p', from);
|
209
221
|
// update peer subscriptions
|
210
|
-
|
211
|
-
this.
|
222
|
+
subscriptions.forEach((subOpt) => {
|
223
|
+
this.processRpcSubOpt(from, subOpt);
|
212
224
|
});
|
213
|
-
|
214
|
-
detail: { peerId: peerStreams.id, subscriptions
|
225
|
+
super.dispatchEvent(new CustomEvent('pubsub:subscription-change', {
|
226
|
+
detail: { peerId: peerStreams.id, subscriptions }
|
215
227
|
}));
|
216
228
|
}
|
217
|
-
if (
|
218
|
-
this.log('
|
219
|
-
|
220
|
-
|
221
|
-
if (msgs.length > 0) {
|
222
|
-
this.queue.addAll(msgs.map(message => async () => {
|
223
|
-
const topics = message.topicIDs != null ? message.topicIDs : [];
|
224
|
-
const hasSubscription = topics.some((topic) => this.subscriptions.has(topic));
|
225
|
-
if (!hasSubscription && !this.canRelayMessage) {
|
229
|
+
if (messages.length > 0) {
|
230
|
+
this.log('messages from %p', from);
|
231
|
+
this.queue.addAll(messages.map(message => async () => {
|
232
|
+
if (!this.subscriptions.has(message.topic) && !this.canRelayMessage) {
|
226
233
|
this.log('received message we didn\'t subscribe to. Dropping.');
|
227
234
|
return;
|
228
235
|
}
|
229
236
|
try {
|
230
|
-
const msg = toMessage(
|
231
|
-
|
232
|
-
from: from.multihash.bytes
|
233
|
-
});
|
234
|
-
await this._processMessage(msg);
|
237
|
+
const msg = await toMessage(message);
|
238
|
+
await this.processMessage(from, msg);
|
235
239
|
}
|
236
240
|
catch (err) {
|
237
241
|
this.log.error(err);
|
@@ -239,13 +243,12 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
239
243
|
}))
|
240
244
|
.catch(err => this.log(err));
|
241
245
|
}
|
242
|
-
return true;
|
243
246
|
}
|
244
247
|
/**
|
245
248
|
* Handles a subscription change from a peer
|
246
249
|
*/
|
247
|
-
|
248
|
-
const t = subOpt.
|
250
|
+
processRpcSubOpt(id, subOpt) {
|
251
|
+
const t = subOpt.topic;
|
249
252
|
if (t == null) {
|
250
253
|
return;
|
251
254
|
}
|
@@ -266,8 +269,8 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
266
269
|
/**
|
267
270
|
* Handles an message from a peer
|
268
271
|
*/
|
269
|
-
async
|
270
|
-
if (this.peerId.equals(
|
272
|
+
async processMessage(from, msg) {
|
273
|
+
if (this.peerId.equals(from) && !this.emitSelf) {
|
271
274
|
return;
|
272
275
|
}
|
273
276
|
// Ensure the message is valid before processing it
|
@@ -278,21 +281,15 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
278
281
|
this.log('Message is invalid, dropping it. %O', err);
|
279
282
|
return;
|
280
283
|
}
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
* Emit a message from a peer
|
287
|
-
*/
|
288
|
-
emitMessage(message) {
|
289
|
-
message.topicIDs.forEach((topic) => {
|
290
|
-
if (this.subscriptions.has(topic)) {
|
291
|
-
this.dispatchEvent(new CustomEvent(topic, {
|
292
|
-
detail: message
|
284
|
+
if (this.subscriptions.has(msg.topic)) {
|
285
|
+
const isFromSelf = this.peerId.equals(from);
|
286
|
+
if (!isFromSelf || this.emitSelf) {
|
287
|
+
super.dispatchEvent(new CustomEvent(msg.topic, {
|
288
|
+
detail: msg
|
293
289
|
}));
|
294
290
|
}
|
295
|
-
}
|
291
|
+
}
|
292
|
+
await this.publishMessage(from, msg);
|
296
293
|
}
|
297
294
|
/**
|
298
295
|
* The default msgID implementation
|
@@ -305,7 +302,10 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
305
302
|
if (msg.seqno == null) {
|
306
303
|
throw errcode(new Error('Need seqno when signature policy is StrictSign but it was missing'), codes.ERR_MISSING_SEQNO);
|
307
304
|
}
|
308
|
-
|
305
|
+
if (msg.key == null) {
|
306
|
+
throw errcode(new Error('Need key when signature policy is StrictSign but it was missing'), codes.ERR_MISSING_KEY);
|
307
|
+
}
|
308
|
+
return msgId(msg.key, msg.seqno);
|
309
309
|
case 'StrictNoSign':
|
310
310
|
return noSignMsgId(msg.data);
|
311
311
|
default:
|
@@ -316,42 +316,44 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
316
316
|
* Whether to accept a message from a peer
|
317
317
|
* Override to create a graylist
|
318
318
|
*/
|
319
|
-
|
319
|
+
acceptFrom(id) {
|
320
320
|
return true;
|
321
321
|
}
|
322
322
|
/**
|
323
323
|
* Decode Uint8Array into an RPC object.
|
324
324
|
* This can be override to use a custom router protobuf.
|
325
325
|
*/
|
326
|
-
|
326
|
+
decodeRpc(bytes) {
|
327
327
|
return RPCProto.decode(bytes);
|
328
328
|
}
|
329
329
|
/**
|
330
330
|
* Encode RPC object into a Uint8Array.
|
331
331
|
* This can be override to use a custom router protobuf.
|
332
332
|
*/
|
333
|
-
|
333
|
+
encodeRpc(rpc) {
|
334
334
|
return RPCProto.encode(rpc).finish();
|
335
335
|
}
|
336
336
|
/**
|
337
337
|
* Send an rpc object to a peer
|
338
338
|
*/
|
339
|
-
|
339
|
+
send(peer, data) {
|
340
|
+
const { messages, subscriptions, subscribe } = data;
|
341
|
+
return this.sendRpc(peer, {
|
342
|
+
subscriptions: (subscriptions ?? []).map(str => ({ topic: str, subscribe: Boolean(subscribe) })),
|
343
|
+
messages: (messages ?? []).map(toRpcMessage)
|
344
|
+
});
|
345
|
+
}
|
346
|
+
/**
|
347
|
+
* Send an rpc object to a peer
|
348
|
+
*/
|
349
|
+
sendRpc(peer, rpc) {
|
340
350
|
const peerStreams = this.peers.get(peer);
|
341
351
|
if (peerStreams == null || !peerStreams.isWritable) {
|
342
352
|
const msg = `Cannot send RPC to ${peer.toString(base58btc)} as there is no open stream to it available`;
|
343
353
|
this.log.error(msg);
|
344
354
|
return;
|
345
355
|
}
|
346
|
-
peerStreams.write(this.
|
347
|
-
}
|
348
|
-
/**
|
349
|
-
* Send subscriptions to a peer
|
350
|
-
*/
|
351
|
-
_sendSubscriptions(id, topics, subscribe) {
|
352
|
-
return this._sendRpc(id, {
|
353
|
-
subscriptions: topics.map(t => ({ topicID: t, subscribe: subscribe }))
|
354
|
-
});
|
356
|
+
peerStreams.write(this.encodeRpc(rpc));
|
355
357
|
}
|
356
358
|
/**
|
357
359
|
* Validates the given message. The signature will be checked for authenticity.
|
@@ -385,18 +387,16 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
385
387
|
default:
|
386
388
|
throw errcode(new Error('Cannot validate message: unhandled signature policy'), codes.ERR_UNHANDLED_SIGNATURE_POLICY);
|
387
389
|
}
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
await validatorFn(topic, message);
|
392
|
-
}
|
390
|
+
const validatorFn = this.topicValidators.get(message.topic);
|
391
|
+
if (validatorFn != null) {
|
392
|
+
await validatorFn(message.topic, message);
|
393
393
|
}
|
394
394
|
}
|
395
395
|
/**
|
396
396
|
* Normalizes the message and signs it, if signing is enabled.
|
397
397
|
* Should be used by the routers to create the message to send.
|
398
398
|
*/
|
399
|
-
async
|
399
|
+
async buildMessage(message) {
|
400
400
|
const signaturePolicy = this.globalSignaturePolicy;
|
401
401
|
switch (signaturePolicy) {
|
402
402
|
case 'StrictSign':
|
@@ -419,7 +419,7 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
419
419
|
if (topic == null) {
|
420
420
|
throw errcode(new Error('topic is required'), 'ERR_NOT_VALID_TOPIC');
|
421
421
|
}
|
422
|
-
const peersInTopic = this.topics.get(topic);
|
422
|
+
const peersInTopic = this.topics.get(topic.toString());
|
423
423
|
if (peersInTopic == null) {
|
424
424
|
return [];
|
425
425
|
}
|
@@ -428,22 +428,40 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
428
428
|
/**
|
429
429
|
* Publishes messages to all subscribed peers
|
430
430
|
*/
|
431
|
-
|
431
|
+
dispatchEvent(event) {
|
432
432
|
if (!this.started) {
|
433
433
|
throw new Error('Pubsub has not started');
|
434
434
|
}
|
435
|
+
const topic = event.type;
|
436
|
+
let message = event.detail;
|
437
|
+
if (message instanceof Uint8Array) {
|
438
|
+
message = {
|
439
|
+
from: this.peerId,
|
440
|
+
topic,
|
441
|
+
data: message
|
442
|
+
};
|
443
|
+
}
|
435
444
|
this.log('publish', topic, message);
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
445
|
+
Promise.resolve().then(async () => {
|
446
|
+
message = await this.buildMessage(message);
|
447
|
+
// dispatch the event if we are interested
|
448
|
+
if (this.emitSelf) {
|
449
|
+
if (this.subscriptions.has(topic)) {
|
450
|
+
super.dispatchEvent(new CustomEvent(topic, {
|
451
|
+
detail: message
|
452
|
+
}));
|
453
|
+
if (this.listenerCount(topic) === 0) {
|
454
|
+
this.unsubscribe(topic);
|
455
|
+
}
|
456
|
+
}
|
457
|
+
}
|
458
|
+
// send to all the other peers
|
459
|
+
await this.publishMessage(this.peerId, message);
|
460
|
+
})
|
461
|
+
.catch(err => {
|
462
|
+
this.log.error(err);
|
463
|
+
});
|
464
|
+
return true;
|
447
465
|
}
|
448
466
|
/**
|
449
467
|
* Subscribes to a given topic.
|
@@ -452,24 +470,37 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
452
470
|
if (!this.started) {
|
453
471
|
throw new Error('Pubsub has not started');
|
454
472
|
}
|
455
|
-
|
456
|
-
|
473
|
+
const topicStr = topic.toString();
|
474
|
+
if (topicStr === 'pubsub:subscription-change') {
|
475
|
+
return;
|
476
|
+
}
|
477
|
+
if (!this.subscriptions.has(topicStr)) {
|
478
|
+
this.subscriptions.add(topicStr);
|
457
479
|
for (const peerId of this.peers.keys()) {
|
458
|
-
this.
|
480
|
+
this.send(peerId, { subscriptions: [topicStr], subscribe: true });
|
459
481
|
}
|
460
482
|
}
|
461
483
|
}
|
462
484
|
/**
|
463
|
-
* Unsubscribe from the given topic
|
485
|
+
* Unsubscribe from the given topic
|
464
486
|
*/
|
465
487
|
unsubscribe(topic) {
|
466
488
|
if (!this.started) {
|
467
489
|
throw new Error('Pubsub is not started');
|
468
490
|
}
|
469
|
-
|
470
|
-
|
491
|
+
// @ts-expect-error topic should be a key of the event map
|
492
|
+
super.removeEventListener(topic);
|
493
|
+
const topicStr = topic.toString();
|
494
|
+
if (topicStr === 'pubsub:subscription-change') {
|
495
|
+
return;
|
496
|
+
}
|
497
|
+
const wasSubscribed = this.subscriptions.has(topicStr);
|
498
|
+
const listeners = this.listenerCount(topicStr);
|
499
|
+
this.log('unsubscribe from %s - am subscribed %s, listeners %d', topic, wasSubscribed, listeners);
|
500
|
+
if (wasSubscribed && listeners === 0) {
|
501
|
+
this.subscriptions.delete(topicStr);
|
471
502
|
for (const peerId of this.peers.keys()) {
|
472
|
-
this.
|
503
|
+
this.send(peerId, { subscriptions: [topicStr], subscribe: false });
|
473
504
|
}
|
474
505
|
}
|
475
506
|
}
|
@@ -488,5 +519,16 @@ export class PubsubBaseProtocol extends EventEmitter {
|
|
488
519
|
}
|
489
520
|
return Array.from(this.peers.keys());
|
490
521
|
}
|
522
|
+
addEventListener(type, callback, options) {
|
523
|
+
this.subscribe(type.toString());
|
524
|
+
super.addEventListener(type, callback, options);
|
525
|
+
}
|
526
|
+
removeEventListener(type, callback, options) {
|
527
|
+
super.removeEventListener(type, callback, options);
|
528
|
+
const topicStr = type.toString();
|
529
|
+
if (this.listenerCount(topicStr) === 0) {
|
530
|
+
this.unsubscribe(topicStr);
|
531
|
+
}
|
532
|
+
}
|
491
533
|
}
|
492
534
|
//# sourceMappingURL=index.js.map
|