1package swift 2 3import ( 4 "io" 5 "time" 6) 7 8var watchdogChunkSize = 1 << 20 // 1 MiB 9 10// An io.Reader which resets a watchdog timer whenever data is read 11type watchdogReader struct { 12 timeout time.Duration 13 reader io.Reader 14 timer *time.Timer 15 chunkSize int 16} 17 18// Returns a new reader which will kick the watchdog timer whenever data is read 19func newWatchdogReader(reader io.Reader, timeout time.Duration, timer *time.Timer) *watchdogReader { 20 return &watchdogReader{ 21 timeout: timeout, 22 reader: reader, 23 timer: timer, 24 chunkSize: watchdogChunkSize, 25 } 26} 27 28// Read reads up to len(p) bytes into p 29func (t *watchdogReader) Read(p []byte) (int, error) { 30 //read from underlying reader in chunks not larger than t.chunkSize 31 //while resetting the watchdog timer before every read; the small chunk 32 //size ensures that the timer does not fire when reading a large amount of 33 //data from a slow connection 34 start := 0 35 end := len(p) 36 for start < end { 37 length := end - start 38 if length > t.chunkSize { 39 length = t.chunkSize 40 } 41 42 resetTimer(t.timer, t.timeout) 43 n, err := t.reader.Read(p[start : start+length]) 44 start += n 45 if n == 0 || err != nil { 46 return start, err 47 } 48 } 49 50 resetTimer(t.timer, t.timeout) 51 return start, nil 52} 53 54// Check it satisfies the interface 55var _ io.Reader = &watchdogReader{} 56