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