| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 | 
							- package naive
 
- import (
 
- 	"encoding/binary"
 
- 	"io"
 
- 	"math/rand"
 
- 	"net"
 
- 	"net/http"
 
- 	"os"
 
- 	"strings"
 
- 	"time"
 
- 	"github.com/sagernet/sing/common"
 
- 	"github.com/sagernet/sing/common/buf"
 
- 	M "github.com/sagernet/sing/common/metadata"
 
- 	"github.com/sagernet/sing/common/rw"
 
- )
 
- const kFirstPaddings = 8
 
- type naiveH1Conn struct {
 
- 	net.Conn
 
- 	readPadding      int
 
- 	writePadding     int
 
- 	readRemaining    int
 
- 	paddingRemaining int
 
- }
 
- func (c *naiveH1Conn) Read(p []byte) (n int, err error) {
 
- 	n, err = c.read(p)
 
- 	return n, wrapHttpError(err)
 
- }
 
- func (c *naiveH1Conn) read(p []byte) (n int, err error) {
 
- 	if c.readRemaining > 0 {
 
- 		if len(p) > c.readRemaining {
 
- 			p = p[:c.readRemaining]
 
- 		}
 
- 		n, err = c.Conn.Read(p)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		c.readRemaining -= n
 
- 		return
 
- 	}
 
- 	if c.paddingRemaining > 0 {
 
- 		err = rw.SkipN(c.Conn, c.paddingRemaining)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		c.paddingRemaining = 0
 
- 	}
 
- 	if c.readPadding < kFirstPaddings {
 
- 		var paddingHdr []byte
 
- 		if len(p) >= 3 {
 
- 			paddingHdr = p[:3]
 
- 		} else {
 
- 			paddingHdr = make([]byte, 3)
 
- 		}
 
- 		_, err = io.ReadFull(c.Conn, paddingHdr)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		originalDataSize := int(binary.BigEndian.Uint16(paddingHdr[:2]))
 
- 		paddingSize := int(paddingHdr[2])
 
- 		if len(p) > originalDataSize {
 
- 			p = p[:originalDataSize]
 
- 		}
 
- 		n, err = c.Conn.Read(p)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		c.readPadding++
 
- 		c.readRemaining = originalDataSize - n
 
- 		c.paddingRemaining = paddingSize
 
- 		return
 
- 	}
 
- 	return c.Conn.Read(p)
 
- }
 
- func (c *naiveH1Conn) Write(p []byte) (n int, err error) {
 
- 	for pLen := len(p); pLen > 0; {
 
- 		var data []byte
 
- 		if pLen > 65535 {
 
- 			data = p[:65535]
 
- 			p = p[65535:]
 
- 			pLen -= 65535
 
- 		} else {
 
- 			data = p
 
- 			pLen = 0
 
- 		}
 
- 		var writeN int
 
- 		writeN, err = c.write(data)
 
- 		n += writeN
 
- 		if err != nil {
 
- 			break
 
- 		}
 
- 	}
 
- 	return n, wrapHttpError(err)
 
- }
 
- func (c *naiveH1Conn) write(p []byte) (n int, err error) {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		paddingSize := rand.Intn(256)
 
- 		buffer := buf.NewSize(3 + len(p) + paddingSize)
 
- 		defer buffer.Release()
 
- 		header := buffer.Extend(3)
 
- 		binary.BigEndian.PutUint16(header, uint16(len(p)))
 
- 		header[2] = byte(paddingSize)
 
- 		common.Must1(buffer.Write(p))
 
- 		_, err = c.Conn.Write(buffer.Bytes())
 
- 		if err == nil {
 
- 			n = len(p)
 
- 		}
 
- 		c.writePadding++
 
- 		return
 
- 	}
 
- 	return c.Conn.Write(p)
 
- }
 
- func (c *naiveH1Conn) FrontHeadroom() int {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		return 3
 
- 	}
 
- 	return 0
 
- }
 
- func (c *naiveH1Conn) RearHeadroom() int {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		return 255
 
- 	}
 
- 	return 0
 
- }
 
- func (c *naiveH1Conn) WriterMTU() int {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		return 65535
 
- 	}
 
- 	return 0
 
- }
 
- func (c *naiveH1Conn) WriteBuffer(buffer *buf.Buffer) error {
 
- 	defer buffer.Release()
 
- 	if c.writePadding < kFirstPaddings {
 
- 		bufferLen := buffer.Len()
 
- 		if bufferLen > 65535 {
 
- 			return common.Error(c.Write(buffer.Bytes()))
 
- 		}
 
- 		paddingSize := rand.Intn(256)
 
- 		header := buffer.ExtendHeader(3)
 
- 		binary.BigEndian.PutUint16(header, uint16(bufferLen))
 
- 		header[2] = byte(paddingSize)
 
- 		buffer.Extend(paddingSize)
 
- 		c.writePadding++
 
- 	}
 
- 	return wrapHttpError(common.Error(c.Conn.Write(buffer.Bytes())))
 
- }
 
