From 832dae34219ec7f9775648754e94d4cd35eb98fa Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 9 Nov 2023 22:19:29 +0800 Subject: [PATCH] chore: direct append data to bufio.Reader's internal buffer as much as possible --- common/net/bufconn.go | 2 +- common/net/bufconn_unsafe.go | 34 ++++++++++++++++++++++++++++++++++ transport/vmess/websocket.go | 9 ++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 common/net/bufconn_unsafe.go diff --git a/common/net/bufconn.go b/common/net/bufconn.go index 37c8ba25f..b7e98e049 100644 --- a/common/net/bufconn.go +++ b/common/net/bufconn.go @@ -84,9 +84,9 @@ func (c *BufferedConn) ReadCached() *buf.Buffer { // call in sing/common/bufio.C length := c.r.Buffered() b, _ := c.r.Peek(length) _, _ = c.r.Discard(length) - c.r = nil // drop bufio.Reader to let gc can clean up its internal buf return buf.As(b) } + c.r = nil // drop bufio.Reader to let gc can clean up its internal buf return nil } diff --git a/common/net/bufconn_unsafe.go b/common/net/bufconn_unsafe.go new file mode 100644 index 000000000..349321dfd --- /dev/null +++ b/common/net/bufconn_unsafe.go @@ -0,0 +1,34 @@ +package net + +import ( + "io" + "unsafe" +) + +// bufioReader copy from stdlib bufio/bufio.go +// This structure has remained unchanged from go1.5 to go1.21. +type bufioReader struct { + buf []byte + rd io.Reader // reader provided by the client + r, w int // buf read and write positions + err error + lastByte int // last byte read for UnreadByte; -1 means invalid + lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid +} + +func (c *BufferedConn) AppendData(buf []byte) (ok bool) { + b := (*bufioReader)(unsafe.Pointer(c.r)) + pos := len(b.buf) - b.w - len(buf) + if pos >= -b.r { // len(b.buf)-(b.w - b.r) >= len(buf) + if pos < 0 { // len(b.buf)-b.w < len(buf) + // Slide existing data to beginning. + copy(b.buf, b.buf[b.r:b.w]) + b.w -= b.r + b.r = 0 + } + + b.w += copy(b.buf[b.w:], buf) + return true + } + return false +} diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index b30bb8aad..8e675bb02 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -554,7 +554,14 @@ func StreamUpgradedWebsocketConn(w http.ResponseWriter, r *http.Request) (net.Co } if edBuf := decodeXray0rtt(r.Header); len(edBuf) > 0 { - conn = N.NewCachedConn(conn, edBuf) + appendOk := false + if bufConn, ok := conn.(*N.BufferedConn); ok { + appendOk = bufConn.AppendData(edBuf) + } + if !appendOk { + conn = N.NewCachedConn(conn, edBuf) + } + } return conn, nil