From 6be79e969eb01e7a53b7c10fc9e1dc73ca2e3b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 31 Dec 2023 15:51:48 +0800 Subject: [PATCH 01/10] Fix h2mux request context --- h2mux.go | 15 +++++++++++++-- h2mux_conn.go | 8 +++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/h2mux.go b/h2mux.go index cb827a9..f328648 100644 --- a/h2mux.go +++ b/h2mux.go @@ -204,10 +204,21 @@ func (s *h2MuxClientSession) OpenContext(ctx context.Context) (net.Conn, error) Body: pipeInReader, URL: &url.URL{Scheme: "https", Host: "localhost"}, } - request = request.WithContext(ctx) - conn := newLateHTTPConn(pipeInWriter) + connCtx, cancel := context.WithCancel(context.Background()) + request = request.WithContext(connCtx) + conn := newLateHTTPConn(pipeInWriter, cancel) + requestDone := make(chan struct{}) + go func() { + select { + case <-requestDone: + return + case <-ctx.Done(): + cancel() + } + }() go func() { response, err := s.transport.RoundTrip(request) + close(requestDone) if err != nil { conn.setup(nil, err) } else if response.StatusCode != 200 { diff --git a/h2mux_conn.go b/h2mux_conn.go index 31c3286..f4f0ef0 100644 --- a/h2mux_conn.go +++ b/h2mux_conn.go @@ -1,6 +1,7 @@ package mux import ( + "context" "io" "net" "os" @@ -16,6 +17,7 @@ type httpConn struct { writer io.Writer create chan struct{} err error + cancel context.CancelFunc } func newHTTPConn(reader io.Reader, writer io.Writer) *httpConn { @@ -25,10 +27,11 @@ func newHTTPConn(reader io.Reader, writer io.Writer) *httpConn { } } -func newLateHTTPConn(writer io.Writer) *httpConn { +func newLateHTTPConn(writer io.Writer, cancel context.CancelFunc) *httpConn { return &httpConn{ create: make(chan struct{}), writer: writer, + cancel: cancel, } } @@ -55,6 +58,9 @@ func (c *httpConn) Write(b []byte) (n int, err error) { } func (c *httpConn) Close() error { + if c.cancel != nil { + c.cancel() + } return common.Close(c.reader, c.writer) } From aa458ed0111592eca294fb633ea4922e252fe9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Wed, 6 Dec 2023 20:42:46 +0800 Subject: [PATCH 02/10] Implement read waiter for UDP --- client.go | 6 ++-- client_conn.go | 84 ++++++++++++++++++++++++--------------------- client_conn_wait.go | 73 +++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +++ 5 files changed, 127 insertions(+), 42 deletions(-) create mode 100644 client_conn_wait.go diff --git a/client.go b/client.go index 86b307b..519f7cd 100644 --- a/client.go +++ b/client.go @@ -86,7 +86,8 @@ func (c *Client) DialContext(ctx context.Context, network string, destination M. if err != nil { return nil, err } - return bufio.NewUnbindPacketConn(&clientPacketConn{ExtendedConn: bufio.NewExtendedConn(stream), destination: destination}), nil + extendedConn := bufio.NewExtendedConn(stream) + return &clientPacketConn{AbstractConn: extendedConn, conn: extendedConn, destination: destination}, nil default: return nil, E.Extend(N.ErrUnknownNetwork, network) } @@ -97,7 +98,8 @@ func (c *Client) ListenPacket(ctx context.Context, destination M.Socksaddr) (net if err != nil { return nil, err } - return &clientPacketAddrConn{ExtendedConn: bufio.NewExtendedConn(stream), destination: destination}, nil + extendedConn := bufio.NewExtendedConn(stream) + return &clientPacketAddrConn{AbstractConn: extendedConn, conn: extendedConn, destination: destination}, nil } func (c *Client) openStream(ctx context.Context) (net.Conn, error) { diff --git a/client_conn.go b/client_conn.go index 694cb62..c0291f6 100644 --- a/client_conn.go +++ b/client_conn.go @@ -93,12 +93,16 @@ func (c *clientConn) Upstream() any { return c.Conn } +var _ N.NetPacketConn = (*clientPacketConn)(nil) + type clientPacketConn struct { - N.ExtendedConn - access sync.Mutex - destination M.Socksaddr - requestWritten bool - responseRead bool + N.AbstractConn + conn N.ExtendedConn + access sync.Mutex + destination M.Socksaddr + requestWritten bool + responseRead bool + readWaitOptions N.ReadWaitOptions } func (c *clientPacketConn) NeedHandshake() bool { @@ -106,7 +110,7 @@ func (c *clientPacketConn) NeedHandshake() bool { } func (c *clientPacketConn) readResponse() error { - response, err := ReadStreamResponse(c.ExtendedConn) + response, err := ReadStreamResponse(c.conn) if err != nil { return err } @@ -125,14 +129,14 @@ func (c *clientPacketConn) Read(b []byte) (n int, err error) { c.responseRead = true } var length uint16 - err = binary.Read(c.ExtendedConn, binary.BigEndian, &length) + err = binary.Read(c.conn, binary.BigEndian, &length) if err != nil { return } if cap(b) < int(length) { return 0, io.ErrShortBuffer } - return io.ReadFull(c.ExtendedConn, b[:length]) + return io.ReadFull(c.conn, b[:length]) } func (c *clientPacketConn) writeRequest(payload []byte) (n int, err error) { @@ -156,7 +160,7 @@ func (c *clientPacketConn) writeRequest(payload []byte) (n int, err error) { common.Error(buffer.Write(payload)), ) } - _, err = c.ExtendedConn.Write(buffer.Bytes()) + _, err = c.conn.Write(buffer.Bytes()) if err != nil { return } @@ -174,11 +178,11 @@ func (c *clientPacketConn) Write(b []byte) (n int, err error) { return c.writeRequest(b) } } - err = binary.Write(c.ExtendedConn, binary.BigEndian, uint16(len(b))) + err = binary.Write(c.conn, binary.BigEndian, uint16(len(b))) if err != nil { return } - return c.ExtendedConn.Write(b) + return c.conn.Write(b) } func (c *clientPacketConn) ReadBuffer(buffer *buf.Buffer) (err error) { @@ -190,11 +194,11 @@ func (c *clientPacketConn) ReadBuffer(buffer *buf.Buffer) (err error) { c.responseRead = true } var length uint16 - err = binary.Read(c.ExtendedConn, binary.BigEndian, &length) + err = binary.Read(c.conn, binary.BigEndian, &length) if err != nil { return } - _, err = buffer.ReadFullFrom(c.ExtendedConn, int(length)) + _, err = buffer.ReadFullFrom(c.conn, int(length)) return } @@ -211,7 +215,7 @@ func (c *clientPacketConn) WriteBuffer(buffer *buf.Buffer) error { } bLen := buffer.Len() binary.BigEndian.PutUint16(buffer.ExtendHeader(2), uint16(bLen)) - return c.ExtendedConn.WriteBuffer(buffer) + return c.conn.WriteBuffer(buffer) } func (c *clientPacketConn) FrontHeadroom() int { @@ -227,14 +231,14 @@ func (c *clientPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) c.responseRead = true } var length uint16 - err = binary.Read(c.ExtendedConn, binary.BigEndian, &length) + err = binary.Read(c.conn, binary.BigEndian, &length) if err != nil { return } if cap(p) < int(length) { return 0, nil, io.ErrShortBuffer } - n, err = io.ReadFull(c.ExtendedConn, p[:length]) + n, err = io.ReadFull(c.conn, p[:length]) return } @@ -248,11 +252,11 @@ func (c *clientPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { return c.writeRequest(p) } } - err = binary.Write(c.ExtendedConn, binary.BigEndian, uint16(len(p))) + err = binary.Write(c.conn, binary.BigEndian, uint16(len(p))) if err != nil { return } - return c.ExtendedConn.Write(p) + return c.conn.Write(p) } func (c *clientPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { @@ -265,7 +269,7 @@ func (c *clientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksad } func (c *clientPacketConn) LocalAddr() net.Addr { - return c.ExtendedConn.LocalAddr() + return c.conn.LocalAddr() } func (c *clientPacketConn) RemoteAddr() net.Addr { @@ -277,17 +281,19 @@ func (c *clientPacketConn) NeedAdditionalReadDeadline() bool { } func (c *clientPacketConn) Upstream() any { - return c.ExtendedConn + return c.conn } var _ N.NetPacketConn = (*clientPacketAddrConn)(nil) type clientPacketAddrConn struct { - N.ExtendedConn - access sync.Mutex - destination M.Socksaddr - requestWritten bool - responseRead bool + N.AbstractConn + conn N.ExtendedConn + access sync.Mutex + destination M.Socksaddr + requestWritten bool + responseRead bool + readWaitOptions N.ReadWaitOptions } func (c *clientPacketAddrConn) NeedHandshake() bool { @@ -295,7 +301,7 @@ func (c *clientPacketAddrConn) NeedHandshake() bool { } func (c *clientPacketAddrConn) readResponse() error { - response, err := ReadStreamResponse(c.ExtendedConn) + response, err := ReadStreamResponse(c.conn) if err != nil { return err } @@ -313,7 +319,7 @@ func (c *clientPacketAddrConn) ReadFrom(p []byte) (n int, addr net.Addr, err err } c.responseRead = true } - destination, err := M.SocksaddrSerializer.ReadAddrPort(c.ExtendedConn) + destination, err := M.SocksaddrSerializer.ReadAddrPort(c.conn) if err != nil { return } @@ -323,14 +329,14 @@ func (c *clientPacketAddrConn) ReadFrom(p []byte) (n int, addr net.Addr, err err addr = destination.UDPAddr() } var length uint16 - err = binary.Read(c.ExtendedConn, binary.BigEndian, &length) + err = binary.Read(c.conn, binary.BigEndian, &length) if err != nil { return } if cap(p) < int(length) { return 0, nil, io.ErrShortBuffer } - n, err = io.ReadFull(c.ExtendedConn, p[:length]) + n, err = io.ReadFull(c.conn, p[:length]) return } @@ -360,7 +366,7 @@ func (c *clientPacketAddrConn) writeRequest(payload []byte, destination M.Socksa common.Error(buffer.Write(payload)), ) } - _, err = c.ExtendedConn.Write(buffer.Bytes()) + _, err = c.conn.Write(buffer.Bytes()) if err != nil { return } @@ -378,15 +384,15 @@ func (c *clientPacketAddrConn) WriteTo(p []byte, addr net.Addr) (n int, err erro return c.writeRequest(p, M.SocksaddrFromNet(addr)) } } - err = M.SocksaddrSerializer.WriteAddrPort(c.ExtendedConn, M.SocksaddrFromNet(addr)) + err = M.SocksaddrSerializer.WriteAddrPort(c.conn, M.SocksaddrFromNet(addr)) if err != nil { return } - err = binary.Write(c.ExtendedConn, binary.BigEndian, uint16(len(p))) + err = binary.Write(c.conn, binary.BigEndian, uint16(len(p))) if err != nil { return } - return c.ExtendedConn.Write(p) + return c.conn.Write(p) } func (c *clientPacketAddrConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { @@ -397,16 +403,16 @@ func (c *clientPacketAddrConn) ReadPacket(buffer *buf.Buffer) (destination M.Soc } c.responseRead = true } - destination, err = M.SocksaddrSerializer.ReadAddrPort(c.ExtendedConn) + destination, err = M.SocksaddrSerializer.ReadAddrPort(c.conn) if err != nil { return } var length uint16 - err = binary.Read(c.ExtendedConn, binary.BigEndian, &length) + err = binary.Read(c.conn, binary.BigEndian, &length) if err != nil { return } - _, err = buffer.ReadFullFrom(c.ExtendedConn, int(length)) + _, err = buffer.ReadFullFrom(c.conn, int(length)) return } @@ -428,11 +434,11 @@ func (c *clientPacketAddrConn) WritePacket(buffer *buf.Buffer, destination M.Soc return err } common.Must(binary.Write(header, binary.BigEndian, uint16(bLen))) - return c.ExtendedConn.WriteBuffer(buffer) + return c.conn.WriteBuffer(buffer) } func (c *clientPacketAddrConn) LocalAddr() net.Addr { - return c.ExtendedConn.LocalAddr() + return c.conn.LocalAddr() } func (c *clientPacketAddrConn) FrontHeadroom() int { @@ -444,5 +450,5 @@ func (c *clientPacketAddrConn) NeedAdditionalReadDeadline() bool { } func (c *clientPacketAddrConn) Upstream() any { - return c.ExtendedConn + return c.conn } diff --git a/client_conn_wait.go b/client_conn_wait.go new file mode 100644 index 0000000..fd8580d --- /dev/null +++ b/client_conn_wait.go @@ -0,0 +1,73 @@ +package mux + +import ( + "encoding/binary" + + "github.com/sagernet/sing/common/buf" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" +) + +var _ N.PacketReadWaiter = (*clientPacketConn)(nil) + +func (c *clientPacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) { + c.readWaitOptions = options + return false +} + +func (c *clientPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) { + if !c.responseRead { + err = c.readResponse() + if err != nil { + return + } + c.responseRead = true + } + var length uint16 + err = binary.Read(c.conn, binary.BigEndian, &length) + if err != nil { + return + } + buffer = c.readWaitOptions.NewPacketBuffer() + _, err = buffer.ReadFullFrom(c.conn, int(length)) + if err != nil { + buffer.Release() + return nil, M.Socksaddr{}, err + } + c.readWaitOptions.PostReturn(buffer) + return +} + +var _ N.PacketReadWaiter = (*clientPacketAddrConn)(nil) + +func (c *clientPacketAddrConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) { + c.readWaitOptions = options + return false +} + +func (c *clientPacketAddrConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) { + if !c.responseRead { + err = c.readResponse() + if err != nil { + return + } + c.responseRead = true + } + destination, err = M.SocksaddrSerializer.ReadAddrPort(c.conn) + if err != nil { + return + } + var length uint16 + err = binary.Read(c.conn, binary.BigEndian, &length) + if err != nil { + return + } + buffer = c.readWaitOptions.NewPacketBuffer() + _, err = buffer.ReadFullFrom(c.conn, int(length)) + if err != nil { + buffer.Release() + return nil, M.Socksaddr{}, err + } + c.readWaitOptions.PostReturn(buffer) + return +} diff --git a/go.mod b/go.mod index d54b547..58c1b27 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/hashicorp/yamux v0.1.1 - github.com/sagernet/sing v0.2.20 + github.com/sagernet/sing v0.3.0-rc.2 github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 golang.org/x/net v0.19.0 golang.org/x/sys v0.15.0 diff --git a/go.sum b/go.sum index 4038bb7..042cdca 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,10 @@ github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbg github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= github.com/sagernet/sing v0.2.20 h1:ckcCB/5xu8G8wElNeH74IF6Soac5xWN+eQUXRuonjPQ= github.com/sagernet/sing v0.2.20/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80= +github.com/sagernet/sing v0.3.0-rc.1 h1:XcdCC9CcLNfMSlObIQPjxyzenGQT2R1sGLHvdwDmQFU= +github.com/sagernet/sing v0.3.0-rc.1/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80= +github.com/sagernet/sing v0.3.0-rc.2 h1:l5rq+bTrNhpAPd2Vjzi/sEhil4O6Bb1CKv6LdPLJKug= +github.com/sagernet/sing v0.3.0-rc.2/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= From c8a558c3f8afc150ad9d117bf9ea851dfebb8dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 9 Dec 2023 02:09:47 +0800 Subject: [PATCH 03/10] Update smux to latest --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 58c1b27..29ffca1 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/hashicorp/yamux v0.1.1 github.com/sagernet/sing v0.3.0-rc.2 - github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 + github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 golang.org/x/net v0.19.0 golang.org/x/sys v0.15.0 ) From 802d9510a7a43838031d34f2da1c6f7fdc344636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 7 Jan 2024 16:39:20 +0800 Subject: [PATCH 04/10] Update dependencies --- go.mod | 4 ++-- go.sum | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 29ffca1..4ff6c9f 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.18 require ( github.com/hashicorp/yamux v0.1.1 - github.com/sagernet/sing v0.3.0-rc.2 + github.com/sagernet/sing v0.3.0 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 golang.org/x/net v0.19.0 - golang.org/x/sys v0.15.0 + golang.org/x/sys v0.16.0 ) require golang.org/x/text v0.14.0 // indirect diff --git a/go.sum b/go.sum index 042cdca..8ee6605 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,18 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.20 h1:ckcCB/5xu8G8wElNeH74IF6Soac5xWN+eQUXRuonjPQ= -github.com/sagernet/sing v0.2.20/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80= -github.com/sagernet/sing v0.3.0-rc.1 h1:XcdCC9CcLNfMSlObIQPjxyzenGQT2R1sGLHvdwDmQFU= -github.com/sagernet/sing v0.3.0-rc.1/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80= -github.com/sagernet/sing v0.3.0-rc.2 h1:l5rq+bTrNhpAPd2Vjzi/sEhil4O6Bb1CKv6LdPLJKug= -github.com/sagernet/sing v0.3.0-rc.2/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= -github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= -github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= +github.com/sagernet/sing v0.3.0 h1:PIDVFZHnQAAYRL1UYqNM+0k5s8f/tb1lUW6UDcQiOc8= +github.com/sagernet/sing v0.3.0/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= +github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= +github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 9bfb33698bb6336f7ae5a5a3c8d334d77441c42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Wed, 24 Jan 2024 11:42:45 +0800 Subject: [PATCH 05/10] Fix h2mux open --- client.go | 4 ++-- h2mux.go | 6 +++--- session.go | 9 ++------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/client.go b/client.go index 519f7cd..a7896e0 100644 --- a/client.go +++ b/client.go @@ -113,7 +113,7 @@ func (c *Client) openStream(ctx context.Context) (net.Conn, error) { if err != nil { continue } - stream, err = session.OpenContext(ctx) + stream, err = session.Open() if err != nil { continue } @@ -206,7 +206,7 @@ func (c *Client) offerNew(ctx context.Context) (abstractSession, error) { } func (c *Client) brutalExchange(ctx context.Context, sessionConn net.Conn, session abstractSession) error { - stream, err := session.OpenContext(ctx) + stream, err := session.Open() if err != nil { return err } diff --git a/h2mux.go b/h2mux.go index f328648..54c3c70 100644 --- a/h2mux.go +++ b/h2mux.go @@ -64,7 +64,7 @@ func (s *h2MuxServerSession) ServeHTTP(writer http.ResponseWriter, request *http } } -func (s *h2MuxServerSession) OpenContext(ctx context.Context) (net.Conn, error) { +func (s *h2MuxServerSession) Open() (net.Conn, error) { return nil, os.ErrInvalid } @@ -197,7 +197,7 @@ func (s *h2MuxClientSession) MarkDead(conn *http2.ClientConn) { s.Close() } -func (s *h2MuxClientSession) OpenContext(ctx context.Context) (net.Conn, error) { +func (s *h2MuxClientSession) Open() (net.Conn, error) { pipeInReader, pipeInWriter := io.Pipe() request := &http.Request{ Method: http.MethodConnect, @@ -212,7 +212,7 @@ func (s *h2MuxClientSession) OpenContext(ctx context.Context) (net.Conn, error) select { case <-requestDone: return - case <-ctx.Done(): + case <-time.After(TCPTimeout): cancel() } }() diff --git a/session.go b/session.go index 524f573..2dc37b3 100644 --- a/session.go +++ b/session.go @@ -1,7 +1,6 @@ package mux import ( - "context" "io" "net" "reflect" @@ -13,7 +12,7 @@ import ( ) type abstractSession interface { - OpenContext(ctx context.Context) (net.Conn, error) + Open() (net.Conn, error) Accept() (net.Conn, error) NumStreams() int Close() error @@ -81,7 +80,7 @@ type smuxSession struct { *smux.Session } -func (s *smuxSession) OpenContext(context.Context) (net.Conn, error) { +func (s *smuxSession) Open() (net.Conn, error) { return s.OpenStream() } @@ -97,10 +96,6 @@ type yamuxSession struct { *yamux.Session } -func (y *yamuxSession) OpenContext(context.Context) (net.Conn, error) { - return y.OpenStream() -} - func (y *yamuxSession) CanTakeNewRequest() bool { return true } From 6d70ef996f147e7257283d3dac7c5a8d808efc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 20 Oct 2024 14:23:08 +0800 Subject: [PATCH 06/10] Update workflows --- .github/renovate.json | 19 ++++++ .github/workflows/debug.yml | 43 -------------- .github/workflows/lint.yml | 21 ++++--- .github/workflows/test.yml | 112 ++++++++++++++++++++++++++++++++++++ .gitignore | 1 + .golangci.yml | 7 ++- Makefile | 12 ++-- 7 files changed, 153 insertions(+), 62 deletions(-) create mode 100644 .github/renovate.json delete mode 100644 .github/workflows/debug.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..6612115 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "commitMessagePrefix": "[dependencies]", + "extends": [ + "config:base", + ":disableRateLimiting" + ], + "golang": { + "enabled": false + }, + "packageRules": [ + { + "matchManagers": [ + "github-actions" + ], + "groupName": "github-actions" + } + ] +} \ No newline at end of file diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml deleted file mode 100644 index fcbf9cb..0000000 --- a/.github/workflows/debug.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Debug build - -on: - push: - branches: - - main - paths-ignore: - - '**.md' - - '.github/**' - - '!.github/workflows/debug.yml' - pull_request: - branches: - - main - -jobs: - build: - name: Debug build - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Get latest go version - id: version - run: | - echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') - - name: Setup Go - uses: actions/setup-go@v4 - with: - go-version: ${{ steps.version.outputs.go_version }} - - name: Add cache to Go proxy - run: | - version=`git rev-parse HEAD` - mkdir build - pushd build - go mod init build - go get -v github.com/sagernet/sing-mux@$version - popd - continue-on-error: true - - name: Build - run: | - make test diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0a1c8f2..c682b25 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,8 +1,9 @@ -name: Lint +name: lint on: push: branches: + - main - dev paths-ignore: - '**.md' @@ -10,6 +11,7 @@ on: - '!.github/workflows/lint.yml' pull_request: branches: + - main - dev jobs: @@ -18,24 +20,21 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Get latest go version - id: version - run: | - echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: - go-version: ${{ steps.version.outputs.go_version }} + go-version: ^1.23 - name: Cache go module - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/go/pkg/mod key: go-${{ hashFiles('**/go.sum') }} - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: - version: latest \ No newline at end of file + version: latest + args: . \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3afe968 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,112 @@ +name: test + +on: + push: + branches: + - main + - dev + paths-ignore: + - '**.md' + - '.github/**' + - '!.github/workflows/debug.yml' + pull_request: + branches: + - main + - dev + +jobs: + build: + name: Linux + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ^1.23 + - name: Build + run: | + make test + build_go120: + name: Linux (Go 1.20) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ~1.20 + continue-on-error: true + - name: Build + run: | + make test + build_go121: + name: Linux (Go 1.21) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ~1.21 + continue-on-error: true + - name: Build + run: | + make test + build_go122: + name: Linux (Go 1.22) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ~1.22 + continue-on-error: true + - name: Build + run: | + make test + build_windows: + name: Windows + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ^1.23 + continue-on-error: true + - name: Build + run: | + make test + build_darwin: + name: macOS + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ^1.23 + continue-on-error: true + - name: Build + run: | + make test \ No newline at end of file diff --git a/.gitignore b/.gitignore index f7f8ac3..f1298ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /.idea/ /vendor/ +.DS_Store diff --git a/.golangci.yml b/.golangci.yml index 4133a1d..eecfec3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,6 +5,8 @@ linters: - govet - gci - staticcheck + - paralleltest + - ineffassign linters-settings: gci: @@ -13,5 +15,6 @@ linters-settings: - standard - prefix(github.com/sagernet/) - default - staticcheck: - go: '1.20' + +run: + go: "1.23" \ No newline at end of file diff --git a/Makefile b/Makefile index e47456e..6985f48 100644 --- a/Makefile +++ b/Makefile @@ -8,14 +8,14 @@ fmt_install: go install -v github.com/daixiang0/gci@latest lint: - GOOS=linux golangci-lint run ./... - GOOS=android golangci-lint run ./... - GOOS=windows golangci-lint run ./... - GOOS=darwin golangci-lint run ./... - GOOS=freebsd golangci-lint run ./... + GOOS=linux golangci-lint run + GOOS=android golangci-lint run + GOOS=windows golangci-lint run + GOOS=darwin golangci-lint run + GOOS=freebsd golangci-lint run lint_install: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest test: - go test -v ./... \ No newline at end of file + go test ./... From 3e7b3cfc5158b2691aa197b89992a33b33df0cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 9 Nov 2024 12:23:03 +0800 Subject: [PATCH 07/10] Update dependencies --- go.mod | 10 +++++----- go.sum | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 4ff6c9f..4387241 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module github.com/sagernet/sing-mux go 1.18 require ( - github.com/hashicorp/yamux v0.1.1 - github.com/sagernet/sing v0.3.0 + github.com/hashicorp/yamux v0.1.2 + github.com/sagernet/sing v0.5.0 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 - golang.org/x/net v0.19.0 - golang.org/x/sys v0.16.0 + golang.org/x/net v0.31.0 + golang.org/x/sys v0.27.0 ) -require golang.org/x/text v0.14.0 // indirect +require golang.org/x/text v0.20.0 // indirect diff --git a/go.sum b/go.sum index 8ee6605..5c662e5 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,18 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.3.0 h1:PIDVFZHnQAAYRL1UYqNM+0k5s8f/tb1lUW6UDcQiOc8= -github.com/sagernet/sing v0.3.0/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= +github.com/sagernet/sing v0.5.0 h1:soo2wVwLcieKWWKIksFNK6CCAojUgAppqQVwyRYGkEM= +github.com/sagernet/sing v0.5.0/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 5c2a0c4fa6086870f03077a0491d919c25dbec27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 9 Nov 2024 12:24:55 +0800 Subject: [PATCH 08/10] Fix accept stream --- server.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server.go b/server.go index b97a97d..6b37cfb 100644 --- a/server.go +++ b/server.go @@ -63,11 +63,10 @@ func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.M } var group task.Group group.Append0(func(_ context.Context) error { - var stream net.Conn for { - stream, err = session.Accept() - if err != nil { - return err + stream, aErr := session.Accept() + if aErr != nil { + return aErr } streamCtx := s.newStreamContext(ctx, stream) go func() { From 54badfa885716a05ade2da91708022015ddf61b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 20 Oct 2024 14:23:34 +0800 Subject: [PATCH 09/10] Update network handler usages --- brutal.go | 6 +++--- go.mod | 2 +- go.sum | 6 ++++-- protocol.go | 16 +++++++++------ server.go | 53 ++++++++++++++++++++++++++++++++++++++++---------- server_conn.go | 14 ++++++------- 6 files changed, 68 insertions(+), 29 deletions(-) diff --git a/brutal.go b/brutal.go index 93e76b3..df52d64 100644 --- a/brutal.go +++ b/brutal.go @@ -7,7 +7,7 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" - "github.com/sagernet/sing/common/rw" + "github.com/sagernet/sing/common/varbin" ) const ( @@ -32,7 +32,7 @@ func WriteBrutalResponse(writer io.Writer, receiveBPS uint64, ok bool, message s if ok { common.Must(binary.Write(buffer, binary.BigEndian, receiveBPS)) } else { - err := rw.WriteVString(buffer, message) + err := varbin.Write(buffer, binary.BigEndian, message) if err != nil { return err } @@ -52,7 +52,7 @@ func ReadBrutalResponse(reader io.Reader) (uint64, error) { return receiveBPS, err } else { var message string - message, err = rw.ReadVString(reader) + message, err = varbin.ReadValue[string](reader, binary.BigEndian) if err != nil { return 0, err } diff --git a/go.mod b/go.mod index 4387241..b9e33ff 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/hashicorp/yamux v0.1.2 - github.com/sagernet/sing v0.5.0 + github.com/sagernet/sing v0.6.0-alpha.3 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 golang.org/x/net v0.31.0 golang.org/x/sys v0.27.0 diff --git a/go.sum b/go.sum index 5c662e5..77006d6 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,10 @@ github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8 github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.5.0 h1:soo2wVwLcieKWWKIksFNK6CCAojUgAppqQVwyRYGkEM= -github.com/sagernet/sing v0.5.0/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing v0.5.1-0.20241109034027-099899991126 h1:pLMpV9pEAinrS9R1n1JLcbNesCl369RfvyxnYCPrkbw= +github.com/sagernet/sing v0.5.1-0.20241109034027-099899991126/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing v0.6.0-alpha.3 h1:GLp9d6Gbt+Ioeplauuzojz1nY2J6moceVGYIOv/h5gA= +github.com/sagernet/sing v0.6.0-alpha.3/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= diff --git a/protocol.go b/protocol.go index d93268b..176d51c 100644 --- a/protocol.go +++ b/protocol.go @@ -12,6 +12,7 @@ import ( M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/rw" + "github.com/sagernet/sing/common/varbin" ) const ( @@ -41,14 +42,18 @@ type Request struct { } func ReadRequest(reader io.Reader) (*Request, error) { - version, err := rw.ReadByte(reader) + var ( + version byte + protocol byte + ) + err := binary.Read(reader, binary.BigEndian, &version) if err != nil { return nil, err } if version < Version0 || version > Version1 { return nil, E.New("unsupported version: ", version) } - protocol, err := rw.ReadByte(reader) + err = binary.Read(reader, binary.BigEndian, &protocol) if err != nil { return nil, err } @@ -166,13 +171,12 @@ type StreamResponse struct { func ReadStreamResponse(reader io.Reader) (*StreamResponse, error) { var response StreamResponse - status, err := rw.ReadByte(reader) + err := binary.Read(reader, binary.BigEndian, &response.Status) if err != nil { return nil, err } - response.Status = status - if status == statusError { - response.Message, err = rw.ReadVString(reader) + if response.Status == statusError { + response.Message, err = varbin.ReadValue[string](reader, binary.BigEndian) if err != nil { return nil, err } diff --git a/server.go b/server.go index 6b37cfb..65c60a5 100644 --- a/server.go +++ b/server.go @@ -13,15 +13,24 @@ import ( "github.com/sagernet/sing/common/task" ) +// Deprecated: Use ServiceHandlerEx instead. +// +//nolint:staticcheck type ServiceHandler interface { N.TCPConnectionHandler N.UDPConnectionHandler } +type ServiceHandlerEx interface { + N.TCPConnectionHandlerEx + N.UDPConnectionHandlerEx +} + type Service struct { newStreamContext func(context.Context, net.Conn) context.Context logger logger.ContextLogger handler ServiceHandler + handlerEx ServiceHandlerEx padding bool brutal BrutalOptions } @@ -30,6 +39,7 @@ type ServiceOptions struct { NewStreamContext func(context.Context, net.Conn) context.Context Logger logger.ContextLogger Handler ServiceHandler + HandlerEx ServiceHandlerEx Padding bool Brutal BrutalOptions } @@ -42,12 +52,26 @@ func NewService(options ServiceOptions) (*Service, error) { newStreamContext: options.NewStreamContext, logger: options.Logger, handler: options.Handler, + handlerEx: options.HandlerEx, padding: options.Padding, brutal: options.Brutal, }, nil } +// Deprecated: Use NewConnectionEx instead. func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + return s.newConnection(ctx, conn, metadata.Source) +} + +func (s *Service) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + err := s.newConnection(ctx, conn, source) + N.CloseOnHandshakeFailure(conn, onClose, err) + if err != nil { + s.logger.ErrorContext(ctx, E.Cause(err, "process multiplex connection from ", source)) + } +} + +func (s *Service) newConnection(ctx context.Context, conn net.Conn, source M.Socksaddr) error { request, err := ReadRequest(conn) if err != nil { return err @@ -70,9 +94,10 @@ func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.M } streamCtx := s.newStreamContext(ctx, stream) go func() { - hErr := s.newConnection(streamCtx, conn, stream, metadata) + hErr := s.newSession(streamCtx, conn, stream, source) if hErr != nil { - s.logger.ErrorContext(streamCtx, E.Cause(hErr, "handle connection")) + stream.Close() + s.logger.ErrorContext(streamCtx, E.Cause(hErr, "process multiplex stream")) } }() } @@ -83,13 +108,13 @@ func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.M return group.Run(ctx) } -func (s *Service) newConnection(ctx context.Context, sessionConn net.Conn, stream net.Conn, metadata M.Metadata) error { +func (s *Service) newSession(ctx context.Context, sessionConn net.Conn, stream net.Conn, source M.Socksaddr) error { stream = &wrapStream{stream} request, err := ReadStreamRequest(stream) if err != nil { return E.Cause(err, "read multiplex stream request") } - metadata.Destination = request.Destination + destination := request.Destination if request.Network == N.NetworkTCP { conn := &serverConn{ExtendedConn: bufio.NewExtendedConn(stream)} if request.Destination.Fqdn == BrutalExchangeDomain { @@ -127,20 +152,28 @@ func (s *Service) newConnection(ctx context.Context, sessionConn net.Conn, strea } return nil } - s.logger.InfoContext(ctx, "inbound multiplex connection to ", metadata.Destination) - s.handler.NewConnection(ctx, conn, metadata) - stream.Close() + s.logger.InfoContext(ctx, "inbound multiplex connection to ", destination) + if s.handler != nil { + //nolint:staticcheck + s.handler.NewConnection(ctx, conn, M.Metadata{Source: source, Destination: destination}) + } else { + s.handlerEx.NewConnectionEx(ctx, conn, source, destination, nil) + } } else { var packetConn N.PacketConn if !request.PacketAddr { - s.logger.InfoContext(ctx, "inbound multiplex packet connection to ", metadata.Destination) + s.logger.InfoContext(ctx, "inbound multiplex packet connection to ", destination) packetConn = &serverPacketConn{ExtendedConn: bufio.NewExtendedConn(stream), destination: request.Destination} } else { s.logger.InfoContext(ctx, "inbound multiplex packet connection") packetConn = &serverPacketAddrConn{ExtendedConn: bufio.NewExtendedConn(stream)} } - s.handler.NewPacketConnection(ctx, packetConn, metadata) - stream.Close() + if s.handler != nil { + //nolint:staticcheck + s.handler.NewPacketConnection(ctx, packetConn, M.Metadata{Source: source, Destination: destination}) + } else { + s.handlerEx.NewPacketConnectionEx(ctx, packetConn, source, destination, nil) + } } return nil } diff --git a/server_conn.go b/server_conn.go index 41151c1..31ed4bf 100644 --- a/server_conn.go +++ b/server_conn.go @@ -10,7 +10,7 @@ import ( "github.com/sagernet/sing/common/buf" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/sing/common/rw" + "github.com/sagernet/sing/common/varbin" ) type serverConn struct { @@ -24,11 +24,11 @@ func (c *serverConn) NeedHandshake() bool { func (c *serverConn) HandshakeFailure(err error) error { errMessage := err.Error() - buffer := buf.NewSize(1 + rw.UVariantLen(uint64(len(errMessage))) + len(errMessage)) + buffer := buf.NewSize(1 + varbin.UvarintLen(uint64(len(errMessage))) + len(errMessage)) defer buffer.Release() common.Must( buffer.WriteByte(statusError), - rw.WriteVString(buffer, errMessage), + varbin.Write(buffer, binary.BigEndian, errMessage), ) return common.Error(c.ExtendedConn.Write(buffer.Bytes())) } @@ -88,11 +88,11 @@ func (c *serverPacketConn) NeedHandshake() bool { func (c *serverPacketConn) HandshakeFailure(err error) error { errMessage := err.Error() - buffer := buf.NewSize(1 + rw.UVariantLen(uint64(len(errMessage))) + len(errMessage)) + buffer := buf.NewSize(1 + varbin.UvarintLen(uint64(len(errMessage))) + len(errMessage)) defer buffer.Release() common.Must( buffer.WriteByte(statusError), - rw.WriteVString(buffer, errMessage), + varbin.Write(buffer, binary.BigEndian, errMessage), ) return common.Error(c.ExtendedConn.Write(buffer.Bytes())) } @@ -188,11 +188,11 @@ func (c *serverPacketAddrConn) NeedHandshake() bool { func (c *serverPacketAddrConn) HandshakeFailure(err error) error { errMessage := err.Error() - buffer := buf.NewSize(1 + rw.UVariantLen(uint64(len(errMessage))) + len(errMessage)) + buffer := buf.NewSize(1 + varbin.UvarintLen(uint64(len(errMessage))) + len(errMessage)) defer buffer.Release() common.Must( buffer.WriteByte(statusError), - rw.WriteVString(buffer, errMessage), + varbin.Write(buffer, binary.BigEndian, errMessage), ) return common.Error(c.ExtendedConn.Write(buffer.Bytes())) } From 93769bd46a7b5631f77a8e877ec81cb58b82a508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 6 Feb 2025 09:07:03 +0800 Subject: [PATCH 10/10] Update dependencies --- go.mod | 8 ++++---- go.sum | 18 ++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index b9e33ff..21496c3 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.18 require ( github.com/hashicorp/yamux v0.1.2 - github.com/sagernet/sing v0.6.0-alpha.3 + github.com/sagernet/sing v0.6.0 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 - golang.org/x/net v0.31.0 - golang.org/x/sys v0.27.0 + golang.org/x/net v0.34.0 + golang.org/x/sys v0.30.0 ) -require golang.org/x/text v0.20.0 // indirect +require golang.org/x/text v0.21.0 // indirect diff --git a/go.sum b/go.sum index 77006d6..7bdd16e 100644 --- a/go.sum +++ b/go.sum @@ -3,18 +3,16 @@ github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8 github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.5.1-0.20241109034027-099899991126 h1:pLMpV9pEAinrS9R1n1JLcbNesCl369RfvyxnYCPrkbw= -github.com/sagernet/sing v0.5.1-0.20241109034027-099899991126/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing v0.6.0-alpha.3 h1:GLp9d6Gbt+Ioeplauuzojz1nY2J6moceVGYIOv/h5gA= -github.com/sagernet/sing v0.6.0-alpha.3/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing v0.6.0 h1:jT55zAXrG7H3x+s/FlrC15xQy3LcmuZ2GGA9+8IJdt0= +github.com/sagernet/sing v0.6.0/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=