github.com/sagernet/sing-box@v1.9.0-rc.20/transport/vless/client.go (about)

     1  package vless
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  	"net"
     7  	"sync"
     8  
     9  	"github.com/sagernet/sing-vmess"
    10  	"github.com/sagernet/sing/common"
    11  	"github.com/sagernet/sing/common/buf"
    12  	"github.com/sagernet/sing/common/bufio"
    13  	E "github.com/sagernet/sing/common/exceptions"
    14  	"github.com/sagernet/sing/common/logger"
    15  	M "github.com/sagernet/sing/common/metadata"
    16  	N "github.com/sagernet/sing/common/network"
    17  
    18  	"github.com/gofrs/uuid/v5"
    19  )
    20  
    21  type Client struct {
    22  	key    [16]byte
    23  	flow   string
    24  	logger logger.Logger
    25  }
    26  
    27  func NewClient(userId string, flow string, logger logger.Logger) (*Client, error) {
    28  	user := uuid.FromStringOrNil(userId)
    29  	if user == uuid.Nil {
    30  		user = uuid.NewV5(user, userId)
    31  	}
    32  	switch flow {
    33  	case "", "xtls-rprx-vision":
    34  	default:
    35  		return nil, E.New("unsupported flow: " + flow)
    36  	}
    37  	return &Client{user, flow, logger}, nil
    38  }
    39  
    40  func (c *Client) prepareConn(conn net.Conn, tlsConn net.Conn) (net.Conn, error) {
    41  	if c.flow == FlowVision {
    42  		protocolConn, err := NewVisionConn(conn, tlsConn, c.key, c.logger)
    43  		if err != nil {
    44  			return nil, E.Cause(err, "initialize vision")
    45  		}
    46  		conn = protocolConn
    47  	}
    48  	return conn, nil
    49  }
    50  
    51  func (c *Client) DialConn(conn net.Conn, destination M.Socksaddr) (net.Conn, error) {
    52  	remoteConn := NewConn(conn, c.key, vmess.CommandTCP, destination, c.flow)
    53  	protocolConn, err := c.prepareConn(remoteConn, conn)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	return protocolConn, common.Error(remoteConn.Write(nil))
    58  }
    59  
    60  func (c *Client) DialEarlyConn(conn net.Conn, destination M.Socksaddr) (net.Conn, error) {
    61  	return c.prepareConn(NewConn(conn, c.key, vmess.CommandTCP, destination, c.flow), conn)
    62  }
    63  
    64  func (c *Client) DialPacketConn(conn net.Conn, destination M.Socksaddr) (*PacketConn, error) {
    65  	serverConn := &PacketConn{Conn: conn, key: c.key, destination: destination, flow: c.flow}
    66  	return serverConn, common.Error(serverConn.Write(nil))
    67  }
    68  
    69  func (c *Client) DialEarlyPacketConn(conn net.Conn, destination M.Socksaddr) (*PacketConn, error) {
    70  	return &PacketConn{Conn: conn, key: c.key, destination: destination, flow: c.flow}, nil
    71  }
    72  
    73  func (c *Client) DialXUDPPacketConn(conn net.Conn, destination M.Socksaddr) (vmess.PacketConn, error) {
    74  	remoteConn := NewConn(conn, c.key, vmess.CommandTCP, destination, c.flow)
    75  	protocolConn, err := c.prepareConn(remoteConn, conn)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return vmess.NewXUDPConn(protocolConn, destination), common.Error(remoteConn.Write(nil))
    80  }
    81  
    82  func (c *Client) DialEarlyXUDPPacketConn(conn net.Conn, destination M.Socksaddr) (vmess.PacketConn, error) {
    83  	remoteConn := NewConn(conn, c.key, vmess.CommandMux, destination, c.flow)
    84  	protocolConn, err := c.prepareConn(remoteConn, conn)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	return vmess.NewXUDPConn(protocolConn, destination), common.Error(remoteConn.Write(nil))
    89  }
    90  
    91  var (
    92  	_ N.EarlyConn        = (*Conn)(nil)
    93  	_ N.VectorisedWriter = (*Conn)(nil)
    94  )
    95  
    96  type Conn struct {
    97  	N.ExtendedConn
    98  	writer         N.VectorisedWriter
    99  	request        Request
   100  	requestWritten bool
   101  	responseRead   bool
   102  }
   103  
   104  func NewConn(conn net.Conn, uuid [16]byte, command byte, destination M.Socksaddr, flow string) *Conn {
   105  	return &Conn{
   106  		ExtendedConn: bufio.NewExtendedConn(conn),
   107  		writer:       bufio.NewVectorisedWriter(conn),
   108  		request: Request{
   109  			UUID:        uuid,
   110  			Command:     command,
   111  			Destination: destination,
   112  			Flow:        flow,
   113  		},
   114  	}
   115  }
   116  
   117  func (c *Conn) Read(b []byte) (n int, err error) {
   118  	if !c.responseRead {
   119  		err = ReadResponse(c.ExtendedConn)
   120  		if err != nil {
   121  			return
   122  		}
   123  		c.responseRead = true
   124  	}
   125  	return c.ExtendedConn.Read(b)
   126  }
   127  
   128  func (c *Conn) ReadBuffer(buffer *buf.Buffer) error {
   129  	if !c.responseRead {
   130  		err := ReadResponse(c.ExtendedConn)
   131  		if err != nil {
   132  			return err
   133  		}
   134  		c.responseRead = true
   135  	}
   136  	return c.ExtendedConn.ReadBuffer(buffer)
   137  }
   138  
   139  func (c *Conn) Write(b []byte) (n int, err error) {
   140  	if !c.requestWritten {
   141  		err = WriteRequest(c.ExtendedConn, c.request, b)
   142  		if err == nil {
   143  			n = len(b)
   144  		}
   145  		c.requestWritten = true
   146  		return
   147  	}
   148  	return c.ExtendedConn.Write(b)
   149  }
   150  
   151  func (c *Conn) WriteBuffer(buffer *buf.Buffer) error {
   152  	if !c.requestWritten {
   153  		err := EncodeRequest(c.request, buf.With(buffer.ExtendHeader(RequestLen(c.request))))
   154  		if err != nil {
   155  			return err
   156  		}
   157  		c.requestWritten = true
   158  	}
   159  	return c.ExtendedConn.WriteBuffer(buffer)
   160  }
   161  
   162  func (c *Conn) WriteVectorised(buffers []*buf.Buffer) error {
   163  	if !c.requestWritten {
   164  		buffer := buf.NewSize(RequestLen(c.request))
   165  		err := EncodeRequest(c.request, buffer)
   166  		if err != nil {
   167  			buffer.Release()
   168  			return err
   169  		}
   170  		c.requestWritten = true
   171  		return c.writer.WriteVectorised(append([]*buf.Buffer{buffer}, buffers...))
   172  	}
   173  	return c.writer.WriteVectorised(buffers)
   174  }
   175  
   176  func (c *Conn) ReaderReplaceable() bool {
   177  	return c.responseRead
   178  }
   179  
   180  func (c *Conn) WriterReplaceable() bool {
   181  	return c.requestWritten
   182  }
   183  
   184  func (c *Conn) NeedHandshake() bool {
   185  	return !c.requestWritten
   186  }
   187  
   188  func (c *Conn) FrontHeadroom() int {
   189  	if c.requestWritten {
   190  		return 0
   191  	}
   192  	return RequestLen(c.request)
   193  }
   194  
   195  func (c *Conn) Upstream() any {
   196  	return c.ExtendedConn
   197  }
   198  
   199  type PacketConn struct {
   200  	net.Conn
   201  	access         sync.Mutex
   202  	key            [16]byte
   203  	destination    M.Socksaddr
   204  	flow           string
   205  	requestWritten bool
   206  	responseRead   bool
   207  }
   208  
   209  func (c *PacketConn) Read(b []byte) (n int, err error) {
   210  	if !c.responseRead {
   211  		err = ReadResponse(c.Conn)
   212  		if err != nil {
   213  			return
   214  		}
   215  		c.responseRead = true
   216  	}
   217  	var length uint16
   218  	err = binary.Read(c.Conn, binary.BigEndian, &length)
   219  	if err != nil {
   220  		return
   221  	}
   222  	if cap(b) < int(length) {
   223  		return 0, io.ErrShortBuffer
   224  	}
   225  	return io.ReadFull(c.Conn, b[:length])
   226  }
   227  
   228  func (c *PacketConn) Write(b []byte) (n int, err error) {
   229  	if !c.requestWritten {
   230  		c.access.Lock()
   231  		if c.requestWritten {
   232  			c.access.Unlock()
   233  		} else {
   234  			err = WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination, c.flow}, nil)
   235  			if err == nil {
   236  				n = len(b)
   237  			}
   238  			c.requestWritten = true
   239  			c.access.Unlock()
   240  		}
   241  	}
   242  	err = binary.Write(c.Conn, binary.BigEndian, uint16(len(b)))
   243  	if err != nil {
   244  		return
   245  	}
   246  	return c.Conn.Write(b)
   247  }
   248  
   249  func (c *PacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
   250  	defer buffer.Release()
   251  	dataLen := buffer.Len()
   252  	binary.BigEndian.PutUint16(buffer.ExtendHeader(2), uint16(dataLen))
   253  	if !c.requestWritten {
   254  		c.access.Lock()
   255  		if c.requestWritten {
   256  			c.access.Unlock()
   257  		} else {
   258  			err := WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination, c.flow}, buffer.Bytes())
   259  			c.requestWritten = true
   260  			c.access.Unlock()
   261  			return err
   262  		}
   263  	}
   264  	return common.Error(c.Conn.Write(buffer.Bytes()))
   265  }
   266  
   267  func (c *PacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
   268  	n, err = c.Read(p)
   269  	if err != nil {
   270  		return
   271  	}
   272  	if c.destination.IsFqdn() {
   273  		addr = c.destination
   274  	} else {
   275  		addr = c.destination.UDPAddr()
   276  	}
   277  	return
   278  }
   279  
   280  func (c *PacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
   281  	return c.Write(p)
   282  }
   283  
   284  func (c *PacketConn) FrontHeadroom() int {
   285  	return 2
   286  }
   287  
   288  func (c *PacketConn) NeedAdditionalReadDeadline() bool {
   289  	return true
   290  }
   291  
   292  func (c *PacketConn) Upstream() any {
   293  	return c.Conn
   294  }