libp2p 0.35.9-rc.2 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.min.js +55 -0
- package/dist/src/circuit/auto-relay.d.ts.map +1 -1
- package/dist/src/config.d.ts +2 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/connection-manager/auto-dialler.d.ts.map +1 -1
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/dialer/index.d.ts +7 -2
- package/dist/src/dialer/index.d.ts.map +1 -1
- package/dist/src/errors.d.ts +2 -0
- package/dist/src/fetch/constants.d.ts +2 -0
- package/dist/src/fetch/constants.d.ts.map +1 -0
- package/dist/src/fetch/index.d.ts +76 -0
- package/dist/src/fetch/index.d.ts.map +1 -0
- package/dist/src/fetch/proto.d.ts +134 -0
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/index.d.ts +110 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/peer-store/address-book.d.ts +3 -1
- package/dist/src/peer-store/address-book.d.ts.map +1 -1
- package/dist/src/peer-store/index.d.ts +5 -2
- package/dist/src/peer-store/index.d.ts.map +1 -1
- package/dist/src/peer-store/store.d.ts.map +1 -1
- package/dist/src/types.d.ts +90 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/upgrader.d.ts +8 -2
- package/dist/src/upgrader.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/circuit/auto-relay.js +36 -22
- package/src/config.js +2 -0
- package/src/connection-manager/auto-dialler.js +15 -6
- package/src/connection-manager/index.js +3 -0
- package/src/dialer/index.js +20 -1
- package/src/errors.js +2 -0
- package/src/fetch/README.md +36 -0
- package/src/fetch/constants.js +6 -0
- package/src/fetch/index.js +159 -0
- package/src/fetch/proto.d.ts +134 -0
- package/src/fetch/proto.js +333 -0
- package/src/fetch/proto.proto +15 -0
- package/src/identify/index.js +21 -17
- package/src/index.js +40 -1
- package/src/peer-store/address-book.js +41 -28
- package/src/peer-store/index.js +4 -2
- package/src/peer-store/store.js +19 -6
- package/src/types.ts +98 -0
- package/src/upgrader.js +29 -1
package/src/index.js
CHANGED
|
@@ -31,6 +31,7 @@ const PubsubAdapter = require('./pubsub-adapter')
|
|
|
31
31
|
const Registrar = require('./registrar')
|
|
32
32
|
const ping = require('./ping')
|
|
33
33
|
const IdentifyService = require('./identify')
|
|
34
|
+
const FetchService = require('./fetch')
|
|
34
35
|
const NatManager = require('./nat-manager')
|
|
35
36
|
const { updateSelfPeerRecord } = require('./record/utils')
|
|
36
37
|
|
|
@@ -47,6 +48,7 @@ const { updateSelfPeerRecord } = require('./record/utils')
|
|
|
47
48
|
* @typedef {import('libp2p-interfaces/src/pubsub').PubsubOptions} PubsubOptions
|
|
48
49
|
* @typedef {import('interface-datastore').Datastore} Datastore
|
|
49
50
|
* @typedef {import('./pnet')} Protector
|
|
51
|
+
* @typedef {import('./types').ConnectionGater} ConnectionGater
|
|
50
52
|
* @typedef {Object} PersistentPeerStoreOptions
|
|
51
53
|
* @property {number} [threshold]
|
|
52
54
|
*/
|
|
@@ -105,6 +107,7 @@ const { updateSelfPeerRecord } = require('./record/utils')
|
|
|
105
107
|
* @property {Libp2pModules} modules libp2p modules to use
|
|
106
108
|
* @property {import('./address-manager').AddressManagerOptions} [addresses]
|
|
107
109
|
* @property {import('./connection-manager').ConnectionManagerOptions} [connectionManager]
|
|
110
|
+
* @property {Partial<import('./types').ConnectionGater>} [connectionGater]
|
|
108
111
|
* @property {Datastore} [datastore]
|
|
109
112
|
* @property {import('./dialer').DialerOptions} [dialer]
|
|
110
113
|
* @property {import('./identify/index').HostProperties} [host] libp2p host
|
|
@@ -171,10 +174,25 @@ class Libp2p extends EventEmitter {
|
|
|
171
174
|
this.metrics = metrics
|
|
172
175
|
}
|
|
173
176
|
|
|
177
|
+
/** @type {ConnectionGater} */
|
|
178
|
+
this.connectionGater = {
|
|
179
|
+
denyDialPeer: async () => Promise.resolve(false),
|
|
180
|
+
denyDialMultiaddr: async () => Promise.resolve(false),
|
|
181
|
+
denyInboundConnection: async () => Promise.resolve(false),
|
|
182
|
+
denyOutboundConnection: async () => Promise.resolve(false),
|
|
183
|
+
denyInboundEncryptedConnection: async () => Promise.resolve(false),
|
|
184
|
+
denyOutboundEncryptedConnection: async () => Promise.resolve(false),
|
|
185
|
+
denyInboundUpgradedConnection: async () => Promise.resolve(false),
|
|
186
|
+
denyOutboundUpgradedConnection: async () => Promise.resolve(false),
|
|
187
|
+
filterMultiaddrForPeer: async () => Promise.resolve(true),
|
|
188
|
+
...this._options.connectionGater
|
|
189
|
+
}
|
|
190
|
+
|
|
174
191
|
/** @type {import('./peer-store/types').PeerStore} */
|
|
175
192
|
this.peerStore = new PeerStore({
|
|
176
193
|
peerId: this.peerId,
|
|
177
|
-
datastore: (this.datastore && this._options.peerStore.persistence) ? this.datastore : new MemoryDatastore()
|
|
194
|
+
datastore: (this.datastore && this._options.peerStore.persistence) ? this.datastore : new MemoryDatastore(),
|
|
195
|
+
addressFilter: this.connectionGater.filterMultiaddrForPeer
|
|
178
196
|
})
|
|
179
197
|
|
|
180
198
|
// Addresses {listen, announce, noAnnounce}
|
|
@@ -219,6 +237,7 @@ class Libp2p extends EventEmitter {
|
|
|
219
237
|
|
|
220
238
|
// Setup the Upgrader
|
|
221
239
|
this.upgrader = new Upgrader({
|
|
240
|
+
connectionGater: this.connectionGater,
|
|
222
241
|
localPeer: this.peerId,
|
|
223
242
|
metrics: this.metrics,
|
|
224
243
|
onConnection: (connection) => this.connectionManager.onConnect(connection),
|
|
@@ -261,6 +280,7 @@ class Libp2p extends EventEmitter {
|
|
|
261
280
|
|
|
262
281
|
this.dialer = new Dialer({
|
|
263
282
|
transportManager: this.transportManager,
|
|
283
|
+
connectionGater: this.connectionGater,
|
|
264
284
|
peerStore: this.peerStore,
|
|
265
285
|
metrics: this.metrics,
|
|
266
286
|
...this._options.dialer
|
|
@@ -323,6 +343,8 @@ class Libp2p extends EventEmitter {
|
|
|
323
343
|
ping.mount(this)
|
|
324
344
|
|
|
325
345
|
this._onDiscoveryPeer = this._onDiscoveryPeer.bind(this)
|
|
346
|
+
|
|
347
|
+
this.fetchService = new FetchService(this)
|
|
326
348
|
}
|
|
327
349
|
|
|
328
350
|
/**
|
|
@@ -356,6 +378,10 @@ class Libp2p extends EventEmitter {
|
|
|
356
378
|
await this.handle(Object.values(IdentifyService.getProtocolStr(this)), this.identifyService.handleMessage)
|
|
357
379
|
}
|
|
358
380
|
|
|
381
|
+
if (this.fetchService) {
|
|
382
|
+
await this.handle(FetchService.PROTOCOL, this.fetchService.handleMessage)
|
|
383
|
+
}
|
|
384
|
+
|
|
359
385
|
try {
|
|
360
386
|
await this._onStarting()
|
|
361
387
|
await this._onDidStart()
|
|
@@ -407,6 +433,8 @@ class Libp2p extends EventEmitter {
|
|
|
407
433
|
await this.natManager.stop()
|
|
408
434
|
await this.transportManager.close()
|
|
409
435
|
|
|
436
|
+
this.unhandle(FetchService.PROTOCOL)
|
|
437
|
+
|
|
410
438
|
ping.unmount(this)
|
|
411
439
|
this.dialer.destroy()
|
|
412
440
|
} catch (/** @type {any} */ err) {
|
|
@@ -559,6 +587,17 @@ class Libp2p extends EventEmitter {
|
|
|
559
587
|
)
|
|
560
588
|
}
|
|
561
589
|
|
|
590
|
+
/**
|
|
591
|
+
* Sends a request to fetch the value associated with the given key from the given peer.
|
|
592
|
+
*
|
|
593
|
+
* @param {PeerId|Multiaddr} peer
|
|
594
|
+
* @param {string} key
|
|
595
|
+
* @returns {Promise<Uint8Array | null>}
|
|
596
|
+
*/
|
|
597
|
+
fetch (peer, key) {
|
|
598
|
+
return this.fetchService.fetch(peer, key)
|
|
599
|
+
}
|
|
600
|
+
|
|
562
601
|
/**
|
|
563
602
|
* Pings the given peer in order to obtain the operation latency.
|
|
564
603
|
*
|
|
@@ -7,6 +7,11 @@ const PeerId = require('peer-id')
|
|
|
7
7
|
const { codes } = require('../errors')
|
|
8
8
|
const PeerRecord = require('../record/peer-record')
|
|
9
9
|
const Envelope = require('../record/envelope')
|
|
10
|
+
const { pipe } = require('it-pipe')
|
|
11
|
+
const all = require('it-all')
|
|
12
|
+
const filter = require('it-filter')
|
|
13
|
+
const map = require('it-map')
|
|
14
|
+
const each = require('it-foreach')
|
|
10
15
|
|
|
11
16
|
/**
|
|
12
17
|
* @typedef {import('./types').PeerStore} PeerStore
|
|
@@ -27,10 +32,12 @@ class PeerStoreAddressBook {
|
|
|
27
32
|
/**
|
|
28
33
|
* @param {PeerStore["emit"]} emit
|
|
29
34
|
* @param {import('./types').Store} store
|
|
35
|
+
* @param {(peerId: PeerId, multiaddr: Multiaddr) => Promise<boolean>} addressFilter
|
|
30
36
|
*/
|
|
31
|
-
constructor (emit, store) {
|
|
37
|
+
constructor (emit, store, addressFilter) {
|
|
32
38
|
this._emit = emit
|
|
33
39
|
this._store = store
|
|
40
|
+
this._addressFilter = addressFilter
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
/**
|
|
@@ -88,7 +95,7 @@ class PeerStoreAddressBook {
|
|
|
88
95
|
// Replace unsigned addresses by the new ones from the record
|
|
89
96
|
// TODO: Once we have ttls for the addresses, we should merge these in
|
|
90
97
|
updatedPeer = await this._store.patchOrCreate(peerId, {
|
|
91
|
-
addresses:
|
|
98
|
+
addresses: await filterMultiaddrs(peerId, multiaddrs, this._addressFilter, true),
|
|
92
99
|
peerRecordEnvelope: envelope.marshal()
|
|
93
100
|
})
|
|
94
101
|
|
|
@@ -180,6 +187,11 @@ class PeerStoreAddressBook {
|
|
|
180
187
|
throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS)
|
|
181
188
|
}
|
|
182
189
|
|
|
190
|
+
if (!Array.isArray(multiaddrs)) {
|
|
191
|
+
log.error('multiaddrs must be an array of Multiaddrs')
|
|
192
|
+
throw errcode(new Error('multiaddrs must be an array of Multiaddrs'), codes.ERR_INVALID_PARAMETERS)
|
|
193
|
+
}
|
|
194
|
+
|
|
183
195
|
log('set await write lock')
|
|
184
196
|
const release = await this._store.lock.writeLock()
|
|
185
197
|
log('set got write lock')
|
|
@@ -188,7 +200,7 @@ class PeerStoreAddressBook {
|
|
|
188
200
|
let updatedPeer
|
|
189
201
|
|
|
190
202
|
try {
|
|
191
|
-
const addresses =
|
|
203
|
+
const addresses = await filterMultiaddrs(peerId, multiaddrs, this._addressFilter)
|
|
192
204
|
|
|
193
205
|
// No valid addresses found
|
|
194
206
|
if (!addresses.length) {
|
|
@@ -238,6 +250,11 @@ class PeerStoreAddressBook {
|
|
|
238
250
|
throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS)
|
|
239
251
|
}
|
|
240
252
|
|
|
253
|
+
if (!Array.isArray(multiaddrs)) {
|
|
254
|
+
log.error('multiaddrs must be an array of Multiaddrs')
|
|
255
|
+
throw errcode(new Error('multiaddrs must be an array of Multiaddrs'), codes.ERR_INVALID_PARAMETERS)
|
|
256
|
+
}
|
|
257
|
+
|
|
241
258
|
log('add await write lock')
|
|
242
259
|
const release = await this._store.lock.writeLock()
|
|
243
260
|
log('add got write lock')
|
|
@@ -246,7 +263,7 @@ class PeerStoreAddressBook {
|
|
|
246
263
|
let updatedPeer
|
|
247
264
|
|
|
248
265
|
try {
|
|
249
|
-
const addresses =
|
|
266
|
+
const addresses = await filterMultiaddrs(peerId, multiaddrs, this._addressFilter)
|
|
250
267
|
|
|
251
268
|
// No valid addresses found
|
|
252
269
|
if (!addresses.length) {
|
|
@@ -337,33 +354,29 @@ class PeerStoreAddressBook {
|
|
|
337
354
|
}
|
|
338
355
|
|
|
339
356
|
/**
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
* @private
|
|
357
|
+
* @param {PeerId} peerId
|
|
343
358
|
* @param {Multiaddr[]} multiaddrs
|
|
344
|
-
* @param {boolean}
|
|
345
|
-
* @
|
|
359
|
+
* @param {(peerId: PeerId, multiaddr: Multiaddr) => Promise<boolean>} addressFilter
|
|
360
|
+
* @param {boolean} isCertified
|
|
346
361
|
*/
|
|
347
|
-
function
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return Array.from(
|
|
355
|
-
new Set(multiaddrs.map(ma => ma.toString()))
|
|
356
|
-
)
|
|
357
|
-
.map(addr => {
|
|
358
|
-
try {
|
|
359
|
-
return {
|
|
360
|
-
multiaddr: new Multiaddr(addr),
|
|
361
|
-
isCertified
|
|
362
|
-
}
|
|
363
|
-
} catch (err) {
|
|
364
|
-
throw errcode(err, codes.ERR_INVALID_PARAMETERS)
|
|
362
|
+
function filterMultiaddrs (peerId, multiaddrs, addressFilter, isCertified = false) {
|
|
363
|
+
return pipe(
|
|
364
|
+
multiaddrs,
|
|
365
|
+
(source) => each(source, (multiaddr) => {
|
|
366
|
+
if (!Multiaddr.isMultiaddr(multiaddr)) {
|
|
367
|
+
log.error('multiaddr must be an instance of Multiaddr')
|
|
368
|
+
throw errcode(new Error('multiaddr must be an instance of Multiaddr'), codes.ERR_INVALID_PARAMETERS)
|
|
365
369
|
}
|
|
366
|
-
})
|
|
370
|
+
}),
|
|
371
|
+
(source) => filter(source, (multiaddr) => addressFilter(peerId, multiaddr)),
|
|
372
|
+
(source) => map(source, (multiaddr) => {
|
|
373
|
+
return {
|
|
374
|
+
multiaddr: new Multiaddr(multiaddr.toString()),
|
|
375
|
+
isCertified
|
|
376
|
+
}
|
|
377
|
+
}),
|
|
378
|
+
(source) => all(source)
|
|
379
|
+
)
|
|
367
380
|
}
|
|
368
381
|
|
|
369
382
|
module.exports = PeerStoreAddressBook
|
package/src/peer-store/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const Store = require('./store')
|
|
|
12
12
|
* @typedef {import('./types').PeerStore} PeerStore
|
|
13
13
|
* @typedef {import('./types').Peer} Peer
|
|
14
14
|
* @typedef {import('peer-id')} PeerId
|
|
15
|
+
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
|
15
16
|
*/
|
|
16
17
|
|
|
17
18
|
const log = Object.assign(debug('libp2p:peer-store'), {
|
|
@@ -28,14 +29,15 @@ class DefaultPeerStore extends EventEmitter {
|
|
|
28
29
|
* @param {object} properties
|
|
29
30
|
* @param {PeerId} properties.peerId
|
|
30
31
|
* @param {import('interface-datastore').Datastore} properties.datastore
|
|
32
|
+
* @param {(peerId: PeerId, multiaddr: Multiaddr) => Promise<boolean>} properties.addressFilter
|
|
31
33
|
*/
|
|
32
|
-
constructor ({ peerId, datastore }) {
|
|
34
|
+
constructor ({ peerId, datastore, addressFilter }) {
|
|
33
35
|
super()
|
|
34
36
|
|
|
35
37
|
this._peerId = peerId
|
|
36
38
|
this._store = new Store(datastore)
|
|
37
39
|
|
|
38
|
-
this.addressBook = new AddressBook(this.emit.bind(this), this._store)
|
|
40
|
+
this.addressBook = new AddressBook(this.emit.bind(this), this._store, addressFilter)
|
|
39
41
|
this.keyBook = new KeyBook(this.emit.bind(this), this._store)
|
|
40
42
|
this.metadataBook = new MetadataBook(this.emit.bind(this), this._store)
|
|
41
43
|
this.protoBook = new ProtoBook(this.emit.bind(this), this._store)
|
package/src/peer-store/store.js
CHANGED
|
@@ -100,13 +100,26 @@ class PersistentStore {
|
|
|
100
100
|
throw errcode(new Error('publicKey bytes do not match peer id publicKey bytes'), codes.ERR_INVALID_PARAMETERS)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
// dedupe addresses
|
|
104
|
+
const addressSet = new Set()
|
|
105
|
+
|
|
103
106
|
const buf = PeerPB.encode({
|
|
104
|
-
addresses: peer.addresses
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
addresses: peer.addresses
|
|
108
|
+
.filter(address => {
|
|
109
|
+
if (addressSet.has(address.multiaddr.toString())) {
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
addressSet.add(address.multiaddr.toString())
|
|
114
|
+
return true
|
|
115
|
+
})
|
|
116
|
+
.sort((a, b) => {
|
|
117
|
+
return a.multiaddr.toString().localeCompare(b.multiaddr.toString())
|
|
118
|
+
})
|
|
119
|
+
.map(({ multiaddr, isCertified }) => ({
|
|
120
|
+
multiaddr: multiaddr.bytes,
|
|
121
|
+
isCertified
|
|
122
|
+
})),
|
|
110
123
|
protocols: peer.protocols.sort(),
|
|
111
124
|
pubKey: peer.pubKey ? marshalPublicKey(peer.pubKey) : undefined,
|
|
112
125
|
metadata: [...peer.metadata.keys()].sort().map(key => ({ key, value: peer.metadata.get(key) })),
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type PeerId from 'peer-id'
|
|
2
|
+
import type { Multiaddr } from 'multiaddr'
|
|
3
|
+
import type { MultiaddrConnection } from 'libp2p-interfaces/src/transport/types'
|
|
4
|
+
|
|
5
|
+
export interface ConnectionGater {
|
|
6
|
+
/**
|
|
7
|
+
* denyDialMultiaddr tests whether we're permitted to Dial the
|
|
8
|
+
* specified peer.
|
|
9
|
+
*
|
|
10
|
+
* This is called by the dialer.connectToPeer implementation before
|
|
11
|
+
* dialling a peer.
|
|
12
|
+
*
|
|
13
|
+
* Return true to prevent dialing the passed peer.
|
|
14
|
+
*/
|
|
15
|
+
denyDialPeer: (peerId: PeerId) => Promise<boolean>
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* denyDialMultiaddr tests whether we're permitted to dial the specified
|
|
19
|
+
* multiaddr for the given peer.
|
|
20
|
+
*
|
|
21
|
+
* This is called by the dialer.connectToPeer implementation after it has
|
|
22
|
+
* resolved the peer's addrs, and prior to dialling each.
|
|
23
|
+
*
|
|
24
|
+
* Return true to prevent dialing the passed peer on the passed multiaddr.
|
|
25
|
+
*/
|
|
26
|
+
denyDialMultiaddr: (peerId: PeerId, multiaddr: Multiaddr) => Promise<boolean>
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* denyInboundConnection tests whether an incipient inbound connection is allowed.
|
|
30
|
+
*
|
|
31
|
+
* This is called by the upgrader, or by the transport directly (e.g. QUIC,
|
|
32
|
+
* Bluetooth), straight after it has accepted a connection from its socket.
|
|
33
|
+
*
|
|
34
|
+
* Return true to deny the incoming passed connection.
|
|
35
|
+
*/
|
|
36
|
+
denyInboundConnection: (maConn: MultiaddrConnection) => Promise<boolean>
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* denyOutboundConnection tests whether an incipient outbound connection is allowed.
|
|
40
|
+
*
|
|
41
|
+
* This is called by the upgrader, or by the transport directly (e.g. QUIC,
|
|
42
|
+
* Bluetooth), straight after it has created a connection with its socket.
|
|
43
|
+
*
|
|
44
|
+
* Return true to deny the incoming passed connection.
|
|
45
|
+
*/
|
|
46
|
+
denyOutboundConnection: (peerId: PeerId, maConn: MultiaddrConnection) => Promise<boolean>
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* denyInboundEncryptedConnection tests whether a given connection, now encrypted,
|
|
50
|
+
* is allowed.
|
|
51
|
+
*
|
|
52
|
+
* This is called by the upgrader, after it has performed the security
|
|
53
|
+
* handshake, and before it negotiates the muxer, or by the directly by the
|
|
54
|
+
* transport, at the exact same checkpoint.
|
|
55
|
+
*
|
|
56
|
+
* Return true to deny the passed secured connection.
|
|
57
|
+
*/
|
|
58
|
+
denyInboundEncryptedConnection: (peerId: PeerId, maConn: MultiaddrConnection) => Promise<boolean>
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* denyOutboundEncryptedConnection tests whether a given connection, now encrypted,
|
|
62
|
+
* is allowed.
|
|
63
|
+
*
|
|
64
|
+
* This is called by the upgrader, after it has performed the security
|
|
65
|
+
* handshake, and before it negotiates the muxer, or by the directly by the
|
|
66
|
+
* transport, at the exact same checkpoint.
|
|
67
|
+
*
|
|
68
|
+
* Return true to deny the passed secured connection.
|
|
69
|
+
*/
|
|
70
|
+
denyOutboundEncryptedConnection: (peerId: PeerId, maConn: MultiaddrConnection) => Promise<boolean>
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* denyInboundUpgradedConnection tests whether a fully capable connection is allowed.
|
|
74
|
+
*
|
|
75
|
+
* This is called after encryption has been negotiated and the connection has been
|
|
76
|
+
* multiplexed, if a multiplexer is configured.
|
|
77
|
+
*
|
|
78
|
+
* Return true to deny the passed upgraded connection.
|
|
79
|
+
*/
|
|
80
|
+
denyInboundUpgradedConnection: (peerId: PeerId, maConn: MultiaddrConnection) => Promise<boolean>
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* denyOutboundUpgradedConnection tests whether a fully capable connection is allowed.
|
|
84
|
+
*
|
|
85
|
+
* This is called after encryption has been negotiated and the connection has been
|
|
86
|
+
* multiplexed, if a multiplexer is configured.
|
|
87
|
+
*
|
|
88
|
+
* Return true to deny the passed upgraded connection.
|
|
89
|
+
*/
|
|
90
|
+
denyOutboundUpgradedConnection: (peerId: PeerId, maConn: MultiaddrConnection) => Promise<boolean>
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Used by the address book to filter passed addresses.
|
|
94
|
+
*
|
|
95
|
+
* Return true to allow storing the passed multiaddr for the passed peer.
|
|
96
|
+
*/
|
|
97
|
+
filterMultiaddrForPeer: (peer: PeerId, multiaddr: Multiaddr) => Promise<boolean>
|
|
98
|
+
}
|
package/src/upgrader.js
CHANGED
|
@@ -5,7 +5,6 @@ const log = Object.assign(debug('libp2p:upgrader'), {
|
|
|
5
5
|
error: debug('libp2p:upgrader:err')
|
|
6
6
|
})
|
|
7
7
|
const errCode = require('err-code')
|
|
8
|
-
// @ts-ignore multistream-select does not export types
|
|
9
8
|
const Multistream = require('multistream-select')
|
|
10
9
|
const { Connection } = require('libp2p-interfaces/src/connection')
|
|
11
10
|
const PeerId = require('peer-id')
|
|
@@ -23,6 +22,7 @@ const { codes } = require('./errors')
|
|
|
23
22
|
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
|
|
24
23
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
|
25
24
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
|
25
|
+
* @typedef {import('./types').ConnectionGater} ConnectionGater
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
/**
|
|
@@ -36,6 +36,8 @@ class Upgrader {
|
|
|
36
36
|
/**
|
|
37
37
|
* @param {object} options
|
|
38
38
|
* @param {PeerId} options.localPeer
|
|
39
|
+
* @param {ConnectionGater} options.connectionGater
|
|
40
|
+
*
|
|
39
41
|
* @param {import('./metrics')} [options.metrics]
|
|
40
42
|
* @param {Map<string, Crypto>} [options.cryptos]
|
|
41
43
|
* @param {Map<string, MuxerFactory>} [options.muxers]
|
|
@@ -45,11 +47,13 @@ class Upgrader {
|
|
|
45
47
|
constructor ({
|
|
46
48
|
localPeer,
|
|
47
49
|
metrics,
|
|
50
|
+
connectionGater,
|
|
48
51
|
cryptos = new Map(),
|
|
49
52
|
muxers = new Map(),
|
|
50
53
|
onConnectionEnd = () => {},
|
|
51
54
|
onConnection = () => {}
|
|
52
55
|
}) {
|
|
56
|
+
this.connectionGater = connectionGater
|
|
53
57
|
this.localPeer = localPeer
|
|
54
58
|
this.metrics = metrics
|
|
55
59
|
this.cryptos = cryptos
|
|
@@ -77,6 +81,10 @@ class Upgrader {
|
|
|
77
81
|
let setPeer
|
|
78
82
|
let proxyPeer
|
|
79
83
|
|
|
84
|
+
if (await this.connectionGater.denyInboundConnection(maConn)) {
|
|
85
|
+
throw errCode(new Error('The multiaddr connection is blocked by gater.acceptConnection'), codes.ERR_CONNECTION_INTERCEPTED)
|
|
86
|
+
}
|
|
87
|
+
|
|
80
88
|
if (this.metrics) {
|
|
81
89
|
({ setTarget: setPeer, proxy: proxyPeer } = mutableProxy())
|
|
82
90
|
const idString = (Math.random() * 1e9).toString(36) + Date.now()
|
|
@@ -100,6 +108,10 @@ class Upgrader {
|
|
|
100
108
|
protocol: cryptoProtocol
|
|
101
109
|
} = await this._encryptInbound(this.localPeer, protectedConn, this.cryptos))
|
|
102
110
|
|
|
111
|
+
if (await this.connectionGater.denyInboundEncryptedConnection(remotePeer, encryptedConn)) {
|
|
112
|
+
throw errCode(new Error('The multiaddr connection is blocked by gater.acceptEncryptedConnection'), codes.ERR_CONNECTION_INTERCEPTED)
|
|
113
|
+
}
|
|
114
|
+
|
|
103
115
|
// Multiplex the connection
|
|
104
116
|
if (this.muxers.size) {
|
|
105
117
|
({ stream: upgradedConn, Muxer } = await this._multiplexInbound(encryptedConn, this.muxers))
|
|
@@ -112,6 +124,10 @@ class Upgrader {
|
|
|
112
124
|
throw err
|
|
113
125
|
}
|
|
114
126
|
|
|
127
|
+
if (await this.connectionGater.denyInboundUpgradedConnection(remotePeer, encryptedConn)) {
|
|
128
|
+
throw errCode(new Error('The multiaddr connection is blocked by gater.acceptEncryptedConnection'), codes.ERR_CONNECTION_INTERCEPTED)
|
|
129
|
+
}
|
|
130
|
+
|
|
115
131
|
if (this.metrics) {
|
|
116
132
|
this.metrics.updatePlaceholder(proxyPeer, remotePeer)
|
|
117
133
|
setPeer(remotePeer)
|
|
@@ -144,6 +160,10 @@ class Upgrader {
|
|
|
144
160
|
|
|
145
161
|
const remotePeerId = PeerId.createFromB58String(idStr)
|
|
146
162
|
|
|
163
|
+
if (await this.connectionGater.denyOutboundConnection(remotePeerId, maConn)) {
|
|
164
|
+
throw errCode(new Error('The multiaddr connection is blocked by connectionGater.denyOutboundConnection'), codes.ERR_CONNECTION_INTERCEPTED)
|
|
165
|
+
}
|
|
166
|
+
|
|
147
167
|
let encryptedConn
|
|
148
168
|
let remotePeer
|
|
149
169
|
let upgradedConn
|
|
@@ -175,6 +195,10 @@ class Upgrader {
|
|
|
175
195
|
protocol: cryptoProtocol
|
|
176
196
|
} = await this._encryptOutbound(this.localPeer, protectedConn, remotePeerId, this.cryptos))
|
|
177
197
|
|
|
198
|
+
if (await this.connectionGater.denyOutboundEncryptedConnection(remotePeer, encryptedConn)) {
|
|
199
|
+
throw errCode(new Error('The multiaddr connection is blocked by gater.acceptEncryptedConnection'), codes.ERR_CONNECTION_INTERCEPTED)
|
|
200
|
+
}
|
|
201
|
+
|
|
178
202
|
// Multiplex the connection
|
|
179
203
|
if (this.muxers.size) {
|
|
180
204
|
({ stream: upgradedConn, Muxer } = await this._multiplexOutbound(encryptedConn, this.muxers))
|
|
@@ -187,6 +211,10 @@ class Upgrader {
|
|
|
187
211
|
throw err
|
|
188
212
|
}
|
|
189
213
|
|
|
214
|
+
if (await this.connectionGater.denyOutboundUpgradedConnection(remotePeer, encryptedConn)) {
|
|
215
|
+
throw errCode(new Error('The multiaddr connection is blocked by gater.acceptEncryptedConnection'), codes.ERR_CONNECTION_INTERCEPTED)
|
|
216
|
+
}
|
|
217
|
+
|
|
190
218
|
if (this.metrics) {
|
|
191
219
|
this.metrics.updatePlaceholder(proxyPeer, remotePeer)
|
|
192
220
|
setPeer(remotePeer)
|