package app import ( "context" "crypto/tls" "errors" "fmt" "net" "strings" "time" "git.yuntuo.hk/k2safe/go-omni/config" h2transport "git.yuntuo.hk/k2safe/go-omni/transport/http2" "git.yuntuo.hk/k2safe/go-omni/transport/native" ) // ServeContext serves a caller-created listener using the configured transport // and TLS. App takes ownership of the listener, including on startup failure, // and runs resource cleanup after the server has stopped. func (a *App) ServeContext(ctx context.Context, listener net.Listener) error { if listener == nil { return errors.Join(errors.New("go-omni: nil listener"), a.Close()) } defer listener.Close() if ctx == nil { ctx = context.Background() } if ctx.Err() != nil { _ = listener.Close() return a.Close() } serve, err := a.prepareTransport() if err != nil { _ = listener.Close() return errors.Join(err, a.Close()) } return errors.Join(serve(ctx, listener), a.Close()) } func (a *App) prepareTransport() (func(context.Context, net.Listener) error, error) { if err := a.config.ValidateTransport(); err != nil { return nil, err } shutdownTimeout := a.config.ShutdownTimeout if shutdownTimeout <= 0 { shutdownTimeout = 10 * time.Second } var tlsConfig *tls.Config if strings.TrimSpace(a.config.TLS.CertFile) != "" { certificate, err := tls.LoadX509KeyPair(a.config.TLS.CertFile, a.config.TLS.KeyFile) if err != nil { return nil, fmt.Errorf("go-omni: load TLS certificate: %w", err) } tlsConfig = &tls.Config{Certificates: []tls.Certificate{certificate}, MinVersion: tls.VersionTLS12} } switch a.config.Transport { case config.TransportNative: server := native.New(a) server.ShutdownTimeout = shutdownTimeout if tlsConfig != nil { return func(ctx context.Context, listener net.Listener) error { return server.ServeTLS(ctx, listener, tlsConfig) }, nil } return server.Serve, nil case config.TransportHTTP2: server := h2transport.New(a) server.ShutdownTimeout = shutdownTimeout return func(ctx context.Context, listener net.Listener) error { return server.ServeTLS(ctx, listener, tlsConfig) }, nil default: server := a.NewServer("") server.TLSConfig = tlsConfig return func(ctx context.Context, listener net.Listener) error { return a.serveContext(ctx, server, listener) }, nil } }