github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/proxy/vless/encoding/encoding.go (about)

     1  package encoding
     2  
     3  //go:generate go run github.com/xtls/xray-core/common/errors/errorgen
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  	"io"
     9  
    10  	"github.com/xtls/xray-core/common/buf"
    11  	"github.com/xtls/xray-core/common/errors"
    12  	"github.com/xtls/xray-core/common/net"
    13  	"github.com/xtls/xray-core/common/protocol"
    14  	"github.com/xtls/xray-core/common/session"
    15  	"github.com/xtls/xray-core/common/signal"
    16  	"github.com/xtls/xray-core/features/stats"
    17  	"github.com/xtls/xray-core/proxy"
    18  	"github.com/xtls/xray-core/proxy/vless"
    19  )
    20  
    21  const (
    22  	Version = byte(0)
    23  )
    24  
    25  var addrParser = protocol.NewAddressParser(
    26  	protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4),
    27  	protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain),
    28  	protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6),
    29  	protocol.PortThenAddress(),
    30  )
    31  
    32  // EncodeRequestHeader writes encoded request header into the given writer.
    33  func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons) error {
    34  	buffer := buf.StackNew()
    35  	defer buffer.Release()
    36  
    37  	if err := buffer.WriteByte(request.Version); err != nil {
    38  		return newError("failed to write request version").Base(err)
    39  	}
    40  
    41  	if _, err := buffer.Write(request.User.Account.(*vless.MemoryAccount).ID.Bytes()); err != nil {
    42  		return newError("failed to write request user id").Base(err)
    43  	}
    44  
    45  	if err := EncodeHeaderAddons(&buffer, requestAddons); err != nil {
    46  		return newError("failed to encode request header addons").Base(err)
    47  	}
    48  
    49  	if err := buffer.WriteByte(byte(request.Command)); err != nil {
    50  		return newError("failed to write request command").Base(err)
    51  	}
    52  
    53  	if request.Command != protocol.RequestCommandMux {
    54  		if err := addrParser.WriteAddressPort(&buffer, request.Address, request.Port); err != nil {
    55  			return newError("failed to write request address and port").Base(err)
    56  		}
    57  	}
    58  
    59  	if _, err := writer.Write(buffer.Bytes()); err != nil {
    60  		return newError("failed to write request header").Base(err)
    61  	}
    62  
    63  	return nil
    64  }
    65  
    66  // DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
    67  func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator *vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) {
    68  	buffer := buf.StackNew()
    69  	defer buffer.Release()
    70  
    71  	request := new(protocol.RequestHeader)
    72  
    73  	if isfb {
    74  		request.Version = first.Byte(0)
    75  	} else {
    76  		if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
    77  			return nil, nil, false, newError("failed to read request version").Base(err)
    78  		}
    79  		request.Version = buffer.Byte(0)
    80  	}
    81  
    82  	switch request.Version {
    83  	case 0:
    84  
    85  		var id [16]byte
    86  
    87  		if isfb {
    88  			copy(id[:], first.BytesRange(1, 17))
    89  		} else {
    90  			buffer.Clear()
    91  			if _, err := buffer.ReadFullFrom(reader, 16); err != nil {
    92  				return nil, nil, false, newError("failed to read request user id").Base(err)
    93  			}
    94  			copy(id[:], buffer.Bytes())
    95  		}
    96  
    97  		if request.User = validator.Get(id); request.User == nil {
    98  			return nil, nil, isfb, newError("invalid request user id")
    99  		}
   100  
   101  		if isfb {
   102  			first.Advance(17)
   103  		}
   104  
   105  		requestAddons, err := DecodeHeaderAddons(&buffer, reader)
   106  		if err != nil {
   107  			return nil, nil, false, newError("failed to decode request header addons").Base(err)
   108  		}
   109  
   110  		buffer.Clear()
   111  		if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
   112  			return nil, nil, false, newError("failed to read request command").Base(err)
   113  		}
   114  
   115  		request.Command = protocol.RequestCommand(buffer.Byte(0))
   116  		switch request.Command {
   117  		case protocol.RequestCommandMux:
   118  			request.Address = net.DomainAddress("v1.mux.cool")
   119  			request.Port = 0
   120  		case protocol.RequestCommandTCP, protocol.RequestCommandUDP:
   121  			if addr, port, err := addrParser.ReadAddressPort(&buffer, reader); err == nil {
   122  				request.Address = addr
   123  				request.Port = port
   124  			}
   125  		}
   126  		if request.Address == nil {
   127  			return nil, nil, false, newError("invalid request address")
   128  		}
   129  		return request, requestAddons, false, nil
   130  	default:
   131  		return nil, nil, isfb, newError("invalid request version")
   132  	}
   133  }
   134  
   135  // EncodeResponseHeader writes encoded response header into the given writer.
   136  func EncodeResponseHeader(writer io.Writer, request *protocol.RequestHeader, responseAddons *Addons) error {
   137  	buffer := buf.StackNew()
   138  	defer buffer.Release()
   139  
   140  	if err := buffer.WriteByte(request.Version); err != nil {
   141  		return newError("failed to write response version").Base(err)
   142  	}
   143  
   144  	if err := EncodeHeaderAddons(&buffer, responseAddons); err != nil {
   145  		return newError("failed to encode response header addons").Base(err)
   146  	}
   147  
   148  	if _, err := writer.Write(buffer.Bytes()); err != nil {
   149  		return newError("failed to write response header").Base(err)
   150  	}
   151  
   152  	return nil
   153  }
   154  
   155  // DecodeResponseHeader decodes and returns (if successful) a ResponseHeader from an input stream.
   156  func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*Addons, error) {
   157  	buffer := buf.StackNew()
   158  	defer buffer.Release()
   159  
   160  	if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
   161  		return nil, newError("failed to read response version").Base(err)
   162  	}
   163  
   164  	if buffer.Byte(0) != request.Version {
   165  		return nil, newError("unexpected response version. Expecting ", int(request.Version), " but actually ", int(buffer.Byte(0)))
   166  	}
   167  
   168  	responseAddons, err := DecodeHeaderAddons(&buffer, reader)
   169  	if err != nil {
   170  		return nil, newError("failed to decode response header addons").Base(err)
   171  	}
   172  
   173  	return responseAddons, nil
   174  }
   175  
   176  // XtlsRead filter and read xtls protocol
   177  func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
   178  	err := func() error {
   179  		for {
   180  			if trafficState.ReaderSwitchToDirectCopy {
   181  				var writerConn net.Conn
   182  				if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil {
   183  					writerConn = inbound.Conn
   184  					if inbound.CanSpliceCopy == 2 {
   185  						inbound.CanSpliceCopy = 1
   186  					}
   187  					if ob != nil && ob.CanSpliceCopy == 2 { // ob need to be passed in due to context can change
   188  						ob.CanSpliceCopy = 1
   189  					}
   190  				}
   191  				return proxy.CopyRawConnIfExist(ctx, conn, writerConn, writer, timer)
   192  			}
   193  			buffer, err := reader.ReadMultiBuffer()
   194  			if !buffer.IsEmpty() {
   195  				timer.Update()
   196  				if trafficState.ReaderSwitchToDirectCopy {
   197  					// XTLS Vision processes struct TLS Conn's input and rawInput
   198  					if inputBuffer, err := buf.ReadFrom(input); err == nil {
   199  						if !inputBuffer.IsEmpty() {
   200  							buffer, _ = buf.MergeMulti(buffer, inputBuffer)
   201  						}
   202  					}
   203  					if rawInputBuffer, err := buf.ReadFrom(rawInput); err == nil {
   204  						if !rawInputBuffer.IsEmpty() {
   205  							buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
   206  						}
   207  					}
   208  				}
   209  				if werr := writer.WriteMultiBuffer(buffer); werr != nil {
   210  					return werr
   211  				}
   212  			}
   213  			if err != nil {
   214  				return err
   215  			}
   216  		}
   217  	}()
   218  	if err != nil && errors.Cause(err) != io.EOF {
   219  		return err
   220  	}
   221  	return nil
   222  }
   223  
   224  // XtlsWrite filter and write xtls protocol
   225  func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
   226  	err := func() error {
   227  		var ct stats.Counter
   228  		for {
   229  			buffer, err := reader.ReadMultiBuffer()
   230  			if trafficState.WriterSwitchToDirectCopy {
   231  				if inbound := session.InboundFromContext(ctx); inbound != nil {
   232  					if inbound.CanSpliceCopy == 2 {
   233  						inbound.CanSpliceCopy = 1
   234  					}
   235  					if ob != nil && ob.CanSpliceCopy == 2 {
   236  						ob.CanSpliceCopy = 1
   237  					}
   238  				}
   239  				rawConn, _, writerCounter := proxy.UnwrapRawConn(conn)
   240  				writer = buf.NewWriter(rawConn)
   241  				ct = writerCounter
   242  				trafficState.WriterSwitchToDirectCopy = false
   243  			}
   244  			if !buffer.IsEmpty() {
   245  				if ct != nil {
   246  					ct.Add(int64(buffer.Len()))
   247  				}
   248  				timer.Update()
   249  				if werr := writer.WriteMultiBuffer(buffer); werr != nil {
   250  					return werr
   251  				}
   252  			}
   253  			if err != nil {
   254  				return err
   255  			}
   256  		}
   257  	}()
   258  	if err != nil && errors.Cause(err) != io.EOF {
   259  		return err
   260  	}
   261  	return nil
   262  }