github.com/metacubex/mihomo@v1.18.5/transport/tuic/v4/server.go (about)

     1  package v4
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"fmt"
     7  	"net"
     8  	"sync"
     9  
    10  	"github.com/metacubex/mihomo/adapter/inbound"
    11  	"github.com/metacubex/mihomo/common/atomic"
    12  	N "github.com/metacubex/mihomo/common/net"
    13  	"github.com/metacubex/mihomo/common/pool"
    14  	C "github.com/metacubex/mihomo/constant"
    15  	"github.com/metacubex/mihomo/transport/socks5"
    16  	"github.com/metacubex/mihomo/transport/tuic/common"
    17  
    18  	"github.com/gofrs/uuid/v5"
    19  	"github.com/metacubex/quic-go"
    20  	"github.com/puzpuzpuz/xsync/v3"
    21  )
    22  
    23  type ServerOption struct {
    24  	HandleTcpFn func(conn net.Conn, addr socks5.Addr, additions ...inbound.Addition) error
    25  	HandleUdpFn func(addr socks5.Addr, packet C.UDPPacket, additions ...inbound.Addition) error
    26  
    27  	Tokens                [][32]byte
    28  	MaxUdpRelayPacketSize int
    29  }
    30  
    31  func NewServerHandler(option *ServerOption, quicConn quic.EarlyConnection, uuid uuid.UUID) common.ServerHandler {
    32  	return &serverHandler{
    33  		ServerOption: option,
    34  		quicConn:     quicConn,
    35  		uuid:         uuid,
    36  		authCh:       make(chan struct{}),
    37  		udpInputMap:  xsync.NewMapOf[uint32, *atomic.Bool](),
    38  	}
    39  }
    40  
    41  type serverHandler struct {
    42  	*ServerOption
    43  	quicConn quic.EarlyConnection
    44  	uuid     uuid.UUID
    45  
    46  	authCh   chan struct{}
    47  	authOk   atomic.Bool
    48  	authOnce sync.Once
    49  
    50  	udpInputMap *xsync.MapOf[uint32, *atomic.Bool]
    51  }
    52  
    53  func (s *serverHandler) AuthOk() bool {
    54  	return s.authOk.Load()
    55  }
    56  
    57  func (s *serverHandler) HandleTimeout() {
    58  	s.authOnce.Do(func() {
    59  		_ = s.quicConn.CloseWithError(AuthenticationTimeout, "AuthenticationTimeout")
    60  		s.authOk.Store(false)
    61  		close(s.authCh)
    62  	})
    63  }
    64  
    65  func (s *serverHandler) HandleMessage(message []byte) (err error) {
    66  	buffer := bytes.NewBuffer(message)
    67  	packet, err := ReadPacket(buffer)
    68  	if err != nil {
    69  		return
    70  	}
    71  	return s.parsePacket(&packet, common.NATIVE)
    72  }
    73  
    74  func (s *serverHandler) parsePacket(packet *Packet, udpRelayMode common.UdpRelayMode) (err error) {
    75  	<-s.authCh
    76  	if !s.authOk.Load() {
    77  		return
    78  	}
    79  	var assocId uint32
    80  
    81  	assocId = packet.ASSOC_ID
    82  
    83  	writeClosed, _ := s.udpInputMap.LoadOrCompute(assocId, func() *atomic.Bool { return &atomic.Bool{} })
    84  	if writeClosed.Load() {
    85  		return nil
    86  	}
    87  
    88  	pc := &quicStreamPacketConn{
    89  		connId:                assocId,
    90  		quicConn:              s.quicConn,
    91  		inputConn:             nil,
    92  		udpRelayMode:          udpRelayMode,
    93  		maxUdpRelayPacketSize: s.MaxUdpRelayPacketSize,
    94  		deferQuicConnFn:       nil,
    95  		closeDeferFn:          nil,
    96  		writeClosed:           writeClosed,
    97  	}
    98  
    99  	return s.HandleUdpFn(packet.ADDR.SocksAddr(), &serverUDPPacket{
   100  		pc:     pc,
   101  		packet: packet,
   102  		rAddr:  N.NewCustomAddr("tuic", fmt.Sprintf("tuic-%s-%d", s.uuid, assocId), s.quicConn.RemoteAddr()), // for tunnel's handleUDPConn
   103  	})
   104  }
   105  
   106  func (s *serverHandler) HandleStream(conn *N.BufferedConn) (err error) {
   107  	connect, err := ReadConnect(conn)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	<-s.authCh
   112  	if !s.authOk.Load() {
   113  		return conn.Close()
   114  	}
   115  
   116  	buf := pool.GetBuffer()
   117  	defer pool.PutBuffer(buf)
   118  	err = s.HandleTcpFn(conn, connect.ADDR.SocksAddr())
   119  	if err != nil {
   120  		err = NewResponseFailed().WriteTo(buf)
   121  		defer conn.Close()
   122  	} else {
   123  		err = NewResponseSucceed().WriteTo(buf)
   124  	}
   125  	if err != nil {
   126  		_ = conn.Close()
   127  		return err
   128  	}
   129  	_, err = buf.WriteTo(conn)
   130  	if err != nil {
   131  		_ = conn.Close()
   132  		return err
   133  	}
   134  
   135  	return
   136  }
   137  
   138  func (s *serverHandler) HandleUniStream(reader *bufio.Reader) (err error) {
   139  	commandHead, err := ReadCommandHead(reader)
   140  	if err != nil {
   141  		return
   142  	}
   143  	switch commandHead.TYPE {
   144  	case AuthenticateType:
   145  		var authenticate Authenticate
   146  		authenticate, err = ReadAuthenticateWithHead(commandHead, reader)
   147  		if err != nil {
   148  			return
   149  		}
   150  		authOk := false
   151  		for _, tkn := range s.Tokens {
   152  			if authenticate.TKN == tkn {
   153  				authOk = true
   154  				break
   155  			}
   156  		}
   157  		s.authOnce.Do(func() {
   158  			if !authOk {
   159  				_ = s.quicConn.CloseWithError(AuthenticationFailed, "AuthenticationFailed")
   160  			}
   161  			s.authOk.Store(authOk)
   162  			close(s.authCh)
   163  		})
   164  	case PacketType:
   165  		var packet Packet
   166  		packet, err = ReadPacketWithHead(commandHead, reader)
   167  		if err != nil {
   168  			return
   169  		}
   170  		return s.parsePacket(&packet, common.QUIC)
   171  	case DissociateType:
   172  		var disassociate Dissociate
   173  		disassociate, err = ReadDissociateWithHead(commandHead, reader)
   174  		if err != nil {
   175  			return
   176  		}
   177  		if writeClosed, loaded := s.udpInputMap.LoadAndDelete(disassociate.ASSOC_ID); loaded {
   178  			writeClosed.Store(true)
   179  		}
   180  	case HeartbeatType:
   181  		var heartbeat Heartbeat
   182  		heartbeat, err = ReadHeartbeatWithHead(commandHead, reader)
   183  		if err != nil {
   184  			return
   185  		}
   186  		heartbeat.BytesLen()
   187  	}
   188  	return
   189  }
   190  
   191  type serverUDPPacket struct {
   192  	pc     *quicStreamPacketConn
   193  	packet *Packet
   194  	rAddr  net.Addr
   195  }
   196  
   197  func (s *serverUDPPacket) InAddr() net.Addr {
   198  	return s.pc.LocalAddr()
   199  }
   200  
   201  func (s *serverUDPPacket) LocalAddr() net.Addr {
   202  	return s.rAddr
   203  }
   204  
   205  func (s *serverUDPPacket) Data() []byte {
   206  	return s.packet.DATA
   207  }
   208  
   209  func (s *serverUDPPacket) WriteBack(b []byte, addr net.Addr) (n int, err error) {
   210  	return s.pc.WriteTo(b, addr)
   211  }
   212  
   213  func (s *serverUDPPacket) Drop() {
   214  	s.packet.DATA = nil
   215  }
   216  
   217  var _ C.UDPPacket = (*serverUDPPacket)(nil)
   218  var _ C.UDPPacketInAddr = (*serverUDPPacket)(nil)