github.com/metacubex/mihomo@v1.18.5/common/net/bufconn.go (about) 1 package net 2 3 import ( 4 "bufio" 5 "net" 6 7 "github.com/metacubex/mihomo/common/buf" 8 ) 9 10 var _ ExtendedConn = (*BufferedConn)(nil) 11 12 type BufferedConn struct { 13 r *bufio.Reader 14 ExtendedConn 15 peeked bool 16 } 17 18 func NewBufferedConn(c net.Conn) *BufferedConn { 19 if bc, ok := c.(*BufferedConn); ok { 20 return bc 21 } 22 return &BufferedConn{bufio.NewReader(c), NewExtendedConn(c), false} 23 } 24 25 func WarpConnWithBioReader(c net.Conn, br *bufio.Reader) net.Conn { 26 if br != nil && br.Buffered() > 0 { 27 if bc, ok := c.(*BufferedConn); ok && bc.r == br { 28 return bc 29 } 30 return &BufferedConn{br, NewExtendedConn(c), true} 31 } 32 return c 33 } 34 35 // Reader returns the internal bufio.Reader. 36 func (c *BufferedConn) Reader() *bufio.Reader { 37 return c.r 38 } 39 40 func (c *BufferedConn) ResetPeeked() { 41 c.peeked = false 42 } 43 44 func (c *BufferedConn) Peeked() bool { 45 return c.peeked 46 } 47 48 // Peek returns the next n bytes without advancing the reader. 49 func (c *BufferedConn) Peek(n int) ([]byte, error) { 50 c.peeked = true 51 return c.r.Peek(n) 52 } 53 54 func (c *BufferedConn) Discard(n int) (discarded int, err error) { 55 return c.r.Discard(n) 56 } 57 58 func (c *BufferedConn) Read(p []byte) (int, error) { 59 return c.r.Read(p) 60 } 61 62 func (c *BufferedConn) ReadByte() (byte, error) { 63 return c.r.ReadByte() 64 } 65 66 func (c *BufferedConn) UnreadByte() error { 67 return c.r.UnreadByte() 68 } 69 70 func (c *BufferedConn) Buffered() int { 71 return c.r.Buffered() 72 } 73 74 func (c *BufferedConn) ReadBuffer(buffer *buf.Buffer) (err error) { 75 if c.r != nil && c.r.Buffered() > 0 { 76 _, err = buffer.ReadOnceFrom(c.r) 77 return 78 } 79 return c.ExtendedConn.ReadBuffer(buffer) 80 } 81 82 func (c *BufferedConn) ReadCached() *buf.Buffer { // call in sing/common/bufio.Copy 83 if c.r != nil && c.r.Buffered() > 0 { 84 length := c.r.Buffered() 85 b, _ := c.r.Peek(length) 86 _, _ = c.r.Discard(length) 87 return buf.As(b) 88 } 89 c.r = nil // drop bufio.Reader to let gc can clean up its internal buf 90 return nil 91 } 92 93 func (c *BufferedConn) Upstream() any { 94 return c.ExtendedConn 95 } 96 97 func (c *BufferedConn) ReaderReplaceable() bool { 98 if c.r != nil && c.r.Buffered() > 0 { 99 return false 100 } 101 return true 102 } 103 104 func (c *BufferedConn) WriterReplaceable() bool { 105 return true 106 }