TODO | 1 - connection.go | 4 ++++ misc.go | 4 ++++ torrent.go | 18 +++++++++++++----- diff --git a/TODO b/TODO index 9895f0449e0f27ff5e305366779a1692cee8ba87..16e9cbb5b3e872e54092baefd52cb792a41f6985 100644 --- a/TODO +++ b/TODO @@ -12,4 +12,3 @@ * Determine if we should accept connections, even if we just close them. http://stackoverflow.com/questions/35108571/can-i-leave-sockets-in-syn-recv-until-im-interested-in-accepting * 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 94451c6de6d6939dda04e1f72aef6f30d116cb01..727f97f7846db605da1f43f487d3e8644e56ed77 100644 --- a/connection.go +++ b/connection.go @@ -1068,3 +1068,7 @@ 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 a9b024ec4c7f9a2cccfb39dd25bf8f68d277e5e9..9d26738c765202f9bf0f1e6aad265e140fc2d6a1 100644 --- a/misc.go +++ b/misc.go @@ -81,3 +81,7 @@ ret.Length = pieceLength - ret.Begin } return ret } + +func connLessTrusted(l, r *connection) bool { + return l.netGoodPiecesDirtied() < r.netGoodPiecesDirtied() +} diff --git a/torrent.go b/torrent.go index 89422917de494b24ecb03724c0b2c5214881db94..8610a5ec99ed7ff95d1c006fd54559efc62ef714 100644 --- a/torrent.go +++ b/torrent.go @@ -1415,18 +1415,18 @@ if t.closed.IsSet() { 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 @@ log.Printf("%T: error completing piece %d: %s", t.storage, piece, err) } 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() } }