149 lines
3.5 KiB
Go
149 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
|
|
"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 {
|
|
// Setup temporary logger, incase config could not be read
|
|
logger := setupServerLogger("INFO")
|
|
cfg, err := config.FromDefaultLocations()
|
|
if err != nil {
|
|
logger.Warn("No config file found.")
|
|
}
|
|
// Setup proper logger
|
|
logger = setupServerLogger(cfg.LogLevel)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
// Setup RTMP-server
|
|
s := server.NewRTMPServer(ctx, cfg.RTMPListenAddr)
|
|
s.Logger = logger
|
|
s.Hostname = cfg.Hostname
|
|
|
|
// 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.Infow("Starting HTTP server.", "listen_addr", ws.ListenAddr)
|
|
err := ws.Serve()
|
|
if err != nil && err != http.ErrServerClosed {
|
|
s.Logger.Infow("HTTP 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.Infow("Starting RTMP server.", "listen_addr", s.ListenAddr)
|
|
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(loglevel string) *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,
|
|
DisableCaller: true,
|
|
}
|
|
|
|
switch strings.ToUpper(loglevel) {
|
|
case "DEBUG":
|
|
rootLoggerConfig.DisableCaller = false
|
|
rootLoggerConfig.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
|
|
case "INFO":
|
|
rootLoggerConfig.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
|
|
case "WARN", "WARNING":
|
|
rootLoggerConfig.Level = zap.NewAtomicLevelAt(zap.WarnLevel)
|
|
case "ERR", "ERROR":
|
|
rootLoggerConfig.Level = zap.NewAtomicLevelAt(zap.ErrorLevel)
|
|
}
|
|
|
|
rootLogger, err := rootLoggerConfig.Build()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return rootLogger.Named("RTMP").WithOptions().Sugar()
|
|
}
|