110 lines
2.2 KiB
Go
110 lines
2.2 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/json"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// ---------------------------------------------------------------------
|
|
// status file watcher
|
|
// ---------------------------------------------------------------------
|
|
|
|
func watchStatusFile(ctx context.Context, every time.Duration) {
|
|
var last [32]byte
|
|
have := false
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-time.After(every):
|
|
}
|
|
|
|
data, err := os.ReadFile(statusFilePath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
h := sha256.Sum256(data)
|
|
if have && h == last {
|
|
continue
|
|
}
|
|
last = h
|
|
have = true
|
|
|
|
var st Status
|
|
if err := json.Unmarshal(data, &st); err != nil {
|
|
events.push("status_error", map[string]any{"error": err.Error()})
|
|
continue
|
|
}
|
|
events.push("status_changed", st)
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// login file watcher
|
|
// ---------------------------------------------------------------------
|
|
|
|
func watchLoginFile(ctx context.Context, every time.Duration) {
|
|
var last [32]byte
|
|
have := false
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-time.After(every):
|
|
}
|
|
|
|
data, err := os.ReadFile(loginStatePath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
h := sha256.Sum256(data)
|
|
if have && h == last {
|
|
continue
|
|
}
|
|
last = h
|
|
have = true
|
|
|
|
var st VPNLoginState
|
|
if err := json.Unmarshal(data, &st); err != nil {
|
|
events.push("login_state_error", map[string]any{"error": err.Error()})
|
|
continue
|
|
}
|
|
events.push("login_state_changed", st)
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// generic file watcher
|
|
// ---------------------------------------------------------------------
|
|
|
|
func watchFileChange(ctx context.Context, path string, kind string, mode string, every time.Duration) {
|
|
var lastMod time.Time
|
|
var lastSize int64 = -1
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-time.After(every):
|
|
}
|
|
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if info.ModTime() == lastMod && info.Size() == lastSize {
|
|
continue
|
|
}
|
|
lastMod = info.ModTime()
|
|
lastSize = info.Size()
|
|
events.push(kind, map[string]any{
|
|
"path": path,
|
|
"mode": mode,
|
|
"size": info.Size(),
|
|
"mtime": info.ModTime().UTC().Format(time.RFC3339Nano),
|
|
})
|
|
}
|
|
}
|