github.com/EagleQL/Xray-core@v1.4.3/common/mux/frame.go (about) 1 package mux 2 3 import ( 4 "encoding/binary" 5 "io" 6 7 "github.com/xtls/xray-core/common" 8 "github.com/xtls/xray-core/common/bitmask" 9 "github.com/xtls/xray-core/common/buf" 10 "github.com/xtls/xray-core/common/net" 11 "github.com/xtls/xray-core/common/protocol" 12 "github.com/xtls/xray-core/common/serial" 13 ) 14 15 type SessionStatus byte 16 17 const ( 18 SessionStatusNew SessionStatus = 0x01 19 SessionStatusKeep SessionStatus = 0x02 20 SessionStatusEnd SessionStatus = 0x03 21 SessionStatusKeepAlive SessionStatus = 0x04 22 ) 23 24 const ( 25 OptionData bitmask.Byte = 0x01 26 OptionError bitmask.Byte = 0x02 27 ) 28 29 type TargetNetwork byte 30 31 const ( 32 TargetNetworkTCP TargetNetwork = 0x01 33 TargetNetworkUDP TargetNetwork = 0x02 34 ) 35 36 var addrParser = protocol.NewAddressParser( 37 protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4), 38 protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain), 39 protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6), 40 protocol.PortThenAddress(), 41 ) 42 43 /* 44 Frame format 45 2 bytes - length 46 2 bytes - session id 47 1 bytes - status 48 1 bytes - option 49 50 1 byte - network 51 2 bytes - port 52 n bytes - address 53 54 */ 55 56 type FrameMetadata struct { 57 Target net.Destination 58 SessionID uint16 59 Option bitmask.Byte 60 SessionStatus SessionStatus 61 } 62 63 func (f FrameMetadata) WriteTo(b *buf.Buffer) error { 64 lenBytes := b.Extend(2) 65 66 len0 := b.Len() 67 sessionBytes := b.Extend(2) 68 binary.BigEndian.PutUint16(sessionBytes, f.SessionID) 69 70 common.Must(b.WriteByte(byte(f.SessionStatus))) 71 common.Must(b.WriteByte(byte(f.Option))) 72 73 if f.SessionStatus == SessionStatusNew { 74 switch f.Target.Network { 75 case net.Network_TCP: 76 common.Must(b.WriteByte(byte(TargetNetworkTCP))) 77 case net.Network_UDP: 78 common.Must(b.WriteByte(byte(TargetNetworkUDP))) 79 } 80 81 if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil { 82 return err 83 } 84 } else if b.UDP != nil { 85 b.WriteByte(byte(TargetNetworkUDP)) 86 addrParser.WriteAddressPort(b, b.UDP.Address, b.UDP.Port) 87 } 88 89 len1 := b.Len() 90 binary.BigEndian.PutUint16(lenBytes, uint16(len1-len0)) 91 return nil 92 } 93 94 // Unmarshal reads FrameMetadata from the given reader. 95 func (f *FrameMetadata) Unmarshal(reader io.Reader) error { 96 metaLen, err := serial.ReadUint16(reader) 97 if err != nil { 98 return err 99 } 100 if metaLen > 512 { 101 return newError("invalid metalen ", metaLen).AtError() 102 } 103 104 b := buf.New() 105 defer b.Release() 106 107 if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil { 108 return err 109 } 110 return f.UnmarshalFromBuffer(b) 111 } 112 113 // UnmarshalFromBuffer reads a FrameMetadata from the given buffer. 114 // Visible for testing only. 115 func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error { 116 if b.Len() < 4 { 117 return newError("insufficient buffer: ", b.Len()) 118 } 119 120 f.SessionID = binary.BigEndian.Uint16(b.BytesTo(2)) 121 f.SessionStatus = SessionStatus(b.Byte(2)) 122 f.Option = bitmask.Byte(b.Byte(3)) 123 f.Target.Network = net.Network_Unknown 124 125 if f.SessionStatus == SessionStatusNew || (f.SessionStatus == SessionStatusKeep && b.Len() != 4) { 126 if b.Len() < 8 { 127 return newError("insufficient buffer: ", b.Len()) 128 } 129 network := TargetNetwork(b.Byte(4)) 130 b.Advance(5) 131 132 addr, port, err := addrParser.ReadAddressPort(nil, b) 133 if err != nil { 134 return newError("failed to parse address and port").Base(err) 135 } 136 137 switch network { 138 case TargetNetworkTCP: 139 f.Target = net.TCPDestination(addr, port) 140 case TargetNetworkUDP: 141 f.Target = net.UDPDestination(addr, port) 142 default: 143 return newError("unknown network type: ", network) 144 } 145 } 146 147 return nil 148 }