in lib/torrent/scheduler/dispatch/dispatcher.go [524:569]
func (d *Dispatcher) handlePiecePayload(
p *peer, msg *p2p.PiecePayloadMessage, payload storage.PieceReader) {
defer payload.Close()
i := int(msg.Index)
if !d.isFullPiece(i, int(msg.Offset), int(msg.Length)) {
d.log("peer", p, "piece", i).Error("Rejecting piece payload: chunk not supported")
d.pieceRequestManager.MarkInvalid(p.id, i)
return
}
if err := d.torrent.WritePiece(payload, i); err != nil {
if err != storage.ErrPieceComplete {
d.log("peer", p, "piece", i).Errorf("Error writing piece payload: %s", err)
d.pieceRequestManager.MarkInvalid(p.id, i)
} else {
p.pstats.incrementDuplicatePiecesReceived()
}
return
}
d.netevents.Produce(
networkevent.ReceivePieceEvent(d.torrent.InfoHash(), d.localPeerID, p.id, i))
p.pstats.incrementGoodPiecesReceived()
p.touchLastGoodPieceReceived()
if d.torrent.Complete() {
d.complete()
}
d.pieceRequestManager.Clear(i)
d.maybeRequestMorePieces(p)
d.peers.Range(func(k, v interface{}) bool {
if k.(core.PeerID) == p.id {
return true
}
pp := v.(*peer)
pp.messages.Send(conn.NewAnnouncePieceMessage(i))
return true
})
}