From 7bb5da30056d45ca7a465e23398053447f5610e0 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Tue, 25 Apr 2023 23:01:05 +0800 Subject: [PATCH] chore: support splice for direct outbound --- adapter/outbound/base.go | 8 ++++++++ common/buf/sing.go | 12 ++++++------ common/callback/callback.go | 8 ++++++++ common/net/bufconn.go | 10 ++++++++++ common/net/refconn.go | 8 ++++++++ common/net/sing.go | 5 +++++ component/dialer/tfo.go | 8 ++++++++ go.mod | 2 +- go.sum | 4 ++-- tunnel/statistic/tracker.go | 20 ++++++++++++++++++++ 10 files changed, 76 insertions(+), 9 deletions(-) diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index 04eec966..367638b8 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -204,6 +204,14 @@ func (c *conn) Upstream() any { return c.ExtendedConn } +func (c *conn) WriterReplaceable() bool { + return true +} + +func (c *conn) ReaderReplaceable() bool { + return true +} + func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { if _, ok := c.(syscall.Conn); !ok { // exclusion system conn like *net.TCPConn c = N.NewDeadlineConn(c) // most conn from outbound can't handle readDeadline correctly diff --git a/common/buf/sing.go b/common/buf/sing.go index c176ecb1..93140887 100644 --- a/common/buf/sing.go +++ b/common/buf/sing.go @@ -9,12 +9,12 @@ const BufferSize = buf.BufferSize type Buffer = buf.Buffer -var ( - New = buf.New - StackNew = buf.StackNew - StackNewSize = buf.StackNewSize - With = buf.With -) +var New = buf.New +var NewSize = buf.NewSize +var StackNew = buf.StackNew +var StackNewSize = buf.StackNewSize +var With = buf.With +var As = buf.As var KeepAlive = common.KeepAlive diff --git a/common/callback/callback.go b/common/callback/callback.go index 0bf720f4..fe76dc67 100644 --- a/common/callback/callback.go +++ b/common/callback/callback.go @@ -36,6 +36,14 @@ func (c *firstWriteCallBackConn) Upstream() any { return c.Conn } +func (c *firstWriteCallBackConn) WriterReplaceable() bool { + return c.written +} + +func (c *firstWriteCallBackConn) ReaderReplaceable() bool { + return true +} + var _ N.ExtendedConn = (*firstWriteCallBackConn)(nil) func NewFirstWriteCallBackConn(c C.Conn, callback func(error)) C.Conn { diff --git a/common/net/bufconn.go b/common/net/bufconn.go index f01a3dda..2ff73c82 100644 --- a/common/net/bufconn.go +++ b/common/net/bufconn.go @@ -69,6 +69,16 @@ func (c *BufferedConn) ReadBuffer(buffer *buf.Buffer) (err error) { return c.ExtendedConn.ReadBuffer(buffer) } +func (c *BufferedConn) ReadCached() *buf.Buffer { // call in sing/common/bufio.Copy + if c.r.Buffered() > 0 { + length := c.r.Buffered() + b, _ := c.r.Peek(length) + _, _ = c.r.Discard(length) + return buf.As(b) + } + return nil +} + func (c *BufferedConn) Upstream() any { return c.ExtendedConn } diff --git a/common/net/refconn.go b/common/net/refconn.go index 59225db0..537cb839 100644 --- a/common/net/refconn.go +++ b/common/net/refconn.go @@ -67,6 +67,14 @@ func (c *refConn) WriteBuffer(buffer *buf.Buffer) error { return c.conn.WriteBuffer(buffer) } +func (c *refConn) ReaderReplaceable() bool { // Relay() will handle reference + return true +} + +func (c *refConn) WriterReplaceable() bool { // Relay() will handle reference + return true +} + var _ ExtendedConn = (*refConn)(nil) func NewRefConn(conn net.Conn, ref any) net.Conn { diff --git a/common/net/sing.go b/common/net/sing.go index 89517326..7eb92f03 100644 --- a/common/net/sing.go +++ b/common/net/sing.go @@ -3,6 +3,7 @@ package net import ( "context" "net" + "runtime" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/bufio" @@ -33,7 +34,11 @@ func NeedHandshake(conn any) bool { return false } +type CountFunc = network.CountFunc + // Relay copies between left and right bidirectionally. func Relay(leftConn, rightConn net.Conn) { + defer runtime.KeepAlive(leftConn) + defer runtime.KeepAlive(rightConn) _ = bufio.CopyConn(context.TODO(), leftConn, rightConn) } diff --git a/component/dialer/tfo.go b/component/dialer/tfo.go index d5337bdb..09d5cced 100644 --- a/component/dialer/tfo.go +++ b/component/dialer/tfo.go @@ -113,6 +113,14 @@ func (c *tfoConn) NeedHandshake() bool { return c.Conn == nil } +func (c *tfoConn) ReaderReplaceable() bool { + return c.Conn != nil +} + +func (c *tfoConn) WriterReplaceable() bool { + return c.Conn != nil +} + func dialTFO(ctx context.Context, netDialer net.Dialer, network, address string) (net.Conn, error) { ctx, cancel := context.WithCancel(ctx) dialer := tfo.Dialer{Dialer: netDialer, DisableTFO: false} diff --git a/go.mod b/go.mod index 4de1206f..3153ab1d 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230423085534-0902e6216207 + github.com/sagernet/sing v0.2.5-0.20230425145913-0c037cb0e2c8 github.com/sagernet/sing-mux v0.0.0-20230424015424-9b0d527c3bb0 github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 diff --git a/go.sum b/go.sum index e8573a63..a747291f 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230423085534-0902e6216207 h1:+dDVjW20IT+e8maKryaDeRY2+RFmTFdrQeIzqE2WOss= -github.com/sagernet/sing v0.2.5-0.20230423085534-0902e6216207/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing v0.2.5-0.20230425145913-0c037cb0e2c8 h1:bf0WjE6g+bRhNCSe5u0xTeZLK/NboSy1/tI4eqPjvU0= +github.com/sagernet/sing v0.2.5-0.20230425145913-0c037cb0e2c8/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230424015424-9b0d527c3bb0 h1:87jyxzTjq01VgEiUVSMNRKjCfsSfp/QwyUVT37eXY50= github.com/sagernet/sing-mux v0.0.0-20230424015424-9b0d527c3bb0/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= diff --git a/tunnel/statistic/tracker.go b/tunnel/statistic/tracker.go index b9682c22..c4feeddb 100644 --- a/tunnel/statistic/tracker.go +++ b/tunnel/statistic/tracker.go @@ -1,11 +1,13 @@ package statistic import ( + "io" "net" "time" "github.com/Dreamacro/clash/common/atomic" "github.com/Dreamacro/clash/common/buf" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/utils" C "github.com/Dreamacro/clash/constant" @@ -61,6 +63,15 @@ func (tt *tcpTracker) ReadBuffer(buffer *buf.Buffer) (err error) { return } +func (tt *tcpTracker) UnwrapReader() (io.Reader, []N.CountFunc) { + return tt.Conn, []N.CountFunc{func(download int64) { + if tt.pushToManager { + tt.manager.PushDownloaded(download) + } + tt.DownloadTotal.Add(download) + }} +} + func (tt *tcpTracker) Write(b []byte) (int, error) { n, err := tt.Conn.Write(b) upload := int64(n) @@ -81,6 +92,15 @@ func (tt *tcpTracker) WriteBuffer(buffer *buf.Buffer) (err error) { return } +func (tt *tcpTracker) UnwrapWriter() (io.Writer, []N.CountFunc) { + return tt.Conn, []N.CountFunc{func(upload int64) { + if tt.pushToManager { + tt.manager.PushUploaded(upload) + } + tt.UploadTotal.Add(upload) + }} +} + func (tt *tcpTracker) Close() error { tt.manager.Leave(tt) return tt.Conn.Close()