Selaa lähdekoodia

Handle Windows power events

世界 1 vuosi sitten
vanhempi
sitoutus
11c7b4a866
1 muutettua tiedostoa jossa 44 lisäystä ja 0 poistoa
  1. 44 0
      route/router.go

+ 44 - 0
route/router.go

@@ -8,6 +8,7 @@ import (
 	"net/url"
 	"os"
 	"os/user"
+	"runtime"
 	"strings"
 	"time"
 
@@ -42,6 +43,7 @@ import (
 	serviceNTP "github.com/sagernet/sing/common/ntp"
 	"github.com/sagernet/sing/common/task"
 	"github.com/sagernet/sing/common/uot"
+	"github.com/sagernet/sing/common/winpowrprof"
 	"github.com/sagernet/sing/service"
 	"github.com/sagernet/sing/service/pause"
 )
@@ -85,6 +87,7 @@ type Router struct {
 	networkMonitor                     tun.NetworkUpdateMonitor
 	interfaceMonitor                   tun.DefaultInterfaceMonitor
 	packageManager                     tun.PackageManager
+	powerListener                      winpowrprof.EventListener
 	processSearcher                    process.Searcher
 	timeService                        *ntp.Service
 	pauseManager                       pause.Manager
@@ -321,6 +324,14 @@ func NewRouter(
 		router.interfaceMonitor = interfaceMonitor
 	}
 
+	if runtime.GOOS == "windows" {
+		powerListener, err := winpowrprof.NewEventListener(router.notifyWindowsPowerEvent)
+		if err != nil {
+			return nil, E.Cause(err, "initialize power listener")
+		}
+		router.powerListener = powerListener
+	}
+
 	if ntpOptions.Enabled {
 		timeService, err := ntp.NewService(ctx, router, logFactory.NewLogger("ntp"), ntpOptions)
 		if err != nil {
@@ -560,6 +571,16 @@ func (r *Router) Start() error {
 			}
 		}
 	}
+
+	if r.powerListener != nil {
+		monitor.Start("start power listener")
+		err := r.powerListener.Start()
+		monitor.Finish()
+		if err != nil {
+			return E.Cause(err, "start power listener")
+		}
+	}
+
 	if (needWIFIStateFromRuleSet || r.needWIFIState) && r.platformInterface != nil {
 		monitor.Start("initialize WIFI state")
 		r.needWIFIState = true
@@ -657,6 +678,13 @@ func (r *Router) Close() error {
 		})
 		monitor.Finish()
 	}
+	if r.powerListener != nil {
+		monitor.Start("close power listener")
+		err = E.Append(err, r.powerListener.Close(), func(err error) error {
+			return E.Cause(err, "close power listener")
+		})
+		monitor.Finish()
+	}
 	if r.timeService != nil {
 		monitor.Start("close time service")
 		err = E.Append(err, r.timeService.Close(), func(err error) error {
@@ -1189,3 +1217,19 @@ func (r *Router) updateWIFIState() {
 		}
 	}
 }
+
+func (r *Router) notifyWindowsPowerEvent(event int) {
+	switch event {
+	case winpowrprof.EVENT_SUSPEND:
+		r.pauseManager.DevicePause()
+		_ = r.ResetNetwork()
+	case winpowrprof.EVENT_RESUME:
+		if !r.pauseManager.IsDevicePaused() {
+			return
+		}
+		fallthrough
+	case winpowrprof.EVENT_RESUME_AUTOMATIC:
+		r.pauseManager.DeviceWake()
+		_ = r.ResetNetwork()
+	}
+}