source: code/trunk/config/config.go@ 822

Last change on this file since 822 was 804, checked in by koizumi.aoi, 2 years ago

Drunk as I like

Signed-off-by: Aoi K <koizumi.aoi@…>

File size: 3.9 KB
RevLine 
[62]1package config
2
3import (
4 "fmt"
[370]5 "net"
[62]6 "os"
[612]7 "strconv"
[200]8
[424]9 "git.sr.ht/~emersion/go-scfg"
[62]10)
11
[370]12type IPSet []*net.IPNet
13
14func (set IPSet) Contains(ip net.IP) bool {
15 for _, n := range set {
16 if n.Contains(ip) {
17 return true
18 }
19 }
20 return false
21}
22
23// loopbackIPs contains the loopback networks 127.0.0.0/8 and ::1/128.
24var loopbackIPs = IPSet{
25 &net.IPNet{
26 IP: net.IP{127, 0, 0, 0},
27 Mask: net.CIDRMask(8, 32),
28 },
29 &net.IPNet{
30 IP: net.IPv6loopback,
31 Mask: net.CIDRMask(128, 128),
32 },
33}
34
[62]35type TLS struct {
36 CertPath, KeyPath string
37}
38
39type Server struct {
[612]40 Listen []string
[662]41 TLS *TLS
[612]42 Hostname string
[662]43 Title string
[636]44 MOTDPath string
[612]45
46 SQLDriver string
47 SQLSource string
48 LogPath string
49
[370]50 HTTPOrigins []string
51 AcceptProxyIPs IPSet
[612]52
53 MaxUserNetworks int
[694]54 MultiUpstream bool
[705]55 UpstreamUserIPs []*net.IPNet
[62]56}
57
58func Defaults() *Server {
59 hostname, err := os.Hostname()
60 if err != nil {
61 hostname = "localhost"
62 }
63 return &Server{
[612]64 Hostname: hostname,
65 SQLDriver: "sqlite3",
[804]66 SQLSource: "suika.db",
[612]67 MaxUserNetworks: -1,
[694]68 MultiUpstream: true,
[62]69 }
70}
71
72func Load(path string) (*Server, error) {
[424]73 cfg, err := scfg.Load(path)
[62]74 if err != nil {
75 return nil, err
76 }
[424]77 return parse(cfg)
[62]78}
79
[424]80func parse(cfg scfg.Block) (*Server, error) {
[62]81 srv := Defaults()
[424]82 for _, d := range cfg {
[62]83 switch d.Name {
84 case "listen":
[317]85 var uri string
[424]86 if err := d.ParseParams(&uri); err != nil {
[62]87 return nil, err
88 }
[317]89 srv.Listen = append(srv.Listen, uri)
[62]90 case "hostname":
[424]91 if err := d.ParseParams(&srv.Hostname); err != nil {
[62]92 return nil, err
93 }
[662]94 case "title":
95 if err := d.ParseParams(&srv.Title); err != nil {
96 return nil, err
97 }
98 case "motd":
99 if err := d.ParseParams(&srv.MOTDPath); err != nil {
100 return nil, err
101 }
[62]102 case "tls":
103 tls := &TLS{}
[424]104 if err := d.ParseParams(&tls.CertPath, &tls.KeyPath); err != nil {
[62]105 return nil, err
106 }
107 srv.TLS = tls
[507]108 case "db":
[424]109 if err := d.ParseParams(&srv.SQLDriver, &srv.SQLSource); err != nil {
[77]110 return nil, err
111 }
[178]112 case "log":
[507]113 var driver string
114 if err := d.ParseParams(&driver, &srv.LogPath); err != nil {
[178]115 return nil, err
116 }
[507]117 if driver != "fs" {
118 return nil, fmt.Errorf("directive %q: unknown driver %q", d.Name, driver)
119 }
[323]120 case "http-origin":
[371]121 srv.HTTPOrigins = d.Params
[370]122 case "accept-proxy-ip":
123 srv.AcceptProxyIPs = nil
124 for _, s := range d.Params {
[426]125 if s == "localhost" {
126 srv.AcceptProxyIPs = append(srv.AcceptProxyIPs, loopbackIPs...)
127 continue
128 }
[370]129 _, n, err := net.ParseCIDR(s)
130 if err != nil {
131 return nil, fmt.Errorf("directive %q: failed to parse CIDR: %v", d.Name, err)
132 }
133 srv.AcceptProxyIPs = append(srv.AcceptProxyIPs, n)
134 }
[612]135 case "max-user-networks":
136 var max string
137 if err := d.ParseParams(&max); err != nil {
138 return nil, err
139 }
140 var err error
141 if srv.MaxUserNetworks, err = strconv.Atoi(max); err != nil {
142 return nil, fmt.Errorf("directive %q: %v", d.Name, err)
143 }
[694]144 case "multi-upstream-mode":
145 var str string
146 if err := d.ParseParams(&str); err != nil {
147 return nil, err
148 }
149 v, err := strconv.ParseBool(str)
150 if err != nil {
151 return nil, fmt.Errorf("directive %q: %v", d.Name, err)
152 }
153 srv.MultiUpstream = v
[705]154 case "upstream-user-ip":
155 if len(srv.UpstreamUserIPs) > 0 {
156 return nil, fmt.Errorf("directive %q: can only be specified once", d.Name)
157 }
158 var hasIPv4, hasIPv6 bool
159 for _, s := range d.Params {
160 _, n, err := net.ParseCIDR(s)
161 if err != nil {
162 return nil, fmt.Errorf("directive %q: failed to parse CIDR: %v", d.Name, err)
163 }
164 if n.IP.To4() == nil {
165 if hasIPv6 {
166 return nil, fmt.Errorf("directive %q: found two IPv6 CIDRs", d.Name)
167 }
168 hasIPv6 = true
169 } else {
170 if hasIPv4 {
171 return nil, fmt.Errorf("directive %q: found two IPv4 CIDRs", d.Name)
172 }
173 hasIPv4 = true
174 }
175 srv.UpstreamUserIPs = append(srv.UpstreamUserIPs, n)
176 }
[62]177 default:
178 return nil, fmt.Errorf("unknown directive %q", d.Name)
179 }
180 }
181
182 return srv, nil
183}
Note: See TracBrowser for help on using the repository browser.