package main import ( "context" "fmt" "net/http" "os" "os/signal" "github.com/urfave/cli/v2" "github.uio.no/torjus/dogtamer" "github.uio.no/torjus/dogtamer/config" "github.uio.no/torjus/dogtamer/server" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) const ( ExitSuccess = 0 ExitGenericError = 1 ) func main() { cli.VersionPrinter = func(c *cli.Context) { fmt.Println(dogtamer.GetVersion()) } app := &cli.App{ Name: "dogtamer", Version: dogtamer.Version, Authors: []*cli.Author{ { Name: "Torjus HÃ¥kestad", Email: "torjus@usit.uio.no", }, }, Flags: []cli.Flag{ &cli.StringFlag{ Name: "config", Usage: "Path to config-file", Aliases: []string{"c"}, }, }, Commands: []*cli.Command{ { Name: "serve", Usage: "Start dogtamer server", Action: ActionServe, }, }, } err := app.Run(os.Args) if err != nil { fmt.Printf("Error: %s\n", err) os.Exit(ExitGenericError) } } func ActionServe(c *cli.Context) error { logger := setupServerLogger() cfg, err := config.FromDefaultLocations() if err != nil { logger.Warn("No config file found.") } ctx, cancel := context.WithCancel(context.Background()) // Setup RTMP-server s := server.NewRTMPServer(ctx, cfg.RTMPListenAddr) s.Logger = logger // Setup web-server webDone := make(chan struct{}) if cfg.HTTPServerEnable { ws := server.NewWebServer(ctx, s) ws.ListenAddr = cfg.HTTPListenAddr ws.Logger = logger go func() { s.Logger.Info("Starting web-server.") err := ws.Serve() if err != nil && err != http.ErrServerClosed { s.Logger.Infow("Web server shut down with error.", "err", err) } close(webDone) }() } else { close(webDone) } // Listen for SIGINT sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt) go func() { <-sigChan s.Logger.Debug("Got shutdown signal.") cancel() }() // Start RTMP-server s.Logger.Info("Starting RTMP-server.") if err := s.Listen(); err != nil { return cli.Exit(err, ExitGenericError) } // Wait for webserver to exit, if started <-webDone s.Logger.Info("Server shut down.") return nil } func setupServerLogger() *zap.SugaredLogger { logEncoderConfig := zap.NewProductionEncoderConfig() logEncoderConfig.EncodeCaller = zapcore.ShortCallerEncoder logEncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder logEncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder logEncoderConfig.EncodeDuration = zapcore.StringDurationEncoder rootLoggerConfig := &zap.Config{ Level: zap.NewAtomicLevelAt(zap.DebugLevel), OutputPaths: []string{"stdout"}, ErrorOutputPaths: []string{"stdout"}, Encoding: "console", EncoderConfig: logEncoderConfig, } rootLogger, err := rootLoggerConfig.Build() if err != nil { panic(err) } return rootLogger.Named("RTMP").WithOptions().Sugar() }