peerconn.go | 16 +++++++++++----- torrent.go | 15 ++++++++++----- diff --git a/peerconn.go b/peerconn.go index 976081ab614a949c773f4c742d6827315dfe5d0c..8e3f5443e464e1197b1dd096b6f89df0f0144a25 100644 --- a/peerconn.go +++ b/peerconn.go @@ -396,7 +396,9 @@ } p.discardPieceInclination() p._pieceRequestOrder.Clear() p.peerImpl.onClose() - p.t.decPeerPieceAvailability(p) + if p.t != nil { + p.t.decPeerPieceAvailability(p) + } for _, f := range p.callbacks.PeerClosed { f(p) } @@ -1651,19 +1653,23 @@ func (cn *Peer) peerMaxRequests() int { return cn.PeerMaxRequests } -// Returns the pieces the peer has claimed to have. +// Returns the pieces the peer could have based on their claims. If we don't know how many pieces +// are in the torrent, it could be a very large range the peer has sent HaveAll. func (cn *PeerConn) PeerPieces() bitmap.Bitmap { cn.locker().RLock() defer cn.locker().RUnlock() return cn.newPeerPieces() } -// Returns a new Bitmap that includes bits for all pieces the peer claims to have. +// Returns a new Bitmap that includes bits for all pieces the peer could have based on their claims. func (cn *Peer) newPeerPieces() bitmap.Bitmap { ret := cn._peerPieces.Copy() if cn.peerSentHaveAll { - - ret.AddRange(0, bitmap.BitRange(cn.t.numPieces())) + if cn.t.haveInfo() { + ret.AddRange(0, bitmap.BitRange(cn.t.numPieces())) + } else { + ret.AddRange(0, bitmap.ToEnd) + } } return ret } diff --git a/torrent.go b/torrent.go index 5190b65ebeb3a9df9cec4877c9caab996df49025..e500a47d36834f9cd287aaf739da1a3d760f10ed 100644 --- a/torrent.go +++ b/torrent.go @@ -436,16 +436,18 @@ t.iterPeers(func(p *Peer) { p.onGotInfo(t.info) }) for i := range t.pieces { - t.updatePieceCompletion(pieceIndex(i)) p := &t.pieces[i] - if !p.storageCompletionOk { - // t.logger.Printf("piece %s completion unknown, queueing check", p) - t.queuePieceCheck(pieceIndex(i)) - } + // Need to add availability before updating piece completion, as that may result in conns + // being dropped. if p.availability != 0 { panic(p.availability) } p.availability = int64(t.pieceAvailabilityFromPeers(i)) + t.updatePieceCompletion(pieceIndex(i)) + if !p.storageCompletionOk { + // t.logger.Printf("piece %s completion unknown, queueing check", p) + t.queuePieceCheck(pieceIndex(i)) + } } t.cl.event.Broadcast() t.gotMetainfo.Set() @@ -1374,6 +1376,9 @@ return } func (t *Torrent) decPeerPieceAvailability(p *Peer) { + if !t.haveInfo() { + return + } p.newPeerPieces().IterTyped(func(i int) bool { p.t.decPieceAvailability(i) return true