github.com/imannamdari/v2ray-core/v5@v5.0.5/common/mux/frame.go (about) 1 package mux 2 3 import ( 4 "encoding/binary" 5 "io" 6 7 "github.com/imannamdari/v2ray-core/v5/common" 8 "github.com/imannamdari/v2ray-core/v5/common/bitmask" 9 "github.com/imannamdari/v2ray-core/v5/common/buf" 10 "github.com/imannamdari/v2ray-core/v5/common/net" 11 "github.com/imannamdari/v2ray-core/v5/common/protocol" 12 "github.com/imannamdari/v2ray-core/v5/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 } 85 86 len1 := b.Len() 87 binary.BigEndian.PutUint16(lenBytes, uint16(len1-len0)) 88 return nil 89 } 90 91 // Unmarshal reads FrameMetadata from the given reader. 92 func (f *FrameMetadata) Unmarshal(reader io.Reader) error { 93 metaLen, err := serial.ReadUint16(reader) 94 if err != nil { 95 return err 96 } 97 if metaLen > 512 { 98 return newError("invalid metalen ", metaLen).AtError() 99 } 100 101 b := buf.New() 102 defer b.Release() 103 104 if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil { 105 return err 106 } 107 return f.UnmarshalFromBuffer(b) 108 } 109 110 // UnmarshalFromBuffer reads a FrameMetadata from the given buffer. 111 // Visible for testing only. 112 func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error { 113 if b.Len() < 4 { 114 return newError("insufficient buffer: ", b.Len()) 115 } 116 117 f.SessionID = binary.BigEndian.Uint16(b.BytesTo(2)) 118 f.SessionStatus = SessionStatus(b.Byte(2)) 119 f.Option = bitmask.Byte(b.Byte(3)) 120 f.Target.Network = net.Network_Unknown 121 122 if f.SessionStatus == SessionStatusNew { 123 if b.Len() < 8 { 124 return newError("insufficient buffer: ", b.Len()) 125 } 126 network := TargetNetwork(b.Byte(4)) 127 b.Advance(5) 128 129 addr, port, err := addrParser.ReadAddressPort(nil, b) 130 if err != nil { 131 return newError("failed to parse address and port").Base(err) 132 } 133 134 switch network { 135 case TargetNetworkTCP: 136 f.Target = net.TCPDestination(addr, port) 137 case TargetNetworkUDP: 138 f.Target = net.UDPDestination(addr, port) 139 default: 140 return newError("unknown network type: ", network) 141 } 142 } 143 144 return nil 145 }