scope config variables.

This commit is contained in:
Miroslav Šedivý 2021-03-16 15:24:58 +01:00
parent a74bf9986b
commit 524d895db8
10 changed files with 107 additions and 115 deletions

View File

@ -104,7 +104,7 @@ COPY runtime/icon-theme /home/$USERNAME/.icons/default
# set default envs # set default envs
ENV USER=$USERNAME ENV USER=$USERNAME
ENV DISPLAY=:99.0 ENV DISPLAY=:99.0
ENV NEKO_BIND=:8080 ENV NEKO_SERVER_BIND=:8080
# #
# copy executabe from previous stage # copy executabe from previous stage

View File

@ -6,6 +6,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"time" "time"
"github.com/rs/zerolog" "github.com/rs/zerolog"
@ -93,6 +94,7 @@ func init() {
} }
viper.SetEnvPrefix("NEKO") viper.SetEnvPrefix("NEKO")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv() // read in environment variables that match viper.AutomaticEnv() // read in environment variables that match
if err := viper.ReadInConfig(); err != nil { if err := viper.ReadInConfig(); err != nil {

View File

@ -62,7 +62,7 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
desktop: desktop, desktop: desktop,
streaming: false, streaming: false,
broadcast: broadcastNew(broadcastPipeline), broadcast: broadcastNew(broadcastPipeline),
screencast: screencastNew(config.Screencast, screencastPipeline), screencast: screencastNew(config.ScreencastEnabled, screencastPipeline),
audio: streamNew(config.AudioCodec, func() string { audio: streamNew(config.AudioCodec, func() string {
if config.AudioPipeline != "" { if config.AudioPipeline != "" {
return config.AudioPipeline return config.AudioPipeline

View File

@ -3,6 +3,7 @@ package config
import ( import (
"os" "os"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -18,7 +19,7 @@ type Capture struct {
BroadcastPipeline string BroadcastPipeline string
Screencast bool ScreencastEnabled bool
ScreencastRate string ScreencastRate string
ScreencastQuality string ScreencastQuality string
ScreencastPipeline string ScreencastPipeline string
@ -26,60 +27,45 @@ type Capture struct {
func (Capture) Init(cmd *cobra.Command) error { func (Capture) Init(cmd *cobra.Command) error {
// audio // audio
cmd.PersistentFlags().String("audio_device", "auto_null.monitor", "audio device to capture") cmd.PersistentFlags().String("capture.audio.device", "auto_null.monitor", "audio device to capture")
if err := viper.BindPFlag("audio_device", cmd.PersistentFlags().Lookup("audio_device")); err != nil { if err := viper.BindPFlag("capture.audio.device", cmd.PersistentFlags().Lookup("capture.audio.device")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("audio_pipeline", "", "gstreamer pipeline used for audio streaming") cmd.PersistentFlags().String("capture.audio.codec", "opus", "audio codec to be used")
if err := viper.BindPFlag("audio_pipeline", cmd.PersistentFlags().Lookup("audio_pipeline")); err != nil { if err := viper.BindPFlag("capture.audio.codec", cmd.PersistentFlags().Lookup("capture.audio.codec")); err != nil {
return err return err
} }
cmd.PersistentFlags().Bool("opus", false, "use Opus audio codec") cmd.PersistentFlags().String("capture.audio.pipeline", "", "gstreamer pipeline used for audio streaming")
if err := viper.BindPFlag("opus", cmd.PersistentFlags().Lookup("opus")); err != nil { if err := viper.BindPFlag("capture.audio.pipeline", cmd.PersistentFlags().Lookup("capture.audio.pipeline")); err != nil {
return err
}
cmd.PersistentFlags().Bool("g722", false, "use G722 audio codec")
if err := viper.BindPFlag("g722", cmd.PersistentFlags().Lookup("g722")); err != nil {
return err
}
cmd.PersistentFlags().Bool("pcmu", false, "use PCMU audio codec")
if err := viper.BindPFlag("pcmu", cmd.PersistentFlags().Lookup("pcmu")); err != nil {
return err
}
cmd.PersistentFlags().Bool("pcma", false, "use PCMA audio codec")
if err := viper.BindPFlag("pcma", cmd.PersistentFlags().Lookup("pcma")); err != nil {
return err return err
} }
// broadcast // broadcast
cmd.PersistentFlags().String("broadcast_pipeline", "", "gstreamer pipeline used for broadcasting") cmd.PersistentFlags().String("capture.broadcast.pipeline", "", "gstreamer pipeline used for broadcasting")
if err := viper.BindPFlag("broadcast_pipeline", cmd.PersistentFlags().Lookup("broadcast_pipeline")); err != nil { if err := viper.BindPFlag("capture.broadcast.pipeline", cmd.PersistentFlags().Lookup("capture.broadcast.pipeline")); err != nil {
return err return err
} }
// screencast // screencast
cmd.PersistentFlags().Bool("screencast", false, "enable screencast") cmd.PersistentFlags().Bool("capture.screencast.enabled", false, "enable screencast")
if err := viper.BindPFlag("screencast", cmd.PersistentFlags().Lookup("screencast")); err != nil { if err := viper.BindPFlag("capture.screencast.enabled", cmd.PersistentFlags().Lookup("capture.screencast.enabled")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("screencast_rate", "10/1", "screencast frame rate") cmd.PersistentFlags().String("capture.screencast.rate", "10/1", "screencast frame rate")
if err := viper.BindPFlag("screencast_rate", cmd.PersistentFlags().Lookup("screencast_rate")); err != nil { if err := viper.BindPFlag("capture.screencast.rate", cmd.PersistentFlags().Lookup("capture.screencast.rate")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("screencast_quality", "60", "screencast JPEG quality") cmd.PersistentFlags().String("capture.screencast.quality", "60", "screencast JPEG quality")
if err := viper.BindPFlag("screencast_quality", cmd.PersistentFlags().Lookup("screencast_quality")); err != nil { if err := viper.BindPFlag("capture.screencast.quality", cmd.PersistentFlags().Lookup("capture.screencast.quality")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("screencast_pipeline", "", "gstreamer pipeline used for screencasting") cmd.PersistentFlags().String("capture.screencast.pipeline", "", "gstreamer pipeline used for screencasting")
if err := viper.BindPFlag("screencast_pipeline", cmd.PersistentFlags().Lookup("screencast_pipeline")); err != nil { if err := viper.BindPFlag("capture.screencast.pipeline", cmd.PersistentFlags().Lookup("capture.screencast.pipeline")); err != nil {
return err return err
} }
@ -90,26 +76,28 @@ func (s *Capture) Set() {
// Display is provided by env variable // Display is provided by env variable
s.Display = os.Getenv("DISPLAY") s.Display = os.Getenv("DISPLAY")
s.AudioDevice = viper.GetString("audio_device") s.AudioDevice = viper.GetString("capture.audio.device")
s.AudioPipeline = viper.GetString("audio_pipeline") s.AudioPipeline = viper.GetString("capture.audio.pipeline")
if viper.GetBool("opus") { audioCodec := viper.GetString("capture.audio.codec")
switch audioCodec {
case "opus":
s.AudioCodec = codec.Opus() s.AudioCodec = codec.Opus()
} else if viper.GetBool("g722") { case "g722":
s.AudioCodec = codec.G722() s.AudioCodec = codec.G722()
} else if viper.GetBool("pcmu") { case "pcmu":
s.AudioCodec = codec.PCMU() s.AudioCodec = codec.PCMU()
} else if viper.GetBool("pcma") { case "pcma":
s.AudioCodec = codec.PCMA() s.AudioCodec = codec.PCMA()
} else { default:
// default log.Warn().Str("codec", audioCodec).Msgf("unknown audio codec, using Opus")
s.AudioCodec = codec.Opus() s.AudioCodec = codec.Opus()
} }
s.BroadcastPipeline = viper.GetString("broadcast_pipeline") s.BroadcastPipeline = viper.GetString("capturebroadcast.pipeline")
s.Screencast = viper.GetBool("screencast") s.ScreencastEnabled = viper.GetBool("capture.screencast.enabled")
s.ScreencastRate = viper.GetString("screencast_rate") s.ScreencastRate = viper.GetString("capture.screencast.rate")
s.ScreencastQuality = viper.GetString("screencast_quality") s.ScreencastQuality = viper.GetString("capture.screencast.quality")
s.ScreencastPipeline = viper.GetString("screencast_pipeline") s.ScreencastPipeline = viper.GetString("capture.screencast.pipeline")
} }

View File

@ -18,8 +18,8 @@ type Desktop struct {
} }
func (Desktop) Init(cmd *cobra.Command) error { func (Desktop) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().String("screen", "1280x720@30", "default screen size and framerate") cmd.PersistentFlags().String("desktop.screen", "1280x720@30", "default screen size and framerate")
if err := viper.BindPFlag("screen", cmd.PersistentFlags().Lookup("screen")); err != nil { if err := viper.BindPFlag("desktop.screen", cmd.PersistentFlags().Lookup("desktop.screen")); err != nil {
return err return err
} }
@ -35,7 +35,7 @@ func (s *Desktop) Set() {
s.ScreenRate = 30 s.ScreenRate = 30
r := regexp.MustCompile(`([0-9]{1,4})x([0-9]{1,4})@([0-9]{1,3})`) r := regexp.MustCompile(`([0-9]{1,4})x([0-9]{1,4})@([0-9]{1,3})`)
res := r.FindStringSubmatch(viper.GetString("screen")) res := r.FindStringSubmatch(viper.GetString("desktop.screen"))
if len(res) > 0 { if len(res) > 0 {
width, err1 := strconv.ParseInt(res[1], 10, 64) width, err1 := strconv.ParseInt(res[1], 10, 64)

View File

@ -6,30 +6,36 @@ import (
) )
type Member struct { type Member struct {
Provider string Provider string
FilePath string
Password string // file provider
AdminPassword string FilePath string
// object provider
ObjectUserPassword string
ObjectAdminPassword string
} }
func (Member) Init(cmd *cobra.Command) error { func (Member) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().String("members_provider", "object", "choose members provider") cmd.PersistentFlags().String("member.provider", "object", "choose member provider")
if err := viper.BindPFlag("members_provider", cmd.PersistentFlags().Lookup("members_provider")); err != nil { if err := viper.BindPFlag("member.provider", cmd.PersistentFlags().Lookup("member.provider")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("members_file_path", "", "mebmer file provider path") // file provider
if err := viper.BindPFlag("members_file_path", cmd.PersistentFlags().Lookup("members_file_path")); err != nil { cmd.PersistentFlags().String("member.file.path", "", "member file provider: storage path")
if err := viper.BindPFlag("member.file.path", cmd.PersistentFlags().Lookup("member.file.path")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("password", "neko", "password for connecting to stream") // object provider
if err := viper.BindPFlag("password", cmd.PersistentFlags().Lookup("password")); err != nil { cmd.PersistentFlags().String("member.object.user_password", "", "member object provider: user password")
if err := viper.BindPFlag("member.object.user_password", cmd.PersistentFlags().Lookup("member.object.user_password")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("password_admin", "admin", "admin password for connecting to stream") cmd.PersistentFlags().String("member.object.admin_password", "", "member object provider: admin password")
if err := viper.BindPFlag("password_admin", cmd.PersistentFlags().Lookup("password_admin")); err != nil { if err := viper.BindPFlag("member.object.admin_password", cmd.PersistentFlags().Lookup("member.object.admin_password")); err != nil {
return err return err
} }
@ -37,8 +43,12 @@ func (Member) Init(cmd *cobra.Command) error {
} }
func (s *Member) Set() { func (s *Member) Set() {
s.Provider = viper.GetString("members_provider") s.Provider = viper.GetString("member.provider")
s.FilePath = viper.GetString("members_file_path")
s.Password = viper.GetString("password") // file provider
s.AdminPassword = viper.GetString("password_admin") s.FilePath = viper.GetString("member.file.path")
// object provider
s.ObjectUserPassword = viper.GetString("member.object.user_password")
s.ObjectAdminPassword = viper.GetString("member.object.admin_password")
} }

View File

@ -13,56 +13,48 @@ type Server struct {
Bind string Bind string
Static string Static string
CORS []string CORS []string
//Proxy bool
} }
func (Server) Init(cmd *cobra.Command) error { func (Server) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().String("bind", "127.0.0.1:8080", "address/port/socket to serve neko") cmd.PersistentFlags().String("server.bind", "127.0.0.1:8080", "address/port/socket to serve neko")
if err := viper.BindPFlag("bind", cmd.PersistentFlags().Lookup("bind")); err != nil { if err := viper.BindPFlag("server.bind", cmd.PersistentFlags().Lookup("server.bind")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("cert", "", "path to the SSL cert used to secure the neko server") cmd.PersistentFlags().String("server.cert", "", "path to the SSL cert used to secure the neko server")
if err := viper.BindPFlag("cert", cmd.PersistentFlags().Lookup("cert")); err != nil { if err := viper.BindPFlag("server.cert", cmd.PersistentFlags().Lookup("server.cert")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("key", "", "path to the SSL key used to secure the neko server") cmd.PersistentFlags().String("server.key", "", "path to the SSL key used to secure the neko server")
if err := viper.BindPFlag("key", cmd.PersistentFlags().Lookup("key")); err != nil { if err := viper.BindPFlag("server.key", cmd.PersistentFlags().Lookup("server.key")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("static", "", "path to neko client files to serve") cmd.PersistentFlags().String("server.static", "", "path to neko client files to serve")
if err := viper.BindPFlag("static", cmd.PersistentFlags().Lookup("static")); err != nil { if err := viper.BindPFlag("server.static", cmd.PersistentFlags().Lookup("server.static")); err != nil {
return err return err
} }
cmd.PersistentFlags().StringSlice("cors", []string{"*"}, "list of allowed origins for CORS") cmd.PersistentFlags().StringSlice("server.cors", []string{"*"}, "list of allowed origins for CORS")
if err := viper.BindPFlag("cors", cmd.PersistentFlags().Lookup("cors")); err != nil { if err := viper.BindPFlag("server.cors", cmd.PersistentFlags().Lookup("server.cors")); err != nil {
return err return err
} }
//cmd.PersistentFlags().Bool("proxy", false, "allow reverse proxies")
//if err := viper.BindPFlag("proxy", cmd.PersistentFlags().Lookup("proxy")); err != nil {
// return err
//}
return nil return nil
} }
func (s *Server) Set() { func (s *Server) Set() {
s.Cert = viper.GetString("cert") s.Cert = viper.GetString("server.cert")
s.Key = viper.GetString("key") s.Key = viper.GetString("server.key")
s.Bind = viper.GetString("bind") s.Bind = viper.GetString("server.bind")
s.Static = viper.GetString("static") s.Static = viper.GetString("server.static")
s.CORS = viper.GetStringSlice("cors") s.CORS = viper.GetStringSlice("server.cors")
in, _ := utils.ArrayIn("*", s.CORS) in, _ := utils.ArrayIn("*", s.CORS)
if len(s.CORS) == 0 || in { if len(s.CORS) == 0 || in {
s.CORS = []string{"*"} s.CORS = []string{"*"}
} }
//s.Proxy = viper.GetBool("proxy")
} }
func (s *Server) AllowOrigin(origin string) bool { func (s *Server) AllowOrigin(origin string) bool {

View File

@ -11,13 +11,13 @@ type Session struct {
} }
func (Session) Init(cmd *cobra.Command) error { func (Session) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().Bool("implicit_hosting", true, "allow implicit control switching") cmd.PersistentFlags().Bool("session.implicit_hosting", true, "allow implicit control switching")
if err := viper.BindPFlag("implicit_hosting", cmd.PersistentFlags().Lookup("implicit_hosting")); err != nil { if err := viper.BindPFlag("session.implicit_hosting", cmd.PersistentFlags().Lookup("session.implicit_hosting")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("api_token", "", "API token for interacting with external services") cmd.PersistentFlags().String("session.api_token", "", "API token for interacting with external services")
if err := viper.BindPFlag("api_token", cmd.PersistentFlags().Lookup("api_token")); err != nil { if err := viper.BindPFlag("session.api_token", cmd.PersistentFlags().Lookup("session.api_token")); err != nil {
return err return err
} }
@ -25,6 +25,6 @@ func (Session) Init(cmd *cobra.Command) error {
} }
func (s *Session) Set() { func (s *Session) Set() {
s.ImplicitHosting = viper.GetBool("implicit_hosting") s.ImplicitHosting = viper.GetBool("session.implicit_hosting")
s.APIToken = viper.GetString("api_token") s.APIToken = viper.GetString("session.api_token")
} }

View File

@ -29,33 +29,33 @@ const (
) )
func (WebRTC) Init(cmd *cobra.Command) error { func (WebRTC) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().Bool("icelite", false, "configures whether or not the ice agent should be a lite agent") cmd.PersistentFlags().Bool("webrtc.icelite", false, "configures whether or not the ICE agent should be a lite agent")
if err := viper.BindPFlag("icelite", cmd.PersistentFlags().Lookup("icelite")); err != nil { if err := viper.BindPFlag("webrtc.icelite", cmd.PersistentFlags().Lookup("webrtc.icelite")); err != nil {
return err return err
} }
cmd.PersistentFlags().Bool("icetrickle", true, "configures whether cadidates should be sent asynchronously using Trickle ICE") cmd.PersistentFlags().Bool("webrtc.icetrickle", true, "configures whether cadidates should be sent asynchronously using Trickle ICE")
if err := viper.BindPFlag("icetrickle", cmd.PersistentFlags().Lookup("icetrickle")); err != nil { if err := viper.BindPFlag("webrtc.icetrickle", cmd.PersistentFlags().Lookup("webrtc.icetrickle")); err != nil {
return err return err
} }
cmd.PersistentFlags().StringSlice("iceserver", []string{"stun:stun.l.google.com:19302"}, "describes a single STUN and TURN server that can be used by the ICEAgent to establish a connection with a peer") cmd.PersistentFlags().StringSlice("webrtc.iceserver", []string{"stun:stun.l.google.com:19302"}, "describes a single STUN and TURN server that can be used by the ICEAgent to establish a connection with a peer")
if err := viper.BindPFlag("iceserver", cmd.PersistentFlags().Lookup("iceserver")); err != nil { if err := viper.BindPFlag("webrtc.iceserver", cmd.PersistentFlags().Lookup("webrtc.iceserver")); err != nil {
return err return err
} }
cmd.PersistentFlags().StringSlice("nat1to1", []string{}, "sets a list of external IP addresses of 1:1 (D)NAT and a candidate type for which the external IP address is used") cmd.PersistentFlags().StringSlice("webrtc.nat1to1", []string{}, "sets a list of external IP addresses of 1:1 (D)NAT and a candidate type for which the external IP address is used")
if err := viper.BindPFlag("nat1to1", cmd.PersistentFlags().Lookup("nat1to1")); err != nil { if err := viper.BindPFlag("webrtc.nat1to1", cmd.PersistentFlags().Lookup("webrtc.nat1to1")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("ip_retrieval_url", "https://checkip.amazonaws.com", "URL address used for retrieval of the external IP address") cmd.PersistentFlags().String("webrtc.ip_retrieval_url", "https://checkip.amazonaws.com", "URL address used for retrieval of the external IP address")
if err := viper.BindPFlag("ip_retrieval_url", cmd.PersistentFlags().Lookup("ip_retrieval_url")); err != nil { if err := viper.BindPFlag("webrtc.ip_retrieval_url", cmd.PersistentFlags().Lookup("webrtc.ip_retrieval_url")); err != nil {
return err return err
} }
cmd.PersistentFlags().String("epr", fmt.Sprintf("%d-%d", defEprMin, defEprMax), "limits the pool of ephemeral ports that ICE UDP connections can allocate from") cmd.PersistentFlags().String("webrtc.epr", fmt.Sprintf("%d-%d", defEprMin, defEprMax), "limits the pool of ephemeral ports that ICE UDP connections can allocate from")
if err := viper.BindPFlag("epr", cmd.PersistentFlags().Lookup("epr")); err != nil { if err := viper.BindPFlag("webrtc.epr", cmd.PersistentFlags().Lookup("webrtc.epr")); err != nil {
return err return err
} }
@ -63,12 +63,12 @@ func (WebRTC) Init(cmd *cobra.Command) error {
} }
func (s *WebRTC) Set() { func (s *WebRTC) Set() {
s.ICELite = viper.GetBool("icelite") s.ICELite = viper.GetBool("webrtc.icelite")
s.ICETrickle = viper.GetBool("icetrickle") s.ICETrickle = viper.GetBool("webrtc.icetrickle")
s.ICEServers = viper.GetStringSlice("iceserver") s.ICEServers = viper.GetStringSlice("webrtc.iceserver")
s.NAT1To1IPs = viper.GetStringSlice("nat1to1") s.NAT1To1IPs = viper.GetStringSlice("webrtc.nat1to1")
s.IpRetrievalUrl = viper.GetString("ip_retrieval_url") s.IpRetrievalUrl = viper.GetString("webrtc.ip_retrieval_url")
if s.IpRetrievalUrl != "" && len(s.NAT1To1IPs) == 0 { if s.IpRetrievalUrl != "" && len(s.NAT1To1IPs) == 0 {
ip, err := utils.HttpRequestGET(s.IpRetrievalUrl) ip, err := utils.HttpRequestGET(s.IpRetrievalUrl)
if err == nil { if err == nil {
@ -81,7 +81,7 @@ func (s *WebRTC) Set() {
min := uint16(defEprMin) min := uint16(defEprMin)
max := uint16(defEprMax) max := uint16(defEprMax)
epr := viper.GetString("epr") epr := viper.GetString("webrtc.epr")
ports := strings.SplitN(epr, "-", -1) ports := strings.SplitN(epr, "-", -1)
if len(ports) > 1 { if len(ports) > 1 {
start, err := strconv.ParseUint(ports[0], 10, 16) start, err := strconv.ParseUint(ports[0], 10, 16)

View File

@ -28,8 +28,8 @@ func New(sessions types.SessionManager, config *config.Member) *MemberManagerCtx
}) })
case "object": case "object":
manager.provider = object.New(object.Config{ manager.provider = object.New(object.Config{
AdminPassword: config.AdminPassword, AdminPassword: config.ObjectAdminPassword,
UserPassword: config.Password, UserPassword: config.ObjectUserPassword,
}) })
case "dummy": case "dummy":
fallthrough fallthrough