| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 | 
							- package io
 
- import (
 
- 	"errors"
 
- 	"hash"
 
- 	"hash/fnv"
 
- 	"io"
 
- 	"v2ray.com/core/common/alloc"
 
- 	"v2ray.com/core/common/serial"
 
- )
 
- // Private: Visible for testing.
 
- type Validator struct {
 
- 	actualAuth   hash.Hash32
 
- 	expectedAuth uint32
 
- }
 
- func NewValidator(expectedAuth uint32) *Validator {
 
- 	return &Validator{
 
- 		actualAuth:   fnv.New32a(),
 
- 		expectedAuth: expectedAuth,
 
- 	}
 
- }
 
- func (this *Validator) Consume(b []byte) {
 
- 	this.actualAuth.Write(b)
 
- }
 
- func (this *Validator) Validate() bool {
 
- 	return this.actualAuth.Sum32() == this.expectedAuth
 
- }
 
- type AuthChunkReader struct {
 
- 	reader      io.Reader
 
- 	last        *alloc.Buffer
 
- 	chunkLength int
 
- 	validator   *Validator
 
- }
 
- func NewAuthChunkReader(reader io.Reader) *AuthChunkReader {
 
- 	return &AuthChunkReader{
 
- 		reader:      reader,
 
- 		chunkLength: -1,
 
- 	}
 
- }
 
- func (this *AuthChunkReader) Read() (*alloc.Buffer, error) {
 
- 	var buffer *alloc.Buffer
 
- 	if this.last != nil {
 
- 		buffer = this.last
 
- 		this.last = nil
 
- 	} else {
 
- 		buffer = alloc.NewBuffer().Clear()
 
- 	}
 
- 	if this.chunkLength == -1 {
 
- 		for buffer.Len() < 6 {
 
- 			_, err := buffer.FillFrom(this.reader)
 
- 			if err != nil {
 
- 				buffer.Release()
 
- 				return nil, io.ErrUnexpectedEOF
 
- 			}
 
- 		}
 
- 		length := serial.BytesToUint16(buffer.Value[:2])
 
- 		this.chunkLength = int(length) - 4
 
- 		this.validator = NewValidator(serial.BytesToUint32(buffer.Value[2:6]))
 
- 		buffer.SliceFrom(6)
 
- 		if buffer.Len() < this.chunkLength && this.chunkLength <= 2048 {
 
- 			_, err := buffer.FillFrom(this.reader)
 
- 			if err != nil {
 
- 				buffer.Release()
 
- 				return nil, io.ErrUnexpectedEOF
 
- 			}
 
- 		}
 
- 	} else if buffer.Len() < this.chunkLength {
 
- 		_, err := buffer.FillFrom(this.reader)
 
- 		if err != nil {
 
- 			buffer.Release()
 
- 			return nil, io.ErrUnexpectedEOF
 
- 		}
 
- 	}
 
- 	if this.chunkLength == 0 {
 
- 		buffer.Release()
 
- 		return nil, io.EOF
 
- 	}
 
- 	if buffer.Len() < this.chunkLength {
 
- 		this.validator.Consume(buffer.Value)
 
- 		this.chunkLength -= buffer.Len()
 
- 	} else {
 
- 		this.validator.Consume(buffer.Value[:this.chunkLength])
 
- 		if !this.validator.Validate() {
 
- 			buffer.Release()
 
- 			return nil, errors.New("VMess|AuthChunkReader: Invalid auth.")
 
- 		}
 
- 		leftLength := buffer.Len() - this.chunkLength
 
- 		if leftLength > 0 {
 
- 			this.last = alloc.NewBuffer().Clear()
 
- 			this.last.Append(buffer.Value[this.chunkLength:])
 
- 			buffer.Slice(0, this.chunkLength)
 
- 		}
 
- 		this.chunkLength = -1
 
- 		this.validator = nil
 
- 	}
 
- 	return buffer, nil
 
- }
 
- func (this *AuthChunkReader) Release() {
 
- 	this.reader = nil
 
- 	this.last.Release()
 
- 	this.last = nil
 
- 	this.validator = nil
 
- }
 
 
  |