diff --git a/Makefile b/Makefile index a851be04..91fab175 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,8 @@ snapshot_install: test: @go test -v . && \ pushd test && \ - go test -v . && \ + go mod tidy && \ + go test -v -tags '$(TAGS)' . && \ popd clean: diff --git a/inbound/hysteria.go b/inbound/hysteria.go index bbcbf953..585f034d 100644 --- a/inbound/hysteria.go +++ b/inbound/hysteria.go @@ -37,6 +37,7 @@ type Hysteria struct { xplusKey []byte sendBPS uint64 recvBPS uint64 + udpListener net.PacketConn listener quic.Listener udpAccess sync.RWMutex udpSessionId uint32 @@ -146,6 +147,7 @@ func (h *Hysteria) Start() error { packetConn = hysteria.NewXPlusPacketConn(packetConn, h.xplusKey) packetConn = &hysteria.PacketConnWrapper{PacketConn: packetConn} } + h.udpListener = packetConn err = h.tlsConfig.Start() if err != nil { return err @@ -314,6 +316,7 @@ func (h *Hysteria) Close() error { h.udpSessions = make(map[uint32]chan *hysteria.UDPMessage) h.udpAccess.Unlock() return common.Close( + h.udpListener, h.listener, common.PtrOrNil(h.tlsConfig), ) diff --git a/inbound/naive.go b/inbound/naive.go index 9fe17c9c..dc8e2cb8 100644 --- a/inbound/naive.go +++ b/inbound/naive.go @@ -10,7 +10,6 @@ import ( "net/http" "net/netip" "os" - "runtime" "strings" "time" @@ -250,8 +249,7 @@ type naivePaddingConn struct { func (c *naivePaddingConn) Read(p []byte) (n int, err error) { n, err = c.read(p) - err = wrapHttpError(err) - return + return n, wrapHttpError(err) } func (c *naivePaddingConn) read(p []byte) (n int, err error) { @@ -259,7 +257,7 @@ func (c *naivePaddingConn) read(p []byte) (n int, err error) { if len(p) > c.readRemaining { p = p[:c.readRemaining] } - n, err = c.read(p) + n, err = c.reader.Read(p) if err != nil { return } @@ -297,35 +295,69 @@ func (c *naivePaddingConn) read(p []byte) (n int, err error) { } func (c *naivePaddingConn) Write(p []byte) (n int, err error) { - n, err = c.write(p) + for pLen := len(p); pLen > 0; { + var data []byte + if pLen > 65535 { + data = p[:65535] + p = p[65535:] + pLen -= 65535 + } else { + data = p + pLen = 0 + } + var writeN int + writeN, err = c.write(data) + n += writeN + if err != nil { + break + } + } if err == nil { c.flusher.Flush() } - err = wrapHttpError(err) - return + return n, wrapHttpError(err) } func (c *naivePaddingConn) write(p []byte) (n int, err error) { if c.writePadding < kFirstPaddings { paddingSize := rand.Intn(256) - _buffer := buf.Make(3 + len(p) + paddingSize) - defer runtime.KeepAlive(_buffer) + + _buffer := buf.StackNewSize(3 + len(p) + paddingSize) + defer common.KeepAlive(_buffer) buffer := common.Dup(_buffer) - binary.BigEndian.PutUint16(buffer, uint16(len(p))) - buffer[2] = byte(paddingSize) - copy(buffer[3:], p) - _, err = c.writer.Write(buffer) - if err != nil { - return + defer buffer.Release() + header := buffer.Extend(3) + binary.BigEndian.PutUint16(header, uint16(len(p))) + header[2] = byte(paddingSize) + + common.Must1(buffer.Write(p)) + _, err = c.writer.Write(buffer.Bytes()) + if err == nil { + n = len(p) } c.writePadding++ + return } return c.writer.Write(p) } func (c *naivePaddingConn) FrontHeadroom() int { if c.writePadding < kFirstPaddings { - return 3 + 255 + return 3 + } + return 0 +} + +func (c *naivePaddingConn) RearHeadroom() int { + if c.writePadding < kFirstPaddings { + return 255 + } + return 0 +} + +func (c *naivePaddingConn) WriterMTU() int { + if c.writePadding < kFirstPaddings { + return 65535 } return 0 } @@ -334,6 +366,9 @@ func (c *naivePaddingConn) WriteBuffer(buffer *buf.Buffer) error { defer buffer.Release() if c.writePadding < kFirstPaddings { bufferLen := buffer.Len() + if bufferLen > 65535 { + return common.Error(c.Write(buffer.Bytes())) + } paddingSize := rand.Intn(256) header := buffer.ExtendHeader(3) binary.BigEndian.PutUint16(header, uint16(bufferLen)) @@ -350,16 +385,20 @@ func (c *naivePaddingConn) WriteBuffer(buffer *buf.Buffer) error { func (c *naivePaddingConn) WriteTo(w io.Writer) (n int64, err error) { if c.readPadding < kFirstPaddings { - return bufio.WriteToN(c, w, kFirstPaddings-c.readPadding) + n, err = bufio.WriteToN(c, w, kFirstPaddings-c.readPadding) + } else { + n, err = bufio.Copy(w, c.reader) } - return bufio.Copy(w, c.reader) + return n, wrapHttpError(err) } func (c *naivePaddingConn) ReadFrom(r io.Reader) (n int64, err error) { if c.writePadding < kFirstPaddings { - return bufio.ReadFromN(c, r, kFirstPaddings-c.writePadding) + n, err = bufio.ReadFromN(c, r, kFirstPaddings-c.writePadding) + } else { + n, err = bufio.Copy(c.writer, r) } - return bufio.Copy(c.writer, r) + return n, wrapHttpError(err) } func (c *naivePaddingConn) Close() error { @@ -389,14 +428,14 @@ func (c *naivePaddingConn) SetWriteDeadline(t time.Time) error { return os.ErrInvalid } -var http2errClientDisconnected = "client disconnected" - func wrapHttpError(err error) error { if err == nil { return err } - switch err.Error() { - case http2errClientDisconnected: + if strings.Contains(err.Error(), "client disconnected") { + return net.ErrClosed + } + if strings.Contains(err.Error(), "body closed by handler") { return net.ErrClosed } return err diff --git a/test/box_test.go b/test/box_test.go index 37f85956..d70caf70 100644 --- a/test/box_test.go +++ b/test/box_test.go @@ -56,7 +56,7 @@ func testTCP(t *testing.T, clientPort uint16, testPort uint16) { dialTCP := func() (net.Conn, error) { return dialer.DialContext(context.Background(), "tcp", M.ParseSocksaddrHostPort("127.0.0.1", testPort)) } - require.NoError(t, testLargeDataWithConn(t, testPort, dialTCP)) + require.NoError(t, testPingPongWithConn(t, testPort, dialTCP)) } func testSuitHy(t *testing.T, clientPort uint16, testPort uint16) { diff --git a/test/go.mod b/test/go.mod index 620f0cbc..7f235ba7 100644 --- a/test/go.mod +++ b/test/go.mod @@ -10,7 +10,7 @@ require ( github.com/docker/docker v20.10.17+incompatible github.com/docker/go-connections v0.4.0 github.com/gofrs/uuid v4.2.0+incompatible - github.com/sagernet/sing v0.0.0-20220821143531-cee85dcd3013 + github.com/sagernet/sing v0.0.0-20220822031040-57fe2e623c82 github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 github.com/spyzhov/ajson v0.7.1 github.com/stretchr/testify v1.8.0 @@ -57,7 +57,7 @@ require ( github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect github.com/sagernet/netlink v0.0.0-20220820041223-3cd8365d17ac // indirect github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb // indirect - github.com/sagernet/sing-dns v0.0.0-20220819010310-839eab1578c9 // indirect + github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 // indirect github.com/sagernet/sing-tun v0.0.0-20220821033717-8b6630a3b006 // indirect github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 // indirect github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 // indirect diff --git a/test/go.sum b/test/go.sum index f87fa284..fac11e44 100644 --- a/test/go.sum +++ b/test/go.sum @@ -123,10 +123,10 @@ github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTY github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4= github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= -github.com/sagernet/sing v0.0.0-20220821143531-cee85dcd3013 h1:i5jP3rs+3IFj0OWB22YB3wSJJAoZiBd3YeBk9/vbDHI= -github.com/sagernet/sing v0.0.0-20220821143531-cee85dcd3013/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ= -github.com/sagernet/sing-dns v0.0.0-20220819010310-839eab1578c9 h1:XgXSOJv8e7+98SJvg1f0luuPR33r4yFcmzxb3R//BTI= -github.com/sagernet/sing-dns v0.0.0-20220819010310-839eab1578c9/go.mod h1:MAHy2IKZAA101t3Gr2x0ldwn6XuAs2cjGzSzHy5RhWk= +github.com/sagernet/sing v0.0.0-20220822031040-57fe2e623c82 h1:DUHIA4lKxDqYNQyzb7NjZp+//voV25Ue7QoDjUvhgio= +github.com/sagernet/sing v0.0.0-20220822031040-57fe2e623c82/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ= +github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 h1:XUTocA/Ek0dFxUX+xJCWMPPFZCn2GC/uLrBjTSr1vHY= +github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM= github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4= github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM= github.com/sagernet/sing-tun v0.0.0-20220821033717-8b6630a3b006 h1:c1UyJ5H4CNLsg4GsAnNNoDAnHzLB13pm/T4zzvaWcFo= diff --git a/test/vmess_test.go b/test/vmess_test.go index 14dd871a..f35942b0 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" ) -func _TestVMessAuto(t *testing.T) { +func TestVMessAuto(t *testing.T) { security := "auto" user, err := uuid.DefaultGenerator.NewV4() require.NoError(t, err) @@ -28,7 +28,7 @@ func _TestVMessAuto(t *testing.T) { }) } -func TestVMess(t *testing.T) { +func _TestVMess(t *testing.T) { for _, security := range []string{ "zero", } {