github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/common/mux/frame.go (about)

     1  package mux
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  
     7  	"github.com/v2fly/v2ray-core/v5/common"
     8  	"github.com/v2fly/v2ray-core/v5/common/bitmask"
     9  	"github.com/v2fly/v2ray-core/v5/common/buf"
    10  	"github.com/v2fly/v2ray-core/v5/common/net"
    11  	"github.com/v2fly/v2ray-core/v5/common/protocol"
    12  	"github.com/v2fly/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  }