Don't close request on cancellation, try to drain it.
Shorten webseed requests to wanted region.
var n int
n, err = io.ReadFull(wr.request.Body, buf)
ws.peer.readBytes(int64(n))
+ if webseed.PrintDebug && wr.cancelled.Load() {
+ fmt.Printf("webseed read error after cancellation: %v\n", err)
+ }
if err != nil {
err = fmt.Errorf("reading chunk: %w", err)
return
// webseed requests are triggered, we want to ensure our existing request is up to date.
wr.next++
err = ws.peer.receiveChunk(&msg)
- stop := err != nil || !ws.keepReading(wr)
+ stop := err != nil || wr.next >= wr.end
+ if !stop {
+ if !ws.keepReading(wr) {
+ wr.Cancel()
+ }
+ }
ws.peer.locker().Unlock()
if err != nil {
err = fmt.Errorf("processing chunk: %w", err)
}
if stop {
- // TODO: Keep reading until the buffer is drained.
return
}
}
}
func (me *webseedRequest) Close() {
- me.request.Cancel()
+ me.request.Close()
}
// Record that it was exceptionally cancelled.
continue
}
t := requestKey.t
- // Run the request to the end of the file for now. TODO: Set a reasonable end so the
- // remote doesn't oversend.
peer := t.webSeeds[requestKey.url]
panicif.NotEq(peer.hostKey, costKey)
printPlan()
begin := t.getRequestIndexContainingOffset(requestKey.startOffset)
- // TODO: Find an actual end, so we don't lose lots of data when requests are cancelled.
- end := t.endRequestIndexForFileIndex(requestKey.fileIndex)
- panicif.Eq(begin, end)
+ fileEnd := t.endRequestIndexForFileIndex(requestKey.fileIndex)
+ last := begin
+ for {
+ if !t.wantReceiveChunk(last) {
+ break
+ }
+ if last >= fileEnd-1 {
+ break
+ }
+ last++
+ }
+ // Request shouldn't exist if this occurs.
+ panicif.LessThan(last, begin)
+ // Hello C++ my old friend.
+ end := last + 1
+ if webseed.PrintDebug {
+ fmt.Printf("shortened webseed request for %v: [%v-%v) to [%v-%v)\n",
+ requestKey.filePath(), begin, last+1, begin, end)
+ }
+ panicif.GreaterThan(end, fileEnd)
peer.spawnRequest(begin, end)
}
}
func (r Request) Cancel() {
r.cancel()
- r.bodyPipe.CloseWithError(context.Canceled)
+}
+
+func (r Request) Close() {
+ // We aren't cancelling because we want to know if we can keep receiving buffered data after
+ // cancellation. PipeReader.Close always returns nil.
+ _ = r.bodyPipe.Close()
}
type Client struct {