Files
kopia/cli/server_watchdog.go
Jarek Kowalski 9680dc376b cli: improvements for 'kopia server' and client
Those will make it possible to securely host 'kopia server' embedded
in a desktop app that runs in the background and can access UI.

- added support for using and generating TLS certificates
- added /api/v1/shutdown API to remotely trigger server shutdown
- added support for automatically shutting down server if no requests
  arrive in certain amount of time
- added support for generating and printing random password to STDERR

TLS supports 3 modes:

1. serve TLS using externally-provided cert/key PEM files
2. generate & write PEM files, then serve TLS using them
3. generate and use emphemeral cert/key (prints SHA256 fingerprint)
2020-01-24 17:25:45 -08:00

69 lines
1.3 KiB
Go

package cli
import (
"net/http"
"sync"
"sync/atomic"
"time"
)
type serverWatchdog struct {
inFlightRequests int32
inner http.Handler
stop func()
interval time.Duration
mu sync.Mutex
deadline time.Time
}
func (d *serverWatchdog) getDeadline() time.Time {
d.mu.Lock()
defer d.mu.Unlock()
return d.deadline
}
func (d *serverWatchdog) setDeadline(t time.Time) {
d.mu.Lock()
defer d.mu.Unlock()
if t.After(d.deadline) {
d.deadline = t
}
}
func (d *serverWatchdog) Run() {
for time.Now().Before(d.getDeadline()) || atomic.LoadInt32(&d.inFlightRequests) > 0 {
// sleep for no less than 1 second to avoid burning CPU
sleepTime := time.Until(d.getDeadline())
if sleepTime < time.Second {
sleepTime = time.Second
}
time.Sleep(sleepTime)
}
d.stop()
}
func (d *serverWatchdog) ServeHTTP(w http.ResponseWriter, r *http.Request) {
atomic.AddInt32(&d.inFlightRequests, 1)
defer atomic.AddInt32(&d.inFlightRequests, -1)
d.setDeadline(time.Now().Add(d.interval))
d.inner.ServeHTTP(w, r)
}
func startServerWatchdog(h http.Handler, interval time.Duration, stop func()) http.Handler {
w := &serverWatchdog{
inner: h,
interval: interval,
deadline: time.Now().Add(interval),
stop: stop,
}
go w.Run()
return w
}