github.com/sagernet/sing-box@v1.2.7/transport/vless/protocol.go (about) 1 package vless 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "io" 7 8 "github.com/sagernet/sing-vmess" 9 "github.com/sagernet/sing/common" 10 "github.com/sagernet/sing/common/buf" 11 E "github.com/sagernet/sing/common/exceptions" 12 M "github.com/sagernet/sing/common/metadata" 13 "github.com/sagernet/sing/common/rw" 14 ) 15 16 const ( 17 Version = 0 18 FlowVision = "xtls-rprx-vision" 19 ) 20 21 type Request struct { 22 UUID [16]byte 23 Command byte 24 Destination M.Socksaddr 25 Flow string 26 } 27 28 func ReadRequest(reader io.Reader) (*Request, error) { 29 var request Request 30 31 var version uint8 32 err := binary.Read(reader, binary.BigEndian, &version) 33 if err != nil { 34 return nil, err 35 } 36 if version != Version { 37 return nil, E.New("unknown version: ", version) 38 } 39 40 _, err = io.ReadFull(reader, request.UUID[:]) 41 if err != nil { 42 return nil, err 43 } 44 45 var addonsLen uint8 46 err = binary.Read(reader, binary.BigEndian, &addonsLen) 47 if err != nil { 48 return nil, err 49 } 50 51 if addonsLen > 0 { 52 addonsBytes, err := rw.ReadBytes(reader, int(addonsLen)) 53 if err != nil { 54 return nil, err 55 } 56 57 addons, err := readAddons(bytes.NewReader(addonsBytes)) 58 if err != nil { 59 return nil, err 60 } 61 request.Flow = addons.Flow 62 } 63 64 err = binary.Read(reader, binary.BigEndian, &request.Command) 65 if err != nil { 66 return nil, err 67 } 68 69 if request.Command != vmess.CommandMux { 70 request.Destination, err = vmess.AddressSerializer.ReadAddrPort(reader) 71 if err != nil { 72 return nil, err 73 } 74 } 75 76 return &request, nil 77 } 78 79 type Addons struct { 80 Flow string 81 Seed string 82 } 83 84 func readAddons(reader io.Reader) (*Addons, error) { 85 protoHeader, err := rw.ReadByte(reader) 86 if err != nil { 87 return nil, err 88 } 89 if protoHeader != 10 { 90 return nil, E.New("unknown protobuf message header: ", protoHeader) 91 } 92 93 var addons Addons 94 95 flowLen, err := rw.ReadUVariant(reader) 96 if err != nil { 97 if err == io.EOF { 98 return &addons, nil 99 } 100 return nil, err 101 } 102 flowBytes, err := rw.ReadBytes(reader, int(flowLen)) 103 if err != nil { 104 return nil, err 105 } 106 addons.Flow = string(flowBytes) 107 108 seedLen, err := rw.ReadUVariant(reader) 109 if err != nil { 110 if err == io.EOF { 111 return &addons, nil 112 } 113 return nil, err 114 } 115 seedBytes, err := rw.ReadBytes(reader, int(seedLen)) 116 if err != nil { 117 return nil, err 118 } 119 addons.Seed = string(seedBytes) 120 121 return &addons, nil 122 } 123 124 func WriteRequest(writer io.Writer, request Request, payload []byte) error { 125 var requestLen int 126 requestLen += 1 // version 127 requestLen += 16 // uuid 128 requestLen += 1 // protobuf length 129 130 var addonsLen int 131 if request.Command == vmess.CommandTCP && request.Flow != "" { 132 addonsLen += 1 // protobuf header 133 addonsLen += UvarintLen(uint64(len(request.Flow))) 134 addonsLen += len(request.Flow) 135 requestLen += addonsLen 136 } 137 requestLen += 1 // command 138 if request.Command != vmess.CommandMux { 139 requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination) 140 } 141 requestLen += len(payload) 142 _buffer := buf.StackNewSize(requestLen) 143 defer common.KeepAlive(_buffer) 144 buffer := common.Dup(_buffer) 145 defer buffer.Release() 146 common.Must( 147 buffer.WriteByte(Version), 148 common.Error(buffer.Write(request.UUID[:])), 149 buffer.WriteByte(byte(addonsLen)), 150 ) 151 if addonsLen > 0 { 152 common.Must(buffer.WriteByte(10)) 153 binary.PutUvarint(buffer.Extend(UvarintLen(uint64(len(request.Flow)))), uint64(len(request.Flow))) 154 common.Must(common.Error(buffer.Write([]byte(request.Flow)))) 155 } 156 common.Must( 157 buffer.WriteByte(request.Command), 158 ) 159 160 if request.Command != vmess.CommandMux { 161 common.Must(vmess.AddressSerializer.WriteAddrPort(buffer, request.Destination)) 162 } 163 164 common.Must1(buffer.Write(payload)) 165 return common.Error(writer.Write(buffer.Bytes())) 166 } 167 168 func WritePacketRequest(writer io.Writer, request Request, payload []byte) error { 169 var requestLen int 170 requestLen += 1 // version 171 requestLen += 16 // uuid 172 requestLen += 1 // protobuf length 173 var addonsLen int 174 /*if request.Flow != "" { 175 addonsLen += 1 // protobuf header 176 addonsLen += UvarintLen(uint64(len(request.Flow))) 177 addonsLen += len(request.Flow) 178 requestLen += addonsLen 179 }*/ 180 requestLen += 1 // command 181 requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination) 182 if len(payload) > 0 { 183 requestLen += 2 184 requestLen += len(payload) 185 } 186 _buffer := buf.StackNewSize(requestLen) 187 defer common.KeepAlive(_buffer) 188 buffer := common.Dup(_buffer) 189 defer buffer.Release() 190 common.Must( 191 buffer.WriteByte(Version), 192 common.Error(buffer.Write(request.UUID[:])), 193 buffer.WriteByte(byte(addonsLen)), 194 ) 195 196 if addonsLen > 0 { 197 common.Must(buffer.WriteByte(10)) 198 binary.PutUvarint(buffer.Extend(UvarintLen(uint64(len(request.Flow)))), uint64(len(request.Flow))) 199 common.Must(common.Error(buffer.Write([]byte(request.Flow)))) 200 } 201 202 common.Must( 203 buffer.WriteByte(vmess.CommandUDP), 204 vmess.AddressSerializer.WriteAddrPort(buffer, request.Destination), 205 ) 206 207 if len(payload) > 0 { 208 common.Must( 209 binary.Write(buffer, binary.BigEndian, uint16(len(payload))), 210 common.Error(buffer.Write(payload)), 211 ) 212 } 213 214 return common.Error(writer.Write(buffer.Bytes())) 215 } 216 217 func ReadResponse(reader io.Reader) error { 218 version, err := rw.ReadByte(reader) 219 if err != nil { 220 return err 221 } 222 if version != Version { 223 return E.New("unknown version: ", version) 224 } 225 protobufLength, err := rw.ReadByte(reader) 226 if err != nil { 227 return err 228 } 229 if protobufLength > 0 { 230 err = rw.SkipN(reader, int(protobufLength)) 231 if err != nil { 232 return err 233 } 234 } 235 return nil 236 } 237 238 func UvarintLen(value uint64) int { 239 var buffer [binary.MaxVarintLen64]byte 240 return binary.PutUvarint(buffer[:], value) 241 }