diff --git a/internal/torrent/peerwire.go b/internal/torrent/peerwire.go index 8fb674f..f978c94 100644 --- a/internal/torrent/peerwire.go +++ b/internal/torrent/peerwire.go @@ -73,7 +73,11 @@ func newPeerClient(ctx context.Context, addr string, infoHash [20]byte, peerID [ return nil, err } - _ = pc.readInitialMessages(ctx) + if err := pc.readInitialMessages(ctx); err != nil { + conn.Close() + return nil, err + } + return pc, nil } diff --git a/internal/torrent/piecescheduler.go b/internal/torrent/piecescheduler.go index 4808468..861214e 100644 --- a/internal/torrent/piecescheduler.go +++ b/internal/torrent/piecescheduler.go @@ -186,21 +186,35 @@ func (ps *pieceScheduler) run(pieceCount int) { } func selectPendingPiece(states []pieceState, have []bool, hasInfo bool) int { - if hasInfo { - for pieceIndex, state := range states { - if state != piecePending { - continue - } - if pieceIndex >= len(have) { - continue - } - if have[pieceIndex] { - return pieceIndex - } - } + firstPending := firstPendingPiece(states) + if firstPending < 0 { return -1 } + // If peer has not sent bitfield/have yet, treat it as potentially having any piece. + if !hasInfo { + return firstPending + } + + // Prefer pieces explicitly advertised by peer. + for pieceIndex, state := range states { + if state != piecePending { + continue + } + if pieceIndex < len(have) && have[pieceIndex] { + return pieceIndex + } + } + + // Some peers send missing/truncated availability info; allow optimistic probing. + if len(have) == 0 || len(have) < len(states) { + return firstPending + } + + return -1 +} + +func firstPendingPiece(states []pieceState) int { for pieceIndex, state := range states { if state == piecePending { return pieceIndex