reader.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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 {
  28. buffer.Release()
  29. buffer = alloc.NewLargeBuffer()
  30. }
  31. buffer.SliceBack(16)
  32. if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil {
  33. buffer.Release()
  34. return nil, err
  35. }
  36. buffer.Slice(0, int(length))
  37. fnvHash := fnv.New32a()
  38. fnvHash.Write(buffer.Value[4:])
  39. expAuth := serial.BytesLiteral(fnvHash.Sum(nil))
  40. actualAuth := serial.BytesLiteral(buffer.Value[:4])
  41. if !actualAuth.Equals(expAuth) {
  42. buffer.Release()
  43. return nil, transport.ErrorCorruptedPacket
  44. }
  45. buffer.SliceFrom(4)
  46. return buffer, nil
  47. }
  48. func (this *AuthChunkReader) Release() {
  49. this.reader = nil
  50. }