From: Matt Joiner Date: Sun, 21 Feb 2016 06:22:55 +0000 (+1100) Subject: Choke peers when we lose pieces they requested, and drop them if they request pieces... X-Git-Tag: v1.0.0~872 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=99e9f41a33fcffd521f07a6429f46dcf1422cb48;p=btrtrc.git Choke peers when we lose pieces they requested, and drop them if they request pieces we don't have --- diff --git a/client.go b/client.go index 612152ef..91ea730e 100644 --- a/client.go +++ b/client.go @@ -40,6 +40,8 @@ import ( "github.com/anacrolix/torrent/tracker" ) +// I could move a lot of these counters to their own file, but I suspect they +// may be attached to a Client someday. var ( unwantedChunksReceived = expvar.NewInt("chunksReceivedUnwanted") unexpectedChunksReceived = expvar.NewInt("chunksReceivedUnexpected") @@ -73,6 +75,8 @@ var ( supportedExtensionMessages = expvar.NewMap("supportedExtensionMessages") postedMessageTypes = expvar.NewMap("postedMessageTypes") postedKeepalives = expvar.NewInt("postedKeepalives") + // Requests received for pieces we don't have. + requestsReceivedForMissingPieces = expvar.NewInt("requestsReceivedForMissingPieces") ) const ( @@ -1333,6 +1337,12 @@ another: err := me.sendChunk(t, c, r) if err != nil { log.Printf("error sending chunk %+v to peer: %s", r, err) + // If we failed to send a chunk, choke the peer to ensure they + // flush all their requests. We've probably dropped a piece, + // but there's no way to communicate this to the peer. If they + // ask for it again, we'll kick them to allow us to send them + // an updated bitfield. + break another } delete(c.PeerRequests, r) goto another @@ -1344,7 +1354,6 @@ another: func (me *Client) sendChunk(t *torrent, c *connection, r request) error { // Count the chunk being sent, even if it isn't. - c.chunksSent++ b := make([]byte, r.Length) p := t.Info.Piece(int(r.Index)) n, err := t.readAt(b, p.Offset()+int64(r.Begin)) @@ -1360,6 +1369,7 @@ func (me *Client) sendChunk(t *torrent, c *connection, r request) error { Begin: r.Begin, Piece: b, }) + c.chunksSent++ uploadChunksPosted.Add(1) c.lastChunkSent = time.Now() return nil @@ -1417,6 +1427,14 @@ func (me *Client) connectionLoop(t *torrent, c *connection) error { err = errors.New("peer sent request but isn't interested") break } + if !t.havePiece(msg.Index.Int()) { + // This isn't necessarily them screwing up. We can drop pieces + // from our storage, and can't communicate this to peers + // except by reconnecting. + requestsReceivedForMissingPieces.Add(1) + err = errors.New("peer requested piece we don't have") + break + } if c.PeerRequests == nil { c.PeerRequests = make(map[request]struct{}, maxRequests) }