mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-06 05:17:38 +03:00
Implementation read waiter for pipe
This commit is contained in:
parent
aa34723225
commit
1f02d6daca
4 changed files with 301 additions and 1 deletions
53
common/pipe/pipe_wait.go
Normal file
53
common/pipe/pipe_wait.go
Normal 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
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue