github.com/xraypb/Xray-core@v1.8.1/common/mux/frame.go (about)

     1  package mux
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  
     7  	"github.com/xraypb/Xray-core/common"
     8  	"github.com/xraypb/Xray-core/common/bitmask"
     9  	"github.com/xraypb/Xray-core/common/buf"
    10  	"github.com/xraypb/Xray-core/common/net"
    11  	"github.com/xraypb/Xray-core/common/protocol"
    12  	"github.com/xraypb/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  	GlobalID      [8]byte
    62  }
    63  
    64  func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
    65  	lenBytes := b.Extend(2)
    66  
    67  	len0 := b.Len()
    68  	sessionBytes := b.Extend(2)
    69  	binary.BigEndian.PutUint16(sessionBytes, f.SessionID)
    70  
    71  	common.Must(b.WriteByte(byte(f.SessionStatus)))
    72  	common.Must(b.WriteByte(byte(f.Option)))
    73  
    74  	if f.SessionStatus == SessionStatusNew {
    75  		switch f.Target.Network {
    76  		case net.Network_TCP:
    77  			common.Must(b.WriteByte(byte(TargetNetworkTCP)))
    78  		case net.Network_UDP:
    79  			common.Must(b.WriteByte(byte(TargetNetworkUDP)))
    80  		}
    81  
    82  		if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
    83  			return err
    84  		}
    85  		if b.UDP != nil {
    86  			b.Write(f.GlobalID[:])
    87  		}
    88  	} else if b.UDP != nil {
    89  		b.WriteByte(byte(TargetNetworkUDP))
    90  		addrParser.WriteAddressPort(b, b.UDP.Address, b.UDP.Port)
    91  	}
    92  
    93  	len1 := b.Len()
    94  	binary.BigEndian.PutUint16(lenBytes, uint16(len1-len0))
    95  	return nil
    96  }
    97  
    98  // Unmarshal reads FrameMetadata from the given reader.
    99  func (f *FrameMetadata) Unmarshal(reader io.Reader) error {
   100  	metaLen, err := serial.ReadUint16(reader)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	if metaLen > 512 {
   105  		return newError("invalid metalen ", metaLen).AtError()
   106  	}
   107  
   108  	b := buf.New()
   109  	defer b.Release()
   110  
   111  	if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil {
   112  		return err
   113  	}
   114  	return f.UnmarshalFromBuffer(b)
   115  }
   116  
   117  // UnmarshalFromBuffer reads a FrameMetadata from the given buffer.
   118  // Visible for testing only.
   119  func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
   120  	if b.Len() < 4 {
   121  		return newError("insufficient buffer: ", b.Len())
   122  	}
   123  
   124  	f.SessionID = binary.BigEndian.Uint16(b.BytesTo(2))
   125  	f.SessionStatus = SessionStatus(b.Byte(2))
   126  	f.Option = bitmask.Byte(b.Byte(3))
   127  	f.Target.Network = net.Network_Unknown
   128  
   129  	if f.SessionStatus == SessionStatusNew || (f.SessionStatus == SessionStatusKeep && b.Len() != 4) {
   130  		if b.Len() < 8 {
   131  			return newError("insufficient buffer: ", b.Len())
   132  		}
   133  		network := TargetNetwork(b.Byte(4))
   134  		b.Advance(5)
   135  
   136  		addr, port, err := addrParser.ReadAddressPort(nil, b)
   137  		if err != nil {
   138  			return newError("failed to parse address and port").Base(err)
   139  		}
   140  
   141  		switch network {
   142  		case TargetNetworkTCP:
   143  			f.Target = net.TCPDestination(addr, port)
   144  		case TargetNetworkUDP:
   145  			f.Target = net.UDPDestination(addr, port)
   146  		default:
   147  			return newError("unknown network type: ", network)
   148  		}
   149  	}
   150  
   151  	if f.SessionStatus == SessionStatusNew && f.Option.Has(OptionData) &&
   152  		f.Target.Network == net.Network_UDP && b.Len() >= 8 {
   153  		copy(f.GlobalID[:], b.Bytes())
   154  	}
   155  
   156  	return nil
   157  }