github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/transport/v2rayquic/server.go (about)

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