Skip to content

Commit

Permalink
Config system
Browse files Browse the repository at this point in the history
see also issue mumble-voip#21
  • Loading branch information
rubenseyer committed Feb 13, 2018
1 parent cb1d3db commit cef326e
Show file tree
Hide file tree
Showing 10 changed files with 516 additions and 47 deletions.
24 changes: 13 additions & 11 deletions cmd/grumble/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ var usageTmpl = `usage: grumble [options]
--log <log-path> (default: $DATADIR/grumble.log)
Log file path.
--config, --ini <config.path> (default: $DATADIR/grumble.ini)
Config file path.
--regen-keys
Force grumble to regenerate its global RSA
keypair (and certificate).
Expand All @@ -46,12 +49,13 @@ var usageTmpl = `usage: grumble [options]
`

type args struct {
ShowHelp bool
DataDir string
LogPath string
RegenKeys bool
SQLiteDB string
CleanUp bool
ShowHelp bool
DataDir string
LogPath string
ConfigPath string
RegenKeys bool
SQLiteDB string
CleanUp bool
}

func defaultDataDir() string {
Expand All @@ -63,10 +67,6 @@ func defaultDataDir() string {
return filepath.Join(homedir, dirname)
}

func defaultLogPath() string {
return filepath.Join(defaultDataDir(), "grumble.log")
}

func Usage() {
t, err := template.New("usage").Parse(usageTmpl)
if err != nil {
Expand All @@ -92,7 +92,9 @@ func init() {

flag.BoolVar(&Args.ShowHelp, "help", false, "")
flag.StringVar(&Args.DataDir, "datadir", defaultDataDir(), "")
flag.StringVar(&Args.LogPath, "log", defaultLogPath(), "")
flag.StringVar(&Args.LogPath, "log", "", "")
flag.StringVar(&Args.ConfigPath, "ini", "", "")
flag.StringVar(&Args.ConfigPath, "config", "", "")
flag.BoolVar(&Args.RegenKeys, "regen-keys", false, "")

flag.StringVar(&Args.SQLiteDB, "import-murmurdb", "", "")
Expand Down
15 changes: 7 additions & 8 deletions cmd/grumble/freeze.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ package main

import (
"errors"
"github.com/golang/protobuf/proto"
"io"
"io/ioutil"
"log"
"mumble.info/grumble/pkg/acl"
"mumble.info/grumble/pkg/ban"
"mumble.info/grumble/pkg/freezer"
"mumble.info/grumble/pkg/mumbleproto"
"mumble.info/grumble/pkg/serverconf"
"os"
"path/filepath"
"strconv"
"time"

"github.com/golang/protobuf/proto"
"mumble.info/grumble/pkg/acl"
"mumble.info/grumble/pkg/ban"
"mumble.info/grumble/pkg/freezer"
"mumble.info/grumble/pkg/mumbleproto"
)

// Freeze a server to disk and closes the log file.
Expand Down Expand Up @@ -418,11 +418,10 @@ func NewServerFromFrozen(name string) (s *Server, err error) {
}
}

s, err = NewServer(id)
s, err = NewServer(id, configFile.ServerConfig(id, cfgMap))
if err != nil {
return nil, err
}
s.cfg = serverconf.New(cfgMap)

// Unfreeze the server's frozen bans.
s.UnfreezeBanList(fs.BanList)
Expand Down
55 changes: 45 additions & 10 deletions cmd/grumble/grumble.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import (
"flag"
"fmt"
"log"
"mumble.info/grumble/pkg/blobstore"
"mumble.info/grumble/pkg/logtarget"
"os"
"path/filepath"
"regexp"

"mumble.info/grumble/pkg/blobstore"
"mumble.info/grumble/pkg/logtarget"
"mumble.info/grumble/pkg/serverconf"
)

var servers map[int64]*Server
var blobStore blobstore.BlobStore
var configFile *serverconf.ConfigFile

func main() {
var err error
Expand All @@ -35,10 +38,42 @@ func main() {
}
dataDir.Close()

// Open the config file
var configFn string
if Args.ConfigPath != "" {
configFn = Args.ConfigPath
} else {
configFn = filepath.Join(Args.DataDir, "grumble.ini")
}
if filepath.Ext(configFn) == ".ini" {
// Create it if it doesn't exist
configFd, err := os.OpenFile(configFn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0700)
if err == nil {
configFd.WriteString(serverconf.DefaultConfigFile)
log.Fatalf("Default config written to %v\n", configFn)
configFd.Close()
} else if err != nil && !os.IsExist(err) {
log.Fatalf("Unable to open config file (%v): %v", configFn, err)
return
}
}
configFile, err = serverconf.NewConfigFile(configFn)
if err != nil {
log.Fatalf("Unable to open config file (%v): %v", configFn, err)
return
}
config := configFile.GlobalConfig()

// Set up logging
err = logtarget.Target.OpenFile(Args.LogPath)
var logFn string
if Args.LogPath != "" {
logFn = Args.LogPath
} else {
logFn = config.PathValue("LogPath", Args.DataDir)
}
err = logtarget.Target.OpenFile(logFn)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to open log file (%v): %v", Args.LogPath, err)
fmt.Fprintf(os.Stderr, "Unable to open log file (%v): %v", logFn, err)
return
}
log.SetPrefix("[G] ")
Expand All @@ -64,9 +99,9 @@ func main() {
// and corresponding certificate.
// These are used as the default certificate of all virtual servers
// and the SSH admin console, but can be overridden using the "key"
// and "cert" arguments to Grumble.
certFn := filepath.Join(Args.DataDir, "cert.pem")
keyFn := filepath.Join(Args.DataDir, "key.pem")
// and "cert" arguments to Grumble. todo(rubenseyer) implement override by cli
certFn := config.PathValue("CertPath", Args.DataDir)
keyFn := config.PathValue("KeyPath", Args.DataDir)
shouldRegen := false
if Args.RegenKeys {
shouldRegen = true
Expand Down Expand Up @@ -163,10 +198,10 @@ func main() {
if err != nil {
log.Fatalf("Unable to read file from data directory: %v", err.Error())
}
// The data dir file descriptor.
// The servers dir file descriptor.
err = serversDir.Close()
if err != nil {
log.Fatalf("Unable to close data directory: %v", err.Error())
log.Fatalf("Unable to close servers directory: %v", err.Error())
return
}

Expand All @@ -190,7 +225,7 @@ func main() {

// If no servers were found, create the default virtual server.
if len(servers) == 0 {
s, err := NewServer(1)
s, err := NewServer(1, configFile.ServerConfig(1, nil))
if err != nil {
log.Fatalf("Couldn't start server: %s", err.Error())
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/grumble/murmurdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ import (
"database/sql"
"errors"
"log"
"mumble.info/grumble/pkg/acl"
"mumble.info/grumble/pkg/ban"
"net"
"os"
"path/filepath"
"strconv"

"mumble.info/grumble/pkg/acl"
"mumble.info/grumble/pkg/ban"
)

const (
Expand Down Expand Up @@ -85,7 +86,7 @@ func MurmurImport(filename string) (err error) {

// Create a new Server from a Murmur SQLite database
func NewServerFromSQLite(id int64, db *sql.DB) (s *Server, err error) {
s, err = NewServer(id)
s, err = NewServer(id, nil)
if err != nil {
return nil, err
}
Expand Down
30 changes: 17 additions & 13 deletions cmd/grumble/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/golang/protobuf/proto"
"hash"
"log"
"net"
"net/http"
"strings"
"sync"
"time"

"github.com/golang/protobuf/proto"
"mumble.info/grumble/pkg/acl"
"mumble.info/grumble/pkg/ban"
"mumble.info/grumble/pkg/freezer"
Expand All @@ -27,12 +33,6 @@ import (
"mumble.info/grumble/pkg/serverconf"
"mumble.info/grumble/pkg/sessionpool"
"mumble.info/grumble/pkg/web"
"net"
"net/http"
"path/filepath"
"strings"
"sync"
"time"
)

// The default port a Murmur server listens on
Expand Down Expand Up @@ -137,12 +137,16 @@ func (lf clientLogForwarder) Write(incoming []byte) (int, error) {
}

// Allocate a new Murmur instance
func NewServer(id int64) (s *Server, err error) {
func NewServer(id int64, config *serverconf.Config) (s *Server, err error) {
s = new(Server)

s.Id = id

s.cfg = serverconf.New(nil)
if config == nil {
s.cfg = serverconf.New(nil)
} else {
s.cfg = config
}

s.Users = make(map[uint32]*User)
s.UserCertMap = make(map[string]*User)
Expand Down Expand Up @@ -1421,8 +1425,8 @@ func (server *Server) Start() (err error) {
*/

// Wrap a TLS listener around the TCP connection
certFn := filepath.Join(Args.DataDir, "cert.pem")
keyFn := filepath.Join(Args.DataDir, "key.pem")
certFn := server.cfg.PathValue("CertPath", Args.DataDir)
keyFn := server.cfg.PathValue("KeyPath", Args.DataDir)
cert, err := tls.LoadX509KeyPair(certFn, keyFn)
if err != nil {
return err
Expand Down Expand Up @@ -1452,9 +1456,9 @@ func (server *Server) Start() (err error) {
// Set sensible timeouts, in case no reverse proxy is in front of Grumble.
// Non-conforming (or malicious) clients may otherwise block indefinitely and cause
// file descriptors (or handles, depending on your OS) to leak and/or be exhausted
ReadTimeout: 5 * time.Second,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 2 * time.Minute,
IdleTimeout: 2 * time.Minute,
}
go func() {
err := server.webhttp.ListenAndServeTLS("", "")
Expand Down
18 changes: 16 additions & 2 deletions pkg/serverconf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package serverconf
import (
"strconv"
"sync"
"path/filepath"
)

var defaultCfg = map[string]string{
Expand All @@ -20,6 +21,9 @@ var defaultCfg = map[string]string{
"RememberChannel": "true",
"WelcomeText": "Welcome to this server running <b>Grumble</b>.",
"SendVersion": "true",
"LogPath": "grumble.log",
"CertPath": "cert.pem",
"KeyPath": "key.pem",
}

type Config struct {
Expand Down Expand Up @@ -80,7 +84,7 @@ func (cfg *Config) StringValue(key string) (value string) {
return ""
}

// Get the value of a speific config key as an int
// Get the value of a specific config key as an int
func (cfg *Config) IntValue(key string) (intval int) {
str := cfg.StringValue(key)
intval, _ = strconv.Atoi(str)
Expand All @@ -94,9 +98,19 @@ func (cfg *Config) Uint32Value(key string) (uint32val uint32) {
return uint32(uintval)
}

// Get the value fo a sepcific config key as a bool
// Get the value of a specific config key as a bool
func (cfg *Config) BoolValue(key string) (boolval bool) {
str := cfg.StringValue(key)
boolval, _ = strconv.ParseBool(str)
return
}

// Get the value of a specific config key as a path,
// joined with the path in rel if not absolute.
func (cfg *Config) PathValue(key string, rel string) (path string) {
str := cfg.StringValue(key)
if filepath.IsAbs(str) {
return filepath.Clean(str)
}
return filepath.Join(rel, str)
}
Loading

0 comments on commit cef326e

Please sign in to comment.