github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/bufio/deadline/reader.go (about) 1 package deadline 2 3 import ( 4 "io" 5 "os" 6 "time" 7 8 "github.com/sagernet/sing/common/atomic" 9 "github.com/sagernet/sing/common/buf" 10 "github.com/sagernet/sing/common/bufio" 11 N "github.com/sagernet/sing/common/network" 12 ) 13 14 type TimeoutReader interface { 15 io.Reader 16 SetReadDeadline(t time.Time) error 17 } 18 19 type Reader interface { 20 N.ExtendedReader 21 TimeoutReader 22 N.WithUpstreamReader 23 N.ReaderWithUpstream 24 } 25 26 type reader struct { 27 N.ExtendedReader 28 timeoutReader TimeoutReader 29 deadline atomic.TypedValue[time.Time] 30 pipeDeadline pipeDeadline 31 result chan *readResult 32 done chan struct{} 33 } 34 35 type readResult struct { 36 buffer *buf.Buffer 37 err error 38 } 39 40 func NewReader(timeoutReader TimeoutReader) Reader { 41 return &reader{ 42 ExtendedReader: bufio.NewExtendedReader(timeoutReader), 43 timeoutReader: timeoutReader, 44 pipeDeadline: makePipeDeadline(), 45 result: make(chan *readResult, 1), 46 done: makeFilledChan(), 47 } 48 } 49 50 func (r *reader) Read(p []byte) (n int, err error) { 51 select { 52 case result := <-r.result: 53 return r.pipeReturn(result, p) 54 default: 55 } 56 select { 57 case result := <-r.result: 58 return r.pipeReturn(result, p) 59 case <-r.pipeDeadline.wait(): 60 return 0, os.ErrDeadlineExceeded 61 case <-r.done: 62 go r.pipeRead(len(p)) 63 } 64 select { 65 case result := <-r.result: 66 return r.pipeReturn(result, p) 67 case <-r.pipeDeadline.wait(): 68 return 0, os.ErrDeadlineExceeded 69 } 70 } 71 72 func (r *reader) pipeReturn(result *readResult, p []byte) (n int, err error) { 73 n = copy(p, result.buffer.Bytes()) 74 result.buffer.Advance(n) 75 if result.buffer.IsEmpty() { 76 result.buffer.Release() 77 err = result.err 78 } else { 79 r.result <- result 80 } 81 return 82 } 83 84 func (r *reader) pipeRead(pLen int) { 85 buffer := buf.NewSize(pLen) 86 _, err := buffer.ReadOnceFrom(r.ExtendedReader) 87 r.result <- &readResult{ 88 buffer: buffer, 89 err: err, 90 } 91 r.done <- struct{}{} 92 } 93 94 func (r *reader) ReadBuffer(buffer *buf.Buffer) error { 95 select { 96 case result := <-r.result: 97 return r.pipeReturnBuffer(result, buffer) 98 default: 99 } 100 select { 101 case result := <-r.result: 102 return r.pipeReturnBuffer(result, buffer) 103 case <-r.pipeDeadline.wait(): 104 return os.ErrDeadlineExceeded 105 case <-r.done: 106 go r.pipeRead(buffer.FreeLen()) 107 } 108 select { 109 case result := <-r.result: 110 return r.pipeReturnBuffer(result, buffer) 111 case <-r.pipeDeadline.wait(): 112 return os.ErrDeadlineExceeded 113 } 114 } 115 116 func (r *reader) pipeReturnBuffer(result *readResult, buffer *buf.Buffer) error { 117 n, _ := buffer.Write(result.buffer.Bytes()) 118 result.buffer.Advance(n) 119 if !result.buffer.IsEmpty() { 120 r.result <- result 121 return nil 122 } else { 123 result.buffer.Release() 124 return result.err 125 } 126 } 127 128 func (r *reader) SetReadDeadline(t time.Time) error { 129 r.deadline.Store(t) 130 r.pipeDeadline.set(t) 131 return nil 132 } 133 134 func (r *reader) ReaderReplaceable() bool { 135 select { 136 case <-r.done: 137 r.done <- struct{}{} 138 default: 139 return false 140 } 141 select { 142 case result := <-r.result: 143 r.result <- result 144 return false 145 default: 146 } 147 return r.deadline.Load().IsZero() 148 } 149 150 func (r *reader) UpstreamReader() any { 151 return r.ExtendedReader 152 }