| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- package io
- import (
- "errors"
- "hash/fnv"
- "io"
- "github.com/v2ray/v2ray-core/common/alloc"
- "github.com/v2ray/v2ray-core/transport"
- )
- var (
- TruncatedPayload = errors.New("Truncated payload.")
- )
- type ValidationReader struct {
- reader io.Reader
- buffer *alloc.Buffer
- }
- func NewValidationReader(reader io.Reader) *ValidationReader {
- return &ValidationReader{
- reader: reader,
- buffer: alloc.NewLargeBuffer().Clear(),
- }
- }
- func (this *ValidationReader) Read(data []byte) (int, error) {
- nBytes, err := this.reader.Read(data)
- if err != nil {
- return nBytes, err
- }
- nBytesActual := 0
- dataActual := data[:]
- for {
- payload, rest, err := parsePayload(data)
- if err != nil {
- return nBytesActual, err
- }
- copy(dataActual, payload)
- nBytesActual += len(payload)
- dataActual = dataActual[nBytesActual:]
- if len(rest) == 0 {
- break
- }
- data = rest
- }
- return nBytesActual, nil
- }
- func parsePayload(data []byte) (payload []byte, rest []byte, err error) {
- dataLen := len(data)
- if dataLen < 6 {
- err = TruncatedPayload
- return
- }
- payloadLen := int(data[0])<<8 + int(data[1])
- if dataLen < payloadLen+6 {
- err = TruncatedPayload
- return
- }
- payload = data[6 : 6+payloadLen]
- rest = data[6+payloadLen:]
- fnv1a := fnv.New32a()
- fnv1a.Write(payload)
- actualHash := fnv1a.Sum32()
- expectedHash := uint32(data[2])<<24 + uint32(data[3])<<16 + uint32(data[4])<<8 + uint32(data[5])
- if actualHash != expectedHash {
- err = transport.CorruptedPacket
- return
- }
- return
- }
|