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

     1  //go:build with_quic
     2  
     3  package v2rayquic
     4  
     5  import (
     6  	"context"
     7  	"net"
     8  	"os"
     9  
    10  	"github.com/sagernet/quic-go"
    11  	"github.com/sagernet/sing-box/adapter"
    12  	"github.com/sagernet/sing-box/common/tls"
    13  	C "github.com/sagernet/sing-box/constant"
    14  	"github.com/sagernet/sing-box/option"
    15  	"github.com/sagernet/sing-quic"
    16  	"github.com/sagernet/sing/common"
    17  	M "github.com/sagernet/sing/common/metadata"
    18  	N "github.com/sagernet/sing/common/network"
    19  )
    20  
    21  var _ adapter.V2RayServerTransport = (*Server)(nil)
    22  
    23  type Server struct {
    24  	ctx          context.Context
    25  	tlsConfig    tls.ServerConfig
    26  	quicConfig   *quic.Config
    27  	handler      adapter.V2RayServerTransportHandler
    28  	udpListener  net.PacketConn
    29  	quicListener qtls.Listener
    30  }
    31  
    32  func NewServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.ServerConfig, handler adapter.V2RayServerTransportHandler) (adapter.V2RayServerTransport, error) {
    33  	quicConfig := &quic.Config{
    34  		DisablePathMTUDiscovery: !C.IsLinux && !C.IsWindows,
    35  	}
    36  	if len(tlsConfig.NextProtos()) == 0 {
    37  		tlsConfig.SetNextProtos([]string{"h2", "http/1.1"})
    38  	}
    39  	server := &Server{
    40  		ctx:        ctx,
    41  		tlsConfig:  tlsConfig,
    42  		quicConfig: quicConfig,
    43  		handler:    handler,
    44  	}
    45  	return server, nil
    46  }
    47  
    48  func (s *Server) Network() []string {
    49  	return []string{N.NetworkUDP}
    50  }
    51  
    52  func (s *Server) Serve(listener net.Listener) error {
    53  	return os.ErrInvalid
    54  }
    55  
    56  func (s *Server) ServePacket(listener net.PacketConn) error {
    57  	quicListener, err := qtls.Listen(listener, s.tlsConfig, s.quicConfig)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	s.udpListener = listener
    62  	s.quicListener = quicListener
    63  	go s.acceptLoop()
    64  	return nil
    65  }
    66  
    67  func (s *Server) acceptLoop() {
    68  	for {
    69  		conn, err := s.quicListener.Accept(s.ctx)
    70  		if err != nil {
    71  			return
    72  		}
    73  		go func() {
    74  			hErr := s.streamAcceptLoop(conn)
    75  			if hErr != nil {
    76  				s.handler.NewError(conn.Context(), hErr)
    77  			}
    78  		}()
    79  	}
    80  }
    81  
    82  func (s *Server) streamAcceptLoop(conn quic.Connection) error {
    83  	for {
    84  		stream, err := conn.AcceptStream(s.ctx)
    85  		if err != nil {
    86  			return err
    87  		}
    88  		go s.handler.NewConnection(conn.Context(), &StreamWrapper{Conn: conn, Stream: stream}, M.Metadata{})
    89  	}
    90  }
    91  
    92  func (s *Server) Close() error {
    93  	return common.Close(s.udpListener, s.quicListener)
    94  }