| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 | 
							- // +build !wasm
 
- package buf
 
- import (
 
- 	"io"
 
- 	"runtime"
 
- 	"syscall"
 
- 	"v2ray.com/core/common/platform"
 
- )
 
- type allocStrategy struct {
 
- 	current uint32
 
- }
 
- func (s *allocStrategy) Current() uint32 {
 
- 	return s.current
 
- }
 
- func (s *allocStrategy) Adjust(n uint32) {
 
- 	if n >= s.current {
 
- 		s.current *= 4
 
- 	} else {
 
- 		s.current = n
 
- 	}
 
- 	if s.current > 32 {
 
- 		s.current = 32
 
- 	}
 
- 	if s.current == 0 {
 
- 		s.current = 1
 
- 	}
 
- }
 
- func (s *allocStrategy) Alloc() []*Buffer {
 
- 	bs := make([]*Buffer, s.current)
 
- 	for i := range bs {
 
- 		bs[i] = New()
 
- 	}
 
- 	return bs
 
- }
 
- type multiReader interface {
 
- 	Init([]*Buffer)
 
- 	Read(fd uintptr) int32
 
- 	Clear()
 
- }
 
- type ReadVReader struct {
 
- 	io.Reader
 
- 	rawConn syscall.RawConn
 
- 	mr      multiReader
 
- 	alloc   allocStrategy
 
- }
 
- func NewReadVReader(reader io.Reader, rawConn syscall.RawConn) *ReadVReader {
 
- 	return &ReadVReader{
 
- 		Reader:  reader,
 
- 		rawConn: rawConn,
 
- 		alloc: allocStrategy{
 
- 			current: 1,
 
- 		},
 
- 		mr: newMultiReader(),
 
- 	}
 
- }
 
- func (r *ReadVReader) readMulti() (MultiBuffer, error) {
 
- 	bs := r.alloc.Alloc()
 
- 	r.mr.Init(bs)
 
- 	var nBytes int32
 
- 	err := r.rawConn.Read(func(fd uintptr) bool {
 
- 		n := r.mr.Read(fd)
 
- 		if n < 0 {
 
- 			return false
 
- 		}
 
- 		nBytes = n
 
- 		return true
 
- 	})
 
- 	r.mr.Clear()
 
- 	if err != nil {
 
- 		mb := MultiBuffer(bs)
 
- 		mb.Release()
 
- 		return nil, err
 
- 	}
 
- 	if nBytes == 0 {
 
- 		mb := MultiBuffer(bs)
 
- 		mb.Release()
 
- 		return nil, io.EOF
 
- 	}
 
- 	nBuf := 0
 
- 	for nBuf < len(bs) {
 
- 		if nBytes <= 0 {
 
- 			break
 
- 		}
 
- 		end := int32(nBytes)
 
- 		if end > Size {
 
- 			end = Size
 
- 		}
 
- 		bs[nBuf].end = end
 
- 		nBytes -= end
 
- 		nBuf++
 
- 	}
 
- 	for i := nBuf; i < len(bs); i++ {
 
- 		bs[i].Release()
 
- 		bs[i] = nil
 
- 	}
 
- 	return MultiBuffer(bs[:nBuf]), nil
 
- }
 
- // ReadMultiBuffer implements Reader.
 
- func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
 
- 	if r.alloc.Current() == 1 {
 
- 		b, err := readOne(r.Reader)
 
- 		if err != nil {
 
- 			return nil, err
 
- 		}
 
- 		if b.IsFull() {
 
- 			r.alloc.Adjust(1)
 
- 		}
 
- 		return NewMultiBufferValue(b), nil
 
- 	}
 
- 	mb, err := r.readMulti()
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	r.alloc.Adjust(uint32(len(mb)))
 
- 	return mb, nil
 
- }
 
- var useReadv = false
 
- func init() {
 
- 	const defaultFlagValue = "NOT_DEFINED_AT_ALL"
 
- 	value := platform.NewEnvFlag("v2ray.buf.readv").GetValue(func() string { return defaultFlagValue })
 
- 	switch value {
 
- 	case defaultFlagValue, "auto":
 
- 		if (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x") && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
 
- 			useReadv = true
 
- 		}
 
- 	case "enable":
 
- 		useReadv = true
 
- 	}
 
- }
 
 
  |