2020-02-18 13:10:23 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-07-22 15:03:01 +00:00
|
|
|
"net"
|
2020-02-18 13:10:23 +00:00
|
|
|
"os"
|
2021-10-07 18:43:10 +00:00
|
|
|
"strconv"
|
2020-04-01 12:57:27 +00:00
|
|
|
|
2020-10-25 17:10:50 +00:00
|
|
|
"git.sr.ht/~emersion/go-scfg"
|
2020-02-18 13:10:23 +00:00
|
|
|
)
|
|
|
|
|
2020-07-22 15:03:01 +00:00
|
|
|
type IPSet []*net.IPNet
|
|
|
|
|
|
|
|
func (set IPSet) Contains(ip net.IP) bool {
|
|
|
|
for _, n := range set {
|
|
|
|
if n.Contains(ip) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// loopbackIPs contains the loopback networks 127.0.0.0/8 and ::1/128.
|
|
|
|
var loopbackIPs = IPSet{
|
|
|
|
&net.IPNet{
|
|
|
|
IP: net.IP{127, 0, 0, 0},
|
|
|
|
Mask: net.CIDRMask(8, 32),
|
|
|
|
},
|
|
|
|
&net.IPNet{
|
|
|
|
IP: net.IPv6loopback,
|
|
|
|
Mask: net.CIDRMask(128, 128),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-02-18 13:10:23 +00:00
|
|
|
type TLS struct {
|
|
|
|
CertPath, KeyPath string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Server struct {
|
2021-10-07 18:43:10 +00:00
|
|
|
Listen []string
|
|
|
|
Hostname string
|
|
|
|
TLS *TLS
|
|
|
|
|
|
|
|
SQLDriver string
|
|
|
|
SQLSource string
|
|
|
|
LogPath string
|
|
|
|
|
2020-07-22 15:03:01 +00:00
|
|
|
HTTPOrigins []string
|
|
|
|
AcceptProxyIPs IPSet
|
2021-10-07 18:43:10 +00:00
|
|
|
|
|
|
|
MaxUserNetworks int
|
2020-02-18 13:10:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func Defaults() *Server {
|
|
|
|
hostname, err := os.Hostname()
|
|
|
|
if err != nil {
|
|
|
|
hostname = "localhost"
|
|
|
|
}
|
|
|
|
return &Server{
|
2021-10-07 18:43:10 +00:00
|
|
|
Hostname: hostname,
|
|
|
|
SQLDriver: "sqlite3",
|
|
|
|
SQLSource: "soju.db",
|
|
|
|
MaxUserNetworks: -1,
|
2020-02-18 13:10:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Load(path string) (*Server, error) {
|
2020-10-25 17:10:50 +00:00
|
|
|
cfg, err := scfg.Load(path)
|
2020-02-18 13:10:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-10-25 17:10:50 +00:00
|
|
|
return parse(cfg)
|
2020-02-18 13:10:23 +00:00
|
|
|
}
|
|
|
|
|
2020-10-25 17:10:50 +00:00
|
|
|
func parse(cfg scfg.Block) (*Server, error) {
|
2020-02-18 13:10:23 +00:00
|
|
|
srv := Defaults()
|
2020-10-25 17:10:50 +00:00
|
|
|
for _, d := range cfg {
|
2020-02-18 13:10:23 +00:00
|
|
|
switch d.Name {
|
|
|
|
case "listen":
|
2020-06-04 18:10:17 +00:00
|
|
|
var uri string
|
2020-10-25 17:10:50 +00:00
|
|
|
if err := d.ParseParams(&uri); err != nil {
|
2020-02-18 13:10:23 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2020-06-04 18:10:17 +00:00
|
|
|
srv.Listen = append(srv.Listen, uri)
|
2020-02-18 13:10:23 +00:00
|
|
|
case "hostname":
|
2020-10-25 17:10:50 +00:00
|
|
|
if err := d.ParseParams(&srv.Hostname); err != nil {
|
2020-02-18 13:10:23 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
case "tls":
|
|
|
|
tls := &TLS{}
|
2020-10-25 17:10:50 +00:00
|
|
|
if err := d.ParseParams(&tls.CertPath, &tls.KeyPath); err != nil {
|
2020-02-18 13:10:23 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
srv.TLS = tls
|
2021-04-21 16:15:04 +00:00
|
|
|
case "db":
|
2020-10-25 17:10:50 +00:00
|
|
|
if err := d.ParseParams(&srv.SQLDriver, &srv.SQLSource); err != nil {
|
2020-03-04 17:22:58 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2020-03-25 22:51:28 +00:00
|
|
|
case "log":
|
2021-04-21 16:15:04 +00:00
|
|
|
var driver string
|
|
|
|
if err := d.ParseParams(&driver, &srv.LogPath); err != nil {
|
2020-03-25 22:51:28 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2021-04-21 16:15:04 +00:00
|
|
|
if driver != "fs" {
|
|
|
|
return nil, fmt.Errorf("directive %q: unknown driver %q", d.Name, driver)
|
|
|
|
}
|
2020-04-23 20:25:43 +00:00
|
|
|
case "http-origin":
|
2020-07-22 16:07:55 +00:00
|
|
|
srv.HTTPOrigins = d.Params
|
2020-07-22 15:03:01 +00:00
|
|
|
case "accept-proxy-ip":
|
|
|
|
srv.AcceptProxyIPs = nil
|
|
|
|
for _, s := range d.Params {
|
2020-10-25 17:22:12 +00:00
|
|
|
if s == "localhost" {
|
|
|
|
srv.AcceptProxyIPs = append(srv.AcceptProxyIPs, loopbackIPs...)
|
|
|
|
continue
|
|
|
|
}
|
2020-07-22 15:03:01 +00:00
|
|
|
_, n, err := net.ParseCIDR(s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("directive %q: failed to parse CIDR: %v", d.Name, err)
|
|
|
|
}
|
|
|
|
srv.AcceptProxyIPs = append(srv.AcceptProxyIPs, n)
|
|
|
|
}
|
2021-10-07 18:43:10 +00:00
|
|
|
case "max-user-networks":
|
|
|
|
var max string
|
|
|
|
if err := d.ParseParams(&max); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
var err error
|
|
|
|
if srv.MaxUserNetworks, err = strconv.Atoi(max); err != nil {
|
|
|
|
return nil, fmt.Errorf("directive %q: %v", d.Name, err)
|
|
|
|
}
|
2020-02-18 13:10:23 +00:00
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unknown directive %q", d.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return srv, nil
|
|
|
|
}
|