|  | @@ -7,6 +7,7 @@ import (
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/buf"
 | 
	
		
			
				|  |  | +	"v2ray.com/core/common/bytespool"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/protocol"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -122,62 +123,85 @@ func (r *AuthenticationReader) readSize() (uint16, uint16, error) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  var errSoft = newError("waiting for more data")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (r *AuthenticationReader) readInternal(soft bool) (*buf.Buffer, error) {
 | 
	
		
			
				|  |  | +func (r *AuthenticationReader) readBuffer(size int32, padding int32) (*buf.Buffer, error) {
 | 
	
		
			
				|  |  | +	b := buf.New()
 | 
	
		
			
				|  |  | +	if err := b.Reset(buf.ReadFullFrom(r.reader, size)); err != nil {
 | 
	
		
			
				|  |  | +		b.Release()
 | 
	
		
			
				|  |  | +		return nil, err
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	size -= padding
 | 
	
		
			
				|  |  | +	rb, err := r.auth.Open(b.BytesTo(0), b.BytesTo(size))
 | 
	
		
			
				|  |  | +	if err != nil {
 | 
	
		
			
				|  |  | +		b.Release()
 | 
	
		
			
				|  |  | +		return nil, err
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	b.Resize(0, int32(len(rb)))
 | 
	
		
			
				|  |  | +	return b, nil
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (r *AuthenticationReader) readInternal(soft bool, mb *buf.MultiBuffer) error {
 | 
	
		
			
				|  |  |  	if soft && r.reader.BufferedBytes() < r.sizeParser.SizeBytes() {
 | 
	
		
			
				|  |  | -		return nil, errSoft
 | 
	
		
			
				|  |  | +		return errSoft
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if r.done {
 | 
	
		
			
				|  |  | -		return nil, io.EOF
 | 
	
		
			
				|  |  | +		return io.EOF
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	size, padding, err := r.readSize()
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | +		return err
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if size == uint16(r.auth.Overhead())+padding {
 | 
	
		
			
				|  |  |  		r.done = true
 | 
	
		
			
				|  |  | -		return nil, io.EOF
 | 
	
		
			
				|  |  | +		return io.EOF
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if soft && int32(size) > r.reader.BufferedBytes() {
 | 
	
		
			
				|  |  |  		r.size = size
 | 
	
		
			
				|  |  |  		r.paddingLen = padding
 | 
	
		
			
				|  |  |  		r.hasSize = true
 | 
	
		
			
				|  |  | -		return nil, errSoft
 | 
	
		
			
				|  |  | +		return errSoft
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	b := buf.NewSize(int32(size))
 | 
	
		
			
				|  |  | -	if err := b.Reset(buf.ReadFullFrom(r.reader, int32(size))); err != nil {
 | 
	
		
			
				|  |  | -		b.Release()
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | +	if size <= buf.Size {
 | 
	
		
			
				|  |  | +		b, err := r.readBuffer(int32(size), int32(padding))
 | 
	
		
			
				|  |  | +		if err != nil {
 | 
	
		
			
				|  |  | +			return nil
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		mb.Append(b)
 | 
	
		
			
				|  |  | +		return nil
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	payload := bytespool.Alloc(int32(size))
 | 
	
		
			
				|  |  | +	defer bytespool.Free(payload)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if _, err := io.ReadFull(r.reader, payload[:size]); err != nil {
 | 
	
		
			
				|  |  | +		return err
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	size -= padding
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	rb, err := r.auth.Open(b.BytesTo(0), b.BytesTo(int32(size)))
 | 
	
		
			
				|  |  | +	rb, err := r.auth.Open(payload[:0], payload[:size])
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  | -		b.Release()
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | +		return err
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	b.Resize(0, int32(len(rb)))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	return b, nil
 | 
	
		
			
				|  |  | +	common.Must2(mb.Write(rb))
 | 
	
		
			
				|  |  | +	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
 | 
	
		
			
				|  |  | -	b, err := r.readInternal(false)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	const readSize = 16
 | 
	
		
			
				|  |  |  	mb := buf.NewMultiBufferCap(readSize)
 | 
	
		
			
				|  |  | -	mb.Append(b)
 | 
	
		
			
				|  |  | +	if err := r.readInternal(false, &mb); err != nil {
 | 
	
		
			
				|  |  | +		mb.Release()
 | 
	
		
			
				|  |  | +		return nil, err
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	for i := 1; i < readSize; i++ {
 | 
	
		
			
				|  |  | -		b, err := r.readInternal(true)
 | 
	
		
			
				|  |  | +		err := r.readInternal(true, &mb)
 | 
	
		
			
				|  |  |  		if err == errSoft || err == io.EOF {
 | 
	
		
			
				|  |  |  			break
 | 
	
		
			
				|  |  |  		}
 | 
	
	
		
			
				|  | @@ -185,7 +209,6 @@ func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
 | 
	
		
			
				|  |  |  			mb.Release()
 | 
	
		
			
				|  |  |  			return nil, err
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		mb.Append(b)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return mb, nil
 |