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 }