2019-08-16 17:30:03 +02:00
|
|
|
'use strict'
|
|
|
|
|
2019-12-10 19:26:54 +01:00
|
|
|
const debug = require('debug')
|
2020-12-10 14:48:14 +01:00
|
|
|
const log = Object.assign(debug('libp2p:ping'), {
|
|
|
|
error: debug('libp2p:ping:err')
|
|
|
|
})
|
2019-12-10 19:26:54 +01:00
|
|
|
const errCode = require('err-code')
|
2019-08-16 17:30:03 +02:00
|
|
|
|
2019-12-10 19:26:54 +01:00
|
|
|
const crypto = require('libp2p-crypto')
|
2020-12-10 14:48:14 +01:00
|
|
|
const { pipe } = require('it-pipe')
|
2021-04-15 09:40:02 +02:00
|
|
|
// @ts-ignore it-buffer has no types exported
|
2019-12-10 19:26:54 +01:00
|
|
|
const { toBuffer } = require('it-buffer')
|
2020-02-03 14:50:40 +00:00
|
|
|
const { collect, take } = require('streaming-iterables')
|
2021-08-16 21:29:06 +02:00
|
|
|
const { equals } = require('uint8arrays/equals')
|
2019-12-10 19:26:54 +01:00
|
|
|
|
2021-08-13 10:21:50 -04:00
|
|
|
const { PROTOCOL_NAME, PING_LENGTH, PROTOCOL_VERSION } = require('./constants')
|
2019-12-10 19:26:54 +01:00
|
|
|
|
2020-12-10 14:48:14 +01:00
|
|
|
/**
|
|
|
|
* @typedef {import('../')} Libp2p
|
2021-04-15 09:40:02 +02:00
|
|
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
2020-12-10 14:48:14 +01:00
|
|
|
* @typedef {import('peer-id')} PeerId
|
2021-04-15 09:40:02 +02:00
|
|
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
2020-12-10 14:48:14 +01:00
|
|
|
*/
|
|
|
|
|
2019-12-10 19:26:54 +01:00
|
|
|
/**
|
|
|
|
* Ping a given peer and wait for its response, getting the operation latency.
|
2020-10-06 14:59:43 +02:00
|
|
|
*
|
2019-12-10 19:26:54 +01:00
|
|
|
* @param {Libp2p} node
|
2020-12-10 14:48:14 +01:00
|
|
|
* @param {PeerId|Multiaddr} peer
|
2020-10-06 14:59:43 +02:00
|
|
|
* @returns {Promise<number>}
|
2019-12-10 19:26:54 +01:00
|
|
|
*/
|
|
|
|
async function ping (node, peer) {
|
2021-08-13 10:21:50 -04:00
|
|
|
const protocol = `/${node._config.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}`
|
2020-12-10 14:48:14 +01:00
|
|
|
// @ts-ignore multiaddr might not have toB58String
|
2021-08-13 10:21:50 -04:00
|
|
|
log('dialing %s to %s', protocol, peer.toB58String ? peer.toB58String() : peer)
|
2019-12-10 19:26:54 +01:00
|
|
|
|
2021-04-15 09:40:02 +02:00
|
|
|
const connection = await node.dial(peer)
|
2021-08-13 10:21:50 -04:00
|
|
|
const { stream } = await connection.newStream(protocol)
|
2019-12-10 19:26:54 +01:00
|
|
|
|
2020-12-10 14:48:14 +01:00
|
|
|
const start = Date.now()
|
2019-12-10 19:26:54 +01:00
|
|
|
const data = crypto.randomBytes(PING_LENGTH)
|
|
|
|
|
|
|
|
const [result] = await pipe(
|
|
|
|
[data],
|
|
|
|
stream,
|
2021-04-15 09:40:02 +02:00
|
|
|
(/** @type {MuxedStream} */ stream) => take(1, stream),
|
2019-12-10 19:26:54 +01:00
|
|
|
toBuffer,
|
|
|
|
collect
|
|
|
|
)
|
|
|
|
const end = Date.now()
|
|
|
|
|
2020-12-10 14:48:14 +01:00
|
|
|
if (!equals(data, result)) {
|
2019-12-10 19:26:54 +01:00
|
|
|
throw errCode(new Error('Received wrong ping ack'), 'ERR_WRONG_PING_ACK')
|
|
|
|
}
|
|
|
|
|
|
|
|
return end - start
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Subscribe ping protocol handler.
|
2020-10-06 14:59:43 +02:00
|
|
|
*
|
2019-12-10 19:26:54 +01:00
|
|
|
* @param {Libp2p} node
|
|
|
|
*/
|
|
|
|
function mount (node) {
|
2021-08-13 10:21:50 -04:00
|
|
|
node.handle(`/${node._config.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}`, ({ stream }) => pipe(stream, stream))
|
2019-12-10 19:26:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unsubscribe ping protocol handler.
|
2020-10-06 14:59:43 +02:00
|
|
|
*
|
2019-12-10 19:26:54 +01:00
|
|
|
* @param {Libp2p} node
|
|
|
|
*/
|
|
|
|
function unmount (node) {
|
2021-08-13 10:21:50 -04:00
|
|
|
node.unhandle(`/${node._config.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}`)
|
2019-12-10 19:26:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
exports = module.exports = ping
|
|
|
|
exports.mount = mount
|
|
|
|
exports.unmount = unmount
|