Files
Xray-core/common/singbridge/pipe.go
T

74 lines
1.5 KiB
Go
Raw Normal View History

2023-04-23 19:31:41 +08:00
package singbridge
import (
"context"
"io"
"net"
2025-10-06 08:15:53 +08:00
"time"
2023-04-23 19:31:41 +08:00
"github.com/sagernet/sing/common/bufio"
2025-10-06 08:15:53 +08:00
"github.com/xtls/xray-core/common"
2023-04-23 19:31:41 +08:00
"github.com/xtls/xray-core/common/buf"
2026-05-04 03:39:52 +08:00
"github.com/xtls/xray-core/common/signal"
2023-04-23 19:31:41 +08:00
"github.com/xtls/xray-core/transport"
)
func CopyConn(ctx context.Context, inboundConn net.Conn, link *transport.Link, serverConn net.Conn) error {
conn := &PipeConnWrapper{
W: link.Writer,
Conn: inboundConn,
}
if ir, ok := link.Reader.(io.Reader); ok {
conn.R = ir
} else {
conn.R = &buf.BufferedReader{Reader: link.Reader}
}
2026-05-04 03:39:52 +08:00
cancel := func() {
common.Interrupt(conn.R)
}
conn.T = signal.CancelAfterInactivity(ctx, cancel, 300*time.Second)
2023-04-23 19:31:41 +08:00
return ReturnError(bufio.CopyConn(ctx, conn, serverConn))
}
type PipeConnWrapper struct {
R io.Reader
W buf.Writer
net.Conn
2026-05-04 03:39:52 +08:00
// A simple patch to avoid goroutine leak since sing infra cannot awake read block by write err
T *signal.ActivityTimer
2023-04-23 19:31:41 +08:00
}
func (w *PipeConnWrapper) Close() error {
return nil
}
func (w *PipeConnWrapper) Read(b []byte) (n int, err error) {
2026-05-04 03:39:52 +08:00
w.T.Update()
return w.R.Read(b)
2023-04-23 19:31:41 +08:00
}
func (w *PipeConnWrapper) Write(p []byte) (n int, err error) {
2026-05-04 03:39:52 +08:00
w.T.Update()
2023-04-23 19:31:41 +08:00
n = len(p)
var mb buf.MultiBuffer
pLen := len(p)
for pLen > 0 {
buffer := buf.New()
if pLen > buf.Size {
_, err = buffer.Write(p[:buf.Size])
p = p[buf.Size:]
} else {
buffer.Write(p)
}
pLen -= int(buffer.Len())
mb = append(mb, buffer)
}
err = w.W.WriteMultiBuffer(mb)
if err != nil {
n = 0
buf.ReleaseMulti(mb)
}
return
}