github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/pipe/pipe_wait.go (about) 1 package pipe 2 3 import ( 4 "io" 5 "net" 6 "os" 7 8 "github.com/sagernet/sing/common/buf" 9 N "github.com/sagernet/sing/common/network" 10 ) 11 12 var _ N.ReadWaiter = (*pipe)(nil) 13 14 func (p *pipe) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) { 15 p.readWaitOptions = options 16 return false 17 } 18 19 func (p *pipe) WaitReadBuffer() (buffer *buf.Buffer, err error) { 20 buffer, err = p.waitReadBuffer() 21 if err != nil && err != io.EOF && err != io.ErrClosedPipe { 22 err = &net.OpError{Op: "read", Net: "pipe", Err: err} 23 } 24 return 25 } 26 27 func (p *pipe) waitReadBuffer() (buffer *buf.Buffer, err error) { 28 switch { 29 case isClosedChan(p.localDone): 30 return nil, io.ErrClosedPipe 31 case isClosedChan(p.remoteDone): 32 return nil, io.EOF 33 case isClosedChan(p.readDeadline.wait()): 34 return nil, os.ErrDeadlineExceeded 35 } 36 select { 37 case bw := <-p.rdRx: 38 buffer = p.readWaitOptions.NewBuffer() 39 var nr int 40 nr, err = buffer.Write(bw) 41 if err != nil { 42 buffer.Release() 43 return 44 } 45 p.readWaitOptions.PostReturn(buffer) 46 p.rdTx <- nr 47 return 48 case <-p.localDone: 49 return nil, io.ErrClosedPipe 50 case <-p.remoteDone: 51 return nil, io.EOF 52 case <-p.readDeadline.wait(): 53 return nil, os.ErrDeadlineExceeded 54 } 55 }