From 293bcf98b7841f6f7b406c18bcc37fa6135a3ea6 Mon Sep 17 00:00:00 2001 From: Melvin Philips Date: Wed, 31 Jan 2018 23:54:21 -0800 Subject: [PATCH] feat: implement `ipfs ping` flags #928 --- src/cli/commands/ping.js | 44 +++++++++++++++++++++++++++++++++ src/core/components/ping.js | 30 ++++++++++++++++++++-- src/http/api/resources/index.js | 1 + src/http/api/resources/ping.js | 18 ++++++++++++++ src/http/api/routes/index.js | 1 + src/http/api/routes/ping.js | 19 ++++++++++++++ test/cli/commands.js | 2 +- 7 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 src/cli/commands/ping.js create mode 100644 src/http/api/resources/ping.js create mode 100644 src/http/api/routes/ping.js diff --git a/src/cli/commands/ping.js b/src/cli/commands/ping.js new file mode 100644 index 0000000000..e1103849f5 --- /dev/null +++ b/src/cli/commands/ping.js @@ -0,0 +1,44 @@ +'use strict' + +const print = require('../utils').print + +module.exports = { + command: 'ping ', + + describe: 'Measure the latency of a connection', + + builder: { + count: { + alias: 'n', + type: 'integer', + default: 10 + } + }, + + handler (argv) { + const peerId = argv.peerId + const count = argv.count || 10 + + print('PING ' + peerId) + + let noOfTimes = 0 + let totalTime = 0 + + const pingCb = (err, p) => { + if (err) { + throw err + } + let time = p.Time + totalTime = totalTime + time + noOfTimes = noOfTimes + 1 + print('Pong received: time=' + time + ' ms') + if (noOfTimes === count) { + print('Average latency: ' + totalTime / count + 'ms') + } + } + + for (let i = 0; i < count; i++) { + argv.ipfs.ping(peerId, pingCb) + } + } +} diff --git a/src/core/components/ping.js b/src/core/components/ping.js index eb7a45b34f..bcf7c10f6c 100644 --- a/src/core/components/ping.js +++ b/src/core/components/ping.js @@ -1,9 +1,35 @@ 'use strict' const promisify = require('promisify-es6') +const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR +const PeerId = require('peer-id') +const PeerInfo = require('peer-info') +var Readable = require('stream').Readable module.exports = function ping (self) { - return promisify((callback) => { - callback(new Error('Not implemented')) + return promisify((peerId, cb) => { + if (!self.isOnline()) { + return cb(new Error(OFFLINE_ERROR)) + } + + var outputStream = new Readable() + outputStream._read = function (size) { + } + + let peer + try { + peer = self._libp2pNode.peerBook.get(peerId) + } catch (err) { + peer = new PeerInfo(PeerId.createFromB58String(peerId)) + } + + self._libp2pNode.ping(peer, (err, p) => { + p.once('ping', (time) => { + outputStream.push(JSON.stringify([{}, { Success: true, Time: time }, { Text: 'Average latency: ' + time + ' ms' }])) + outputStream.push(null) + p.stop() + cb(err, outputStream) + }) + }) }) } diff --git a/src/http/api/resources/index.js b/src/http/api/resources/index.js index 16b0f17128..4f54eccc5c 100644 --- a/src/http/api/resources/index.js +++ b/src/http/api/resources/index.js @@ -2,6 +2,7 @@ exports.version = require('./version') exports.id = require('./id') +exports.ping = require('./ping') exports.bootstrap = require('./bootstrap') exports.repo = require('./repo') exports.object = require('./object') diff --git a/src/http/api/resources/ping.js b/src/http/api/resources/ping.js new file mode 100644 index 0000000000..b8eaef90f4 --- /dev/null +++ b/src/http/api/resources/ping.js @@ -0,0 +1,18 @@ +'use strict' + +const boom = require('boom') + +exports = module.exports + +exports.get = (request, reply) => { + const ipfs = request.server.app.ipfs + const peerId = request.query.arg + + ipfs.ping(peerId, (err, outputStream) => { + if (err) { + return reply(boom.badRequest(err)) + } + + return reply(outputStream).type('application/json').header('x-chunked-output', '1') + }) +} diff --git a/src/http/api/routes/index.js b/src/http/api/routes/index.js index 908c0c0878..6a3b085359 100644 --- a/src/http/api/routes/index.js +++ b/src/http/api/routes/index.js @@ -8,6 +8,7 @@ module.exports = (server) => { require('./object')(server) // require('./repo')(server) require('./config')(server) + require('./ping')(server) require('./swarm')(server) require('./bitswap')(server) require('./file')(server) diff --git a/src/http/api/routes/ping.js b/src/http/api/routes/ping.js new file mode 100644 index 0000000000..3d75a8580f --- /dev/null +++ b/src/http/api/routes/ping.js @@ -0,0 +1,19 @@ +'use strict' + +const resources = require('./../resources') + +module.exports = (server) => { + const api = server.select('API') + + api.route({ + method: '*', + path: '/api/v0/ping', + config: { + payload: { + parse: false, + output: 'stream' + }, + handler: resources.ping.get + } + }) +} diff --git a/test/cli/commands.js b/test/cli/commands.js index 3a2d85a418..cc85d812f6 100644 --- a/test/cli/commands.js +++ b/test/cli/commands.js @@ -4,7 +4,7 @@ const expect = require('chai').expect const runOnAndOff = require('../utils/on-and-off') -const commandCount = 60 +const commandCount = 61 describe('commands', () => runOnAndOff((thing) => { let ipfs