| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- package vless
- import (
- "context"
- "encoding/binary"
- "io"
- "net"
- "github.com/sagernet/sing-vmess"
- "github.com/sagernet/sing/common/auth"
- "github.com/sagernet/sing/common/buf"
- "github.com/sagernet/sing/common/bufio"
- E "github.com/sagernet/sing/common/exceptions"
- "github.com/sagernet/sing/common/logger"
- M "github.com/sagernet/sing/common/metadata"
- N "github.com/sagernet/sing/common/network"
- "github.com/gofrs/uuid/v5"
- )
- type Service[T comparable] struct {
- userMap map[[16]byte]T
- userFlow map[T]string
- logger logger.Logger
- handler Handler
- }
- type Handler interface {
- N.TCPConnectionHandler
- N.UDPConnectionHandler
- E.Handler
- }
- func NewService[T comparable](logger logger.Logger, handler Handler) *Service[T] {
- return &Service[T]{
- logger: logger,
- handler: handler,
- }
- }
- func (s *Service[T]) UpdateUsers(userList []T, userUUIDList []string, userFlowList []string) {
- userMap := make(map[[16]byte]T)
- userFlowMap := make(map[T]string)
- for i, userName := range userList {
- userID := uuid.FromStringOrNil(userUUIDList[i])
- if userID == uuid.Nil {
- userID = uuid.NewV5(uuid.Nil, userUUIDList[i])
- }
- userMap[userID] = userName
- userFlowMap[userName] = userFlowList[i]
- }
- s.userMap = userMap
- s.userFlow = userFlowMap
- }
- var _ N.TCPConnectionHandler = (*Service[int])(nil)
- func (s *Service[T]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
- request, err := ReadRequest(conn)
- if err != nil {
- return err
- }
- user, loaded := s.userMap[request.UUID]
- if !loaded {
- return E.New("unknown UUID: ", uuid.FromBytesOrNil(request.UUID[:]))
- }
- ctx = auth.ContextWithUser(ctx, user)
- metadata.Destination = request.Destination
- userFlow := s.userFlow[user]
- if request.Flow == FlowVision && request.Command == vmess.NetworkUDP {
- return E.New(FlowVision, " flow does not support UDP")
- } else if request.Flow != userFlow {
- return E.New("flow mismatch: expected ", flowName(userFlow), ", but got ", flowName(request.Flow))
- }
- if request.Command == vmess.CommandUDP {
- return s.handler.NewPacketConnection(ctx, &serverPacketConn{ExtendedConn: bufio.NewExtendedConn(conn), destination: request.Destination}, metadata)
- }
- responseConn := &serverConn{ExtendedConn: bufio.NewExtendedConn(conn), writer: bufio.NewVectorisedWriter(conn)}
- switch userFlow {
- case FlowVision:
- conn, err = NewVisionConn(responseConn, conn, request.UUID, s.logger)
- if err != nil {
- return E.Cause(err, "initialize vision")
- }
- case "":
- conn = responseConn
- default:
- return E.New("unknown flow: ", userFlow)
- }
- switch request.Command {
- case vmess.CommandTCP:
- return s.handler.NewConnection(ctx, conn, metadata)
- case vmess.CommandMux:
- return vmess.HandleMuxConnection(ctx, conn, s.handler)
- default:
- return E.New("unknown command: ", request.Command)
- }
- }
- func flowName(value string) string {
- if value == "" {
- return "none"
- }
- return value
- }
- var _ N.VectorisedWriter = (*serverConn)(nil)
- type serverConn struct {
- N.ExtendedConn
- writer N.VectorisedWriter
- responseWritten bool
- }
- func (c *serverConn) Read(b []byte) (n int, err error) {
- return c.ExtendedConn.Read(b)
- }
- func (c *serverConn) Write(b []byte) (n int, err error) {
- if !c.responseWritten {
- _, err = bufio.WriteVectorised(c.writer, [][]byte{{Version, 0}, b})
- if err == nil {
- n = len(b)
- }
- c.responseWritten = true
- return
- }
- return c.ExtendedConn.Write(b)
- }
- func (c *serverConn) WriteBuffer(buffer *buf.Buffer) error {
- if !c.responseWritten {
- header := buffer.ExtendHeader(2)
- header[0] = Version
- header[1] = 0
- c.responseWritten = true
- }
- return c.ExtendedConn.WriteBuffer(buffer)
- }
- func (c *serverConn) WriteVectorised(buffers []*buf.Buffer) error {
- if !c.responseWritten {
- err := c.writer.WriteVectorised(append([]*buf.Buffer{buf.As([]byte{Version, 0})}, buffers...))
- c.responseWritten = true
- return err
- }
- return c.writer.WriteVectorised(buffers)
- }
- func (c *serverConn) NeedAdditionalReadDeadline() bool {
- return true
- }
- func (c *serverConn) FrontHeadroom() int {
- if c.responseWritten {
- return 0
- }
- return 2
- }
- func (c *serverConn) ReaderReplaceable() bool {
- return true
- }
- func (c *serverConn) WriterReplaceable() bool {
- return c.responseWritten
- }
- func (c *serverConn) Upstream() any {
- return c.ExtendedConn
- }
- type serverPacketConn struct {
- N.ExtendedConn
- responseWriter io.Writer
- responseWritten bool
- destination M.Socksaddr
- }
- func (c *serverPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
- n, err = c.ExtendedConn.Read(p)
- if err != nil {
- return
- }
- if c.destination.IsFqdn() {
- addr = c.destination
- } else {
- addr = c.destination.UDPAddr()
- }
- return
- }
- func (c *serverPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
- if !c.responseWritten {
- if c.responseWriter == nil {
- var packetLen [2]byte
- binary.BigEndian.PutUint16(packetLen[:], uint16(len(p)))
- _, err = bufio.WriteVectorised(bufio.NewVectorisedWriter(c.ExtendedConn), [][]byte{{Version, 0}, packetLen[:], p})
- if err == nil {
- n = len(p)
- }
- c.responseWritten = true
- return
- } else {
- _, err = c.responseWriter.Write([]byte{Version, 0})
- if err != nil {
- return
- }
- c.responseWritten = true
- }
- }
- return c.ExtendedConn.Write(p)
- }
- func (c *serverPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
- var packetLen uint16
- err = binary.Read(c.ExtendedConn, binary.BigEndian, &packetLen)
- if err != nil {
- return
- }
- _, err = buffer.ReadFullFrom(c.ExtendedConn, int(packetLen))
- if err != nil {
- return
- }
- destination = c.destination
- return
- }
- func (c *serverPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
- if !c.responseWritten {
- if c.responseWriter == nil {
- var packetLen [2]byte
- binary.BigEndian.PutUint16(packetLen[:], uint16(buffer.Len()))
- err := bufio.NewVectorisedWriter(c.ExtendedConn).WriteVectorised([]*buf.Buffer{buf.As([]byte{Version, 0}), buf.As(packetLen[:]), buffer})
- c.responseWritten = true
- return err
- } else {
- _, err := c.responseWriter.Write([]byte{Version, 0})
- if err != nil {
- return err
- }
- c.responseWritten = true
- }
- }
- packetLen := buffer.Len()
- binary.BigEndian.PutUint16(buffer.ExtendHeader(2), uint16(packetLen))
- return c.ExtendedConn.WriteBuffer(buffer)
- }
- func (c *serverPacketConn) FrontHeadroom() int {
- return 2
- }
- func (c *serverPacketConn) Upstream() any {
- return c.ExtendedConn
- }
|