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

     1  package encoding
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  
     7  	"github.com/xtls/xray-core/common/buf"
     8  	"github.com/xtls/xray-core/common/protocol"
     9  	"github.com/xtls/xray-core/proxy"
    10  	"github.com/xtls/xray-core/proxy/vless"
    11  	"google.golang.org/protobuf/proto"
    12  )
    13  
    14  func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error {
    15  	switch addons.Flow {
    16  	case vless.XRV:
    17  		bytes, err := proto.Marshal(addons)
    18  		if err != nil {
    19  			return newError("failed to marshal addons protobuf value").Base(err)
    20  		}
    21  		if err := buffer.WriteByte(byte(len(bytes))); err != nil {
    22  			return newError("failed to write addons protobuf length").Base(err)
    23  		}
    24  		if _, err := buffer.Write(bytes); err != nil {
    25  			return newError("failed to write addons protobuf value").Base(err)
    26  		}
    27  	default:
    28  		if err := buffer.WriteByte(0); err != nil {
    29  			return newError("failed to write addons protobuf length").Base(err)
    30  		}
    31  	}
    32  
    33  	return nil
    34  }
    35  
    36  func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) {
    37  	addons := new(Addons)
    38  	buffer.Clear()
    39  	if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
    40  		return nil, newError("failed to read addons protobuf length").Base(err)
    41  	}
    42  
    43  	if length := int32(buffer.Byte(0)); length != 0 {
    44  		buffer.Clear()
    45  		if _, err := buffer.ReadFullFrom(reader, length); err != nil {
    46  			return nil, newError("failed to read addons protobuf value").Base(err)
    47  		}
    48  
    49  		if err := proto.Unmarshal(buffer.Bytes(), addons); err != nil {
    50  			return nil, newError("failed to unmarshal addons protobuf value").Base(err)
    51  		}
    52  
    53  		// Verification.
    54  		switch addons.Flow {
    55  		default:
    56  		}
    57  	}
    58  
    59  	return addons, nil
    60  }
    61  
    62  // EncodeBodyAddons returns a Writer that auto-encrypt content written by caller.
    63  func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, context context.Context) buf.Writer {
    64  	if request.Command == protocol.RequestCommandUDP {
    65  		return NewMultiLengthPacketWriter(writer.(buf.Writer))
    66  	}
    67  	w := buf.NewWriter(writer)
    68  	if requestAddons.Flow == vless.XRV {
    69  		w = proxy.NewVisionWriter(w, state, context)
    70  	}
    71  	return w
    72  }
    73  
    74  // DecodeBodyAddons returns a Reader from which caller can fetch decrypted body.
    75  func DecodeBodyAddons(reader io.Reader, request *protocol.RequestHeader, addons *Addons) buf.Reader {
    76  	switch addons.Flow {
    77  	default:
    78  		if request.Command == protocol.RequestCommandUDP {
    79  			return NewLengthPacketReader(reader)
    80  		}
    81  	}
    82  	return buf.NewReader(reader)
    83  }
    84  
    85  func NewMultiLengthPacketWriter(writer buf.Writer) *MultiLengthPacketWriter {
    86  	return &MultiLengthPacketWriter{
    87  		Writer: writer,
    88  	}
    89  }
    90  
    91  type MultiLengthPacketWriter struct {
    92  	buf.Writer
    93  }
    94  
    95  func (w *MultiLengthPacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
    96  	defer buf.ReleaseMulti(mb)
    97  	mb2Write := make(buf.MultiBuffer, 0, len(mb)+1)
    98  	for _, b := range mb {
    99  		length := b.Len()
   100  		if length == 0 || length+2 > buf.Size {
   101  			continue
   102  		}
   103  		eb := buf.New()
   104  		if err := eb.WriteByte(byte(length >> 8)); err != nil {
   105  			eb.Release()
   106  			continue
   107  		}
   108  		if err := eb.WriteByte(byte(length)); err != nil {
   109  			eb.Release()
   110  			continue
   111  		}
   112  		if _, err := eb.Write(b.Bytes()); err != nil {
   113  			eb.Release()
   114  			continue
   115  		}
   116  		mb2Write = append(mb2Write, eb)
   117  	}
   118  	if mb2Write.IsEmpty() {
   119  		return nil
   120  	}
   121  	return w.Writer.WriteMultiBuffer(mb2Write)
   122  }
   123  
   124  func NewLengthPacketWriter(writer io.Writer) *LengthPacketWriter {
   125  	return &LengthPacketWriter{
   126  		Writer: writer,
   127  		cache:  make([]byte, 0, 65536),
   128  	}
   129  }
   130  
   131  type LengthPacketWriter struct {
   132  	io.Writer
   133  	cache []byte
   134  }
   135  
   136  func (w *LengthPacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
   137  	length := mb.Len() // none of mb is nil
   138  	// fmt.Println("Write", length)
   139  	if length == 0 {
   140  		return nil
   141  	}
   142  	defer func() {
   143  		w.cache = w.cache[:0]
   144  	}()
   145  	w.cache = append(w.cache, byte(length>>8), byte(length))
   146  	for i, b := range mb {
   147  		w.cache = append(w.cache, b.Bytes()...)
   148  		b.Release()
   149  		mb[i] = nil
   150  	}
   151  	if _, err := w.Write(w.cache); err != nil {
   152  		return newError("failed to write a packet").Base(err)
   153  	}
   154  	return nil
   155  }
   156  
   157  func NewLengthPacketReader(reader io.Reader) *LengthPacketReader {
   158  	return &LengthPacketReader{
   159  		Reader: reader,
   160  		cache:  make([]byte, 2),
   161  	}
   162  }
   163  
   164  type LengthPacketReader struct {
   165  	io.Reader
   166  	cache []byte
   167  }
   168  
   169  func (r *LengthPacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
   170  	if _, err := io.ReadFull(r.Reader, r.cache); err != nil { // maybe EOF
   171  		return nil, newError("failed to read packet length").Base(err)
   172  	}
   173  	length := int32(r.cache[0])<<8 | int32(r.cache[1])
   174  	// fmt.Println("Read", length)
   175  	mb := make(buf.MultiBuffer, 0, length/buf.Size+1)
   176  	for length > 0 {
   177  		size := length
   178  		if size > buf.Size {
   179  			size = buf.Size
   180  		}
   181  		length -= size
   182  		b := buf.New()
   183  		if _, err := b.ReadFullFrom(r.Reader, size); err != nil {
   184  			return nil, newError("failed to read packet payload").Base(err)
   185  		}
   186  		mb = append(mb, b)
   187  	}
   188  	return mb, nil
   189  }