Pull request: home: rm var shadowing, vol. 4

Closes #2803.

Squashed commit of the following:

commit cb36cc8811160bb39a32fb8eddf962d0ebe9035a
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Mar 12 14:21:46 2021 +0300

    home: imp more

commit 9ea7ccec8bb293881cf724d7ad57e6744243d8b9
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Mar 12 13:58:10 2021 +0300

    all: imp naming, refactor http srv shutdown

commit f29221007c16fd3e7230bf2c1ac37b365f3e29aa
Merge: 2247c05b bfbf73f3
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Mar 12 13:35:17 2021 +0300

    Merge branch 'master' into 2803-shadow-4

commit 2247c05b5521346aaf362d81ccdd64fee31f1e6d
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Jan 29 20:53:21 2021 +0300

    home: rm var shadowing, vol. 4
This commit is contained in:
Ainar Garipov 2021-03-12 14:32:08 +03:00
parent bfbf73f3cd
commit 7e64205d44
17 changed files with 195 additions and 169 deletions

View File

@ -37,7 +37,7 @@ and this project adheres to
- Wrong DNS-over-TLS ALPN configuration ([#2681]). - Wrong DNS-over-TLS ALPN configuration ([#2681]).
- Inconsistent responses for messages with EDNS0 and AD when DNS caching is - Inconsistent responses for messages with EDNS0 and AD when DNS caching is
enabled ([#2600]). enabled ([#2600]).
- Incomplete OpenWRT detection ([#2757]). - Incomplete OpenWrt detection ([#2757]).
- DHCP lease's `expired` field incorrect time format ([#2692]). - DHCP lease's `expired` field incorrect time format ([#2692]).
- Incomplete DNS upstreams validation ([#2674]). - Incomplete DNS upstreams validation ([#2674]).
- Wrong parsing of DHCP options of the `ip` type ([#2688]). - Wrong parsing of DHCP options of the `ip` type ([#2688]).

View File

@ -66,6 +66,8 @@ func glCheckToken(sess string) bool {
return now <= (tokenDate + glTokenTimeoutSeconds) return now <= (tokenDate + glTokenTimeoutSeconds)
} }
// TODO(a.garipov): Replace with a smaller version of
// https://github.com/josharian/native.
func archIsLittleEndian() bool { func archIsLittleEndian() bool {
var i int32 = 0x01020304 var i int32 = 0x01020304
u := unsafe.Pointer(&i) u := unsafe.Pointer(&i)
@ -102,18 +104,17 @@ func glGetTokenDate(file string) uint32 {
} }
buf := bytes.NewBuffer(bs) buf := bytes.NewBuffer(bs)
var order binary.ByteOrder = binary.BigEndian
if archIsLittleEndian() { if archIsLittleEndian() {
err := binary.Read(buf, binary.LittleEndian, &dateToken) order = binary.LittleEndian
if err != nil {
log.Error("binary.Read: %s", err)
return 0
}
} else {
err := binary.Read(buf, binary.BigEndian, &dateToken)
if err != nil {
log.Error("binary.Read: %s", err)
return 0
}
} }
err = binary.Read(buf, order, &dateToken)
if err != nil {
log.Error("binary.Read: %s", err)
return 0
}
return dateToken return dateToken
} }

View File

@ -517,7 +517,7 @@ func (clients *clientsContainer) Update(name string, c *Client) (err error) {
return agherr.Error("client not found") return agherr.Error("client not found")
} }
// check Name index // First, check the name index.
if prev.Name != c.Name { if prev.Name != c.Name {
_, ok = clients.list[c.Name] _, ok = clients.list[c.Name]
if ok { if ok {
@ -525,12 +525,12 @@ func (clients *clientsContainer) Update(name string, c *Client) (err error) {
} }
} }
// check IP index // Second, check the IP index.
if !equalStringSlices(prev.IDs, c.IDs) { if !equalStringSlices(prev.IDs, c.IDs) {
for _, id := range c.IDs { for _, id := range c.IDs {
c2, ok := clients.idIndex[id] c2, ok2 := clients.idIndex[id]
if ok && c2 != prev { if ok2 && c2 != prev {
return fmt.Errorf("another client uses the same ID (%q): %q", id, c2.Name) return fmt.Errorf("another client uses the same id (%q): %q", id, c2.Name)
} }
} }

View File

@ -272,6 +272,27 @@ func copyInstallSettings(dst, src *configuration) {
// shutdownTimeout is the timeout for shutting HTTP server down operation. // shutdownTimeout is the timeout for shutting HTTP server down operation.
const shutdownTimeout = 5 * time.Second const shutdownTimeout = 5 * time.Second
func logPanic() {
if v := recover(); v != nil {
log.Error("recovered from panic: %v", v)
}
}
func shutdownSrv(ctx context.Context, cancel context.CancelFunc, srv *http.Server) {
defer logPanic()
if srv == nil {
return
}
defer cancel()
err := srv.Shutdown(ctx)
if err != nil {
log.Error("error while shutting down http server %q: %s", srv.Addr, err)
}
}
// Apply new configuration, start DNS server, restart Web server // Apply new configuration, start DNS server, restart Web server
func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) { func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) {
newSettings := applyConfigReq{} newSettings := applyConfigReq{}
@ -359,23 +380,13 @@ func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) {
f.Flush() f.Flush()
} }
// The Shutdown() method of (*http.Server) needs to be called in a // Method http.(*Server).Shutdown needs to be called in a separate
// separate goroutine, because it waits until all requests are handled // goroutine and with its own context, because it waits until all
// and will be blocked by it's own caller. // requests are handled and will be blocked by it's own caller.
if restartHTTP { if restartHTTP {
ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
go shutdownSrv(ctx, cancel, web.httpServer)
shut := func(srv *http.Server) { go shutdownSrv(ctx, cancel, web.httpServerBeta)
defer cancel()
err := srv.Shutdown(ctx)
if err != nil {
log.Debug("error while shutting down HTTP server: %s", err)
}
}
go shut(web.httpServer)
if web.httpServerBeta != nil {
go shut(web.httpServerBeta)
}
} }
} }

View File

@ -268,15 +268,15 @@ func getDNSAddresses() []string {
addDNSAddress(&dnsAddresses, config.DNS.BindHost) addDNSAddress(&dnsAddresses, config.DNS.BindHost)
} }
dnsEncryption := getDNSEncryption() de := getDNSEncryption()
if dnsEncryption.https != "" { if de.https != "" {
dnsAddresses = append(dnsAddresses, dnsEncryption.https) dnsAddresses = append(dnsAddresses, de.https)
} }
if dnsEncryption.tls != "" { if de.tls != "" {
dnsAddresses = append(dnsAddresses, dnsEncryption.tls) dnsAddresses = append(dnsAddresses, de.tls)
} }
if dnsEncryption.quic != "" { if de.quic != "" {
dnsAddresses = append(dnsAddresses, dnsEncryption.quic) dnsAddresses = append(dnsAddresses, de.quic)
} }
return dnsAddresses return dnsAddresses

View File

@ -556,35 +556,37 @@ func (f *Filtering) updateIntl(filter *filter) (updated bool, err error) {
return updated, err return updated, err
} }
defer func() { defer func() {
var derr error
if tmpFile != nil { if tmpFile != nil {
if err := tmpFile.Close(); err != nil { if derr = tmpFile.Close(); derr != nil {
log.Printf("Couldn't close temporary file: %s", err) log.Printf("Couldn't close temporary file: %s", derr)
}
tmpFileName := tmpFile.Name()
if err := os.Remove(tmpFileName); err != nil {
log.Printf("Couldn't delete temporary file %s: %s", tmpFileName, err)
} }
tmpFileName := tmpFile.Name()
if derr = os.Remove(tmpFileName); derr != nil {
log.Printf("Couldn't delete temporary file %s: %s", tmpFileName, derr)
}
} }
}() }()
var reader io.Reader var reader io.Reader
if filepath.IsAbs(filter.URL) { if filepath.IsAbs(filter.URL) {
f, err := os.Open(filter.URL) var f io.ReadCloser
f, err = os.Open(filter.URL)
if err != nil { if err != nil {
return updated, fmt.Errorf("open file: %w", err) return updated, fmt.Errorf("open file: %w", err)
} }
defer f.Close() defer f.Close()
reader = f reader = f
} else { } else {
resp, err := Context.client.Get(filter.URL) var resp *http.Response
if resp != nil && resp.Body != nil { resp, err = Context.client.Get(filter.URL)
defer resp.Body.Close()
}
if err != nil { if err != nil {
log.Printf("Couldn't request filter from URL %s, skipping: %s", filter.URL, err) log.Printf("Couldn't request filter from URL %s, skipping: %s", filter.URL, err)
return updated, err return updated, err
} }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
log.Printf("Got status code %d from URL %s, skipping", resp.StatusCode, filter.URL) log.Printf("Got status code %d from URL %s, skipping", resp.StatusCode, filter.URL)
@ -703,7 +705,8 @@ func enableFilters(async bool) {
if !filter.Enabled { if !filter.Enabled {
continue continue
} }
f := dnsfilter.Filter{
f = dnsfilter.Filter{
ID: filter.ID, ID: filter.ID,
FilePath: filter.Path(), FilePath: filter.Path(),
} }
@ -713,7 +716,8 @@ func enableFilters(async bool) {
if !filter.Enabled { if !filter.Enabled {
continue continue
} }
f := dnsfilter.Filter{
f = dnsfilter.Filter{
ID: filter.ID, ID: filter.ID,
FilePath: filter.Path(), FilePath: filter.Path(),
} }

View File

@ -265,8 +265,8 @@ func run(args options) {
mux.HandleFunc("/debug/pprof/trace", pprof.Trace) mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
go func() { go func() {
log.Info("pprof: listening on localhost:6060") log.Info("pprof: listening on localhost:6060")
err := http.ListenAndServe("localhost:6060", mux) lerr := http.ListenAndServe("localhost:6060", mux)
log.Error("Error while running the pprof server: %s", err) log.Error("Error while running the pprof server: %s", lerr)
}() }()
} }
} }
@ -310,18 +310,19 @@ func run(args options) {
} }
if !Context.firstRun { if !Context.firstRun {
err := initDNSServer() err = initDNSServer()
if err != nil { if err != nil {
log.Fatalf("%s", err) log.Fatalf("%s", err)
} }
Context.tls.Start() Context.tls.Start()
Context.autoHosts.Start() Context.autoHosts.Start()
go func() { go func() {
err := startDNSServer() serr := startDNSServer()
if err != nil { if serr != nil {
closeDNSServer() closeDNSServer()
log.Fatal(err) log.Fatal(serr)
} }
}() }()
@ -376,10 +377,8 @@ func checkPermissions() {
return return
} }
if opErr, ok := err.(*net.OpError); ok { if errors.Is(err, os.ErrPermission) {
if sysErr, ok := opErr.Err.(*os.SyscallError); ok { msg := `Permission check failed.
if errno, ok := sysErr.Err.(syscall.Errno); ok && errno == syscall.EACCES {
msg := `Permission check failed.
AdGuard Home is not allowed to bind to privileged ports (for instance, port 53). AdGuard Home is not allowed to bind to privileged ports (for instance, port 53).
Please note, that this is crucial for a server to be able to use privileged ports. Please note, that this is crucial for a server to be able to use privileged ports.
@ -389,9 +388,7 @@ You have two options:
2. On Linux you can grant the CAP_NET_BIND_SERVICE capability: 2. On Linux you can grant the CAP_NET_BIND_SERVICE capability:
https://github.com/AdguardTeam/AdGuardHome/internal/wiki/Getting-Started#running-without-superuser` https://github.com/AdguardTeam/AdGuardHome/internal/wiki/Getting-Started#running-without-superuser`
log.Fatal(msg) log.Fatal(msg)
}
}
} }
msg := fmt.Sprintf(`AdGuard failed to bind to port 53 due to %v msg := fmt.Sprintf(`AdGuard failed to bind to port 53 due to %v
@ -437,9 +434,12 @@ func initWorkingDir(args options) {
Context.workDir = filepath.Dir(execPath) Context.workDir = filepath.Dir(execPath)
} }
if workDir, err := filepath.EvalSymlinks(Context.workDir); err == nil { workDir, err := filepath.EvalSymlinks(Context.workDir)
Context.workDir = workDir if err != nil {
panic(err)
} }
Context.workDir = workDir
} }
// configureLogger configures logger level and output // configureLogger configures logger level and output
@ -634,7 +634,7 @@ func detectFirstRun() bool {
} }
// Connect to a remote server resolving hostname using our own DNS server // Connect to a remote server resolving hostname using our own DNS server
func customDialContext(ctx context.Context, network, addr string) (net.Conn, error) { func customDialContext(ctx context.Context, network, addr string) (conn net.Conn, err error) {
log.Tracef("network:%v addr:%v", network, addr) log.Tracef("network:%v addr:%v", network, addr)
host, port, err := net.SplitHostPort(addr) host, port, err := net.SplitHostPort(addr)
@ -647,14 +647,13 @@ func customDialContext(ctx context.Context, network, addr string) (net.Conn, err
} }
if net.ParseIP(host) != nil || config.DNS.Port == 0 { if net.ParseIP(host) != nil || config.DNS.Port == 0 {
con, err := dialer.DialContext(ctx, network, addr) return dialer.DialContext(ctx, network, addr)
return con, err
} }
addrs, e := Context.dnsServer.Resolve(host) addrs, err := Context.dnsServer.Resolve(host)
log.Debug("dnsServer.Resolve: %s: %v", host, addrs) log.Debug("dnsServer.Resolve: %s: %v", host, addrs)
if e != nil { if err != nil {
return nil, e return nil, err
} }
if len(addrs) == 0 { if len(addrs) == 0 {
@ -664,13 +663,16 @@ func customDialContext(ctx context.Context, network, addr string) (net.Conn, err
var dialErrs []error var dialErrs []error
for _, a := range addrs { for _, a := range addrs {
addr = net.JoinHostPort(a.String(), port) addr = net.JoinHostPort(a.String(), port)
con, err := dialer.DialContext(ctx, network, addr) conn, err = dialer.DialContext(ctx, network, addr)
if err != nil { if err != nil {
dialErrs = append(dialErrs, err) dialErrs = append(dialErrs, err)
continue continue
} }
return con, err
return conn, err
} }
return nil, agherr.Many(fmt.Sprintf("couldn't dial to %s", addr), dialErrs...) return nil, agherr.Many(fmt.Sprintf("couldn't dial to %s", addr), dialErrs...)
} }

View File

@ -174,8 +174,9 @@ func TestHome(t *testing.T) {
assert.True(t, haveIP) assert.True(t, haveIP)
for i := 1; ; i++ { for i := 1; ; i++ {
st, err := os.Stat(filepath.Join(dir, "data", "filters", "1.txt")) var fi os.FileInfo
if err == nil && st.Size() != 0 { fi, err = os.Stat(filepath.Join(dir, "data", "filters", "1.txt"))
if err == nil && fi.Size() != 0 {
break break
} }
if i == 5 { if i == 5 {

View File

@ -47,7 +47,8 @@ func newIPDetector() (ipd *ipDetector, err error) {
nets: make([]*net.IPNet, len(specialNetworks)), nets: make([]*net.IPNet, len(specialNetworks)),
} }
for i, ipnetStr := range specialNetworks { for i, ipnetStr := range specialNetworks {
_, ipnet, err := net.ParseCIDR(ipnetStr) var ipnet *net.IPNet
_, ipnet, err = net.ParseCIDR(ipnetStr)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -296,15 +296,14 @@ func parse(exec string, ss []string) (o options, f effect, err error) {
} }
if eff != nil { if eff != nil {
prevf := f prevf := f
f = func() error { f = func() (ferr error) {
var err error
if prevf != nil { if prevf != nil {
err = prevf() ferr = prevf()
} }
if err == nil { if ferr == nil {
err = eff() ferr = eff()
} }
return err return ferr
} }
} }
} }

View File

@ -50,32 +50,38 @@ func (p *program) Stop(s service.Service) error {
return nil return nil
} }
// Check the service's status // svcStatus check the service's status.
// Note: on OpenWrt 'service' utility may not exist - we use our service script directly in this case. //
func svcStatus(s service.Service) (service.Status, error) { // On OpenWrt, the service utility may not exist. We use our service script
status, err := s.Status() // directly in this case.
func svcStatus(s service.Service) (status service.Status, err error) {
status, err = s.Status()
if err != nil && service.Platform() == "unix-systemv" { if err != nil && service.Platform() == "unix-systemv" {
code, err := runInitdCommand("status") var code int
if err != nil { code, err = runInitdCommand("status")
return service.StatusStopped, nil if err != nil || code != 0 {
}
if code != 0 {
return service.StatusStopped, nil return service.StatusStopped, nil
} }
return service.StatusRunning, nil return service.StatusRunning, nil
} }
return status, err return status, err
} }
// Perform an action on the service // svcAction performs the action on the service.
// Note: on OpenWrt 'service' utility may not exist - we use our service script directly in this case. //
func svcAction(s service.Service, action string) error { // On OpenWrt, the service utility may not exist. We use our service script
err := service.Control(s, action) // directly in this case.
func svcAction(s service.Service, action string) (err error) {
err = service.Control(s, action)
if err != nil && service.Platform() == "unix-systemv" && if err != nil && service.Platform() == "unix-systemv" &&
(action == "start" || action == "stop" || action == "restart") { (action == "start" || action == "stop" || action == "restart") {
_, err := runInitdCommand(action) _, err = runInitdCommand(action)
return err return err
} }
return err return err
} }
@ -90,7 +96,9 @@ func sendSigReload() {
pidfile := fmt.Sprintf("/var/run/%s.pid", serviceName) pidfile := fmt.Sprintf("/var/run/%s.pid", serviceName)
data, err := ioutil.ReadFile(pidfile) data, err := ioutil.ReadFile(pidfile)
if os.IsNotExist(err) { if os.IsNotExist(err) {
code, psdata, err := util.RunCommand("ps", "-C", serviceName, "-o", "pid=") var code int
var psdata string
code, psdata, err = util.RunCommand("ps", "-C", serviceName, "-o", "pid=")
if err != nil || code != 0 { if err != nil || code != 0 {
log.Error("Can't find AdGuardHome process: %s code:%d", err, code) log.Error("Can't find AdGuardHome process: %s code:%d", err, code)
return return
@ -207,10 +215,10 @@ func handleServiceInstallCommand(s service.Service) {
log.Fatal(err) log.Fatal(err)
} }
if util.IsOpenWRT() { if util.IsOpenWrt() {
// On OpenWrt it is important to run enable after the service installation // On OpenWrt it is important to run enable after the service installation
// Otherwise, the service won't start on the system startup // Otherwise, the service won't start on the system startup
_, err := runInitdCommand("enable") _, err = runInitdCommand("enable")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -234,7 +242,7 @@ Click on the link below and follow the Installation Wizard steps to finish setup
// handleServiceStatusCommand handles service "uninstall" command // handleServiceStatusCommand handles service "uninstall" command
func handleServiceUninstallCommand(s service.Service) { func handleServiceUninstallCommand(s service.Service) {
if util.IsOpenWRT() { if util.IsOpenWrt() {
// On OpenWrt it is important to run disable command first // On OpenWrt it is important to run disable command first
// as it will remove the symlink // as it will remove the symlink
_, err := runInitdCommand("disable") _, err := runInitdCommand("disable")
@ -249,14 +257,15 @@ func handleServiceUninstallCommand(s service.Service) {
} }
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
// Removing log files on cleanup and ignore errors // Remove log files on cleanup and log errors.
err := os.Remove(launchdStdoutPath) err = os.Remove(launchdStdoutPath)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
log.Printf("cannot remove %s", launchdStdoutPath) log.Printf("removing stdout file: %s", err)
} }
err = os.Remove(launchdStderrPath) err = os.Remove(launchdStderrPath)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
log.Printf("cannot remove %s", launchdStderrPath) log.Printf("removing stderr file: %s", err)
} }
} }
} }
@ -281,7 +290,7 @@ func configureService(c *service.Config) {
c.Option["SysvScript"] = sysvScript c.Option["SysvScript"] = sysvScript
// On OpenWrt we're using a different type of sysvScript. // On OpenWrt we're using a different type of sysvScript.
if util.IsOpenWRT() { if util.IsOpenWrt() {
c.Option["SysvScript"] = openWrtScript c.Option["SysvScript"] = openWrtScript
} else if runtime.GOOS == "freebsd" { } else if runtime.GOOS == "freebsd" {
c.Option["SysvScript"] = freeBSDScript c.Option["SysvScript"] = freeBSDScript

View File

@ -497,23 +497,26 @@ func unmarshalTLS(r *http.Request) (tlsConfigSettings, error) {
} }
if data.CertificateChain != "" { if data.CertificateChain != "" {
certPEM, err := base64.StdEncoding.DecodeString(data.CertificateChain) var cert []byte
cert, err = base64.StdEncoding.DecodeString(data.CertificateChain)
if err != nil { if err != nil {
return data, fmt.Errorf("failed to base64-decode certificate chain: %w", err) return data, fmt.Errorf("failed to base64-decode certificate chain: %w", err)
} }
data.CertificateChain = string(certPEM)
data.CertificateChain = string(cert)
if data.CertificatePath != "" { if data.CertificatePath != "" {
return data, fmt.Errorf("certificate data and file can't be set together") return data, fmt.Errorf("certificate data and file can't be set together")
} }
} }
if data.PrivateKey != "" { if data.PrivateKey != "" {
keyPEM, err := base64.StdEncoding.DecodeString(data.PrivateKey) var key []byte
key, err = base64.StdEncoding.DecodeString(data.PrivateKey)
if err != nil { if err != nil {
return data, fmt.Errorf("failed to base64-decode private key: %w", err) return data, fmt.Errorf("failed to base64-decode private key: %w", err)
} }
data.PrivateKey = string(keyPEM) data.PrivateKey = string(key)
if data.PrivateKeyPath != "" { if data.PrivateKeyPath != "" {
return data, fmt.Errorf("private key data and file can't be set together") return data, fmt.Errorf("private key data and file can't be set together")
} }

View File

@ -188,14 +188,15 @@ func upgradeSchema2to3(diskConfig *map[string]interface{}) error {
} }
// Replace bootstrap_dns value filed with new array contains old bootstrap_dns inside // Replace bootstrap_dns value filed with new array contains old bootstrap_dns inside
if bootstrapDNS, ok := (newDNSConfig)["bootstrap_dns"]; ok { bootstrapDNS, ok := newDNSConfig["bootstrap_dns"]
newBootstrapConfig := []string{fmt.Sprint(bootstrapDNS)} if !ok {
(newDNSConfig)["bootstrap_dns"] = newBootstrapConfig
(*diskConfig)["dns"] = newDNSConfig
} else {
return fmt.Errorf("no bootstrap DNS in DNS config") return fmt.Errorf("no bootstrap DNS in DNS config")
} }
newBootstrapConfig := []string{fmt.Sprint(bootstrapDNS)}
newDNSConfig["bootstrap_dns"] = newBootstrapConfig
(*diskConfig)["dns"] = newDNSConfig
// Bump schema version // Bump schema version
(*diskConfig)["schema_version"] = 3 (*diskConfig)["schema_version"] = 3
@ -306,17 +307,17 @@ func upgradeSchema5to6(diskConfig *map[string]interface{}) error {
switch arr := clients.(type) { switch arr := clients.(type) {
case []interface{}: case []interface{}:
for i := range arr { for i := range arr {
switch c := arr[i].(type) { switch c := arr[i].(type) {
case map[interface{}]interface{}: case map[interface{}]interface{}:
_ip, ok := c["ip"] var ipVal interface{}
ipVal, ok = c["ip"]
ids := []string{} ids := []string{}
if ok { if ok {
ip, ok := _ip.(string) var ip string
ip, ok = ipVal.(string)
if !ok { if !ok {
log.Fatalf("client.ip is not a string: %v", _ip) log.Fatalf("client.ip is not a string: %v", ipVal)
return nil return nil
} }
if len(ip) != 0 { if len(ip) != 0 {
@ -324,11 +325,13 @@ func upgradeSchema5to6(diskConfig *map[string]interface{}) error {
} }
} }
_mac, ok := c["mac"] var macVal interface{}
macVal, ok = c["mac"]
if ok { if ok {
mac, ok := _mac.(string) var mac string
mac, ok = macVal.(string)
if !ok { if !ok {
log.Fatalf("client.mac is not a string: %v", _mac) log.Fatalf("client.mac is not a string: %v", macVal)
return nil return nil
} }
if len(mac) != 0 { if len(mac) != 0 {
@ -337,12 +340,10 @@ func upgradeSchema5to6(diskConfig *map[string]interface{}) error {
} }
c["ids"] = ids c["ids"] = ids
default: default:
continue continue
} }
} }
default: default:
return nil return nil
} }
@ -369,64 +370,67 @@ func upgradeSchema6to7(diskConfig *map[string]interface{}) error {
(*diskConfig)["schema_version"] = 7 (*diskConfig)["schema_version"] = 7
_dhcp, ok := (*diskConfig)["dhcp"] dhcpVal, ok := (*diskConfig)["dhcp"]
if !ok { if !ok {
return nil return nil
} }
switch dhcp := _dhcp.(type) { switch dhcp := dhcpVal.(type) {
case map[interface{}]interface{}: case map[interface{}]interface{}:
dhcpv4 := map[string]interface{}{} var str string
val, ok := dhcp["gateway_ip"].(string) str, ok = dhcp["gateway_ip"].(string)
if !ok { if !ok {
log.Fatalf("expecting dhcp.%s to be a string", "gateway_ip") log.Fatalf("expecting dhcp.%s to be a string", "gateway_ip")
return nil return nil
} }
dhcpv4["gateway_ip"] = val
dhcpv4 := map[string]interface{}{
"gateway_ip": str,
}
delete(dhcp, "gateway_ip") delete(dhcp, "gateway_ip")
val, ok = dhcp["subnet_mask"].(string) str, ok = dhcp["subnet_mask"].(string)
if !ok { if !ok {
log.Fatalf("expecting dhcp.%s to be a string", "subnet_mask") log.Fatalf("expecting dhcp.%s to be a string", "subnet_mask")
return nil return nil
} }
dhcpv4["subnet_mask"] = val dhcpv4["subnet_mask"] = str
delete(dhcp, "subnet_mask") delete(dhcp, "subnet_mask")
val, ok = dhcp["range_start"].(string) str, ok = dhcp["range_start"].(string)
if !ok { if !ok {
log.Fatalf("expecting dhcp.%s to be a string", "range_start") log.Fatalf("expecting dhcp.%s to be a string", "range_start")
return nil return nil
} }
dhcpv4["range_start"] = val dhcpv4["range_start"] = str
delete(dhcp, "range_start") delete(dhcp, "range_start")
val, ok = dhcp["range_end"].(string) str, ok = dhcp["range_end"].(string)
if !ok { if !ok {
log.Fatalf("expecting dhcp.%s to be a string", "range_end") log.Fatalf("expecting dhcp.%s to be a string", "range_end")
return nil return nil
} }
dhcpv4["range_end"] = val dhcpv4["range_end"] = str
delete(dhcp, "range_end") delete(dhcp, "range_end")
intVal, ok := dhcp["lease_duration"].(int) var n int
n, ok = dhcp["lease_duration"].(int)
if !ok { if !ok {
log.Fatalf("expecting dhcp.%s to be an integer", "lease_duration") log.Fatalf("expecting dhcp.%s to be an integer", "lease_duration")
return nil return nil
} }
dhcpv4["lease_duration"] = intVal dhcpv4["lease_duration"] = n
delete(dhcp, "lease_duration") delete(dhcp, "lease_duration")
intVal, ok = dhcp["icmp_timeout_msec"].(int) n, ok = dhcp["icmp_timeout_msec"].(int)
if !ok { if !ok {
log.Fatalf("expecting dhcp.%s to be an integer", "icmp_timeout_msec") log.Fatalf("expecting dhcp.%s to be an integer", "icmp_timeout_msec")
return nil return nil
} }
dhcpv4["icmp_timeout_msec"] = intVal dhcpv4["icmp_timeout_msec"] = n
delete(dhcp, "icmp_timeout_msec") delete(dhcp, "icmp_timeout_msec")
dhcp["dhcpv4"] = dhcpv4 dhcp["dhcpv4"] = dhcpv4
default: default:
return nil return nil
} }

View File

@ -141,13 +141,11 @@ func (web *Web) TLSConfigChanged(ctx context.Context, tlsConf tlsConfigSettings)
web.httpsServer.cond.L.Lock() web.httpsServer.cond.L.Lock()
if web.httpsServer.server != nil { if web.httpsServer.server != nil {
ctx, cancel := context.WithTimeout(ctx, shutdownTimeout) var cancel context.CancelFunc
err = web.httpsServer.server.Shutdown(ctx) ctx, cancel = context.WithTimeout(ctx, shutdownTimeout)
cancel() shutdownSrv(ctx, cancel, web.httpsServer.server)
if err != nil {
log.Debug("error while shutting down HTTP server: %s", err)
}
} }
web.httpsServer.enabled = enabled web.httpsServer.enabled = enabled
web.httpsServer.cert = cert web.httpsServer.cert = cert
web.httpsServer.cond.Broadcast() web.httpsServer.cond.Broadcast()
@ -206,27 +204,20 @@ func (web *Web) Start() {
// Close gracefully shuts down the HTTP servers. // Close gracefully shuts down the HTTP servers.
func (web *Web) Close(ctx context.Context) { func (web *Web) Close(ctx context.Context) {
log.Info("Stopping HTTP server...") log.Info("stopping http server...")
web.httpsServer.cond.L.Lock() web.httpsServer.cond.L.Lock()
web.httpsServer.shutdown = true web.httpsServer.shutdown = true
web.httpsServer.cond.L.Unlock() web.httpsServer.cond.L.Unlock()
shut := func(srv *http.Server) { var cancel context.CancelFunc
if srv == nil { ctx, cancel = context.WithTimeout(ctx, shutdownTimeout)
return
}
ctx, cancel := context.WithTimeout(ctx, shutdownTimeout)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Debug("error while shutting down HTTP server: %s", err)
}
}
shut(web.httpsServer.server) shutdownSrv(ctx, cancel, web.httpsServer.server)
shut(web.httpServer) shutdownSrv(ctx, cancel, web.httpServer)
shut(web.httpServerBeta) shutdownSrv(ctx, cancel, web.httpServerBeta)
log.Info("Stopped HTTP server") log.Info("stopped http server")
} }
func (web *Web) tlsServerLoop() { func (web *Web) tlsServerLoop() {

View File

@ -65,8 +65,9 @@ func (a *AutoHosts) Init(hostsFn string) {
a.hostsFn = hostsFn a.hostsFn = hostsFn
} }
if IsOpenWRT() { if IsOpenWrt() {
a.hostsDirs = append(a.hostsDirs, "/tmp/hosts") // OpenWRT: "/tmp/hosts/dhcp.cfg01411c" // OpenWrt: "/tmp/hosts/dhcp.cfg01411c".
a.hostsDirs = append(a.hostsDirs, "/tmp/hosts")
} }
// Load hosts initially // Load hosts initially

View File

@ -66,8 +66,8 @@ func SplitNext(str *string, splitBy byte) string {
return strings.TrimSpace(s) return strings.TrimSpace(s)
} }
// IsOpenWRT returns true if host OS is OpenWRT. // IsOpenWrt returns true if host OS is OpenWrt.
func IsOpenWRT() bool { func IsOpenWrt() bool {
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
return false return false
} }

View File

@ -148,8 +148,7 @@ looppointer ./...
nilness ./... nilness ./...
# TODO(a.garipov): Enable shadow after fixing all of the shadowing. exit_on_output shadow --strict ./...
# shadow --strict ./...
# TODO(a.garipov): Enable errcheck fully after handling all errors, # TODO(a.garipov): Enable errcheck fully after handling all errors,
# including the deferred and generated ones, properly. Also, perhaps, # including the deferred and generated ones, properly. Also, perhaps,