client.go | 5 +++++ connection.go | 12 ++++++++++++ misc.go | 4 ++++ diff --git a/client.go b/client.go index 76425ccc2c37eb91866848145f685d256df9c586..f8737600b776514a91533fbcce65ee13c90ea839 100644 --- a/client.go +++ b/client.go @@ -425,6 +425,11 @@ Index: msg.Index, Begin: msg.Begin, Piece: p, }) + case peer_protocol.Cancel: + req := newRequest(msg.Index, msg.Begin, msg.Length) + if !conn.PeerCancel(req) { + log.Printf("received unexpected cancel: %v", req) + } case peer_protocol.Bitfield: if len(msg.Bitfield) < len(torrent.Pieces) { err = errors.New("received invalid bitfield") diff --git a/connection.go b/connection.go index ee54f10ccbbc964f256b268b3636a9285696882b..aefe0ba0bb0c26b84e1d6a4bbaf51fd98ae4a0bb 100644 --- a/connection.go +++ b/connection.go @@ -88,6 +88,18 @@ c.Requests[chunk] = struct{}{} return true } +// Returns true if an unsatisfied request was canceled. +func (c *connection) PeerCancel(r Request) bool { + if c.PeerRequests == nil { + return false + } + if _, ok := c.PeerRequests[r]; !ok { + return false + } + delete(c.PeerRequests, r) + return true +} + func (c *connection) Unchoke() { if !c.Choked { return diff --git a/misc.go b/misc.go index ce0997f21f6f122f13a8ef977fb498e4bdd2a93c..b0fb349e04024fe7f0d2d08dff820844edd7255e 100644 --- a/misc.go +++ b/misc.go @@ -65,6 +65,10 @@ Index peer_protocol.Integer chunkSpec } +func newRequest(index, begin, length peer_protocol.Integer) Request { + return Request{index, chunkSpec{begin, length}} +} + type pieceByBytesPendingSlice struct { Pending, Indices []peer_protocol.Integer }