github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/transport/v2raygrpclite/conn.go (about)

     1  package v2raygrpclite
     2  
     3  import (
     4  	std_bufio "bufio"
     5  	"bytes"
     6  	"encoding/binary"
     7  	"io"
     8  	"net"
     9  	"net/http"
    10  	"os"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/inazumav/sing-box/common/baderror"
    15  	"github.com/sagernet/sing/common"
    16  	"github.com/sagernet/sing/common/buf"
    17  	"github.com/sagernet/sing/common/bufio"
    18  	M "github.com/sagernet/sing/common/metadata"
    19  	"github.com/sagernet/sing/common/rw"
    20  )
    21  
    22  // kanged from: https://github.com/Qv2ray/gun-lite
    23  
    24  var _ net.Conn = (*GunConn)(nil)
    25  
    26  type GunConn struct {
    27  	reader        *std_bufio.Reader
    28  	writer        io.Writer
    29  	flusher       http.Flusher
    30  	create        chan struct{}
    31  	err           error
    32  	readRemaining int
    33  	writeAccess   sync.Mutex
    34  }
    35  
    36  func newGunConn(reader io.Reader, writer io.Writer, flusher http.Flusher) *GunConn {
    37  	return &GunConn{
    38  		reader:  std_bufio.NewReader(reader),
    39  		writer:  writer,
    40  		flusher: flusher,
    41  	}
    42  }
    43  
    44  func newLateGunConn(writer io.Writer) *GunConn {
    45  	return &GunConn{
    46  		create: make(chan struct{}),
    47  		writer: writer,
    48  	}
    49  }
    50  
    51  func (c *GunConn) setup(reader io.Reader, err error) {
    52  	c.reader = std_bufio.NewReader(reader)
    53  	c.err = err
    54  	close(c.create)
    55  }
    56  
    57  func (c *GunConn) Read(b []byte) (n int, err error) {
    58  	n, err = c.read(b)
    59  	return n, baderror.WrapH2(err)
    60  }
    61  
    62  func (c *GunConn) read(b []byte) (n int, err error) {
    63  	if c.reader == nil {
    64  		<-c.create
    65  		if c.err != nil {
    66  			return 0, c.err
    67  		}
    68  	}
    69  
    70  	if c.readRemaining > 0 {
    71  		if len(b) > c.readRemaining {
    72  			b = b[:c.readRemaining]
    73  		}
    74  		n, err = c.reader.Read(b)
    75  		c.readRemaining -= n
    76  		return
    77  	}
    78  
    79  	_, err = c.reader.Discard(6)
    80  	if err != nil {
    81  		return
    82  	}
    83  
    84  	dataLen, err := binary.ReadUvarint(c.reader)
    85  	if err != nil {
    86  		return
    87  	}
    88  
    89  	readLen := int(dataLen)
    90  	c.readRemaining = readLen
    91  	if len(b) > readLen {
    92  		b = b[:readLen]
    93  	}
    94  
    95  	n, err = c.reader.Read(b)
    96  	c.readRemaining -= n
    97  	return
    98  }
    99  
   100  func (c *GunConn) Write(b []byte) (n int, err error) {
   101  	protobufHeader := [1 + binary.MaxVarintLen64]byte{0x0A}
   102  	varuintLen := binary.PutUvarint(protobufHeader[1:], uint64(len(b)))
   103  	grpcHeader := buf.Get(5)
   104  	grpcPayloadLen := uint32(1 + varuintLen + len(b))
   105  	binary.BigEndian.PutUint32(grpcHeader[1:5], grpcPayloadLen)
   106  	c.writeAccess.Lock()
   107  	_, err = bufio.Copy(c.writer, io.MultiReader(bytes.NewReader(grpcHeader), bytes.NewReader(protobufHeader[:varuintLen+1]), bytes.NewReader(b)))
   108  	c.writeAccess.Unlock()
   109  	buf.Put(grpcHeader)
   110  	if err == nil && c.flusher != nil {
   111  		c.flusher.Flush()
   112  	}
   113  	return len(b), baderror.WrapH2(err)
   114  }
   115  
   116  func (c *GunConn) WriteBuffer(buffer *buf.Buffer) error {
   117  	defer buffer.Release()
   118  	dataLen := buffer.Len()
   119  	varLen := rw.UVariantLen(uint64(dataLen))
   120  	header := buffer.ExtendHeader(6 + varLen)
   121  	_ = header[6]
   122  	header[0] = 0x00
   123  	binary.BigEndian.PutUint32(header[1:5], uint32(1+varLen+dataLen))
   124  	header[5] = 0x0A
   125  	binary.PutUvarint(header[6:], uint64(dataLen))
   126  	err := rw.WriteBytes(c.writer, buffer.Bytes())
   127  	if err == nil && c.flusher != nil {
   128  		c.flusher.Flush()
   129  	}
   130  	return baderror.WrapH2(err)
   131  }
   132  
   133  func (c *GunConn) FrontHeadroom() int {
   134  	return 6 + binary.MaxVarintLen64
   135  }
   136  
   137  func (c *GunConn) Close() error {
   138  	return common.Close(c.reader, c.writer)
   139  }
   140  
   141  func (c *GunConn) LocalAddr() net.Addr {
   142  	return M.Socksaddr{}
   143  }
   144  
   145  func (c *GunConn) RemoteAddr() net.Addr {
   146  	return nil
   147  }
   148  
   149  func (c *GunConn) SetDeadline(t time.Time) error {
   150  	return os.ErrInvalid
   151  }
   152  
   153  func (c *GunConn) SetReadDeadline(t time.Time) error {
   154  	return os.ErrInvalid
   155  }
   156  
   157  func (c *GunConn) SetWriteDeadline(t time.Time) error {
   158  	return os.ErrInvalid
   159  }
   160  
   161  func (c *GunConn) NeedAdditionalReadDeadline() bool {
   162  	return true
   163  }