- // FIXME
 
- /*func (c *naiveH1Conn) WriteTo(w io.Writer) (n int64, err error) {
 
- 	if c.readPadding < kFirstPaddings {
 
- 		n, err = bufio.WriteToN(c, w, kFirstPaddings-c.readPadding)
 
- 	} else {
 
- 		n, err = bufio.Copy(w, c.Conn)
 
- 	}
 
- 	return n, wrapHttpError(err)
 
- }
 
- func (c *naiveH1Conn) ReadFrom(r io.Reader) (n int64, err error) {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		n, err = bufio.ReadFromN(c, r, kFirstPaddings-c.writePadding)
 
- 	} else {
 
- 		n, err = bufio.Copy(c.Conn, r)
 
- 	}
 
- 	return n, wrapHttpError(err)
 
- }
 
- */
 
- func (c *naiveH1Conn) Upstream() any {
 
- 	return c.Conn
 
- }
 
- func (c *naiveH1Conn) ReaderReplaceable() bool {
 
- 	return c.readPadding == kFirstPaddings
 
- }
 
- func (c *naiveH1Conn) WriterReplaceable() bool {
 
- 	return c.writePadding == kFirstPaddings
 
- }
 
- type naiveH2Conn struct {
 
- 	reader           io.Reader
 
- 	writer           io.Writer
 
- 	flusher          http.Flusher
 
- 	rAddr            net.Addr
 
- 	readPadding      int
 
- 	writePadding     int
 
- 	readRemaining    int
 
- 	paddingRemaining int
 
- }
 
- func (c *naiveH2Conn) Read(p []byte) (n int, err error) {
 
- 	n, err = c.read(p)
 
- 	return n, wrapHttpError(err)
 
- }
 
- func (c *naiveH2Conn) read(p []byte) (n int, err error) {
 
- 	if c.readRemaining > 0 {
 
- 		if len(p) > c.readRemaining {
 
- 			p = p[:c.readRemaining]
 
- 		}
 
- 		n, err = c.reader.Read(p)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		c.readRemaining -= n
 
- 		return
 
- 	}
 
- 	if c.paddingRemaining > 0 {
 
- 		err = rw.SkipN(c.reader, c.paddingRemaining)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		c.paddingRemaining = 0
 
- 	}
 
- 	if c.readPadding < kFirstPaddings {
 
- 		var paddingHdr []byte
 
- 		if len(p) >= 3 {
 
- 			paddingHdr = p[:3]
 
- 		} else {
 
- 			paddingHdr = make([]byte, 3)
 
- 		}
 
- 		_, err = io.ReadFull(c.reader, paddingHdr)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		originalDataSize := int(binary.BigEndian.Uint16(paddingHdr[:2]))
 
- 		paddingSize := int(paddingHdr[2])
 
- 		if len(p) > originalDataSize {
 
- 			p = p[:originalDataSize]
 
- 		}
 
- 		n, err = c.reader.Read(p)
 
- 		if err != nil {
 
- 			return
 
- 		}
 
- 		c.readPadding++
 
- 		c.readRemaining = originalDataSize - n
 
- 		c.paddingRemaining = paddingSize
 
- 		return
 
- 	}
 
- 	return c.reader.Read(p)
 
- }
 
- func (c *naiveH2Conn) Write(p []byte) (n int, err error) {
 
- 	for pLen := len(p); pLen > 0; {
 
- 		var data []byte
 
- 		if pLen > 65535 {
 
- 			data = p[:65535]
 
- 			p = p[65535:]
 
- 			pLen -= 65535
 
- 		} else {
 
- 			data = p
 
- 			pLen = 0
 
- 		}
 
- 		var writeN int
 
- 		writeN, err = c.write(data)
 
- 		n += writeN
 
- 		if err != nil {
 
- 			break
 
- 		}
 
- 	}
 
- 	if err == nil {
 
- 		c.flusher.Flush()
 
- 	}
 
- 	return n, wrapHttpError(err)
 
- }
 
