github.com/sagernet/sing-box@v1.9.0-rc.20/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.Flow != "" { 132 addonsLen += 1 // protobuf header 133 addonsLen += rw.UVariantLen(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.NewSize(requestLen) 143 defer buffer.Release() 144 common.Must( 145 buffer.WriteByte(Version), 146 common.Error(buffer.Write(request.UUID[:])), 147 buffer.WriteByte(byte(addonsLen)), 148 ) 149 if addonsLen > 0 { 150 common.Must(buffer.WriteByte(10)) 151 binary.PutUvarint(buffer.Extend(rw.UVariantLen(uint64(len(request.Flow)))), uint64(len(request.Flow))) 152 common.Must(common.Error(buffer.WriteString(request.Flow))) 153 } 154 common.Must( 155 buffer.WriteByte(request.Command), 156 ) 157 158 if request.Command != vmess.CommandMux { 159 err := vmess.AddressSerializer.WriteAddrPort(buffer, request.Destination) 160 if err != nil { 161 return err 162 } 163 } 164 165 common.Must1(buffer.Write(payload)) 166 return common.Error(writer.Write(buffer.Bytes())) 167 } 168 169 func EncodeRequest(request Request, buffer *buf.Buffer) error { 170 var requestLen int 171 requestLen += 1 // version 172 requestLen += 16 // uuid 173 requestLen += 1 // protobuf length 174 175 var addonsLen int 176 if request.Flow != "" { 177 addonsLen += 1 // protobuf header 178 addonsLen += rw.UVariantLen(uint64(len(request.Flow))) 179 addonsLen += len(request.Flow) 180 requestLen += addonsLen 181 } 182 requestLen += 1 // command 183 if request.Command != vmess.CommandMux { 184 requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination) 185 } 186 common.Must( 187 buffer.WriteByte(Version), 188 common.Error(buffer.Write(request.UUID[:])), 189 buffer.WriteByte(byte(addonsLen)), 190 ) 191 if addonsLen > 0 { 192 common.Must(buffer.WriteByte(10)) 193 binary.PutUvarint(buffer.Extend(rw.UVariantLen(uint64(len(request.Flow)))), uint64(len(request.Flow))) 194 common.Must(common.Error(buffer.WriteString(request.Flow))) 195 } 196 common.Must( 197 buffer.WriteByte(request.Command), 198 ) 199 200 if request.Command != vmess.CommandMux { 201 err := vmess.AddressSerializer.WriteAddrPort(buffer, request.Destination) 202 if err != nil { 203 return err 204 } 205 } 206 return nil 207 } 208 209 func RequestLen(request Request) int { 210 var requestLen int 211 requestLen += 1 // version 212 requestLen += 16 // uuid 213 requestLen += 1 // protobuf length 214 215 var addonsLen int 216 if request.Flow != "" { 217 addonsLen += 1 // protobuf header 218 addonsLen += rw.UVariantLen(uint64(len(request.Flow))) 219 addonsLen += len(request.Flow) 220 requestLen += addonsLen 221 } 222 requestLen += 1 // command 223 if request.Command != vmess.CommandMux { 224 requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination) 225 } 226 return requestLen 227 } 228 229 func WritePacketRequest(writer io.Writer, request Request, payload []byte) error { 230 var requestLen int 231 requestLen += 1 // version 232 requestLen += 16 // uuid 233 requestLen += 1 // protobuf length 234 var addonsLen int 235 /*if request.Flow != "" { 236 addonsLen += 1 // protobuf header 237 addonsLen += rw.UVariantLen(uint64(len(request.Flow))) 238 addonsLen += len(request.Flow) 239 requestLen += addonsLen 240 }*/ 241 requestLen += 1 // command 242 requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination) 243 if len(payload) > 0 { 244 requestLen += 2 245 requestLen += len(payload) 246 } 247 buffer := buf.NewSize(requestLen) 248 defer buffer.Release() 249 common.Must( 250 buffer.WriteByte(Version), 251 common.Error(buffer.Write(request.UUID[:])), 252 buffer.WriteByte(byte(addonsLen)), 253 ) 254 255 if addonsLen > 0 { 256 common.Must(buffer.WriteByte(10)) 257 binary.PutUvarint(buffer.Extend(rw.UVariantLen(uint64(len(request.Flow)))), uint64(len(request.Flow))) 258 common.Must(common.Error(buffer.WriteString(request.Flow))) 259 } 260 261 common.Must(buffer.WriteByte(vmess.CommandUDP)) 262 263 err := vmess.AddressSerializer.WriteAddrPort(buffer, request.Destination) 264 if err != nil { 265 return err 266 } 267 268 if len(payload) > 0 { 269 common.Must( 270 binary.Write(buffer, binary.BigEndian, uint16(len(payload))), 271 common.Error(buffer.Write(payload)), 272 ) 273 } 274 275 return common.Error(writer.Write(buffer.Bytes())) 276 } 277 278 func ReadResponse(reader io.Reader) error { 279 version, err := rw.ReadByte(reader) 280 if err != nil { 281 return err 282 } 283 if version != Version { 284 return E.New("unknown version: ", version) 285 } 286 protobufLength, err := rw.ReadByte(reader) 287 if err != nil { 288 return err 289 } 290 if protobufLength > 0 { 291 err = rw.SkipN(reader, int(protobufLength)) 292 if err != nil { 293 return err 294 } 295 } 296 return nil 297 }