Implementation read waiter for pipe

This commit is contained in:
世界 2023-12-06 20:31:44 +08:00
parent aa34723225
commit 1f02d6daca
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
4 changed files with 301 additions and 1 deletions

53
common/pipe/pipe_wait.go Normal file
View file

@ -0,0 +1,53 @@
package pipe
import (
"io"
"net"
"os"
"github.com/sagernet/sing/common/buf"
N "github.com/sagernet/sing/common/network"
)
var _ N.ReadWaiter = (*pipe)(nil)
func (p *pipe) InitializeReadWaiter(newBuffer func() *buf.Buffer) {
p.newBuffer = newBuffer
}
func (p *pipe) WaitReadBuffer() (buffer *buf.Buffer, err error) {
buffer, err = p.waitReadBuffer()
if err != nil && err != io.EOF && err != io.ErrClosedPipe {
err = &net.OpError{Op: "read", Net: "pipe", Err: err}
}
return
}
func (p *pipe) waitReadBuffer() (buffer *buf.Buffer, err error) {
switch {
case isClosedChan(p.localDone):
return nil, io.ErrClosedPipe
case isClosedChan(p.remoteDone):
return nil, io.EOF
case isClosedChan(p.readDeadline.wait()):
return nil, os.ErrDeadlineExceeded
}
select {
case bw := <-p.rdRx:
buffer = p.newBuffer()
var nr int
nr, err = buffer.Write(bw)
if err != nil {
buffer.Release()
return
}
p.rdTx <- nr
return
case <-p.localDone:
return nil, io.ErrClosedPipe
case <-p.remoteDone:
return nil, io.EOF
case <-p.readDeadline.wait():
return nil, os.ErrDeadlineExceeded
}
}