Add reload support

(cherry picked from commit e98000c371)
This commit is contained in:
yaotthaha 2023-10-10 10:40:10 +08:00 committed by CHIZI-0618
parent 186c17abe5
commit a189daaa66
7 changed files with 76 additions and 4 deletions

View File

@ -71,6 +71,8 @@ type Router interface {
SetV2RayServer(server V2RayServer) SetV2RayServer(server V2RayServer)
ResetNetwork() error ResetNetwork() error
Reload()
} }
func ContextWithRouter(ctx context.Context, router Router) context.Context { func ContextWithRouter(ctx context.Context, router Router) context.Context {

8
box.go
View File

@ -40,6 +40,7 @@ type Box struct {
preServices1 map[string]adapter.Service preServices1 map[string]adapter.Service
preServices2 map[string]adapter.Service preServices2 map[string]adapter.Service
postServices map[string]adapter.Service postServices map[string]adapter.Service
reloadChan chan struct{}
done chan struct{} done chan struct{}
} }
@ -52,6 +53,7 @@ type Options struct {
func New(options Options) (*Box, error) { func New(options Options) (*Box, error) {
createdAt := time.Now() createdAt := time.Now()
reloadChan := make(chan struct{}, 1)
ctx := options.Context ctx := options.Context
if ctx == nil { if ctx == nil {
ctx = context.Background() ctx = context.Background()
@ -95,6 +97,7 @@ func New(options Options) (*Box, error) {
common.PtrValueOrDefault(options.NTP), common.PtrValueOrDefault(options.NTP),
options.Inbounds, options.Inbounds,
options.PlatformInterface, options.PlatformInterface,
reloadChan,
) )
if err != nil { if err != nil {
return nil, E.Cause(err, "parse route options") return nil, E.Cause(err, "parse route options")
@ -218,6 +221,7 @@ func New(options Options) (*Box, error) {
preServices1: preServices1, preServices1: preServices1,
preServices2: preServices2, preServices2: preServices2,
postServices: postServices, postServices: postServices,
reloadChan: reloadChan,
done: make(chan struct{}), done: make(chan struct{}),
}, nil }, nil
} }
@ -462,3 +466,7 @@ func (s *Box) Close() error {
func (s *Box) Router() adapter.Router { func (s *Box) Router() adapter.Router {
return s.router return s.router
} }
func (s *Box) ReloadChan() <-chan struct{} {
return s.reloadChan
}

View File

@ -177,20 +177,31 @@ func run() error {
} }
runtimeDebug.FreeOSMemory() runtimeDebug.FreeOSMemory()
for { for {
osSignal := <-osSignals reloadTag := false
select {
case osSignal := <-osSignals:
if osSignal == syscall.SIGHUP { if osSignal == syscall.SIGHUP {
err = check() err = check()
if err != nil { if err != nil {
log.Error(E.Cause(err, "reload service")) log.Error(E.Cause(err, "reload service"))
continue continue
} }
reloadTag = true
}
case <-instance.ReloadChan():
err = check()
if err != nil {
log.Error(E.Cause(err, "reload service"))
continue
}
reloadTag = true
} }
cancel() cancel()
closeCtx, closed := context.WithCancel(context.Background()) closeCtx, closed := context.WithCancel(context.Background())
go closeMonitor(closeCtx) go closeMonitor(closeCtx)
err = instance.Close() err = instance.Close()
closed() closed()
if osSignal != syscall.SIGHUP { if !reloadTag {
if err != nil { if err != nil {
log.Error(E.Cause(err, "sing-box did not closed properly")) log.Error(E.Cause(err, "sing-box did not closed properly"))
} }

View File

@ -12,7 +12,8 @@ import (
func configRouter(server *Server, logFactory log.Factory) http.Handler { func configRouter(server *Server, logFactory log.Factory) http.Handler {
r := chi.NewRouter() r := chi.NewRouter()
r.Get("/", getConfigs(server, logFactory)) r.Get("/", getConfigs(server, logFactory))
r.Put("/", updateConfigs) // r.Put("/", updateConfigs)
r.Put("/", reload(server))
r.Patch("/", patchConfigs(server)) r.Patch("/", patchConfigs(server))
return r return r
} }

View File

@ -0,0 +1,19 @@
//go:build !ios
package clashapi
import (
"net/http"
"github.com/go-chi/render"
)
func reload(server *Server) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
defer func() {
server.logger.Warn("sing-box restarting...")
server.router.Reload()
}()
render.NoContent(w, r)
}
}

View File

@ -0,0 +1,19 @@
//go:build ios
package clashapi
import (
"net/http"
"github.com/go-chi/render"
)
var ErrOSNotSupported = &HTTPError{
Message: "OS not supported",
}
func reload(server *Server) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, ErrOSNotSupported)
}
}

View File

@ -100,6 +100,7 @@ type Router struct {
needPackageManager bool needPackageManager bool
wifiState adapter.WIFIState wifiState adapter.WIFIState
started bool started bool
reloadChan chan<- struct{}
} }
func NewRouter( func NewRouter(
@ -110,6 +111,7 @@ func NewRouter(
ntpOptions option.NTPOptions, ntpOptions option.NTPOptions,
inbounds []option.Inbound, inbounds []option.Inbound,
platformInterface platform.Interface, platformInterface platform.Interface,
reloadChan chan<- struct{},
) (*Router, error) { ) (*Router, error) {
router := &Router{ router := &Router{
ctx: ctx, ctx: ctx,
@ -138,6 +140,7 @@ func NewRouter(
needPackageManager: common.Any(inbounds, func(inbound option.Inbound) bool { needPackageManager: common.Any(inbounds, func(inbound option.Inbound) bool {
return len(inbound.TunOptions.IncludePackage) > 0 || len(inbound.TunOptions.ExcludePackage) > 0 return len(inbound.TunOptions.IncludePackage) > 0 || len(inbound.TunOptions.ExcludePackage) > 0
}), }),
reloadChan: reloadChan,
} }
router.dnsClient = dns.NewClient(dns.ClientOptions{ router.dnsClient = dns.NewClient(dns.ClientOptions{
DisableCache: dnsOptions.DNSClientOptions.DisableCache, DisableCache: dnsOptions.DNSClientOptions.DisableCache,
@ -1438,3 +1441,12 @@ func (r *Router) notifyWindowsPowerEvent(event int) {
_ = r.ResetNetwork() _ = r.ResetNetwork()
} }
} }
func (r *Router) Reload() {
if r.platformInterface == nil {
select {
case r.reloadChan <- struct{}{}:
default:
}
}
}