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