github.com/xtls/xray-core@v1.8.3/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  	"crypto/rand"
     9  	"io"
    10  	"math/big"
    11  	"runtime"
    12  	"strconv"
    13  	"syscall"
    14  	"time"
    15  
    16  	"github.com/xtls/xray-core/common/buf"
    17  	"github.com/xtls/xray-core/common/errors"
    18  	"github.com/xtls/xray-core/common/net"
    19  	"github.com/xtls/xray-core/common/protocol"
    20  	"github.com/xtls/xray-core/common/session"
    21  	"github.com/xtls/xray-core/common/signal"
    22  	"github.com/xtls/xray-core/features/stats"
    23  	"github.com/xtls/xray-core/proxy/vless"
    24  	"github.com/xtls/xray-core/transport/internet/reality"
    25  	"github.com/xtls/xray-core/transport/internet/stat"
    26  	"github.com/xtls/xray-core/transport/internet/tls"
    27  )
    28  
    29  const (
    30  	Version = byte(0)
    31  )
    32  
    33  var (
    34  	tls13SupportedVersions  = []byte{0x00, 0x2b, 0x00, 0x02, 0x03, 0x04}
    35  	tlsClientHandShakeStart = []byte{0x16, 0x03}
    36  	tlsServerHandShakeStart = []byte{0x16, 0x03, 0x03}
    37  	tlsApplicationDataStart = []byte{0x17, 0x03, 0x03}
    38  
    39  	Tls13CipherSuiteDic = map[uint16]string{
    40  		0x1301: "TLS_AES_128_GCM_SHA256",
    41  		0x1302: "TLS_AES_256_GCM_SHA384",
    42  		0x1303: "TLS_CHACHA20_POLY1305_SHA256",
    43  		0x1304: "TLS_AES_128_CCM_SHA256",
    44  		0x1305: "TLS_AES_128_CCM_8_SHA256",
    45  	}
    46  )
    47  
    48  const (
    49  	tlsHandshakeTypeClientHello byte = 0x01
    50  	tlsHandshakeTypeServerHello byte = 0x02
    51  
    52  	CommandPaddingContinue byte = 0x00
    53  	CommandPaddingEnd      byte = 0x01
    54  	CommandPaddingDirect   byte = 0x02
    55  )
    56  
    57  var addrParser = protocol.NewAddressParser(
    58  	protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4),
    59  	protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain),
    60  	protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6),
    61  	protocol.PortThenAddress(),
    62  )
    63  
    64  // EncodeRequestHeader writes encoded request header into the given writer.
    65  func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons) error {
    66  	buffer := buf.StackNew()
    67  	defer buffer.Release()
    68  
    69  	if err := buffer.WriteByte(request.Version); err != nil {
    70  		return newError("failed to write request version").Base(err)
    71  	}
    72  
    73  	if _, err := buffer.Write(request.User.Account.(*vless.MemoryAccount).ID.Bytes()); err != nil {
    74  		return newError("failed to write request user id").Base(err)
    75  	}
    76  
    77  	if err := EncodeHeaderAddons(&buffer, requestAddons); err != nil {
    78  		return newError("failed to encode request header addons").Base(err)
    79  	}
    80  
    81  	if err := buffer.WriteByte(byte(request.Command)); err != nil {
    82  		return newError("failed to write request command").Base(err)
    83  	}
    84  
    85  	if request.Command != protocol.RequestCommandMux {
    86  		if err := addrParser.WriteAddressPort(&buffer, request.Address, request.Port); err != nil {
    87  			return newError("failed to write request address and port").Base(err)
    88  		}
    89  	}
    90  
    91  	if _, err := writer.Write(buffer.Bytes()); err != nil {
    92  		return newError("failed to write request header").Base(err)
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  // DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
    99  func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator *vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) {
   100  	buffer := buf.StackNew()
   101  	defer buffer.Release()
   102  
   103  	request := new(protocol.RequestHeader)
   104  
   105  	if isfb {
   106  		request.Version = first.Byte(0)
   107  	} else {
   108  		if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
   109  			return nil, nil, false, newError("failed to read request version").Base(err)
   110  		}
   111  		request.Version = buffer.Byte(0)
   112  	}
   113  
   114  	switch request.Version {
   115  	case 0:
   116  
   117  		var id [16]byte
   118  
   119  		if isfb {
   120  			copy(id[:], first.BytesRange(1, 17))
   121  		} else {
   122  			buffer.Clear()
   123  			if _, err := buffer.ReadFullFrom(reader, 16); err != nil {
   124  				return nil, nil, false, newError("failed to read request user id").Base(err)
   125  			}
   126  			copy(id[:], buffer.Bytes())
   127  		}
   128  
   129  		if request.User = validator.Get(id); request.User == nil {
   130  			return nil, nil, isfb, newError("invalid request user id")
   131  		}
   132  
   133  		if isfb {
   134  			first.Advance(17)
   135  		}
   136  
   137  		requestAddons, err := DecodeHeaderAddons(&buffer, reader)
   138  		if err != nil {
   139  			return nil, nil, false, newError("failed to decode request header addons").Base(err)
   140  		}
   141  
   142  		buffer.Clear()
   143  		if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
   144  			return nil, nil, false, newError("failed to read request command").Base(err)
   145  		}
   146  
   147  		request.Command = protocol.RequestCommand(buffer.Byte(0))
   148  		switch request.Command {
   149  		case protocol.RequestCommandMux:
   150  			request.Address = net.DomainAddress("v1.mux.cool")
   151  			request.Port = 0
   152  		case protocol.RequestCommandTCP, protocol.RequestCommandUDP:
   153  			if addr, port, err := addrParser.ReadAddressPort(&buffer, reader); err == nil {
   154  				request.Address = addr
   155  				request.Port = port
   156  			}
   157  		}
   158  		if request.Address == nil {
   159  			return nil, nil, false, newError("invalid request address")
   160  		}
   161  		return request, requestAddons, false, nil
   162  	default:
   163  		return nil, nil, isfb, newError("invalid request version")
   164  	}
   165  }
   166  
   167  // EncodeResponseHeader writes encoded response header into the given writer.
   168  func EncodeResponseHeader(writer io.Writer, request *protocol.RequestHeader, responseAddons *Addons) error {
   169  	buffer := buf.StackNew()
   170  	defer buffer.Release()
   171  
   172  	if err := buffer.WriteByte(request.Version); err != nil {
   173  		return newError("failed to write response version").Base(err)
   174  	}
   175  
   176  	if err := EncodeHeaderAddons(&buffer, responseAddons); err != nil {
   177  		return newError("failed to encode response header addons").Base(err)
   178  	}
   179  
   180  	if _, err := writer.Write(buffer.Bytes()); err != nil {
   181  		return newError("failed to write response header").Base(err)
   182  	}
   183  
   184  	return nil
   185  }
   186  
   187  // DecodeResponseHeader decodes and returns (if successful) a ResponseHeader from an input stream.
   188  func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*Addons, error) {
   189  	buffer := buf.StackNew()
   190  	defer buffer.Release()
   191  
   192  	if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
   193  		return nil, newError("failed to read response version").Base(err)
   194  	}
   195  
   196  	if buffer.Byte(0) != request.Version {
   197  		return nil, newError("unexpected response version. Expecting ", int(request.Version), " but actually ", int(buffer.Byte(0)))
   198  	}
   199  
   200  	responseAddons, err := DecodeHeaderAddons(&buffer, reader)
   201  	if err != nil {
   202  		return nil, newError("failed to decode response header addons").Base(err)
   203  	}
   204  
   205  	return responseAddons, nil
   206  }
   207  
   208  // XtlsRead filter and read xtls protocol
   209  func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn,
   210  	input *bytes.Reader, rawInput *bytes.Buffer,
   211  	counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, enableXtls *bool,
   212  	isTLS12orAbove *bool, isTLS *bool, cipher *uint16, remainingServerHello *int32,
   213  ) error {
   214  	err := func() error {
   215  		var ct stats.Counter
   216  		withinPaddingBuffers := true
   217  		shouldSwitchToDirectCopy := false
   218  		var remainingContent int32 = -1
   219  		var remainingPadding int32 = -1
   220  		currentCommand := 0
   221  		for {
   222  			if shouldSwitchToDirectCopy {
   223  				shouldSwitchToDirectCopy = false
   224  				if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
   225  					if _, ok := inbound.User.Account.(*vless.MemoryAccount); inbound.User.Account == nil || ok {
   226  						iConn := inbound.Conn
   227  						statConn, ok := iConn.(*stat.CounterConnection)
   228  						if ok {
   229  							iConn = statConn.Connection
   230  						}
   231  						if tlsConn, ok := iConn.(*tls.Conn); ok {
   232  							iConn = tlsConn.NetConn()
   233  						} else if realityConn, ok := iConn.(*reality.Conn); ok {
   234  							iConn = realityConn.NetConn()
   235  						}
   236  						if tc, ok := iConn.(*net.TCPConn); ok {
   237  							newError("XtlsRead splice").WriteToLog(session.ExportIDToError(ctx))
   238  							runtime.Gosched() // necessary
   239  							w, err := tc.ReadFrom(conn)
   240  							if counter != nil {
   241  								counter.Add(w)
   242  							}
   243  							if statConn != nil && statConn.WriteCounter != nil {
   244  								statConn.WriteCounter.Add(w)
   245  							}
   246  							return err
   247  						}
   248  					}
   249  				}
   250  				reader = buf.NewReadVReader(conn, rawConn, nil)
   251  				ct = counter
   252  				newError("XtlsRead readV").WriteToLog(session.ExportIDToError(ctx))
   253  			}
   254  			buffer, err := reader.ReadMultiBuffer()
   255  			if !buffer.IsEmpty() {
   256  				if withinPaddingBuffers || *numberOfPacketToFilter > 0 {
   257  					buffer = XtlsUnpadding(ctx, buffer, userUUID, &remainingContent, &remainingPadding, &currentCommand)
   258  					if remainingContent == 0 && remainingPadding == 0 {
   259  						if currentCommand == 1 {
   260  							withinPaddingBuffers = false
   261  							remainingContent = -1
   262  							remainingPadding = -1 // set to initial state to parse the next padding
   263  						} else if currentCommand == 2 {
   264  							withinPaddingBuffers = false
   265  							shouldSwitchToDirectCopy = true
   266  							// XTLS Vision processes struct TLS Conn's input and rawInput
   267  							if inputBuffer, err := buf.ReadFrom(input); err == nil {
   268  								if !inputBuffer.IsEmpty() {
   269  									buffer, _ = buf.MergeMulti(buffer, inputBuffer)
   270  								}
   271  							}
   272  							if rawInputBuffer, err := buf.ReadFrom(rawInput); err == nil {
   273  								if !rawInputBuffer.IsEmpty() {
   274  									buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
   275  								}
   276  							}
   277  						} else if currentCommand == 0 {
   278  							withinPaddingBuffers = true
   279  						} else {
   280  							newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
   281  						}
   282  					} else if remainingContent > 0 || remainingPadding > 0 {
   283  						withinPaddingBuffers = true
   284  					} else {
   285  						withinPaddingBuffers = false
   286  					}
   287  				}
   288  				if *numberOfPacketToFilter > 0 {
   289  					XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
   290  				}
   291  				if ct != nil {
   292  					ct.Add(int64(buffer.Len()))
   293  				}
   294  				timer.Update()
   295  				if werr := writer.WriteMultiBuffer(buffer); werr != nil {
   296  					return werr
   297  				}
   298  			}
   299  			if err != nil {
   300  				return err
   301  			}
   302  		}
   303  	}()
   304  	if err != nil && errors.Cause(err) != io.EOF {
   305  		return err
   306  	}
   307  	return nil
   308  }
   309  
   310  // XtlsWrite filter and write xtls protocol
   311  func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter,
   312  	ctx context.Context, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
   313  	cipher *uint16, remainingServerHello *int32,
   314  ) error {
   315  	err := func() error {
   316  		var ct stats.Counter
   317  		isPadding := true
   318  		shouldSwitchToDirectCopy := false
   319  		for {
   320  			buffer, err := reader.ReadMultiBuffer()
   321  			if !buffer.IsEmpty() {
   322  				if *numberOfPacketToFilter > 0 {
   323  					XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
   324  				}
   325  				if isPadding {
   326  					buffer = ReshapeMultiBuffer(ctx, buffer)
   327  					var xtlsSpecIndex int
   328  					for i, b := range buffer {
   329  						if *isTLS && b.Len() >= 6 && bytes.Equal(tlsApplicationDataStart, b.BytesTo(3)) {
   330  							var command byte = CommandPaddingEnd
   331  							if *enableXtls {
   332  								shouldSwitchToDirectCopy = true
   333  								xtlsSpecIndex = i
   334  								command = CommandPaddingDirect
   335  							}
   336  							isPadding = false
   337  							buffer[i] = XtlsPadding(b, command, nil, *isTLS, ctx)
   338  							break
   339  						} else if !*isTLS12orAbove && *numberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
   340  							isPadding = false
   341  							buffer[i] = XtlsPadding(b, CommandPaddingEnd, nil, *isTLS, ctx)
   342  							break
   343  						}
   344  						buffer[i] = XtlsPadding(b, CommandPaddingContinue, nil, *isTLS, ctx)
   345  					}
   346  					if shouldSwitchToDirectCopy {
   347  						encryptBuffer, directBuffer := buf.SplitMulti(buffer, xtlsSpecIndex+1)
   348  						length := encryptBuffer.Len()
   349  						if !encryptBuffer.IsEmpty() {
   350  							timer.Update()
   351  							if werr := writer.WriteMultiBuffer(encryptBuffer); werr != nil {
   352  								return werr
   353  							}
   354  						}
   355  						buffer = directBuffer
   356  						writer = buf.NewWriter(conn)
   357  						ct = counter
   358  						newError("XtlsWrite writeV ", xtlsSpecIndex, " ", length, " ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
   359  						time.Sleep(5 * time.Millisecond) // for some device, the first xtls direct packet fails without this delay
   360  					}
   361  				}
   362  				if !buffer.IsEmpty() {
   363  					if ct != nil {
   364  						ct.Add(int64(buffer.Len()))
   365  					}
   366  					timer.Update()
   367  					if werr := writer.WriteMultiBuffer(buffer); werr != nil {
   368  						return werr
   369  					}
   370  				}
   371  			}
   372  			if err != nil {
   373  				return err
   374  			}
   375  		}
   376  	}()
   377  	if err != nil && errors.Cause(err) != io.EOF {
   378  		return err
   379  	}
   380  	return nil
   381  }
   382  
   383  // XtlsFilterTls filter and recognize tls 1.3 and other info
   384  func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
   385  	cipher *uint16, remainingServerHello *int32, ctx context.Context,
   386  ) {
   387  	for _, b := range buffer {
   388  		*numberOfPacketToFilter--
   389  		if b.Len() >= 6 {
   390  			startsBytes := b.BytesTo(6)
   391  			if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == tlsHandshakeTypeServerHello {
   392  				*remainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5
   393  				*isTLS12orAbove = true
   394  				*isTLS = true
   395  				if b.Len() >= 79 && *remainingServerHello >= 79 {
   396  					sessionIdLen := int32(b.Byte(43))
   397  					cipherSuite := b.BytesRange(43+sessionIdLen+1, 43+sessionIdLen+3)
   398  					*cipher = uint16(cipherSuite[0])<<8 | uint16(cipherSuite[1])
   399  				} else {
   400  					newError("XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx))
   401  				}
   402  			} else if bytes.Equal(tlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == tlsHandshakeTypeClientHello {
   403  				*isTLS = true
   404  				newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
   405  			}
   406  		}
   407  		if *remainingServerHello > 0 {
   408  			end := *remainingServerHello
   409  			if end > b.Len() {
   410  				end = b.Len()
   411  			}
   412  			*remainingServerHello -= b.Len()
   413  			if bytes.Contains(b.BytesTo(end), tls13SupportedVersions) {
   414  				v, ok := Tls13CipherSuiteDic[*cipher]
   415  				if !ok {
   416  					v = "Old cipher: " + strconv.FormatUint(uint64(*cipher), 16)
   417  				} else if v != "TLS_AES_128_CCM_8_SHA256" {
   418  					*enableXtls = true
   419  				}
   420  				newError("XtlsFilterTls found tls 1.3! ", b.Len(), " ", v).WriteToLog(session.ExportIDToError(ctx))
   421  				*numberOfPacketToFilter = 0
   422  				return
   423  			} else if *remainingServerHello <= 0 {
   424  				newError("XtlsFilterTls found tls 1.2! ", b.Len()).WriteToLog(session.ExportIDToError(ctx))
   425  				*numberOfPacketToFilter = 0
   426  				return
   427  			}
   428  			newError("XtlsFilterTls inconclusive server hello ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx))
   429  		}
   430  		if *numberOfPacketToFilter <= 0 {
   431  			newError("XtlsFilterTls stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
   432  		}
   433  	}
   434  }
   435  
   436  // ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes)
   437  func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer {
   438  	needReshape := 0
   439  	for _, b := range buffer {
   440  		if b.Len() >= buf.Size-21 {
   441  			needReshape += 1
   442  		}
   443  	}
   444  	if needReshape == 0 {
   445  		return buffer
   446  	}
   447  	mb2 := make(buf.MultiBuffer, 0, len(buffer)+needReshape)
   448  	toPrint := ""
   449  	for i, buffer1 := range buffer {
   450  		if buffer1.Len() >= buf.Size-21 {
   451  			index := int32(bytes.LastIndex(buffer1.Bytes(), tlsApplicationDataStart))
   452  			if index <= 0 || index > buf.Size-21 {
   453  				index = buf.Size / 2
   454  			}
   455  			buffer2 := buf.New()
   456  			buffer2.Write(buffer1.BytesFrom(index))
   457  			buffer1.Resize(0, index)
   458  			mb2 = append(mb2, buffer1, buffer2)
   459  			toPrint += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len()))
   460  		} else {
   461  			mb2 = append(mb2, buffer1)
   462  			toPrint += " " + strconv.Itoa(int(buffer1.Len()))
   463  		}
   464  		buffer[i] = nil
   465  	}
   466  	buffer = buffer[:0]
   467  	newError("ReshapeMultiBuffer ", toPrint).WriteToLog(session.ExportIDToError(ctx))
   468  	return mb2
   469  }
   470  
   471  // XtlsPadding add padding to eliminate length siganature during tls handshake
   472  func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool, ctx context.Context) *buf.Buffer {
   473  	var contentLen int32 = 0
   474  	var paddingLen int32 = 0
   475  	if b != nil {
   476  		contentLen = b.Len()
   477  	}
   478  	if contentLen < 900 && longPadding {
   479  		l, err := rand.Int(rand.Reader, big.NewInt(500))
   480  		if err != nil {
   481  			newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
   482  		}
   483  		paddingLen = int32(l.Int64()) + 900 - contentLen
   484  	} else {
   485  		l, err := rand.Int(rand.Reader, big.NewInt(256))
   486  		if err != nil {
   487  			newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
   488  		}
   489  		paddingLen = int32(l.Int64())
   490  	}
   491  	if paddingLen > buf.Size-21-contentLen {
   492  		paddingLen = buf.Size - 21 - contentLen
   493  	}
   494  	newbuffer := buf.New()
   495  	if userUUID != nil {
   496  		newbuffer.Write(*userUUID)
   497  		*userUUID = nil
   498  	}
   499  	newbuffer.Write([]byte{command, byte(contentLen >> 8), byte(contentLen), byte(paddingLen >> 8), byte(paddingLen)})
   500  	if b != nil {
   501  		newbuffer.Write(b.Bytes())
   502  		b.Release()
   503  		b = nil
   504  	}
   505  	newbuffer.Extend(paddingLen)
   506  	newError("XtlsPadding ", contentLen, " ", paddingLen, " ", command).WriteToLog(session.ExportIDToError(ctx))
   507  	return newbuffer
   508  }
   509  
   510  // XtlsUnpadding remove padding and parse command
   511  func XtlsUnpadding(ctx context.Context, buffer buf.MultiBuffer, userUUID []byte, remainingContent *int32, remainingPadding *int32, currentCommand *int) buf.MultiBuffer {
   512  	posindex := 0
   513  	var posByte int32 = 0
   514  	if *remainingContent == -1 && *remainingPadding == -1 {
   515  		for i, b := range buffer {
   516  			if b.Len() >= 21 && bytes.Equal(userUUID, b.BytesTo(16)) {
   517  				posindex = i
   518  				posByte = 16
   519  				*remainingContent = 0
   520  				*remainingPadding = 0
   521  				*currentCommand = 0
   522  				break
   523  			}
   524  		}
   525  	}
   526  	if *remainingContent == -1 && *remainingPadding == -1 {
   527  		return buffer
   528  	}
   529  	mb2 := make(buf.MultiBuffer, 0, len(buffer))
   530  	for i := 0; i < posindex; i++ {
   531  		newbuffer := buf.New()
   532  		newbuffer.Write(buffer[i].Bytes())
   533  		mb2 = append(mb2, newbuffer)
   534  	}
   535  	for i := posindex; i < len(buffer); i++ {
   536  		b := buffer[i]
   537  		for posByte < b.Len() {
   538  			if *remainingContent <= 0 && *remainingPadding <= 0 {
   539  				if *currentCommand == 1 { // possible buffer after padding, no need to worry about xtls (command 2)
   540  					len := b.Len() - posByte
   541  					newbuffer := buf.New()
   542  					newbuffer.Write(b.BytesRange(posByte, posByte+len))
   543  					mb2 = append(mb2, newbuffer)
   544  					posByte += len
   545  				} else {
   546  					paddingInfo := b.BytesRange(posByte, posByte+5)
   547  					*currentCommand = int(paddingInfo[0])
   548  					*remainingContent = int32(paddingInfo[1])<<8 | int32(paddingInfo[2])
   549  					*remainingPadding = int32(paddingInfo[3])<<8 | int32(paddingInfo[4])
   550  					newError("Xtls Unpadding new block", i, " ", posByte, " content ", *remainingContent, " padding ", *remainingPadding, " ", paddingInfo[0]).WriteToLog(session.ExportIDToError(ctx))
   551  					posByte += 5
   552  				}
   553  			} else if *remainingContent > 0 {
   554  				len := *remainingContent
   555  				if b.Len() < posByte+*remainingContent {
   556  					len = b.Len() - posByte
   557  				}
   558  				newbuffer := buf.New()
   559  				newbuffer.Write(b.BytesRange(posByte, posByte+len))
   560  				mb2 = append(mb2, newbuffer)
   561  				*remainingContent -= len
   562  				posByte += len
   563  			} else { // remainingPadding > 0
   564  				len := *remainingPadding
   565  				if b.Len() < posByte+*remainingPadding {
   566  					len = b.Len() - posByte
   567  				}
   568  				*remainingPadding -= len
   569  				posByte += len
   570  			}
   571  			if posByte == b.Len() {
   572  				posByte = 0
   573  				break
   574  			}
   575  		}
   576  	}
   577  	buf.ReleaseMulti(buffer)
   578  	return mb2
   579  }