diff --git a/home/config.go b/home/config.go index 66f51ea7..0615613d 100644 --- a/home/config.go +++ b/home/config.go @@ -39,6 +39,13 @@ type clientObject struct { SafeBrowsingEnabled bool `yaml:"safesearch_enabled"` } +type HTTPSServer struct { + server *http.Server + cond *sync.Cond // reacts to config.TLS.Enabled, PortHTTPS, CertificateChain and PrivateKey + sync.Mutex // protects config.TLS + shutdown bool // if TRUE, don't restart the server +} + // configuration is loaded from YAML // field ordering is important -- yaml fields will mirror ordering from here type configuration struct { @@ -63,6 +70,8 @@ type configuration struct { versionCheckJSON []byte versionCheckLastTime time.Time + httpsServer HTTPSServer + BindHost string `yaml:"bind_host"` // BindHost is the IP address of the HTTP server to bind to BindPort int `yaml:"bind_port"` // BindPort is the port the HTTP server AuthName string `yaml:"auth_name"` // AuthName is the basic auth username diff --git a/home/control_tls.go b/home/control_tls.go index cdf62843..ea83dba1 100644 --- a/home/control_tls.go +++ b/home/control_tls.go @@ -46,7 +46,7 @@ func handleTLSValidate(w http.ResponseWriter, r *http.Request) { // check if port is available // BUT: if we are already using this port, no need alreadyRunning := false - if httpsServer.server != nil { + if config.httpsServer.server != nil { alreadyRunning = true } if !alreadyRunning { @@ -72,7 +72,7 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) { // check if port is available // BUT: if we are already using this port, no need alreadyRunning := false - if httpsServer.server != nil { + if config.httpsServer.server != nil { alreadyRunning = true } if !alreadyRunning { @@ -101,12 +101,12 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) { if restartHTTPS { go func() { time.Sleep(time.Second) // TODO: could not find a way to reliably know that data was fully sent to client by https server, so we wait a bit to let response through before closing the server - httpsServer.cond.L.Lock() - httpsServer.cond.Broadcast() - if httpsServer.server != nil { - httpsServer.server.Shutdown(context.TODO()) + config.httpsServer.cond.L.Lock() + config.httpsServer.cond.Broadcast() + if config.httpsServer.server != nil { + config.httpsServer.server.Shutdown(context.TODO()) } - httpsServer.cond.L.Unlock() + config.httpsServer.cond.L.Unlock() }() } } diff --git a/home/helpers.go b/home/helpers.go index 6c78cfc6..7ff08004 100644 --- a/home/helpers.go +++ b/home/helpers.go @@ -148,7 +148,7 @@ func postInstall(handler func(http.ResponseWriter, *http.Request)) func(http.Res return } // enforce https? - if config.TLS.ForceHTTPS && r.TLS == nil && config.TLS.Enabled && config.TLS.PortHTTPS != 0 && httpsServer.server != nil { + if config.TLS.ForceHTTPS && r.TLS == nil && config.TLS.Enabled && config.TLS.PortHTTPS != 0 && config.httpsServer.server != nil { // yes, and we want host from host:port host, _, err := net.SplitHostPort(r.Host) if err != nil { diff --git a/home/home.go b/home/home.go index 00b11c4b..21061b92 100644 --- a/home/home.go +++ b/home/home.go @@ -26,12 +26,6 @@ import ( ) var httpServer *http.Server -var httpsServer struct { - server *http.Server - cond *sync.Cond // reacts to config.TLS.Enabled, PortHTTPS, CertificateChain and PrivateKey - sync.Mutex // protects config.TLS - shutdown bool // if TRUE, don't restart the server -} const ( // Used in config to indicate that syslog or eventlog (win) should be used for logger output @@ -192,13 +186,13 @@ func run(args options) { registerInstallHandlers() } - httpsServer.cond = sync.NewCond(&httpsServer.Mutex) + config.httpsServer.cond = sync.NewCond(&config.httpsServer.Mutex) // for https, we have a separate goroutine loop go httpServerLoop() // this loop is used as an ability to change listening host and/or port - for !httpsServer.shutdown { + for !config.httpsServer.shutdown { printHTTPAddresses("http") // we need to have new instance, because after Shutdown() the Server is not usable @@ -219,14 +213,14 @@ func run(args options) { } func httpServerLoop() { - for !httpsServer.shutdown { - httpsServer.cond.L.Lock() + for !config.httpsServer.shutdown { + config.httpsServer.cond.L.Lock() // this mechanism doesn't let us through until all conditions are met for config.TLS.Enabled == false || config.TLS.PortHTTPS == 0 || config.TLS.PrivateKey == "" || config.TLS.CertificateChain == "" { // sleep until necessary data is supplied - httpsServer.cond.Wait() + config.httpsServer.cond.Wait() } address := net.JoinHostPort(config.BindHost, strconv.Itoa(config.TLS.PortHTTPS)) // validate current TLS config and update warnings (it could have been loaded from file) @@ -250,10 +244,10 @@ func httpServerLoop() { cleanupAlways() log.Fatal(err) } - httpsServer.cond.L.Unlock() + config.httpsServer.cond.L.Unlock() // prepare HTTPS server - httpsServer.server = &http.Server{ + config.httpsServer.server = &http.Server{ Addr: address, TLSConfig: &tls.Config{ Certificates: []tls.Certificate{cert}, @@ -262,7 +256,7 @@ func httpServerLoop() { } printHTTPAddresses("https") - err = httpsServer.server.ListenAndServeTLS("", "") + err = config.httpsServer.server.ListenAndServeTLS("", "") if err != http.ErrServerClosed { cleanupAlways() log.Fatal(err) @@ -399,9 +393,9 @@ func cleanup() { // Stop HTTP server, possibly waiting for all active connections to be closed func stopHTTPServer() { - httpsServer.shutdown = true - if httpsServer.server != nil { - httpsServer.server.Shutdown(context.TODO()) + config.httpsServer.shutdown = true + if config.httpsServer.server != nil { + config.httpsServer.server.Shutdown(context.TODO()) } httpServer.Shutdown(context.TODO()) }