1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-07-01 11:35:23 +00:00
v2fly/common/crypto/chunk.go

155 lines
3.3 KiB
Go
Raw Normal View History

2017-04-23 11:30:08 +00:00
package crypto
import (
"io"
2017-11-07 13:40:51 +00:00
"v2ray.com/core/common"
2017-04-23 11:30:08 +00:00
"v2ray.com/core/common/buf"
"v2ray.com/core/common/serial"
)
2017-11-08 10:11:13 +00:00
// ChunkSizeDecoder is an utility class to decode size value from bytes.
2017-04-23 11:30:08 +00:00
type ChunkSizeDecoder interface {
SizeBytes() int
Decode([]byte) (uint16, error)
}
2017-11-08 10:11:13 +00:00
// ChunkSizeEncoder is an utility class to encode size value into bytes.
2017-04-23 11:30:08 +00:00
type ChunkSizeEncoder interface {
SizeBytes() int
Encode(uint16, []byte) []byte
}
type PlainChunkSizeParser struct{}
func (PlainChunkSizeParser) SizeBytes() int {
return 2
}
func (PlainChunkSizeParser) Encode(size uint16, b []byte) []byte {
return serial.Uint16ToBytes(size, b)
}
func (PlainChunkSizeParser) Decode(b []byte) (uint16, error) {
return serial.BytesToUint16(b), nil
}
type ChunkStreamReader struct {
sizeDecoder ChunkSizeDecoder
reader buf.Reader
buffer []byte
leftOver buf.MultiBuffer
2017-05-02 20:50:27 +00:00
leftOverSize int
2017-04-23 11:30:08 +00:00
}
func NewChunkStreamReader(sizeDecoder ChunkSizeDecoder, reader io.Reader) *ChunkStreamReader {
return &ChunkStreamReader{
sizeDecoder: sizeDecoder,
reader: buf.NewReader(reader),
buffer: make([]byte, sizeDecoder.SizeBytes()),
2017-11-09 21:33:15 +00:00
leftOver: buf.NewMultiBufferCap(16),
2017-04-23 11:30:08 +00:00
}
}
2017-04-28 18:11:44 +00:00
func (r *ChunkStreamReader) readAtLeast(size int) error {
2017-04-23 11:30:08 +00:00
mb := r.leftOver
2017-05-02 20:50:27 +00:00
r.leftOver = nil
2017-04-23 11:30:08 +00:00
for mb.Len() < size {
2017-11-09 21:33:15 +00:00
extra, err := r.reader.ReadMultiBuffer()
2017-04-23 11:30:08 +00:00
if err != nil {
mb.Release()
2017-04-28 18:11:44 +00:00
return err
2017-04-23 11:30:08 +00:00
}
mb.AppendMulti(extra)
}
2017-04-28 18:11:44 +00:00
r.leftOver = mb
2017-04-23 11:30:08 +00:00
2017-04-28 18:11:44 +00:00
return nil
2017-04-23 11:30:08 +00:00
}
func (r *ChunkStreamReader) readSize() (uint16, error) {
if r.sizeDecoder.SizeBytes() > r.leftOver.Len() {
2017-04-28 18:11:44 +00:00
if err := r.readAtLeast(r.sizeDecoder.SizeBytes() - r.leftOver.Len()); err != nil {
2017-04-23 11:30:08 +00:00
return 0, err
}
}
2017-11-08 21:41:46 +00:00
common.Must2(io.ReadFull(&r.leftOver, r.buffer))
2017-04-23 11:30:08 +00:00
return r.sizeDecoder.Decode(r.buffer)
}
2017-11-09 21:33:15 +00:00
func (r *ChunkStreamReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
2017-05-02 20:50:27 +00:00
size := r.leftOverSize
2017-04-23 11:30:08 +00:00
if size == 0 {
nextSize, err := r.readSize()
if err != nil {
return nil, err
}
if nextSize == 0 {
return nil, io.EOF
}
size = int(nextSize)
}
2017-04-28 18:11:44 +00:00
if r.leftOver.IsEmpty() {
if err := r.readAtLeast(1); err != nil {
2017-04-23 11:30:08 +00:00
return nil, err
}
}
2017-11-07 13:40:51 +00:00
leftOverLen := r.leftOver.Len()
if size >= leftOverLen {
2017-04-28 18:11:44 +00:00
mb := r.leftOver
2017-11-07 13:40:51 +00:00
r.leftOverSize = size - leftOverLen
2017-04-23 11:30:08 +00:00
r.leftOver = nil
2017-04-28 18:11:44 +00:00
return mb, nil
2017-04-23 11:30:08 +00:00
}
2017-04-28 18:11:44 +00:00
mb := r.leftOver.SliceBySize(size)
2017-11-07 13:40:51 +00:00
mbLen := mb.Len()
if mbLen != size {
2017-04-23 11:30:08 +00:00
b := buf.New()
2017-11-07 13:40:51 +00:00
common.Must(b.Reset(buf.ReadFullFrom(&r.leftOver, size-mbLen)))
2017-04-23 11:30:08 +00:00
mb.Append(b)
}
r.leftOverSize = 0
2017-11-07 13:40:51 +00:00
2017-04-23 11:30:08 +00:00
return mb, nil
}
type ChunkStreamWriter struct {
sizeEncoder ChunkSizeEncoder
writer buf.Writer
}
func NewChunkStreamWriter(sizeEncoder ChunkSizeEncoder, writer io.Writer) *ChunkStreamWriter {
return &ChunkStreamWriter{
sizeEncoder: sizeEncoder,
writer: buf.NewWriter(writer),
}
}
2017-11-09 21:33:15 +00:00
func (w *ChunkStreamWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
2017-04-23 11:30:08 +00:00
const sliceSize = 8192
2017-11-08 23:55:28 +00:00
mbLen := mb.Len()
2017-11-09 21:33:15 +00:00
mb2Write := buf.NewMultiBufferCap(mbLen/buf.Size + mbLen/sliceSize + 2)
2017-04-23 11:30:08 +00:00
for {
slice := mb.SliceBySize(sliceSize)
b := buf.New()
2017-11-08 10:11:13 +00:00
common.Must(b.Reset(func(buffer []byte) (int, error) {
2017-04-23 11:30:08 +00:00
w.sizeEncoder.Encode(uint16(slice.Len()), buffer[:0])
return w.sizeEncoder.SizeBytes(), nil
2017-11-07 13:40:51 +00:00
}))
2017-04-23 11:30:08 +00:00
mb2Write.Append(b)
mb2Write.AppendMulti(slice)
if mb.IsEmpty() {
break
}
}
2017-11-09 21:33:15 +00:00
return w.writer.WriteMultiBuffer(mb2Write)
2017-04-23 11:30:08 +00:00
}