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