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 }