+func (c *connection) onReadRequest(r request) error {
+ requestedChunkLengths.Add(strconv.FormatUint(r.Length.Uint64(), 10), 1)
+ if c.Choked {
+ return nil
+ }
+ if len(c.PeerRequests) >= maxRequests {
+ // TODO: Should we drop them or Choke them instead?
+ return nil
+ }
+ if !c.t.havePiece(r.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)
+ return fmt.Errorf("peer requested piece we don't have: %v", r.Index.Int())
+ }
+ if c.PeerRequests == nil {
+ c.PeerRequests = make(map[request]struct{}, maxRequests)
+ }
+ c.PeerRequests[r] = struct{}{}
+ c.tickleWriter()
+ return nil
+}
+