Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add uTP support #1328

Closed
wants to merge 7 commits into from
Closed
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

Small refactor/cleanup

  • Loading branch information
pldubouilh committed Mar 7, 2018
commit 9d40a62546a6f6ce23a5fb3ba0c36a123db5d069
@@ -52,14 +52,14 @@ function ConnPool (client) {
self.utpServer.on('listening', self._onListening)
self.utpServer.on('error', self._onError)

// Start listening TCP then UDP
// Start listening TCP then uTP
self.tcpServer.listen(client.torrentPort, function () {
self.utpServer.listen(this.address().port)
})
}

/**
* Destroy this TCP pool.
* Destroy this pool.
* @param {function} cb
*/
ConnPool.prototype.destroy = function (cb) {
@@ -118,7 +118,7 @@ ConnPool.prototype._onConnection = function (conn) {
self._pendingConns.push(conn)
conn.once('close', cleanupPending)

var peer = Peer.createIncomingPeer(conn, conn._utp ? 'utpIncoming' : 'tcpIncoming')
var peer = Peer.createIncomingPeer(conn)

var wire = peer.wire
wire.once('handshake', onHandshake)
@@ -4,10 +4,16 @@ var Wire = require('bittorrent-protocol')

var WebConn = require('./webconn')

var CONNECT_TIMEOUT_TCP = 5000
var CONNECT_TIMEOUT_WEBRTC = 25000
var CONNECT_TIMEOUT = {
utpOutgoing: 5000,
tcpOutgoing: 5000,
webrtc: 2500
}

var HANDSHAKE_TIMEOUT = 25000

var RECONNECT_WAIT = [1000, 5000, 15000]

/**
* WebRTC peer connections start out connected, because WebRTC peers require an
* "introduction" (i.e. WebRTC signaling), and there's no equivalent to an IP address
@@ -39,7 +45,7 @@ exports.createIncomingPeer = function (conn, type) {
var addr = conn.address()
var addrStr = addr.address + ':' + addr.port
var peer = new Peer(addrStr)
peer.type = type
peer.type = conn._utp ? 'utpIncoming' : 'tcpIncoming'
peer.conn = conn
peer.addr = addrStr

@@ -187,6 +193,32 @@ Peer.prototype.onHandshake = function (infoHash, peerId) {
if (!self.sentHandshake) self.handshake()
}

// When connection closes, attempt reconnect after timeout (with exponential backoff)
Peer.prototype.onClose = function (torrent) {
var self = this
if (torrent.destroyed || torrent.done) return

if (self.retries >= RECONNECT_WAIT.length) {
self._debug(
'conn %s closed: will not re-add (max %s attempts)',
self.addr, RECONNECT_WAIT.length
)
return
}

var ms = RECONNECT_WAIT[self.retries]
self._debug(
'conn %s closed: will re-add to queue in %sms (attempt %s)',
self.addr, ms, self.retries + 1
)

var reconnectTimeout = setTimeout(function reconnectTimeout () {
var newPeer = torrent._addPeer(self.addr)
if (newPeer) newPeer.retries = self.retries + 1
}, ms)
if (reconnectTimeout.unref) reconnectTimeout.unref()
}

Peer.prototype.handshake = function () {
var self = this
var opts = {
@@ -196,12 +228,12 @@ Peer.prototype.handshake = function () {
self.sentHandshake = true
}

Peer.prototype.startConnectTimeout = function () {
Peer.prototype.startConnectTimeout = function (cb) {
var self = this
clearTimeout(self.connectTimeout)
self.connectTimeout = setTimeout(function () {
self.destroy(new Error('connect timeout'))
}, self.type === 'webrtc' ? CONNECT_TIMEOUT_WEBRTC : CONNECT_TIMEOUT_TCP)
function defaultCB () { self.destroy(new Error('connect timeout')) }

self.connectTimeout = setTimeout(cb || defaultCB, CONNECT_TIMEOUT[self.type])
if (self.connectTimeout.unref) self.connectTimeout.unref()
}

@@ -50,8 +50,6 @@ var RECHOKE_OPTIMISTIC_DURATION = 2 // 30 seconds

var FILESYSTEM_CONCURRENCY = 2

var RECONNECT_WAIT = [ 1000, 5000, 15000 ]

var VERSION = require('../package.json').version
var USER_AGENT = 'WebTorrent/' + VERSION + ' (https://webtorrent.io)'

@@ -1692,7 +1690,7 @@ Torrent.prototype._utpConnect = function (peer, connOpts) {
var conn = peer.conn = utp.connect(connOpts.port, connOpts.host)
peer.type = 'utpOutgoing'

function fallbackTCP (err) {
function fallbackToTCP (err) {
if (!err && (peer.destroyed || peer.connected)) return
self._debug('utp timeout/error %s, (%s)', peer.addr, err)
conn.once('connect', noop)
@@ -1701,10 +1699,10 @@ Torrent.prototype._utpConnect = function (peer, connOpts) {
self._tcpConnect(peer, connOpts)
}

peer.connectTimeout = setTimeout(fallbackTCP, 3000)
peer.startConnectTimeout(fallbackToTCP)
conn.once('connect', function () { peer.onConnect() })
conn.once('error', e => fallbackTCP(e))
// conn.once('close', function () { })
conn.once('error', function (e) { peer.fallbackTCP(e) })
conn.once('close', function () { peer.onClose(self) })
}

Torrent.prototype._tcpConnect = function (peer, connOpts) {
@@ -1716,34 +1714,8 @@ Torrent.prototype._tcpConnect = function (peer, connOpts) {

conn.once('connect', function () { peer.onConnect() })
conn.once('error', function (err) { peer.destroy(err) })
conn.on('close', function () { peer.onClose(self) })
peer.startConnectTimeout()

// When connection closes, attempt reconnect after timeout (with exponential backoff)
conn.on('close', function () {
if (self.destroyed) return

// TODO: If torrent is done, do not try to reconnect after a timeout

if (peer.retries >= RECONNECT_WAIT.length) {
self._debug(
'conn %s closed: will not re-add (max %s attempts)',
peer.addr, RECONNECT_WAIT.length
)
return
}

var ms = RECONNECT_WAIT[peer.retries]
self._debug(
'conn %s closed: will re-add to queue in %sms (attempt %s)',
peer.addr, ms, peer.retries + 1
)

var reconnectTimeout = setTimeout(function reconnectTimeout () {
var newPeer = self._addPeer(peer.addr)
if (newPeer) newPeer.retries = peer.retries + 1
}, ms)
if (reconnectTimeout.unref) reconnectTimeout.unref()
})
}

/**
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.