reader.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package io
  2. import (
  3. "hash"
  4. "hash/fnv"
  5. "io"
  6. "github.com/v2ray/v2ray-core/common/alloc"
  7. "github.com/v2ray/v2ray-core/common/serial"
  8. "github.com/v2ray/v2ray-core/transport"
  9. )
  10. // @Private
  11. type Validator struct {
  12. actualAuth hash.Hash32
  13. expectedAuth uint32
  14. }
  15. func NewValidator(expectedAuth uint32) *Validator {
  16. return &Validator{
  17. actualAuth: fnv.New32a(),
  18. expectedAuth: expectedAuth,
  19. }
  20. }
  21. func (this *Validator) Consume(b []byte) {
  22. this.actualAuth.Write(b)
  23. }
  24. func (this *Validator) Validate() bool {
  25. return this.actualAuth.Sum32() == this.expectedAuth
  26. }
  27. type AuthChunkReader struct {
  28. reader io.Reader
  29. last *alloc.Buffer
  30. chunkLength int
  31. validator *Validator
  32. }
  33. func NewAuthChunkReader(reader io.Reader) *AuthChunkReader {
  34. return &AuthChunkReader{
  35. reader: reader,
  36. chunkLength: -1,
  37. }
  38. }
  39. func (this *AuthChunkReader) Read() (*alloc.Buffer, error) {
  40. var buffer *alloc.Buffer
  41. if this.last != nil {
  42. buffer = this.last
  43. this.last = nil
  44. } else {
  45. buffer = alloc.NewBufferWithSize(4096).Clear()
  46. }
  47. if this.chunkLength == -1 {
  48. for buffer.Len() < 6 {
  49. _, err := buffer.FillFrom(this.reader)
  50. if err != nil {
  51. buffer.Release()
  52. return nil, io.ErrUnexpectedEOF
  53. }
  54. }
  55. length := serial.BytesToUint16(buffer.Value[:2])
  56. this.chunkLength = int(length) - 4
  57. this.validator = NewValidator(serial.BytesToUint32(buffer.Value[2:6]))
  58. buffer.SliceFrom(6)
  59. } else if buffer.Len() < this.chunkLength {
  60. _, err := buffer.FillFrom(this.reader)
  61. if err != nil {
  62. buffer.Release()
  63. return nil, io.ErrUnexpectedEOF
  64. }
  65. }
  66. if this.chunkLength == 0 {
  67. buffer.Release()
  68. return nil, io.EOF
  69. }
  70. if buffer.Len() < this.chunkLength {
  71. this.validator.Consume(buffer.Value)
  72. this.chunkLength -= buffer.Len()
  73. } else {
  74. this.validator.Consume(buffer.Value[:this.chunkLength])
  75. if !this.validator.Validate() {
  76. buffer.Release()
  77. return nil, transport.ErrCorruptedPacket
  78. }
  79. leftLength := buffer.Len() - this.chunkLength
  80. if leftLength > 0 {
  81. this.last = alloc.NewBufferWithSize(leftLength + 4096).Clear()
  82. this.last.Append(buffer.Value[this.chunkLength:])
  83. buffer.Slice(0, this.chunkLength)
  84. }
  85. this.chunkLength = -1
  86. this.validator = nil
  87. }
  88. return buffer, nil
  89. }
  90. func (this *AuthChunkReader) Release() {
  91. this.reader = nil
  92. this.last.Release()
  93. this.last = nil
  94. this.validator = nil
  95. }