From 2475393ee2e298938655452b394efef099409dc6 Mon Sep 17 00:00:00 2001 From: Mathias Buus Date: Tue, 25 Oct 2016 13:22:25 +0200 Subject: [PATCH] add holepunching capability --- index.js | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 6203b40..0716a80 100644 --- a/index.js +++ b/index.js @@ -181,6 +181,10 @@ DHT.prototype._ping = function (peer, cb) { this._request({command: '_ping', id: this._queryId}, peer, false, cb) } +DHT.prototype._holepunch = function (peer, referrer, cb) { + this._request({command: '_ping', id: this._queryId, forwardRequest: peers.encode([peer])}, referrer, false, cb) +} + DHT.prototype._request = function (request, peer, important, cb) { if (this.socket.inflight >= this.concurrency || this._pendingRequests.length) { this._pendingRequests.push({request: request, peer: peer, callback: cb}) @@ -192,16 +196,6 @@ DHT.prototype._request = function (request, peer, important, cb) { DHT.prototype._onrequest = function (request, peer) { if (validateId(request.id)) this._addNode(request.id, peer, request.roundtripToken) - var forwardRequest = decodePeer(request.forwardRequest) - if (forwardRequest) { // TODO: security stuff - console.error('TODO: [forward request]', forwardRequest) - } - - var forwardResponse = decodePeer(request.forwardResponse) - if (forwardResponse) { - console.error('TODO: [forward response]', forwardResponse) - } - if (request.roundtripToken) { if (!bufferEquals(request.roundtripToken, this._token(peer, 0))) { if (!bufferEquals(request.roundtripToken, this._token(peer, 1))) { @@ -210,6 +204,13 @@ DHT.prototype._onrequest = function (request, peer) { } } + if (request.forwardRequest) { + this._forwardRequest(request, peer) + return + } + + if (request.forwardResponse) peer = this._forwardResponse(request, peer) + switch (request.command) { case '_ping': return this._onping(request, peer) case '_find_node': return this._onfindnode(request, peer) @@ -218,6 +219,38 @@ DHT.prototype._onrequest = function (request, peer) { this._onquery(request, peer) } +DHT.prototype._forwardResponse = function (request, peer) { + if (request.command !== '_ping') return // only allow ping for now + + try { + var from = peers.decode(request.forwardResponse)[0] + if (!from) return + } catch (err) { + return + } + + from.request = true + from.tid = peer.tid + + return from +} + +DHT.prototype._forwardRequest = function (request, peer) { + if (request.command !== '_ping') return // only allow ping forwards right now + + try { + var to = peers.decode(request.forwardRequest)[0] + if (!to) return + } catch (err) { + return + } + + this.emit('holepunch', peer, to) + request.forwardRequest = null + request.forwardResponse = peers.encode([peer]) + this.socket.forwardRequest(request, peer, to) +} + DHT.prototype._onquery = function (request, peer) { var self = this var query = {