mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 15:26:40 +00:00
could interleave with a sleep/wake event causing out-of-order state transitions. The mutex now covers the full duration of each handler including the status check, the Up/Down call, and the flag update. Note: if Up or Down commands are triggered in parallel with sleep/wake events, the overall ordering of up/down/sleep/wake operations is still not guaranteed beyond what the mutex provides within the handler itself.
81 lines
1.6 KiB
Go
81 lines
1.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/netbirdio/netbird/client/internal"
|
|
)
|
|
|
|
type Agent interface {
|
|
Up(ctx context.Context) error
|
|
Down(ctx context.Context) error
|
|
Status() (internal.StatusType, error)
|
|
}
|
|
|
|
type SleepHandler struct {
|
|
agent Agent
|
|
|
|
mu sync.Mutex
|
|
// sleepTriggeredDown indicates whether the sleep handler triggered the last client down, to avoid unnecessary up on wake
|
|
sleepTriggeredDown bool
|
|
}
|
|
|
|
func New(agent Agent) *SleepHandler {
|
|
return &SleepHandler{
|
|
agent: agent,
|
|
}
|
|
}
|
|
|
|
func (s *SleepHandler) HandleWakeUp(ctx context.Context) error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
if !s.sleepTriggeredDown {
|
|
log.Info("skipping up because wasn't sleep down")
|
|
return nil
|
|
}
|
|
|
|
// avoid other wakeup runs if sleep didn't make the computer sleep
|
|
s.sleepTriggeredDown = false
|
|
|
|
log.Info("running up after wake up")
|
|
err := s.agent.Up(ctx)
|
|
if err != nil {
|
|
log.Errorf("running up failed: %v", err)
|
|
return err
|
|
}
|
|
|
|
log.Info("running up command executed successfully")
|
|
return nil
|
|
}
|
|
|
|
func (s *SleepHandler) HandleSleep(ctx context.Context) error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
status, err := s.agent.Status()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if status != internal.StatusConnecting && status != internal.StatusConnected {
|
|
log.Infof("skipping setting the agent down because status is %s", status)
|
|
return nil
|
|
}
|
|
|
|
log.Info("running down after system started sleeping")
|
|
|
|
if err = s.agent.Down(ctx); err != nil {
|
|
log.Errorf("running down failed: %v", err)
|
|
return err
|
|
}
|
|
|
|
s.sleepTriggeredDown = true
|
|
|
|
log.Info("running down executed successfully")
|
|
return nil
|
|
}
|