chunk.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package crypto
  2. import (
  3. "encoding/binary"
  4. "io"
  5. "github.com/v2fly/v2ray-core/v5/common"
  6. "github.com/v2fly/v2ray-core/v5/common/buf"
  7. )
  8. // ChunkSizeDecoder is a utility class to decode size value from bytes.
  9. type ChunkSizeDecoder interface {
  10. // SizeBytes must be stable, return the same value across all calls
  11. SizeBytes() int32
  12. Decode([]byte) (uint16, error)
  13. }
  14. type ChunkSizeDecoderWithOffset interface {
  15. ChunkSizeDecoder
  16. // HasConstantOffset set the constant offset of Decode
  17. // The effective size should be HasConstantOffset() + Decode(_).[0](uint64)
  18. HasConstantOffset() uint16
  19. }
  20. // ChunkSizeEncoder is a utility class to encode size value into bytes.
  21. type ChunkSizeEncoder interface {
  22. SizeBytes() int32
  23. Encode(uint16, []byte) []byte
  24. }
  25. type PaddingLengthGenerator interface {
  26. MaxPaddingLen() uint16
  27. NextPaddingLen() uint16
  28. }
  29. type PlainChunkSizeParser struct{}
  30. func (PlainChunkSizeParser) SizeBytes() int32 {
  31. return 2
  32. }
  33. func (PlainChunkSizeParser) Encode(size uint16, b []byte) []byte {
  34. binary.BigEndian.PutUint16(b, size)
  35. return b[:2]
  36. }
  37. func (PlainChunkSizeParser) Decode(b []byte) (uint16, error) {
  38. return binary.BigEndian.Uint16(b), nil
  39. }
  40. type AEADChunkSizeParser struct {
  41. Auth *AEADAuthenticator
  42. }
  43. func (p *AEADChunkSizeParser) SizeBytes() int32 {
  44. return 2 + int32(p.Auth.Overhead())
  45. }
  46. func (p *AEADChunkSizeParser) Encode(size uint16, b []byte) []byte {
  47. binary.BigEndian.PutUint16(b, size-uint16(p.Auth.Overhead()))
  48. b, err := p.Auth.Seal(b[:0], b[:2])
  49. common.Must(err)
  50. return b
  51. }
  52. func (p *AEADChunkSizeParser) Decode(b []byte) (uint16, error) {
  53. b, err := p.Auth.Open(b[:0], b)
  54. if err != nil {
  55. return 0, err
  56. }
  57. return binary.BigEndian.Uint16(b) + uint16(p.Auth.Overhead()), nil
  58. }
  59. type ChunkStreamReader struct {
  60. sizeDecoder ChunkSizeDecoder
  61. reader *buf.BufferedReader
  62. buffer []byte
  63. leftOverSize int32
  64. maxNumChunk uint32
  65. numChunk uint32
  66. }
  67. func NewChunkStreamReader(sizeDecoder ChunkSizeDecoder, reader io.Reader) *ChunkStreamReader {
  68. return NewChunkStreamReaderWithChunkCount(sizeDecoder, reader, 0)
  69. }
  70. func NewChunkStreamReaderWithChunkCount(sizeDecoder ChunkSizeDecoder, reader io.Reader, maxNumChunk uint32) *ChunkStreamReader {
  71. r := &ChunkStreamReader{
  72. sizeDecoder: sizeDecoder,
  73. buffer: make([]byte, sizeDecoder.SizeBytes()),
  74. maxNumChunk: maxNumChunk,
  75. }
  76. if breader, ok := reader.(*buf.BufferedReader); ok {
  77. r.reader = breader
  78. } else {
  79. r.reader = &buf.BufferedReader{Reader: buf.NewReader(reader)}
  80. }
  81. return r
  82. }
  83. func (r *ChunkStreamReader) readSize() (uint16, error) {
  84. if _, err := io.ReadFull(r.reader, r.buffer); err != nil {
  85. return 0, err
  86. }
  87. return r.sizeDecoder.Decode(r.buffer)
  88. }
  89. func (r *ChunkStreamReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
  90. size := r.leftOverSize
  91. if size == 0 {
  92. r.numChunk++
  93. if r.maxNumChunk > 0 && r.numChunk > r.maxNumChunk {
  94. return nil, io.EOF
  95. }
  96. nextSize, err := r.readSize()
  97. if err != nil {
  98. return nil, err
  99. }
  100. if nextSize == 0 {
  101. return nil, io.EOF
  102. }
  103. size = int32(nextSize)
  104. }
  105. r.leftOverSize = size
  106. mb, err := r.reader.ReadAtMost(size)
  107. if !mb.IsEmpty() {
  108. r.leftOverSize -= mb.Len()
  109. return mb, nil
  110. }
  111. return nil, err
  112. }
  113. type ChunkStreamWriter struct {
  114. sizeEncoder ChunkSizeEncoder
  115. writer buf.Writer
  116. }
  117. func NewChunkStreamWriter(sizeEncoder ChunkSizeEncoder, writer io.Writer) *ChunkStreamWriter {
  118. return &ChunkStreamWriter{
  119. sizeEncoder: sizeEncoder,
  120. writer: buf.NewWriter(writer),
  121. }
  122. }
  123. func (w *ChunkStreamWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
  124. const sliceSize = 8192
  125. mbLen := mb.Len()
  126. mb2Write := make(buf.MultiBuffer, 0, mbLen/buf.Size+mbLen/sliceSize+2)
  127. for {
  128. mb2, slice := buf.SplitSize(mb, sliceSize)
  129. mb = mb2
  130. b := buf.New()
  131. w.sizeEncoder.Encode(uint16(slice.Len()), b.Extend(w.sizeEncoder.SizeBytes()))
  132. mb2Write = append(mb2Write, b)
  133. mb2Write = append(mb2Write, slice...)
  134. if mb.IsEmpty() {
  135. break
  136. }
  137. }
  138. return w.writer.WriteMultiBuffer(mb2Write)
  139. }