From: Matt Joiner Date: Wed, 23 Nov 2016 01:59:23 +0000 (+1100) Subject: Kick only the worst connection when a piece fails a check X-Git-Tag: v1.0.0~528 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=fdf75d59c833a26dde9facbd564cb0a203ef07c2;p=btrtrc.git Kick only the worst connection when a piece fails a check --- diff --git a/TODO b/TODO index 9895f044..16e9cbb5 100644 --- a/TODO +++ b/TODO @@ -12,4 +12,3 @@ * Implement BEP 40. * Rewrite tracker package to be announce-centric, rather than client. Currently the clients are private and adapted onto by the Announce() func. * Move tracker management code in the torrent package to its own file. - * Kick only the poorest connection when a piece hash fails diff --git a/connection.go b/connection.go index 94451c6d..727f97f7 100644 --- a/connection.go +++ b/connection.go @@ -1068,3 +1068,7 @@ func (cn *connection) Drop() { func (cn *connection) sentHave(piece int) bool { return piece < len(cn.sentHaves) && cn.sentHaves[piece] } + +func (cn *connection) netGoodPiecesDirtied() int { + return cn.goodPiecesDirtied - cn.badPiecesDirtied +} diff --git a/misc.go b/misc.go index a9b024ec..9d26738c 100644 --- a/misc.go +++ b/misc.go @@ -81,3 +81,7 @@ func chunkIndexSpec(index int, pieceLength, chunkSize pp.Integer) chunkSpec { } return ret } + +func connLessTrusted(l, r *connection) bool { + return l.netGoodPiecesDirtied() < r.netGoodPiecesDirtied() +} diff --git a/torrent.go b/torrent.go index 89422917..8610a5ec 100644 --- a/torrent.go +++ b/torrent.go @@ -1415,18 +1415,18 @@ func (t *Torrent) pieceHashed(piece int, correct bool) { return } p := &t.pieces[piece] + touchers := t.reapPieceTouchers(piece) if p.EverHashed { // Don't score the first time a piece is hashed, it could be an // initial check. if correct { pieceHashedCorrect.Add(1) } else { - log.Printf("%s: piece %d (%x) failed hash", t, piece, p.Hash) + log.Printf("%s: piece %d (%x) failed hash: %d connections contributed", t, piece, p.Hash, len(touchers)) pieceHashedNotCorrect.Add(1) } } p.EverHashed = true - touchers := t.reapPieceTouchers(piece) if correct { for _, c := range touchers { c.goodPiecesDirtied++ @@ -1437,12 +1437,20 @@ func (t *Torrent) pieceHashed(piece int, correct bool) { } t.updatePieceCompletion(piece) } else if len(touchers) != 0 { - log.Printf("dropping and banning %d conns that touched piece", len(touchers)) for _, c := range touchers { + // Y u do dis peer?! c.badPiecesDirtied++ - t.cl.banPeerIP(missinggo.AddrIP(c.remoteAddr())) - t.dropConnection(c) } + slices.Sort(touchers, connLessTrusted) + log.Printf("dropping first corresponding conn from trust: %s", func() (ret []int) { + for _, c := range touchers { + ret = append(ret, c.netGoodPiecesDirtied()) + } + return + }) + c := touchers[0] + t.cl.banPeerIP(missinggo.AddrIP(c.remoteAddr())) + c.Drop() } }