libp2p 0.37.0 → 0.37.2
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/config.d.ts.map +1 -1
- package/dist/src/config.js +13 -4
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-manager/dialer/dial-request.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/dial-request.js +28 -4
- package/dist/src/connection-manager/dialer/dial-request.js.map +1 -1
- package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/index.js +0 -1
- package/dist/src/connection-manager/dialer/index.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +8 -2
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/errors.d.ts +2 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +1 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/fetch/constants.d.ts +2 -1
- package/dist/src/fetch/constants.d.ts.map +1 -1
- package/dist/src/fetch/constants.js +2 -1
- package/dist/src/fetch/constants.js.map +1 -1
- package/dist/src/fetch/index.d.ts +5 -4
- package/dist/src/fetch/index.d.ts.map +1 -1
- package/dist/src/fetch/index.js +12 -6
- package/dist/src/fetch/index.js.map +1 -1
- package/dist/src/identify/index.d.ts +18 -1
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +75 -19
- package/dist/src/identify/index.js.map +1 -1
- package/dist/src/index.d.ts +8 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/libp2p.d.ts +2 -2
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +9 -12
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/nat-manager.d.ts +5 -2
- package/dist/src/nat-manager.d.ts.map +1 -1
- package/dist/src/nat-manager.js +6 -3
- package/dist/src/nat-manager.js.map +1 -1
- package/dist/src/peer-routing.d.ts.map +1 -1
- package/dist/src/peer-routing.js +0 -1
- package/dist/src/peer-routing.js.map +1 -1
- package/dist/src/ping/index.d.ts +3 -2
- package/dist/src/ping/index.d.ts.map +1 -1
- package/dist/src/ping/index.js +19 -8
- package/dist/src/ping/index.js.map +1 -1
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +9 -4
- package/dist/src/upgrader.js.map +1 -1
- package/package.json +8 -12
- package/src/config.ts +13 -4
- package/src/connection-manager/dialer/dial-request.ts +30 -5
- package/src/connection-manager/dialer/index.ts +0 -1
- package/src/connection-manager/index.ts +8 -3
- package/src/errors.ts +2 -1
- package/src/fetch/constants.ts +2 -1
- package/src/fetch/index.ts +19 -9
- package/src/identify/index.ts +112 -28
- package/src/index.ts +8 -5
- package/src/libp2p.ts +9 -12
- package/src/nat-manager.ts +7 -3
- package/src/peer-routing.ts +0 -1
- package/src/ping/index.ts +27 -13
- package/src/upgrader.ts +13 -5
package/src/identify/index.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { logger } from '@libp2p/logger'
|
|
|
2
2
|
import errCode from 'err-code'
|
|
3
3
|
import * as lp from 'it-length-prefixed'
|
|
4
4
|
import { pipe } from 'it-pipe'
|
|
5
|
-
import all from 'it-all'
|
|
6
|
-
import take from 'it-take'
|
|
7
5
|
import drain from 'it-drain'
|
|
8
6
|
import first from 'it-first'
|
|
9
7
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
@@ -21,20 +19,47 @@ import {
|
|
|
21
19
|
} from './consts.js'
|
|
22
20
|
import { codes } from '../errors.js'
|
|
23
21
|
import type { IncomingStreamData } from '@libp2p/interfaces/registrar'
|
|
24
|
-
import type { Connection } from '@libp2p/interfaces/connection'
|
|
22
|
+
import type { Connection, Stream } from '@libp2p/interfaces/connection'
|
|
25
23
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
26
24
|
import { peerIdFromKeys } from '@libp2p/peer-id'
|
|
27
25
|
import type { Components } from '@libp2p/interfaces/components'
|
|
26
|
+
import { TimeoutController } from 'timeout-abort-controller'
|
|
27
|
+
import type { AbortOptions } from '@libp2p/interfaces'
|
|
28
|
+
import { abortableDuplex } from 'abortable-iterator'
|
|
29
|
+
import type { Duplex } from 'it-stream-types'
|
|
28
30
|
|
|
29
31
|
const log = logger('libp2p:identify')
|
|
30
32
|
|
|
33
|
+
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
|
|
34
|
+
const IDENTIFY_TIMEOUT = 60000
|
|
35
|
+
|
|
36
|
+
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52
|
|
37
|
+
const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8
|
|
38
|
+
|
|
31
39
|
export interface HostProperties {
|
|
32
40
|
agentVersion: string
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
export interface IdentifyServiceInit {
|
|
44
|
+
/**
|
|
45
|
+
* The prefix to use for the protocol (default: 'ipfs')
|
|
46
|
+
*/
|
|
36
47
|
protocolPrefix: string
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* What details we should send as part of an identify message
|
|
51
|
+
*/
|
|
37
52
|
host: HostProperties
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* How long we should wait for a remote peer to send their identify response
|
|
56
|
+
*/
|
|
57
|
+
timeout?: number
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Identify responses larger than this in bytes will be rejected (default: 8192)
|
|
61
|
+
*/
|
|
62
|
+
maxIdentifyMessageSize?: number
|
|
38
63
|
}
|
|
39
64
|
|
|
40
65
|
export class IdentifyService implements Startable {
|
|
@@ -46,11 +71,13 @@ export class IdentifyService implements Startable {
|
|
|
46
71
|
agentVersion: string
|
|
47
72
|
}
|
|
48
73
|
|
|
74
|
+
private readonly init: IdentifyServiceInit
|
|
49
75
|
private started: boolean
|
|
50
76
|
|
|
51
77
|
constructor (components: Components, init: IdentifyServiceInit) {
|
|
52
78
|
this.components = components
|
|
53
79
|
this.started = false
|
|
80
|
+
this.init = init
|
|
54
81
|
|
|
55
82
|
this.handleMessage = this.handleMessage.bind(this)
|
|
56
83
|
|
|
@@ -128,8 +155,17 @@ export class IdentifyService implements Startable {
|
|
|
128
155
|
const protocols = await this.components.getPeerStore().protoBook.get(this.components.getPeerId())
|
|
129
156
|
|
|
130
157
|
const pushes = connections.map(async connection => {
|
|
158
|
+
const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
159
|
+
let stream: Stream | undefined
|
|
160
|
+
|
|
131
161
|
try {
|
|
132
|
-
const
|
|
162
|
+
const data = await connection.newStream([this.identifyPushProtocolStr], {
|
|
163
|
+
signal: timeoutController.signal
|
|
164
|
+
})
|
|
165
|
+
stream = data.stream
|
|
166
|
+
|
|
167
|
+
// make stream abortable
|
|
168
|
+
const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
|
|
133
169
|
|
|
134
170
|
await pipe(
|
|
135
171
|
[Identify.encode({
|
|
@@ -138,12 +174,18 @@ export class IdentifyService implements Startable {
|
|
|
138
174
|
protocols
|
|
139
175
|
})],
|
|
140
176
|
lp.encode(),
|
|
141
|
-
|
|
177
|
+
source,
|
|
142
178
|
drain
|
|
143
179
|
)
|
|
144
180
|
} catch (err: any) {
|
|
145
181
|
// Just log errors
|
|
146
182
|
log.error('could not push identify update to peer', err)
|
|
183
|
+
} finally {
|
|
184
|
+
if (stream != null) {
|
|
185
|
+
stream.close()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
timeoutController.clear()
|
|
147
189
|
}
|
|
148
190
|
})
|
|
149
191
|
|
|
@@ -175,31 +217,56 @@ export class IdentifyService implements Startable {
|
|
|
175
217
|
await this.push(connections)
|
|
176
218
|
}
|
|
177
219
|
|
|
220
|
+
async _identify (connection: Connection, options: AbortOptions = {}): Promise<Identify> {
|
|
221
|
+
const { stream } = await connection.newStream([this.identifyProtocolStr], options)
|
|
222
|
+
let source: Duplex<Uint8Array> = stream
|
|
223
|
+
let timeoutController
|
|
224
|
+
let signal = options.signal
|
|
225
|
+
|
|
226
|
+
// create a timeout if no abort signal passed
|
|
227
|
+
if (signal == null) {
|
|
228
|
+
timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
229
|
+
signal = timeoutController.signal
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// make stream abortable if AbortSignal passed
|
|
233
|
+
source = abortableDuplex(stream, signal)
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
const data = await pipe(
|
|
237
|
+
[],
|
|
238
|
+
source,
|
|
239
|
+
lp.decode({
|
|
240
|
+
maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
|
|
241
|
+
}),
|
|
242
|
+
async (source) => await first(source)
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
if (data == null) {
|
|
246
|
+
throw errCode(new Error('No data could be retrieved'), codes.ERR_CONNECTION_ENDED)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
return Identify.decode(data)
|
|
251
|
+
} catch (err: any) {
|
|
252
|
+
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
|
253
|
+
}
|
|
254
|
+
} finally {
|
|
255
|
+
if (timeoutController != null) {
|
|
256
|
+
timeoutController.clear()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
stream.close()
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
178
263
|
/**
|
|
179
264
|
* Requests the `Identify` message from peer associated with the given `connection`.
|
|
180
265
|
* If the identified peer does not match the `PeerId` associated with the connection,
|
|
181
266
|
* an error will be thrown.
|
|
182
267
|
*/
|
|
183
|
-
async identify (connection: Connection): Promise<void> {
|
|
184
|
-
const
|
|
185
|
-
const [data] = await pipe(
|
|
186
|
-
[],
|
|
187
|
-
stream,
|
|
188
|
-
lp.decode(),
|
|
189
|
-
(source) => take(source, 1),
|
|
190
|
-
async (source) => await all(source)
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
if (data == null) {
|
|
194
|
-
throw errCode(new Error('No data could be retrieved'), codes.ERR_CONNECTION_ENDED)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
let message: Identify
|
|
198
|
-
try {
|
|
199
|
-
message = Identify.decode(data)
|
|
200
|
-
} catch (err: any) {
|
|
201
|
-
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
|
202
|
-
}
|
|
268
|
+
async identify (connection: Connection, options: AbortOptions = {}): Promise<void> {
|
|
269
|
+
const message = await this._identify(connection, options)
|
|
203
270
|
|
|
204
271
|
const {
|
|
205
272
|
publicKey,
|
|
@@ -308,6 +375,8 @@ export class IdentifyService implements Startable {
|
|
|
308
375
|
*/
|
|
309
376
|
async _handleIdentify (data: IncomingStreamData) {
|
|
310
377
|
const { connection, stream } = data
|
|
378
|
+
const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
379
|
+
|
|
311
380
|
try {
|
|
312
381
|
const publicKey = this.components.getPeerId().publicKey ?? new Uint8Array(0)
|
|
313
382
|
const peerData = await this.components.getPeerStore().get(this.components.getPeerId())
|
|
@@ -335,14 +404,20 @@ export class IdentifyService implements Startable {
|
|
|
335
404
|
protocols: peerData.protocols
|
|
336
405
|
})
|
|
337
406
|
|
|
407
|
+
// make stream abortable
|
|
408
|
+
const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
|
|
409
|
+
|
|
338
410
|
await pipe(
|
|
339
411
|
[message],
|
|
340
412
|
lp.encode(),
|
|
341
|
-
|
|
413
|
+
source,
|
|
342
414
|
drain
|
|
343
415
|
)
|
|
344
416
|
} catch (err: any) {
|
|
345
417
|
log.error('could not respond to identify request', err)
|
|
418
|
+
} finally {
|
|
419
|
+
stream.close()
|
|
420
|
+
timeoutController.clear()
|
|
346
421
|
}
|
|
347
422
|
}
|
|
348
423
|
|
|
@@ -351,13 +426,19 @@ export class IdentifyService implements Startable {
|
|
|
351
426
|
*/
|
|
352
427
|
async _handlePush (data: IncomingStreamData) {
|
|
353
428
|
const { connection, stream } = data
|
|
429
|
+
const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
354
430
|
|
|
355
431
|
let message: Identify | undefined
|
|
356
432
|
try {
|
|
433
|
+
// make stream abortable
|
|
434
|
+
const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
|
|
435
|
+
|
|
357
436
|
const data = await pipe(
|
|
358
437
|
[],
|
|
359
|
-
|
|
360
|
-
lp.decode(
|
|
438
|
+
source,
|
|
439
|
+
lp.decode({
|
|
440
|
+
maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
|
|
441
|
+
}),
|
|
361
442
|
async (source) => await first(source)
|
|
362
443
|
)
|
|
363
444
|
|
|
@@ -366,6 +447,9 @@ export class IdentifyService implements Startable {
|
|
|
366
447
|
}
|
|
367
448
|
} catch (err: any) {
|
|
368
449
|
return log.error('received invalid message', err)
|
|
450
|
+
} finally {
|
|
451
|
+
stream.close()
|
|
452
|
+
timeoutController.clear()
|
|
369
453
|
}
|
|
370
454
|
|
|
371
455
|
if (message == null) {
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { EventEmitter } from '@libp2p/interfaces/events'
|
|
|
4
4
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
5
5
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
6
6
|
import type { FaultTolerance } from './transport-manager.js'
|
|
7
|
-
import type {
|
|
7
|
+
import type { IdentifyServiceInit } from './identify/index.js'
|
|
8
8
|
import type { DualDHT } from '@libp2p/interfaces/dht'
|
|
9
9
|
import type { Datastore } from 'interface-datastore'
|
|
10
10
|
import type { PeerStore, PeerStoreInit } from '@libp2p/interfaces/peer-store'
|
|
@@ -24,6 +24,8 @@ import type { Metrics, MetricsInit } from '@libp2p/interfaces/metrics'
|
|
|
24
24
|
import type { PeerInfo } from '@libp2p/interfaces/peer-info'
|
|
25
25
|
import type { KeyChain } from './keychain/index.js'
|
|
26
26
|
import type { ConnectionManagerInit } from './connection-manager/index.js'
|
|
27
|
+
import type { PingServiceInit } from './ping/index.js'
|
|
28
|
+
import type { FetchServiceInit } from './fetch/index.js'
|
|
27
29
|
|
|
28
30
|
export interface PersistentPeerStoreOptions {
|
|
29
31
|
threshold?: number
|
|
@@ -95,7 +97,6 @@ export interface RefreshManagerConfig {
|
|
|
95
97
|
|
|
96
98
|
export interface Libp2pInit {
|
|
97
99
|
peerId: PeerId
|
|
98
|
-
host: HostProperties
|
|
99
100
|
addresses: AddressesConfig
|
|
100
101
|
connectionManager: ConnectionManagerInit
|
|
101
102
|
connectionGater: Partial<ConnectionGater>
|
|
@@ -105,9 +106,11 @@ export interface Libp2pInit {
|
|
|
105
106
|
peerStore: PeerStoreInit
|
|
106
107
|
peerRouting: PeerRoutingConfig
|
|
107
108
|
keychain: KeychainConfig
|
|
108
|
-
protocolPrefix: string
|
|
109
109
|
nat: NatManagerConfig
|
|
110
110
|
relay: RelayConfig
|
|
111
|
+
identify: IdentifyServiceInit
|
|
112
|
+
ping: PingServiceInit
|
|
113
|
+
fetch: FetchServiceInit
|
|
111
114
|
|
|
112
115
|
transports: Transport[]
|
|
113
116
|
streamMuxers?: StreamMuxerFactory[]
|
|
@@ -195,12 +198,12 @@ export interface Libp2p extends Startable, EventEmitter<Libp2pEvents> {
|
|
|
195
198
|
/**
|
|
196
199
|
* Pings the given peer in order to obtain the operation latency
|
|
197
200
|
*/
|
|
198
|
-
ping: (peer: Multiaddr |PeerId) => Promise<number>
|
|
201
|
+
ping: (peer: Multiaddr | PeerId, options?: AbortOptions) => Promise<number>
|
|
199
202
|
|
|
200
203
|
/**
|
|
201
204
|
* Sends a request to fetch the value associated with the given key from the given peer.
|
|
202
205
|
*/
|
|
203
|
-
fetch: (peer: PeerId | Multiaddr | string, key: string) => Promise<Uint8Array | null>
|
|
206
|
+
fetch: (peer: PeerId | Multiaddr | string, key: string, options?: AbortOptions) => Promise<Uint8Array | null>
|
|
204
207
|
|
|
205
208
|
/**
|
|
206
209
|
* Returns the public key for the passed PeerId. If the PeerId is of the 'RSA' type
|
package/src/libp2p.ts
CHANGED
|
@@ -166,10 +166,7 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
|
|
|
166
166
|
if (init.streamMuxers != null && init.streamMuxers.length > 0) {
|
|
167
167
|
// Add the identify service since we can multiplex
|
|
168
168
|
this.identifyService = new IdentifyService(this.components, {
|
|
169
|
-
|
|
170
|
-
host: {
|
|
171
|
-
agentVersion: init.host.agentVersion
|
|
172
|
-
}
|
|
169
|
+
...init.identify
|
|
173
170
|
})
|
|
174
171
|
this.configureComponent(this.identifyService)
|
|
175
172
|
}
|
|
@@ -229,11 +226,11 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
|
|
|
229
226
|
}
|
|
230
227
|
|
|
231
228
|
this.fetchService = this.configureComponent(new FetchService(this.components, {
|
|
232
|
-
|
|
229
|
+
...init.fetch
|
|
233
230
|
}))
|
|
234
231
|
|
|
235
232
|
this.pingService = this.configureComponent(new PingService(this.components, {
|
|
236
|
-
|
|
233
|
+
...init.ping
|
|
237
234
|
}))
|
|
238
235
|
|
|
239
236
|
const autoDialer = this.configureComponent(new AutoDialer(this.components, {
|
|
@@ -419,9 +416,9 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
|
|
|
419
416
|
throw errCode(new Error('no protocols were provided to open a stream'), codes.ERR_INVALID_PROTOCOLS_FOR_STREAM)
|
|
420
417
|
}
|
|
421
418
|
|
|
422
|
-
const connection = await this.dial(peer)
|
|
419
|
+
const connection = await this.dial(peer, options)
|
|
423
420
|
|
|
424
|
-
return await connection.newStream(protocols)
|
|
421
|
+
return await connection.newStream(protocols, options)
|
|
425
422
|
}
|
|
426
423
|
|
|
427
424
|
getMultiaddrs (): Multiaddr[] {
|
|
@@ -473,24 +470,24 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
|
|
|
473
470
|
throw errCode(new Error(`Node not responding with its public key: ${peer.toString()}`), codes.ERR_INVALID_RECORD)
|
|
474
471
|
}
|
|
475
472
|
|
|
476
|
-
async fetch (peer: PeerId | Multiaddr | string, key: string): Promise<Uint8Array | null> {
|
|
473
|
+
async fetch (peer: PeerId | Multiaddr | string, key: string, options: AbortOptions = {}): Promise<Uint8Array | null> {
|
|
477
474
|
const { id, multiaddrs } = getPeer(peer)
|
|
478
475
|
|
|
479
476
|
if (multiaddrs != null) {
|
|
480
477
|
await this.components.getPeerStore().addressBook.add(id, multiaddrs)
|
|
481
478
|
}
|
|
482
479
|
|
|
483
|
-
return await this.fetchService.fetch(id, key)
|
|
480
|
+
return await this.fetchService.fetch(id, key, options)
|
|
484
481
|
}
|
|
485
482
|
|
|
486
|
-
async ping (peer: PeerId | Multiaddr | string): Promise<number> {
|
|
483
|
+
async ping (peer: PeerId | Multiaddr | string, options: AbortOptions = {}): Promise<number> {
|
|
487
484
|
const { id, multiaddrs } = getPeer(peer)
|
|
488
485
|
|
|
489
486
|
if (multiaddrs.length > 0) {
|
|
490
487
|
await this.components.getPeerStore().addressBook.add(id, multiaddrs)
|
|
491
488
|
}
|
|
492
489
|
|
|
493
|
-
return await this.pingService.ping(id)
|
|
490
|
+
return await this.pingService.ping(id, options)
|
|
494
491
|
}
|
|
495
492
|
|
|
496
493
|
async handle (protocols: string | string[], handler: StreamHandler): Promise<void> {
|
package/src/nat-manager.ts
CHANGED
|
@@ -94,10 +94,14 @@ export class NatManager implements Startable {
|
|
|
94
94
|
return this.started
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
start () {}
|
|
98
|
+
|
|
97
99
|
/**
|
|
98
|
-
*
|
|
100
|
+
* Attempt to use uPnP to configure port mapping using the current gateway.
|
|
101
|
+
*
|
|
102
|
+
* Run after start to ensure the transport manager has all addresses configured.
|
|
99
103
|
*/
|
|
100
|
-
|
|
104
|
+
afterStart () {
|
|
101
105
|
if (isBrowser || !this.enabled || this.started) {
|
|
102
106
|
return
|
|
103
107
|
}
|
|
@@ -105,7 +109,7 @@ export class NatManager implements Startable {
|
|
|
105
109
|
this.started = true
|
|
106
110
|
|
|
107
111
|
// done async to not slow down startup
|
|
108
|
-
this._start().catch((err) => {
|
|
112
|
+
void this._start().catch((err) => {
|
|
109
113
|
// hole punching errors are non-fatal
|
|
110
114
|
log.error(err)
|
|
111
115
|
})
|
package/src/peer-routing.ts
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
clearDelayedInterval
|
|
18
18
|
// @ts-expect-error module with no types
|
|
19
19
|
} from 'set-delayed-interval'
|
|
20
|
-
// @ts-expect-error setMaxListeners is missing from the node 16 types
|
|
21
20
|
import { setMaxListeners } from 'events'
|
|
22
21
|
import type { PeerId } from '@libp2p/interfaces/peer-id'
|
|
23
22
|
import type { PeerRouting } from '@libp2p/interfaces/peer-routing'
|
package/src/ping/index.ts
CHANGED
|
@@ -10,6 +10,9 @@ import type { IncomingStreamData } from '@libp2p/interfaces/registrar'
|
|
|
10
10
|
import type { PeerId } from '@libp2p/interfaces/peer-id'
|
|
11
11
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
12
12
|
import type { Components } from '@libp2p/interfaces/components'
|
|
13
|
+
import type { AbortOptions } from '@libp2p/interfaces'
|
|
14
|
+
import type { Duplex } from 'it-stream-types'
|
|
15
|
+
import { abortableDuplex } from 'abortable-iterator'
|
|
13
16
|
|
|
14
17
|
const log = logger('libp2p:ping')
|
|
15
18
|
|
|
@@ -18,8 +21,8 @@ export interface PingServiceInit {
|
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export class PingService implements Startable {
|
|
24
|
+
public readonly protocol: string
|
|
21
25
|
private readonly components: Components
|
|
22
|
-
private readonly protocol: string
|
|
23
26
|
private started: boolean
|
|
24
27
|
|
|
25
28
|
constructor (components: Components, init: PingServiceInit) {
|
|
@@ -60,25 +63,36 @@ export class PingService implements Startable {
|
|
|
60
63
|
* @param {PeerId|Multiaddr} peer
|
|
61
64
|
* @returns {Promise<number>}
|
|
62
65
|
*/
|
|
63
|
-
async ping (peer: PeerId): Promise<number> {
|
|
66
|
+
async ping (peer: PeerId, options: AbortOptions = {}): Promise<number> {
|
|
64
67
|
log('dialing %s to %p', this.protocol, peer)
|
|
65
68
|
|
|
66
|
-
const connection = await this.components.getConnectionManager().openConnection(peer)
|
|
67
|
-
const { stream } = await connection.newStream([this.protocol])
|
|
69
|
+
const connection = await this.components.getConnectionManager().openConnection(peer, options)
|
|
70
|
+
const { stream } = await connection.newStream([this.protocol], options)
|
|
68
71
|
const start = Date.now()
|
|
69
72
|
const data = randomBytes(PING_LENGTH)
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
[data],
|
|
73
|
-
stream,
|
|
74
|
-
async (source) => await first(source)
|
|
75
|
-
)
|
|
76
|
-
const end = Date.now()
|
|
74
|
+
let source: Duplex<Uint8Array> = stream
|
|
77
75
|
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
// make stream abortable if AbortSignal passed
|
|
77
|
+
if (options.signal != null) {
|
|
78
|
+
source = abortableDuplex(stream, options.signal)
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
try {
|
|
82
|
+
const result = await pipe(
|
|
83
|
+
[data],
|
|
84
|
+
source,
|
|
85
|
+
async (source) => await first(source)
|
|
86
|
+
)
|
|
87
|
+
const end = Date.now()
|
|
88
|
+
|
|
89
|
+
if (result == null || !uint8ArrayEquals(data, result)) {
|
|
90
|
+
throw errCode(new Error('Received wrong ping ack'), codes.ERR_WRONG_PING_ACK)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return end - start
|
|
94
|
+
} finally {
|
|
95
|
+
stream.close()
|
|
96
|
+
}
|
|
83
97
|
}
|
|
84
98
|
}
|
package/src/upgrader.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type { PeerId } from '@libp2p/interfaces/peer-id'
|
|
|
15
15
|
import type { MultiaddrConnection, Upgrader, UpgraderEvents } from '@libp2p/interfaces/transport'
|
|
16
16
|
import type { Duplex } from 'it-stream-types'
|
|
17
17
|
import type { Components } from '@libp2p/interfaces/components'
|
|
18
|
+
import type { AbortOptions } from '@libp2p/interfaces'
|
|
18
19
|
|
|
19
20
|
const log = logger('libp2p:upgrader')
|
|
20
21
|
|
|
@@ -266,7 +267,7 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
|
|
|
266
267
|
} = opts
|
|
267
268
|
|
|
268
269
|
let muxer: StreamMuxer | undefined
|
|
269
|
-
let newStream: ((multicodecs: string[]) => Promise<ProtocolStream>) | undefined
|
|
270
|
+
let newStream: ((multicodecs: string[], options?: AbortOptions) => Promise<ProtocolStream>) | undefined
|
|
270
271
|
let connection: Connection // eslint-disable-line prefer-const
|
|
271
272
|
|
|
272
273
|
if (muxerFactory != null) {
|
|
@@ -308,7 +309,7 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
|
|
|
308
309
|
}
|
|
309
310
|
})
|
|
310
311
|
|
|
311
|
-
newStream = async (protocols: string[]): Promise<ProtocolStream> => {
|
|
312
|
+
newStream = async (protocols: string[], options: AbortOptions = {}): Promise<ProtocolStream> => {
|
|
312
313
|
if (muxer == null) {
|
|
313
314
|
throw errCode(new Error('Stream is not multiplexed'), codes.ERR_MUXER_UNAVAILABLE)
|
|
314
315
|
}
|
|
@@ -319,7 +320,7 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
|
|
|
319
320
|
const metrics = this.components.getMetrics()
|
|
320
321
|
|
|
321
322
|
try {
|
|
322
|
-
let { stream, protocol } = await mss.select(protocols)
|
|
323
|
+
let { stream, protocol } = await mss.select(protocols, options)
|
|
323
324
|
|
|
324
325
|
if (metrics != null) {
|
|
325
326
|
stream = metrics.trackStream({ stream, remotePeer, protocol })
|
|
@@ -328,6 +329,11 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
|
|
|
328
329
|
return { stream: { ...muxedStream, ...stream }, protocol }
|
|
329
330
|
} catch (err: any) {
|
|
330
331
|
log.error('could not create new stream', err)
|
|
332
|
+
|
|
333
|
+
if (err.code != null) {
|
|
334
|
+
throw err
|
|
335
|
+
}
|
|
336
|
+
|
|
331
337
|
throw errCode(err, codes.ERR_UNSUPPORTED_PROTOCOL)
|
|
332
338
|
}
|
|
333
339
|
}
|
|
@@ -382,9 +388,11 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
|
|
|
382
388
|
getStreams: () => muxer != null ? muxer.streams : errConnectionNotMultiplexed(),
|
|
383
389
|
close: async () => {
|
|
384
390
|
await maConn.close()
|
|
385
|
-
// Ensure remaining streams are
|
|
391
|
+
// Ensure remaining streams are closed
|
|
386
392
|
if (muxer != null) {
|
|
387
|
-
muxer.streams.map(stream =>
|
|
393
|
+
await Promise.all(muxer.streams.map(async stream => {
|
|
394
|
+
await stream.close()
|
|
395
|
+
}))
|
|
388
396
|
}
|
|
389
397
|
}
|
|
390
398
|
})
|