|  | @@ -8,7 +8,6 @@ import (
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/bitmask"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/buf"
 | 
	
		
			
				|  |  | -	"v2ray.com/core/common/crypto"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/net"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/protocol"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/serial"
 | 
	
	
		
			
				|  | @@ -40,11 +39,11 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	iv := append([]byte(nil), buffer.BytesTo(ivLen)...)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	stream, err := account.Cipher.NewDecodingStream(account.Key, iv)
 | 
	
		
			
				|  |  | +	r, err := account.Cipher.NewDecryptionReader(account.Key, iv, reader)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError()
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	reader = crypto.NewCryptionReader(stream, reader)
 | 
	
		
			
				|  |  | +	reader = r.(io.Reader)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv))
 | 
	
		
			
				|  |  |  	request := &protocol.RequestHeader{
 | 
	
	
		
			
				|  | @@ -144,12 +143,12 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
 | 
	
		
			
				|  |  |  		return nil, newError("failed to write IV")
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	stream, err := account.Cipher.NewEncodingStream(account.Key, iv)
 | 
	
		
			
				|  |  | +	w, err := account.Cipher.NewEncryptionWriter(account.Key, iv, writer)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return nil, newError("failed to create encoding stream").Base(err).AtError()
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	writer = crypto.NewCryptionWriter(stream, writer)
 | 
	
		
			
				|  |  | +	writer = w.(io.Writer)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	header := buf.NewLocal(512)
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -208,11 +207,7 @@ func ReadTCPResponse(user *protocol.User, reader io.Reader) (buf.Reader, error)
 | 
	
		
			
				|  |  |  		return nil, newError("failed to read IV").Base(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	stream, err := account.Cipher.NewDecodingStream(account.Key, iv)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, newError("failed to initialize decoding stream").Base(err).AtError()
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return buf.NewReader(crypto.NewCryptionReader(stream, reader)), nil
 | 
	
		
			
				|  |  | +	return account.Cipher.NewDecryptionReader(account.Key, iv, reader)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
 | 
	
	
		
			
				|  | @@ -230,12 +225,7 @@ func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Wr
 | 
	
		
			
				|  |  |  		return nil, newError("failed to write IV.").Base(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	stream, err := account.Cipher.NewEncodingStream(account.Key, iv)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, newError("failed to create encoding stream.").Base(err).AtError()
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	return buf.NewWriter(crypto.NewCryptionWriter(stream, writer)), nil
 | 
	
		
			
				|  |  | +	return account.Cipher.NewEncryptionWriter(account.Key, iv, writer)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buffer, error) {
 | 
	
	
		
			
				|  | @@ -251,36 +241,41 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff
 | 
	
		
			
				|  |  |  	buffer.AppendSupplier(buf.ReadFullFrom(rand.Reader, ivLen))
 | 
	
		
			
				|  |  |  	iv := buffer.Bytes()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	payloadBuffer := buf.NewLocal(512)
 | 
	
		
			
				|  |  | +	defer payloadBuffer.Release()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	switch request.Address.Family() {
 | 
	
		
			
				|  |  |  	case net.AddressFamilyIPv4:
 | 
	
		
			
				|  |  | -		buffer.AppendBytes(AddrTypeIPv4)
 | 
	
		
			
				|  |  | -		buffer.Append([]byte(request.Address.IP()))
 | 
	
		
			
				|  |  | +		payloadBuffer.AppendBytes(AddrTypeIPv4)
 | 
	
		
			
				|  |  | +		payloadBuffer.Append([]byte(request.Address.IP()))
 | 
	
		
			
				|  |  |  	case net.AddressFamilyIPv6:
 | 
	
		
			
				|  |  | -		buffer.AppendBytes(AddrTypeIPv6)
 | 
	
		
			
				|  |  | -		buffer.Append([]byte(request.Address.IP()))
 | 
	
		
			
				|  |  | +		payloadBuffer.AppendBytes(AddrTypeIPv6)
 | 
	
		
			
				|  |  | +		payloadBuffer.Append([]byte(request.Address.IP()))
 | 
	
		
			
				|  |  |  	case net.AddressFamilyDomain:
 | 
	
		
			
				|  |  | -		buffer.AppendBytes(AddrTypeDomain, byte(len(request.Address.Domain())))
 | 
	
		
			
				|  |  | -		buffer.Append([]byte(request.Address.Domain()))
 | 
	
		
			
				|  |  | +		payloadBuffer.AppendBytes(AddrTypeDomain, byte(len(request.Address.Domain())))
 | 
	
		
			
				|  |  | +		payloadBuffer.Append([]byte(request.Address.Domain()))
 | 
	
		
			
				|  |  |  	default:
 | 
	
		
			
				|  |  |  		return nil, newError("unsupported address type: ", request.Address.Family()).AtError()
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	buffer.AppendSupplier(serial.WriteUint16(uint16(request.Port)))
 | 
	
		
			
				|  |  | -	buffer.Append(payload)
 | 
	
		
			
				|  |  | +	payloadBuffer.AppendSupplier(serial.WriteUint16(uint16(request.Port)))
 | 
	
		
			
				|  |  | +	payloadBuffer.Append(payload)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if request.Option.Has(RequestOptionOneTimeAuth) {
 | 
	
		
			
				|  |  |  		authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv))
 | 
	
		
			
				|  |  | -		buffer.SetByte(ivLen, buffer.Byte(ivLen)|0x10)
 | 
	
		
			
				|  |  | +		payloadBuffer.SetByte(0, payloadBuffer.Byte(0)|0x10)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		buffer.AppendSupplier(authenticator.Authenticate(buffer.BytesFrom(ivLen)))
 | 
	
		
			
				|  |  | +		payloadBuffer.AppendSupplier(authenticator.Authenticate(payloadBuffer.Bytes()))
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	stream, err := account.Cipher.NewEncodingStream(account.Key, iv)
 | 
	
		
			
				|  |  | +	w, err := account.Cipher.NewEncryptionWriter(account.Key, iv, buffer)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return nil, newError("failed to create encoding stream").Base(err).AtError()
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	if err := w.WriteMultiBuffer(buf.NewMultiBufferValue(payloadBuffer)); err != nil {
 | 
	
		
			
				|  |  | +		return nil, newError("failed to encrypt UDP payload").Base(err).AtWarning()
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	stream.XORKeyStream(buffer.BytesFrom(ivLen), buffer.BytesFrom(ivLen))
 | 
	
		
			
				|  |  |  	return buffer, nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -295,11 +290,17 @@ func DecodeUDPPacket(user *protocol.User, payload *buf.Buffer) (*protocol.Reques
 | 
	
		
			
				|  |  |  	iv := payload.BytesTo(ivLen)
 | 
	
		
			
				|  |  |  	payload.SliceFrom(ivLen)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	stream, err := account.Cipher.NewDecodingStream(account.Key, iv)
 | 
	
		
			
				|  |  | +	r, err := account.Cipher.NewDecryptionReader(account.Key, iv, payload)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError()
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	stream.XORKeyStream(payload.Bytes(), payload.Bytes())
 | 
	
		
			
				|  |  | +	mb, err := r.ReadMultiBuffer()
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		return nil, nil, newError("failed to decrypt UDP payload").Base(err).AtWarning()
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	payload.Release()
 | 
	
		
			
				|  |  | +	payload = mb.SplitFirst()
 | 
	
		
			
				|  |  | +	mb.Release()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv))
 | 
	
		
			
				|  |  |  	request := &protocol.RequestHeader{
 |