libp2p 0.37.3-e6f646e → 0.38.0-0e7096d
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/README.md +0 -2
- package/dist/src/circuit/circuit/hop.d.ts +5 -3
- package/dist/src/circuit/circuit/hop.d.ts.map +1 -1
- package/dist/src/circuit/circuit/hop.js +8 -4
- package/dist/src/circuit/circuit/hop.js.map +1 -1
- package/dist/src/circuit/circuit/stop.d.ts +5 -3
- package/dist/src/circuit/circuit/stop.d.ts.map +1 -1
- package/dist/src/circuit/circuit/stop.js +4 -2
- package/dist/src/circuit/circuit/stop.js.map +1 -1
- package/dist/src/circuit/circuit/stream-handler.d.ts +2 -1
- package/dist/src/circuit/circuit/stream-handler.d.ts.map +1 -1
- package/dist/src/circuit/circuit/stream-handler.js +2 -2
- package/dist/src/circuit/circuit/stream-handler.js.map +1 -1
- package/dist/src/circuit/index.d.ts +2 -10
- package/dist/src/circuit/index.d.ts.map +1 -1
- package/dist/src/circuit/index.js.map +1 -1
- package/dist/src/circuit/pb/index.d.ts +5 -4
- package/dist/src/circuit/pb/index.d.ts.map +1 -1
- package/dist/src/circuit/pb/index.js +107 -11
- package/dist/src/circuit/pb/index.js.map +1 -1
- package/dist/src/circuit/transport.d.ts +3 -0
- package/dist/src/circuit/transport.d.ts.map +1 -1
- package/dist/src/circuit/transport.js +79 -57
- package/dist/src/circuit/transport.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +19 -4
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-manager/dialer/auto-dialer.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/auto-dialer.js +6 -0
- package/dist/src/connection-manager/dialer/auto-dialer.js.map +1 -1
- package/dist/src/connection-manager/dialer/index.d.ts +4 -4
- package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/index.js +10 -10
- package/dist/src/connection-manager/dialer/index.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +8 -1
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +42 -16
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/constants.d.ts +4 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +4 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/fetch/index.d.ts +4 -0
- package/dist/src/fetch/index.d.ts.map +1 -1
- package/dist/src/fetch/index.js +25 -6
- package/dist/src/fetch/index.js.map +1 -1
- package/dist/src/fetch/pb/proto.d.ts +4 -3
- package/dist/src/fetch/pb/proto.d.ts.map +1 -1
- package/dist/src/fetch/pb/proto.js +88 -8
- package/dist/src/fetch/pb/proto.js.map +1 -1
- package/dist/src/identify/index.d.ts +1 -1
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +35 -12
- package/dist/src/identify/index.js.map +1 -1
- package/dist/src/identify/pb/message.d.ts +2 -1
- package/dist/src/identify/pb/message.d.ts.map +1 -1
- package/dist/src/identify/pb/message.js +94 -10
- package/dist/src/identify/pb/message.js.map +1 -1
- package/dist/src/index.d.ts +1 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/insecure/index.d.ts.map +1 -1
- package/dist/src/insecure/index.js +7 -3
- package/dist/src/insecure/index.js.map +1 -1
- package/dist/src/insecure/pb/proto.d.ts +4 -3
- package/dist/src/insecure/pb/proto.d.ts.map +1 -1
- package/dist/src/insecure/pb/proto.js +89 -9
- package/dist/src/insecure/pb/proto.js.map +1 -1
- package/dist/src/keychain/index.d.ts +6 -1
- package/dist/src/keychain/index.d.ts.map +1 -1
- package/dist/src/keychain/index.js +19 -2
- package/dist/src/keychain/index.js.map +1 -1
- package/dist/src/libp2p.d.ts +0 -5
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +3 -17
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/metrics/index.d.ts +1 -2
- package/dist/src/metrics/index.d.ts.map +1 -1
- package/dist/src/metrics/index.js +3 -4
- package/dist/src/metrics/index.js.map +1 -1
- package/dist/src/ping/index.d.ts +4 -0
- package/dist/src/ping/index.d.ts.map +1 -1
- package/dist/src/ping/index.js +27 -8
- package/dist/src/ping/index.js.map +1 -1
- package/dist/src/pnet/index.d.ts.map +1 -1
- package/dist/src/pnet/index.js +2 -1
- package/dist/src/pnet/index.js.map +1 -1
- package/dist/src/registrar.d.ts +2 -2
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +2 -2
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/upgrader.d.ts +6 -0
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +121 -75
- package/dist/src/upgrader.js.map +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js.map +1 -1
- package/package.json +48 -47
- package/src/circuit/README.md +2 -2
- package/src/circuit/circuit/hop.ts +18 -9
- package/src/circuit/circuit/stop.ts +9 -4
- package/src/circuit/circuit/stream-handler.ts +5 -4
- package/src/circuit/index.ts +2 -11
- package/src/circuit/pb/index.ts +133 -15
- package/src/circuit/transport.ts +87 -58
- package/src/config.ts +19 -4
- package/src/connection-manager/dialer/auto-dialer.ts +6 -0
- package/src/connection-manager/dialer/index.ts +10 -10
- package/src/connection-manager/index.ts +54 -19
- package/src/constants.ts +5 -0
- package/src/fetch/index.ts +34 -8
- package/src/fetch/pb/proto.ts +109 -11
- package/src/identify/index.ts +41 -19
- package/src/identify/pb/message.ts +111 -11
- package/src/index.ts +1 -6
- package/src/insecure/index.ts +8 -3
- package/src/insecure/pb/proto.ts +111 -12
- package/src/keychain/index.ts +27 -3
- package/src/libp2p.ts +3 -18
- package/src/metrics/index.ts +4 -7
- package/src/ping/index.ts +37 -11
- package/src/pnet/index.ts +2 -0
- package/src/registrar.ts +2 -2
- package/src/upgrader.ts +138 -78
- package/src/version.ts +1 -2
|
@@ -177,7 +177,7 @@ export class Dialer implements Startable, Initializable {
|
|
|
177
177
|
|
|
178
178
|
log('creating dial target for %p', id)
|
|
179
179
|
|
|
180
|
-
const dialTarget = await this._createCancellableDialTarget(id)
|
|
180
|
+
const dialTarget = await this._createCancellableDialTarget(id, options)
|
|
181
181
|
|
|
182
182
|
if (dialTarget.addrs.length === 0) {
|
|
183
183
|
throw errCode(new Error('The dial request has no valid addresses'), codes.ERR_NO_VALID_ADDRESSES)
|
|
@@ -207,7 +207,7 @@ export class Dialer implements Startable, Initializable {
|
|
|
207
207
|
* The dial to the first address that is successfully able to upgrade a connection
|
|
208
208
|
* will be used.
|
|
209
209
|
*/
|
|
210
|
-
async _createCancellableDialTarget (peer: PeerId): Promise<DialTarget> {
|
|
210
|
+
async _createCancellableDialTarget (peer: PeerId, options: AbortOptions): Promise<DialTarget> {
|
|
211
211
|
// Make dial target promise cancellable
|
|
212
212
|
const id = `${(parseInt(String(Math.random() * 1e9), 10)).toString()}${Date.now()}`
|
|
213
213
|
const cancellablePromise = new Promise<DialTarget>((resolve, reject) => {
|
|
@@ -216,7 +216,7 @@ export class Dialer implements Startable, Initializable {
|
|
|
216
216
|
|
|
217
217
|
try {
|
|
218
218
|
const dialTarget = await Promise.race([
|
|
219
|
-
this._createDialTarget(peer),
|
|
219
|
+
this._createDialTarget(peer, options),
|
|
220
220
|
cancellablePromise
|
|
221
221
|
])
|
|
222
222
|
|
|
@@ -232,7 +232,7 @@ export class Dialer implements Startable, Initializable {
|
|
|
232
232
|
* If a multiaddr is received it should be the first address attempted.
|
|
233
233
|
* Multiaddrs not supported by the available transports will be filtered out.
|
|
234
234
|
*/
|
|
235
|
-
async _createDialTarget (peer: PeerId): Promise<DialTarget> {
|
|
235
|
+
async _createDialTarget (peer: PeerId, options: AbortOptions): Promise<DialTarget> {
|
|
236
236
|
const knownAddrs = await pipe(
|
|
237
237
|
await this.components.getPeerStore().addressBook.get(peer),
|
|
238
238
|
(source) => filter(source, async (address) => {
|
|
@@ -253,7 +253,7 @@ export class Dialer implements Startable, Initializable {
|
|
|
253
253
|
|
|
254
254
|
const addrs: Multiaddr[] = []
|
|
255
255
|
for (const a of knownAddrs) {
|
|
256
|
-
const resolvedAddrs = await this._resolve(a)
|
|
256
|
+
const resolvedAddrs = await this._resolve(a, options)
|
|
257
257
|
resolvedAddrs.forEach(ra => addrs.push(ra))
|
|
258
258
|
}
|
|
259
259
|
|
|
@@ -341,7 +341,7 @@ export class Dialer implements Startable, Initializable {
|
|
|
341
341
|
/**
|
|
342
342
|
* Resolve multiaddr recursively
|
|
343
343
|
*/
|
|
344
|
-
async _resolve (ma: Multiaddr): Promise<Multiaddr[]> {
|
|
344
|
+
async _resolve (ma: Multiaddr, options: AbortOptions): Promise<Multiaddr[]> {
|
|
345
345
|
// TODO: recursive logic should live in multiaddr once dns4/dns6 support is in place
|
|
346
346
|
// Now only supporting resolve for dnsaddr
|
|
347
347
|
const resolvableProto = ma.protoNames().includes('dnsaddr')
|
|
@@ -351,9 +351,9 @@ export class Dialer implements Startable, Initializable {
|
|
|
351
351
|
return [ma]
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
-
const resolvedMultiaddrs = await this._resolveRecord(ma)
|
|
354
|
+
const resolvedMultiaddrs = await this._resolveRecord(ma, options)
|
|
355
355
|
const recursiveMultiaddrs = await Promise.all(resolvedMultiaddrs.map(async (nm) => {
|
|
356
|
-
return await this._resolve(nm)
|
|
356
|
+
return await this._resolve(nm, options)
|
|
357
357
|
}))
|
|
358
358
|
|
|
359
359
|
const addrs = recursiveMultiaddrs.flat()
|
|
@@ -368,10 +368,10 @@ export class Dialer implements Startable, Initializable {
|
|
|
368
368
|
/**
|
|
369
369
|
* Resolve a given multiaddr. If this fails, an empty array will be returned
|
|
370
370
|
*/
|
|
371
|
-
async _resolveRecord (ma: Multiaddr): Promise<Multiaddr[]> {
|
|
371
|
+
async _resolveRecord (ma: Multiaddr, options: AbortOptions): Promise<Multiaddr[]> {
|
|
372
372
|
try {
|
|
373
373
|
ma = new Multiaddr(ma.toString()) // Use current multiaddr module
|
|
374
|
-
const multiaddrs = await ma.resolve()
|
|
374
|
+
const multiaddrs = await ma.resolve(options)
|
|
375
375
|
return multiaddrs
|
|
376
376
|
} catch (err) {
|
|
377
377
|
log.error(`multiaddr ${ma.toString()} could not be resolved`, err)
|
|
@@ -107,10 +107,17 @@ export interface ConnectionManagerInit {
|
|
|
107
107
|
maxAddrsToDial?: number
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* How long a dial attempt is allowed to take
|
|
110
|
+
* How long a dial attempt is allowed to take, including DNS resolution
|
|
111
|
+
* of the multiaddr, opening a socket and upgrading it to a Connection.
|
|
111
112
|
*/
|
|
112
113
|
dialTimeout?: number
|
|
113
114
|
|
|
115
|
+
/**
|
|
116
|
+
* When a new inbound connection is opened, the upgrade process (e.g. protect,
|
|
117
|
+
* encrypt, multiplex etc) must complete within this number of ms.
|
|
118
|
+
*/
|
|
119
|
+
inboundUpgradeTimeout: number
|
|
120
|
+
|
|
114
121
|
/**
|
|
115
122
|
* Number of max concurrent dials per peer
|
|
116
123
|
*/
|
|
@@ -146,6 +153,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
146
153
|
private readonly latencyMonitor: LatencyMonitor
|
|
147
154
|
private readonly startupReconnectTimeout: number
|
|
148
155
|
private connectOnStartupController?: TimeoutController
|
|
156
|
+
private readonly dialTimeout: number
|
|
149
157
|
|
|
150
158
|
constructor (init: ConnectionManagerInit) {
|
|
151
159
|
super()
|
|
@@ -182,6 +190,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
182
190
|
this.onDisconnect = this.onDisconnect.bind(this)
|
|
183
191
|
|
|
184
192
|
this.startupReconnectTimeout = init.startupReconnectTimeout ?? STARTUP_RECONNECT_TIMEOUT
|
|
193
|
+
this.dialTimeout = init.dialTimeout ?? 30000
|
|
185
194
|
}
|
|
186
195
|
|
|
187
196
|
init (components: Components): void {
|
|
@@ -322,6 +331,11 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
322
331
|
this.connectOnStartupController?.clear()
|
|
323
332
|
this.connectOnStartupController = new TimeoutController(this.startupReconnectTimeout)
|
|
324
333
|
|
|
334
|
+
try {
|
|
335
|
+
// fails on node < 15.4
|
|
336
|
+
setMaxListeners?.(Infinity, this.connectOnStartupController.signal)
|
|
337
|
+
} catch {}
|
|
338
|
+
|
|
325
339
|
await Promise.all(
|
|
326
340
|
keepAlivePeers.map(async peer => {
|
|
327
341
|
await this.openConnection(peer, {
|
|
@@ -333,6 +347,9 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
333
347
|
})
|
|
334
348
|
)
|
|
335
349
|
})
|
|
350
|
+
.catch(err => {
|
|
351
|
+
log.error(err)
|
|
352
|
+
})
|
|
336
353
|
.finally(() => {
|
|
337
354
|
this.connectOnStartupController?.clear()
|
|
338
355
|
})
|
|
@@ -486,7 +503,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
486
503
|
return conns
|
|
487
504
|
}
|
|
488
505
|
|
|
489
|
-
async openConnection (peerId: PeerId, options
|
|
506
|
+
async openConnection (peerId: PeerId, options: AbortOptions = {}): Promise<Connection> {
|
|
490
507
|
log('dial to %p', peerId)
|
|
491
508
|
const existingConnections = this.getConnections(peerId)
|
|
492
509
|
|
|
@@ -496,30 +513,48 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
496
513
|
return existingConnections[0]
|
|
497
514
|
}
|
|
498
515
|
|
|
499
|
-
|
|
500
|
-
let peerConnections = this.connections.get(peerId.toString())
|
|
516
|
+
let timeoutController: TimeoutController | undefined
|
|
501
517
|
|
|
502
|
-
if (
|
|
503
|
-
|
|
504
|
-
|
|
518
|
+
if (options?.signal == null) {
|
|
519
|
+
timeoutController = new TimeoutController(this.dialTimeout)
|
|
520
|
+
options.signal = timeoutController.signal
|
|
521
|
+
|
|
522
|
+
try {
|
|
523
|
+
// fails on node < 15.4
|
|
524
|
+
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
525
|
+
} catch {}
|
|
505
526
|
}
|
|
506
527
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
let trackedConnection = false
|
|
528
|
+
try {
|
|
529
|
+
const connection = await this.dialer.dial(peerId, options)
|
|
530
|
+
let peerConnections = this.connections.get(peerId.toString())
|
|
511
531
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
532
|
+
if (peerConnections == null) {
|
|
533
|
+
peerConnections = []
|
|
534
|
+
this.connections.set(peerId.toString(), peerConnections)
|
|
515
535
|
}
|
|
516
|
-
}
|
|
517
536
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
537
|
+
// we get notified of connections via the Upgrader emitting "connection"
|
|
538
|
+
// events, double check we aren't already tracking this connection before
|
|
539
|
+
// storing it
|
|
540
|
+
let trackedConnection = false
|
|
541
|
+
|
|
542
|
+
for (const conn of peerConnections) {
|
|
543
|
+
if (conn.id === connection.id) {
|
|
544
|
+
trackedConnection = true
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (!trackedConnection) {
|
|
549
|
+
peerConnections.push(connection)
|
|
550
|
+
}
|
|
521
551
|
|
|
522
|
-
|
|
552
|
+
return connection
|
|
553
|
+
} finally {
|
|
554
|
+
if (timeoutController != null) {
|
|
555
|
+
timeoutController.clear()
|
|
556
|
+
}
|
|
557
|
+
}
|
|
523
558
|
}
|
|
524
559
|
|
|
525
560
|
async closeConnections (peerId: PeerId): Promise<void> {
|
package/src/constants.ts
CHANGED
package/src/fetch/index.ts
CHANGED
|
@@ -10,10 +10,11 @@ import type { Stream } from '@libp2p/interface-connection'
|
|
|
10
10
|
import type { IncomingStreamData } from '@libp2p/interface-registrar'
|
|
11
11
|
import type { Components } from '@libp2p/components'
|
|
12
12
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
13
|
-
import type { Duplex } from 'it-stream-types'
|
|
14
13
|
import { abortableDuplex } from 'abortable-iterator'
|
|
15
14
|
import { pipe } from 'it-pipe'
|
|
16
15
|
import first from 'it-first'
|
|
16
|
+
import { TimeoutController } from 'timeout-abort-controller'
|
|
17
|
+
import { setMaxListeners } from 'events'
|
|
17
18
|
|
|
18
19
|
const log = logger('libp2p:fetch')
|
|
19
20
|
|
|
@@ -21,6 +22,11 @@ export interface FetchServiceInit {
|
|
|
21
22
|
protocolPrefix: string
|
|
22
23
|
maxInboundStreams: number
|
|
23
24
|
maxOutboundStreams: number
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* How long we should wait for a remote peer to send any data
|
|
28
|
+
*/
|
|
29
|
+
timeout: number
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
export interface HandleMessageOptions {
|
|
@@ -86,15 +92,29 @@ export class FetchService implements Startable {
|
|
|
86
92
|
log('dialing %s to %p', this.protocol, peer)
|
|
87
93
|
|
|
88
94
|
const connection = await this.components.getConnectionManager().openConnection(peer, options)
|
|
89
|
-
|
|
90
|
-
let
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if
|
|
94
|
-
|
|
95
|
+
let timeoutController
|
|
96
|
+
let signal = options.signal
|
|
97
|
+
let stream: Stream | undefined
|
|
98
|
+
|
|
99
|
+
// create a timeout if no abort signal passed
|
|
100
|
+
if (signal == null) {
|
|
101
|
+
timeoutController = new TimeoutController(this.init.timeout)
|
|
102
|
+
signal = timeoutController.signal
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
// fails on node < 15.4
|
|
106
|
+
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
107
|
+
} catch {}
|
|
95
108
|
}
|
|
96
109
|
|
|
97
110
|
try {
|
|
111
|
+
stream = await connection.newStream([this.protocol], {
|
|
112
|
+
signal
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// make stream abortable
|
|
116
|
+
const source = abortableDuplex(stream, signal)
|
|
117
|
+
|
|
98
118
|
const result = await pipe(
|
|
99
119
|
[FetchRequest.encode({ identifier: key })],
|
|
100
120
|
lp.encode(),
|
|
@@ -129,7 +149,13 @@ export class FetchService implements Startable {
|
|
|
129
149
|
|
|
130
150
|
return result ?? null
|
|
131
151
|
} finally {
|
|
132
|
-
|
|
152
|
+
if (timeoutController != null) {
|
|
153
|
+
timeoutController.clear()
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (stream != null) {
|
|
157
|
+
stream.close()
|
|
158
|
+
}
|
|
133
159
|
}
|
|
134
160
|
}
|
|
135
161
|
|
package/src/fetch/pb/proto.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* eslint-disable import/export */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-namespace */
|
|
3
3
|
|
|
4
|
-
import { encodeMessage, decodeMessage, message,
|
|
4
|
+
import { encodeMessage, decodeMessage, message, enumeration } from 'protons-runtime'
|
|
5
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
5
6
|
import type { Codec } from 'protons-runtime'
|
|
6
7
|
|
|
7
8
|
export interface FetchRequest {
|
|
@@ -9,17 +10,59 @@ export interface FetchRequest {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export namespace FetchRequest {
|
|
13
|
+
let _codec: Codec<FetchRequest>
|
|
14
|
+
|
|
12
15
|
export const codec = (): Codec<FetchRequest> => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
if (_codec == null) {
|
|
17
|
+
_codec = message<FetchRequest>((obj, writer, opts = {}) => {
|
|
18
|
+
if (opts.lengthDelimited !== false) {
|
|
19
|
+
writer.fork()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (obj.identifier != null) {
|
|
23
|
+
writer.uint32(10)
|
|
24
|
+
writer.string(obj.identifier)
|
|
25
|
+
} else {
|
|
26
|
+
throw new Error('Protocol error: required field "identifier" was not found in object')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (opts.lengthDelimited !== false) {
|
|
30
|
+
writer.ldelim()
|
|
31
|
+
}
|
|
32
|
+
}, (reader, length) => {
|
|
33
|
+
const obj: any = {}
|
|
34
|
+
|
|
35
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
36
|
+
|
|
37
|
+
while (reader.pos < end) {
|
|
38
|
+
const tag = reader.uint32()
|
|
39
|
+
|
|
40
|
+
switch (tag >>> 3) {
|
|
41
|
+
case 1:
|
|
42
|
+
obj.identifier = reader.string()
|
|
43
|
+
break
|
|
44
|
+
default:
|
|
45
|
+
reader.skipType(tag & 7)
|
|
46
|
+
break
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (obj.identifier == null) {
|
|
51
|
+
throw new Error('Protocol error: value for required field "identifier" was not found in protobuf')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return obj
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return _codec
|
|
16
59
|
}
|
|
17
60
|
|
|
18
61
|
export const encode = (obj: FetchRequest): Uint8Array => {
|
|
19
62
|
return encodeMessage(obj, FetchRequest.codec())
|
|
20
63
|
}
|
|
21
64
|
|
|
22
|
-
export const decode = (buf: Uint8Array): FetchRequest => {
|
|
65
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): FetchRequest => {
|
|
23
66
|
return decodeMessage(buf, FetchRequest.codec())
|
|
24
67
|
}
|
|
25
68
|
}
|
|
@@ -44,22 +87,77 @@ export namespace FetchResponse {
|
|
|
44
87
|
|
|
45
88
|
export namespace StatusCode {
|
|
46
89
|
export const codec = () => {
|
|
47
|
-
return enumeration<
|
|
90
|
+
return enumeration<StatusCode>(__StatusCodeValues)
|
|
48
91
|
}
|
|
49
92
|
}
|
|
50
93
|
|
|
94
|
+
let _codec: Codec<FetchResponse>
|
|
95
|
+
|
|
51
96
|
export const codec = (): Codec<FetchResponse> => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
97
|
+
if (_codec == null) {
|
|
98
|
+
_codec = message<FetchResponse>((obj, writer, opts = {}) => {
|
|
99
|
+
if (opts.lengthDelimited !== false) {
|
|
100
|
+
writer.fork()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (obj.status != null) {
|
|
104
|
+
writer.uint32(8)
|
|
105
|
+
FetchResponse.StatusCode.codec().encode(obj.status, writer)
|
|
106
|
+
} else {
|
|
107
|
+
throw new Error('Protocol error: required field "status" was not found in object')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (obj.data != null) {
|
|
111
|
+
writer.uint32(18)
|
|
112
|
+
writer.bytes(obj.data)
|
|
113
|
+
} else {
|
|
114
|
+
throw new Error('Protocol error: required field "data" was not found in object')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (opts.lengthDelimited !== false) {
|
|
118
|
+
writer.ldelim()
|
|
119
|
+
}
|
|
120
|
+
}, (reader, length) => {
|
|
121
|
+
const obj: any = {}
|
|
122
|
+
|
|
123
|
+
const end = length == null ? reader.len : reader.pos + length
|
|
124
|
+
|
|
125
|
+
while (reader.pos < end) {
|
|
126
|
+
const tag = reader.uint32()
|
|
127
|
+
|
|
128
|
+
switch (tag >>> 3) {
|
|
129
|
+
case 1:
|
|
130
|
+
obj.status = FetchResponse.StatusCode.codec().decode(reader)
|
|
131
|
+
break
|
|
132
|
+
case 2:
|
|
133
|
+
obj.data = reader.bytes()
|
|
134
|
+
break
|
|
135
|
+
default:
|
|
136
|
+
reader.skipType(tag & 7)
|
|
137
|
+
break
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (obj.status == null) {
|
|
142
|
+
throw new Error('Protocol error: value for required field "status" was not found in protobuf')
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (obj.data == null) {
|
|
146
|
+
throw new Error('Protocol error: value for required field "data" was not found in protobuf')
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return obj
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return _codec
|
|
56
154
|
}
|
|
57
155
|
|
|
58
156
|
export const encode = (obj: FetchResponse): Uint8Array => {
|
|
59
157
|
return encodeMessage(obj, FetchResponse.codec())
|
|
60
158
|
}
|
|
61
159
|
|
|
62
|
-
export const decode = (buf: Uint8Array): FetchResponse => {
|
|
160
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList): FetchResponse => {
|
|
63
161
|
return decodeMessage(buf, FetchResponse.codec())
|
|
64
162
|
}
|
|
65
163
|
}
|
package/src/identify/index.ts
CHANGED
|
@@ -26,13 +26,10 @@ import type { Components } from '@libp2p/components'
|
|
|
26
26
|
import { TimeoutController } from 'timeout-abort-controller'
|
|
27
27
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
28
28
|
import { abortableDuplex } from 'abortable-iterator'
|
|
29
|
-
import
|
|
29
|
+
import { setMaxListeners } from 'events'
|
|
30
30
|
|
|
31
31
|
const log = logger('libp2p:identify')
|
|
32
32
|
|
|
33
|
-
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
|
|
34
|
-
const IDENTIFY_TIMEOUT = 60000
|
|
35
|
-
|
|
36
33
|
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52
|
|
37
34
|
const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8
|
|
38
35
|
|
|
@@ -54,7 +51,7 @@ export interface IdentifyServiceInit {
|
|
|
54
51
|
/**
|
|
55
52
|
* How long we should wait for a remote peer to send their identify response
|
|
56
53
|
*/
|
|
57
|
-
timeout
|
|
54
|
+
timeout: number
|
|
58
55
|
|
|
59
56
|
/**
|
|
60
57
|
* Identify responses larger than this in bytes will be rejected (default: 8192)
|
|
@@ -167,8 +164,13 @@ export class IdentifyService implements Startable {
|
|
|
167
164
|
const protocols = await this.components.getPeerStore().protoBook.get(this.components.getPeerId())
|
|
168
165
|
|
|
169
166
|
const pushes = connections.map(async connection => {
|
|
170
|
-
const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
171
167
|
let stream: Stream | undefined
|
|
168
|
+
const timeoutController = new TimeoutController(this.init.timeout)
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
// fails on node < 15.4
|
|
172
|
+
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
173
|
+
} catch {}
|
|
172
174
|
|
|
173
175
|
try {
|
|
174
176
|
stream = await connection.newStream([this.identifyPushProtocolStr], {
|
|
@@ -176,7 +178,7 @@ export class IdentifyService implements Startable {
|
|
|
176
178
|
})
|
|
177
179
|
|
|
178
180
|
// make stream abortable
|
|
179
|
-
const source
|
|
181
|
+
const source = abortableDuplex(stream, timeoutController.signal)
|
|
180
182
|
|
|
181
183
|
await pipe(
|
|
182
184
|
[Identify.encode({
|
|
@@ -229,21 +231,29 @@ export class IdentifyService implements Startable {
|
|
|
229
231
|
}
|
|
230
232
|
|
|
231
233
|
async _identify (connection: Connection, options: AbortOptions = {}): Promise<Identify> {
|
|
232
|
-
const stream = await connection.newStream([this.identifyProtocolStr], options)
|
|
233
|
-
let source: Duplex<Uint8Array> = stream
|
|
234
234
|
let timeoutController
|
|
235
235
|
let signal = options.signal
|
|
236
|
+
let stream: Stream | undefined
|
|
236
237
|
|
|
237
238
|
// create a timeout if no abort signal passed
|
|
238
239
|
if (signal == null) {
|
|
239
|
-
timeoutController = new TimeoutController(this.init.timeout
|
|
240
|
+
timeoutController = new TimeoutController(this.init.timeout)
|
|
240
241
|
signal = timeoutController.signal
|
|
241
|
-
}
|
|
242
242
|
|
|
243
|
-
|
|
244
|
-
|
|
243
|
+
try {
|
|
244
|
+
// fails on node < 15.4
|
|
245
|
+
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
246
|
+
} catch {}
|
|
247
|
+
}
|
|
245
248
|
|
|
246
249
|
try {
|
|
250
|
+
stream = await connection.newStream([this.identifyProtocolStr], {
|
|
251
|
+
signal
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
// make stream abortable
|
|
255
|
+
const source = abortableDuplex(stream, signal)
|
|
256
|
+
|
|
247
257
|
const data = await pipe(
|
|
248
258
|
[],
|
|
249
259
|
source,
|
|
@@ -267,7 +277,9 @@ export class IdentifyService implements Startable {
|
|
|
267
277
|
timeoutController.clear()
|
|
268
278
|
}
|
|
269
279
|
|
|
270
|
-
stream
|
|
280
|
+
if (stream != null) {
|
|
281
|
+
stream.close()
|
|
282
|
+
}
|
|
271
283
|
}
|
|
272
284
|
}
|
|
273
285
|
|
|
@@ -370,7 +382,12 @@ export class IdentifyService implements Startable {
|
|
|
370
382
|
*/
|
|
371
383
|
async _handleIdentify (data: IncomingStreamData) {
|
|
372
384
|
const { connection, stream } = data
|
|
373
|
-
const timeoutController = new TimeoutController(this.init.timeout
|
|
385
|
+
const timeoutController = new TimeoutController(this.init.timeout)
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
// fails on node < 15.4
|
|
389
|
+
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
390
|
+
} catch {}
|
|
374
391
|
|
|
375
392
|
try {
|
|
376
393
|
const publicKey = this.components.getPeerId().publicKey ?? new Uint8Array(0)
|
|
@@ -386,7 +403,7 @@ export class IdentifyService implements Startable {
|
|
|
386
403
|
|
|
387
404
|
const envelope = await RecordEnvelope.seal(peerRecord, this.components.getPeerId())
|
|
388
405
|
await this.components.getPeerStore().addressBook.consumePeerRecord(envelope)
|
|
389
|
-
signedPeerRecord = envelope.marshal()
|
|
406
|
+
signedPeerRecord = envelope.marshal().subarray()
|
|
390
407
|
}
|
|
391
408
|
|
|
392
409
|
const message = Identify.encode({
|
|
@@ -400,7 +417,7 @@ export class IdentifyService implements Startable {
|
|
|
400
417
|
})
|
|
401
418
|
|
|
402
419
|
// make stream abortable
|
|
403
|
-
const source
|
|
420
|
+
const source = abortableDuplex(stream, timeoutController.signal)
|
|
404
421
|
|
|
405
422
|
await pipe(
|
|
406
423
|
[message],
|
|
@@ -421,12 +438,17 @@ export class IdentifyService implements Startable {
|
|
|
421
438
|
*/
|
|
422
439
|
async _handlePush (data: IncomingStreamData) {
|
|
423
440
|
const { connection, stream } = data
|
|
424
|
-
const timeoutController = new TimeoutController(this.init.timeout
|
|
441
|
+
const timeoutController = new TimeoutController(this.init.timeout)
|
|
442
|
+
|
|
443
|
+
try {
|
|
444
|
+
// fails on node < 15.4
|
|
445
|
+
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
446
|
+
} catch {}
|
|
425
447
|
|
|
426
448
|
let message: Identify | undefined
|
|
427
449
|
try {
|
|
428
450
|
// make stream abortable
|
|
429
|
-
const source
|
|
451
|
+
const source = abortableDuplex(stream, timeoutController.signal)
|
|
430
452
|
|
|
431
453
|
const data = await pipe(
|
|
432
454
|
[],
|