github.com/sagernet/sing-box@v1.2.7/transport/v2raygrpclite/conn.go (about) 1 package v2raygrpclite 2 3 import ( 4 std_bufio "bufio" 5 "bytes" 6 "encoding/binary" 7 "io" 8 "net" 9 "net/http" 10 "os" 11 "sync" 12 "time" 13 14 "github.com/sagernet/sing-box/common/baderror" 15 "github.com/sagernet/sing/common" 16 "github.com/sagernet/sing/common/buf" 17 "github.com/sagernet/sing/common/bufio" 18 "github.com/sagernet/sing/common/rw" 19 ) 20 21 // kanged from: https://github.com/Qv2ray/gun-lite 22 23 var _ net.Conn = (*GunConn)(nil) 24 25 type GunConn struct { 26 reader *std_bufio.Reader 27 writer io.Writer 28 flusher http.Flusher 29 create chan struct{} 30 err error 31 readRemaining int 32 writeAccess sync.Mutex 33 } 34 35 func newGunConn(reader io.Reader, writer io.Writer, flusher http.Flusher) *GunConn { 36 return &GunConn{ 37 reader: std_bufio.NewReader(reader), 38 writer: writer, 39 flusher: flusher, 40 } 41 } 42 43 func newLateGunConn(writer io.Writer) *GunConn { 44 return &GunConn{ 45 create: make(chan struct{}), 46 writer: writer, 47 } 48 } 49 50 func (c *GunConn) setup(reader io.Reader, err error) { 51 c.reader = std_bufio.NewReader(reader) 52 c.err = err 53 close(c.create) 54 } 55 56 func (c *GunConn) Read(b []byte) (n int, err error) { 57 n, err = c.read(b) 58 return n, baderror.WrapH2(err) 59 } 60 61 func (c *GunConn) read(b []byte) (n int, err error) { 62 if c.reader == nil { 63 <-c.create 64 if c.err != nil { 65 return 0, c.err 66 } 67 } 68 69 if c.readRemaining > 0 { 70 if len(b) > c.readRemaining { 71 b = b[:c.readRemaining] 72 } 73 n, err = c.reader.Read(b) 74 c.readRemaining -= n 75 return 76 } 77 78 _, err = c.reader.Discard(6) 79 if err != nil { 80 return 81 } 82 83 dataLen, err := binary.ReadUvarint(c.reader) 84 if err != nil { 85 return 86 } 87 88 readLen := int(dataLen) 89 c.readRemaining = readLen 90 if len(b) > readLen { 91 b = b[:readLen] 92 } 93 94 n, err = c.reader.Read(b) 95 c.readRemaining -= n 96 return 97 } 98 99 func (c *GunConn) Write(b []byte) (n int, err error) { 100 protobufHeader := [1 + binary.MaxVarintLen64]byte{0x0A} 101 varuintLen := binary.PutUvarint(protobufHeader[1:], uint64(len(b))) 102 grpcHeader := buf.Get(5) 103 grpcPayloadLen := uint32(1 + varuintLen + len(b)) 104 binary.BigEndian.PutUint32(grpcHeader[1:5], grpcPayloadLen) 105 c.writeAccess.Lock() 106 _, err = bufio.Copy(c.writer, io.MultiReader(bytes.NewReader(grpcHeader), bytes.NewReader(protobufHeader[:varuintLen+1]), bytes.NewReader(b))) 107 c.writeAccess.Unlock() 108 buf.Put(grpcHeader) 109 if err == nil && c.flusher != nil { 110 c.flusher.Flush() 111 } 112 return len(b), baderror.WrapH2(err) 113 } 114 115 func (c *GunConn) WriteBuffer(buffer *buf.Buffer) error { 116 defer buffer.Release() 117 dataLen := buffer.Len() 118 varLen := rw.UVariantLen(uint64(dataLen)) 119 header := buffer.ExtendHeader(6 + varLen) 120 _ = header[6] 121 header[0] = 0x00 122 binary.BigEndian.PutUint32(header[1:5], uint32(1+varLen+dataLen)) 123 header[5] = 0x0A 124 binary.PutUvarint(header[6:], uint64(dataLen)) 125 err := rw.WriteBytes(c.writer, buffer.Bytes()) 126 if err == nil && c.flusher != nil { 127 c.flusher.Flush() 128 } 129 return baderror.WrapH2(err) 130 } 131 132 func (c *GunConn) FrontHeadroom() int { 133 return 6 + binary.MaxVarintLen64 134 } 135 136 func (c *GunConn) Close() error { 137 return common.Close(c.reader, c.writer) 138 } 139 140 func (c *GunConn) LocalAddr() net.Addr { 141 return nil 142 } 143 144 func (c *GunConn) RemoteAddr() net.Addr { 145 return nil 146 } 147 148 func (c *GunConn) SetDeadline(t time.Time) error { 149 return os.ErrInvalid 150 } 151 152 func (c *GunConn) SetReadDeadline(t time.Time) error { 153 return os.ErrInvalid 154 } 155 156 func (c *GunConn) SetWriteDeadline(t time.Time) error { 157 return os.ErrInvalid 158 } 159 160 func (c *GunConn) NeedAdditionalReadDeadline() bool { 161 return true 162 }