github.com/anacrolix/torrent@v1.61.0/idle-reader.go (about) 1 package torrent 2 3 import ( 4 "fmt" 5 "io" 6 "time" 7 ) 8 9 func newIdleTimeoutReader(r io.Reader, timeout time.Duration, interrupt func()) io.Reader { 10 tr := &idleTimeoutReader{ 11 r: r, 12 interrupt: interrupt, 13 timeout: timeout, 14 } 15 tr.timer = time.AfterFunc(timeout, tr.timerFunc) 16 tr.timer.Stop() 17 return tr 18 } 19 20 type idleTimeoutReader struct { 21 r io.Reader 22 interrupt func() 23 timer *time.Timer 24 timeout time.Duration 25 fired bool 26 } 27 28 func (me *idleTimeoutReader) Read(p []byte) (n int, err error) { 29 // Allow resuming reading even after a previous idle timeout. 30 me.fired = false 31 me.timer.Reset(me.timeout) 32 n, err = me.r.Read(p) 33 me.timer.Stop() 34 if me.fired { 35 // Wrap the error, we don't know if the interrupt caused the inner reader to return early. 36 err = fmt.Errorf("idle timeout, original error: %w", err) 37 } 38 return 39 } 40 41 func (me *idleTimeoutReader) timerFunc() { 42 me.fired = true 43 me.interrupt() 44 }