libp2p 0.37.0 → 0.37.1
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 +5 -1
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +60 -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 +77 -27
- 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,13 +19,19 @@ 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
|
+
const IDENTIFY_TIMEOUT = 30000
|
|
34
|
+
|
|
31
35
|
export interface HostProperties {
|
|
32
36
|
agentVersion: string
|
|
33
37
|
}
|
|
@@ -35,6 +39,7 @@ export interface HostProperties {
|
|
|
35
39
|
export interface IdentifyServiceInit {
|
|
36
40
|
protocolPrefix: string
|
|
37
41
|
host: HostProperties
|
|
42
|
+
timeout?: number
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
export class IdentifyService implements Startable {
|
|
@@ -46,11 +51,13 @@ export class IdentifyService implements Startable {
|
|
|
46
51
|
agentVersion: string
|
|
47
52
|
}
|
|
48
53
|
|
|
54
|
+
private readonly init: IdentifyServiceInit
|
|
49
55
|
private started: boolean
|
|
50
56
|
|
|
51
57
|
constructor (components: Components, init: IdentifyServiceInit) {
|
|
52
58
|
this.components = components
|
|
53
59
|
this.started = false
|
|
60
|
+
this.init = init
|
|
54
61
|
|
|
55
62
|
this.handleMessage = this.handleMessage.bind(this)
|
|
56
63
|
|
|
@@ -128,8 +135,17 @@ export class IdentifyService implements Startable {
|
|
|
128
135
|
const protocols = await this.components.getPeerStore().protoBook.get(this.components.getPeerId())
|
|
129
136
|
|
|
130
137
|
const pushes = connections.map(async connection => {
|
|
138
|
+
const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
139
|
+
let stream: Stream | undefined
|
|
140
|
+
|
|
131
141
|
try {
|
|
132
|
-
const
|
|
142
|
+
const data = await connection.newStream([this.identifyPushProtocolStr], {
|
|
143
|
+
signal: timeoutController.signal
|
|
144
|
+
})
|
|
145
|
+
stream = data.stream
|
|
146
|
+
|
|
147
|
+
// make stream abortable
|
|
148
|
+
const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
|
|
133
149
|
|
|
134
150
|
await pipe(
|
|
135
151
|
[Identify.encode({
|
|
@@ -138,12 +154,18 @@ export class IdentifyService implements Startable {
|
|
|
138
154
|
protocols
|
|
139
155
|
})],
|
|
140
156
|
lp.encode(),
|
|
141
|
-
|
|
157
|
+
source,
|
|
142
158
|
drain
|
|
143
159
|
)
|
|
144
160
|
} catch (err: any) {
|
|
145
161
|
// Just log errors
|
|
146
162
|
log.error('could not push identify update to peer', err)
|
|
163
|
+
} finally {
|
|
164
|
+
if (stream != null) {
|
|
165
|
+
stream.close()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
timeoutController.clear()
|
|
147
169
|
}
|
|
148
170
|
})
|
|
149
171
|
|
|
@@ -175,31 +197,44 @@ export class IdentifyService implements Startable {
|
|
|
175
197
|
await this.push(connections)
|
|
176
198
|
}
|
|
177
199
|
|
|
200
|
+
async _identify (connection: Connection, options: AbortOptions = {}): Promise<Identify> {
|
|
201
|
+
const { stream } = await connection.newStream([this.identifyProtocolStr], options)
|
|
202
|
+
let source: Duplex<Uint8Array> = stream
|
|
203
|
+
|
|
204
|
+
// make stream abortable if AbortSignal passed
|
|
205
|
+
if (options.signal != null) {
|
|
206
|
+
source = abortableDuplex(stream, options.signal)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
const data = await pipe(
|
|
211
|
+
[],
|
|
212
|
+
source,
|
|
213
|
+
lp.decode(),
|
|
214
|
+
async (source) => await first(source)
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
if (data == null) {
|
|
218
|
+
throw errCode(new Error('No data could be retrieved'), codes.ERR_CONNECTION_ENDED)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
return Identify.decode(data)
|
|
223
|
+
} catch (err: any) {
|
|
224
|
+
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
|
225
|
+
}
|
|
226
|
+
} finally {
|
|
227
|
+
stream.close()
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
178
231
|
/**
|
|
179
232
|
* Requests the `Identify` message from peer associated with the given `connection`.
|
|
180
233
|
* If the identified peer does not match the `PeerId` associated with the connection,
|
|
181
234
|
* an error will be thrown.
|
|
182
235
|
*/
|
|
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
|
-
}
|
|
236
|
+
async identify (connection: Connection, options: AbortOptions = {}): Promise<void> {
|
|
237
|
+
const message = await this._identify(connection, options)
|
|
203
238
|
|
|
204
239
|
const {
|
|
205
240
|
publicKey,
|
|
@@ -308,6 +343,8 @@ export class IdentifyService implements Startable {
|
|
|
308
343
|
*/
|
|
309
344
|
async _handleIdentify (data: IncomingStreamData) {
|
|
310
345
|
const { connection, stream } = data
|
|
346
|
+
const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
347
|
+
|
|
311
348
|
try {
|
|
312
349
|
const publicKey = this.components.getPeerId().publicKey ?? new Uint8Array(0)
|
|
313
350
|
const peerData = await this.components.getPeerStore().get(this.components.getPeerId())
|
|
@@ -335,14 +372,20 @@ export class IdentifyService implements Startable {
|
|
|
335
372
|
protocols: peerData.protocols
|
|
336
373
|
})
|
|
337
374
|
|
|
375
|
+
// make stream abortable
|
|
376
|
+
const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
|
|
377
|
+
|
|
338
378
|
await pipe(
|
|
339
379
|
[message],
|
|
340
380
|
lp.encode(),
|
|
341
|
-
|
|
381
|
+
source,
|
|
342
382
|
drain
|
|
343
383
|
)
|
|
344
384
|
} catch (err: any) {
|
|
345
385
|
log.error('could not respond to identify request', err)
|
|
386
|
+
} finally {
|
|
387
|
+
stream.close()
|
|
388
|
+
timeoutController.clear()
|
|
346
389
|
}
|
|
347
390
|
}
|
|
348
391
|
|
|
@@ -351,12 +394,16 @@ export class IdentifyService implements Startable {
|
|
|
351
394
|
*/
|
|
352
395
|
async _handlePush (data: IncomingStreamData) {
|
|
353
396
|
const { connection, stream } = data
|
|
397
|
+
const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
|
|
354
398
|
|
|
355
399
|
let message: Identify | undefined
|
|
356
400
|
try {
|
|
401
|
+
// make stream abortable
|
|
402
|
+
const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
|
|
403
|
+
|
|
357
404
|
const data = await pipe(
|
|
358
405
|
[],
|
|
359
|
-
|
|
406
|
+
source,
|
|
360
407
|
lp.decode(),
|
|
361
408
|
async (source) => await first(source)
|
|
362
409
|
)
|
|
@@ -366,6 +413,9 @@ export class IdentifyService implements Startable {
|
|
|
366
413
|
}
|
|
367
414
|
} catch (err: any) {
|
|
368
415
|
return log.error('received invalid message', err)
|
|
416
|
+
} finally {
|
|
417
|
+
stream.close()
|
|
418
|
+
timeoutController.clear()
|
|
369
419
|
}
|
|
370
420
|
|
|
371
421
|
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
|
})
|