- func (c *naiveH2Conn) write(p []byte) (n int, err error) {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		paddingSize := rand.Intn(256)
 
- 		buffer := buf.NewSize(3 + len(p) + paddingSize)
 
- 		defer buffer.Release()
 
- 		header := buffer.Extend(3)
 
- 		binary.BigEndian.PutUint16(header, uint16(len(p)))
 
- 		header[2] = byte(paddingSize)
 
- 		common.Must1(buffer.Write(p))
 
- 		_, err = c.writer.Write(buffer.Bytes())
 
- 		if err == nil {
 
- 			n = len(p)
 
- 		}
 
- 		c.writePadding++
 
- 		return
 
- 	}
 
- 	return c.writer.Write(p)
 
- }
 
- func (c *naiveH2Conn) FrontHeadroom() int {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		return 3
 
- 	}
 
- 	return 0
 
- }
 
- func (c *naiveH2Conn) RearHeadroom() int {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		return 255
 
- 	}
 
- 	return 0
 
- }
 
- func (c *naiveH2Conn) WriterMTU() int {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		return 65535
 
- 	}
 
- 	return 0
 
- }
 
- func (c *naiveH2Conn) WriteBuffer(buffer *buf.Buffer) error {
 
- 	defer buffer.Release()
 
- 	if c.writePadding < kFirstPaddings {
 
- 		bufferLen := buffer.Len()
 
- 		if bufferLen > 65535 {
 
- 			return common.Error(c.Write(buffer.Bytes()))
 
- 		}
 
- 		paddingSize := rand.Intn(256)
 
- 		header := buffer.ExtendHeader(3)
 
- 		binary.BigEndian.PutUint16(header, uint16(bufferLen))
 
- 		header[2] = byte(paddingSize)
 
- 		buffer.Extend(paddingSize)
 
- 		c.writePadding++
 
- 	}
 
- 	err := common.Error(c.writer.Write(buffer.Bytes()))
 
- 	if err == nil {
 
- 		c.flusher.Flush()
 
- 	}
 
- 	return wrapHttpError(err)
 
- }
 
- // FIXME
 
- /*func (c *naiveH2Conn) WriteTo(w io.Writer) (n int64, err error) {
 
- 	if c.readPadding < kFirstPaddings {
 
- 		n, err = bufio.WriteToN(c, w, kFirstPaddings-c.readPadding)
 
- 	} else {
 
- 		n, err = bufio.Copy(w, c.reader)
 
- 	}
 
- 	return n, wrapHttpError(err)
 
- }
 
- func (c *naiveH2Conn) ReadFrom(r io.Reader) (n int64, err error) {
 
- 	if c.writePadding < kFirstPaddings {
 
- 		n, err = bufio.ReadFromN(c, r, kFirstPaddings-c.writePadding)
 
- 	} else {
 
- 		n, err = bufio.Copy(c.writer, r)
 
- 	}
 
- 	return n, wrapHttpError(err)
 
- }*/
 
- func (c *naiveH2Conn) Close() error {
 
- 	return common.Close(
 
- 		c.reader,
 
- 		c.writer,
 
- 	)
 
- }
 
- func (c *naiveH2Conn) LocalAddr() net.Addr {
 
- 	return M.Socksaddr{}
 
- }
 
- func (c *naiveH2Conn) RemoteAddr() net.Addr {
 
- 	return c.rAddr
 
- }
 
- func (c *naiveH2Conn) SetDeadline(t time.Time) error {
 
- 	return os.ErrInvalid
 
- }
 
- func (c *naiveH2Conn) SetReadDeadline(t time.Time) error {
 
- 	return os.ErrInvalid
 
- }
 
- func (c *naiveH2Conn) SetWriteDeadline(t time.Time) error {
 
- 	return os.ErrInvalid
 
- }
 
- func (c *naiveH2Conn) NeedAdditionalReadDeadline() bool {
 
- 	return true
 
- }
 
- func (c *naiveH2Conn) UpstreamReader() any {
 
- 	return c.reader
 
- }
 
- func (c *naiveH2Conn) UpstreamWriter() any {
 
- 	return c.writer
 
- }
 
- func (c *naiveH2Conn) ReaderReplaceable() bool {
 
- 	return c.readPadding == kFirstPaddings
 
- }
 
- func (c *naiveH2Conn) WriterReplaceable() bool {
 
- 	return c.writePadding == kFirstPaddings
 
- }
 
- func wrapHttpError(err error) error {
 
- 	if err == nil {
 
- 		return err
 
- 	}
 
- 	if strings.Contains(err.Error(), "client disconnected") {
 
- 		return net.ErrClosed
 
- 	}
 
- 	if strings.Contains(err.Error(), "body closed by handler") {
 
- 		return net.ErrClosed
 
- 	}
 
- 	if strings.Contains(err.Error(), "canceled with error code 268") {
 
- 		return io.EOF
 
- 	}
 
- 	return err
 
- }
 
 
  |