reader.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package io
  2. import (
  3. "hash/fnv"
  4. "io"
  5. "github.com/v2ray/v2ray-core/common/alloc"
  6. "github.com/v2ray/v2ray-core/common/serial"
  7. "github.com/v2ray/v2ray-core/transport"
  8. )
  9. type AuthChunkReader struct {
  10. reader io.Reader
  11. }
  12. func NewAuthChunkReader(reader io.Reader) *AuthChunkReader {
  13. return &AuthChunkReader{
  14. reader: reader,
  15. }
  16. }
  17. func (this *AuthChunkReader) Read() (*alloc.Buffer, error) {
  18. buffer := alloc.NewBuffer()
  19. if _, err := io.ReadFull(this.reader, buffer.Value[:2]); err != nil {
  20. buffer.Release()
  21. return nil, err
  22. }
  23. length := serial.BytesLiteral(buffer.Value[:2]).Uint16Value()
  24. if length <= 4 { // Length of authentication bytes.
  25. return nil, io.EOF
  26. }
  27. if length > 8*1024-16 {
  28. buffer.Release()
  29. buffer = alloc.NewLargeBuffer()
  30. }
  31. if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil {
  32. buffer.Release()
  33. return nil, err
  34. }
  35. buffer.Slice(0, int(length))
  36. fnvHash := fnv.New32a()
  37. fnvHash.Write(buffer.Value[4:])
  38. expAuth := serial.BytesLiteral(fnvHash.Sum(nil))
  39. actualAuth := serial.BytesLiteral(buffer.Value[:4])
  40. if !actualAuth.Equals(expAuth) {
  41. buffer.Release()
  42. return nil, transport.ErrorCorruptedPacket
  43. }
  44. buffer.SliceFrom(4)
  45. return buffer, nil
  46. }
  47. func (this *AuthChunkReader) Release() {
  48. this.reader = nil
  49. }