chunk.go 3.7 KB

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