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