mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-12-27 04:25:44 -05:00
rewrite vmess encoding using buf
This commit is contained in:
@@ -71,57 +71,61 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
|
||||
common.Must2(idHash.Write(timestamp.Bytes(nil)))
|
||||
common.Must2(writer.Write(idHash.Sum(nil)))
|
||||
|
||||
buffer := make([]byte, 0, 512)
|
||||
buffer = append(buffer, Version)
|
||||
buffer = append(buffer, c.requestBodyIV...)
|
||||
buffer = append(buffer, c.requestBodyKey...)
|
||||
buffer = append(buffer, c.responseHeader, byte(header.Option))
|
||||
buffer := buf.New()
|
||||
defer buffer.Release()
|
||||
|
||||
buffer.AppendBytes(Version)
|
||||
buffer.Append(c.requestBodyIV)
|
||||
buffer.Append(c.requestBodyKey)
|
||||
buffer.AppendBytes(c.responseHeader, byte(header.Option))
|
||||
|
||||
padingLen := dice.Roll(16)
|
||||
if header.Security.Is(protocol.SecurityType_LEGACY) {
|
||||
// Disable padding in legacy mode for a smooth transition.
|
||||
padingLen = 0
|
||||
}
|
||||
security := byte(padingLen<<4) | byte(header.Security)
|
||||
buffer = append(buffer, security, byte(0), byte(header.Command))
|
||||
buffer.AppendBytes(security, byte(0), byte(header.Command))
|
||||
|
||||
if header.Command != protocol.RequestCommandMux {
|
||||
buffer = header.Port.Bytes(buffer)
|
||||
common.Must(buffer.AppendSupplier(serial.WriteUint16(header.Port.Value())))
|
||||
|
||||
switch header.Address.Family() {
|
||||
case net.AddressFamilyIPv4:
|
||||
buffer = append(buffer, byte(protocol.AddressTypeIPv4))
|
||||
buffer = append(buffer, header.Address.IP()...)
|
||||
buffer.AppendBytes(byte(protocol.AddressTypeIPv4))
|
||||
buffer.Append(header.Address.IP())
|
||||
case net.AddressFamilyIPv6:
|
||||
buffer = append(buffer, byte(protocol.AddressTypeIPv6))
|
||||
buffer = append(buffer, header.Address.IP()...)
|
||||
buffer.AppendBytes(byte(protocol.AddressTypeIPv6))
|
||||
buffer.Append(header.Address.IP())
|
||||
case net.AddressFamilyDomain:
|
||||
domain := header.Address.Domain()
|
||||
if protocol.IsDomainTooLong(domain) {
|
||||
return newError("long domain not supported: ", domain)
|
||||
}
|
||||
nDomain := len(domain)
|
||||
buffer = append(buffer, byte(protocol.AddressTypeDomain), byte(nDomain))
|
||||
buffer = append(buffer, domain...)
|
||||
buffer.AppendBytes(byte(protocol.AddressTypeDomain), byte(nDomain))
|
||||
common.Must(buffer.AppendSupplier(serial.WriteString(domain)))
|
||||
}
|
||||
}
|
||||
|
||||
if padingLen > 0 {
|
||||
pading := make([]byte, padingLen)
|
||||
common.Must2(rand.Read(pading))
|
||||
buffer = append(buffer, pading...)
|
||||
common.Must(buffer.AppendSupplier(buf.ReadFullFrom(rand.Reader, padingLen)))
|
||||
}
|
||||
|
||||
fnv1a := fnv.New32a()
|
||||
common.Must2(fnv1a.Write(buffer))
|
||||
common.Must2(fnv1a.Write(buffer.Bytes()))
|
||||
|
||||
buffer = fnv1a.Sum(buffer)
|
||||
common.Must(buffer.AppendSupplier(func(b []byte) (int, error) {
|
||||
fnv1a.Sum(b[:0])
|
||||
return fnv1a.Size(), nil
|
||||
}))
|
||||
|
||||
timestampHash := md5.New()
|
||||
common.Must2(timestampHash.Write(hashTimestamp(timestamp)))
|
||||
iv := timestampHash.Sum(nil)
|
||||
aesStream := crypto.NewAesEncryptionStream(account.(*vmess.InternalAccount).ID.CmdKey(), iv)
|
||||
aesStream.XORKeyStream(buffer, buffer)
|
||||
common.Must2(writer.Write(buffer))
|
||||
aesStream.XORKeyStream(buffer.Bytes(), buffer.Bytes())
|
||||
common.Must2(writer.Write(buffer.Bytes()))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -197,32 +201,31 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
|
||||
aesStream := crypto.NewAesDecryptionStream(c.responseBodyKey, c.responseBodyIV)
|
||||
c.responseReader = crypto.NewCryptionReader(aesStream, reader)
|
||||
|
||||
buffer := make([]byte, 256)
|
||||
buffer := buf.New()
|
||||
defer buffer.Release()
|
||||
|
||||
_, err := io.ReadFull(c.responseReader, buffer[:4])
|
||||
if err != nil {
|
||||
if err := buffer.AppendSupplier(buf.ReadFullFrom(c.responseReader, 4)); err != nil {
|
||||
log.Trace(newError("failed to read response header").Base(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if buffer[0] != c.responseHeader {
|
||||
return nil, newError("unexpected response header. Expecting ", int(c.responseHeader), " but actually ", int(buffer[0]))
|
||||
if buffer.Byte(0) != c.responseHeader {
|
||||
return nil, newError("unexpected response header. Expecting ", int(c.responseHeader), " but actually ", int(buffer.Byte(0)))
|
||||
}
|
||||
|
||||
header := &protocol.ResponseHeader{
|
||||
Option: bitmask.Byte(buffer[1]),
|
||||
Option: bitmask.Byte(buffer.Byte(1)),
|
||||
}
|
||||
|
||||
if buffer[2] != 0 {
|
||||
cmdID := buffer[2]
|
||||
dataLen := int(buffer[3])
|
||||
_, err := io.ReadFull(c.responseReader, buffer[:dataLen])
|
||||
if err != nil {
|
||||
if buffer.Byte(2) != 0 {
|
||||
cmdID := buffer.Byte(2)
|
||||
dataLen := int(buffer.Byte(3))
|
||||
|
||||
if err := buffer.Reset(buf.ReadFullFrom(c.responseReader, dataLen)); err != nil {
|
||||
log.Trace(newError("failed to read response command").Base(err))
|
||||
return nil, err
|
||||
}
|
||||
data := buffer[:dataLen]
|
||||
command, err := UnmarshalCommand(cmdID, data)
|
||||
command, err := UnmarshalCommand(cmdID, buffer.Bytes())
|
||||
if err == nil {
|
||||
header.Command = command
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user