From 6c97ad88716dc0bbb844e70bd0dc52dc4b641609 Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Thu, 29 May 2025 23:49:09 +0200 Subject: [PATCH] clash api and v2ray api #468 --- core/box.go | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/core/box.go b/core/box.go index 5fb329b..bee3c1c 100644 --- a/core/box.go +++ b/core/box.go @@ -19,6 +19,7 @@ import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/dns" "github.com/sagernet/sing-box/dns/transport/local" + "github.com/sagernet/sing-box/experimental" "github.com/sagernet/sing-box/experimental/cachefile" "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/log" @@ -125,9 +126,17 @@ func NewBox(options Options) (*Box, error) { ctx = pause.WithDefaultManager(ctx) experimentalOptions := sbCommon.PtrValueOrDefault(options.Experimental) var needCacheFile bool + var needClashAPI bool + var needV2RayAPI bool if experimentalOptions.CacheFile != nil && experimentalOptions.CacheFile.Enabled { needCacheFile = true } + if experimentalOptions.ClashAPI != nil { + needClashAPI = true + } + if experimentalOptions.V2RayAPI != nil && experimentalOptions.V2RayAPI.Listen != "" { + needV2RayAPI = true + } platformInterface := service.FromContext[platform.Interface](ctx) var defaultLogWriter io.Writer if platformInterface != nil { @@ -325,6 +334,28 @@ func NewBox(options Options) (*Box, error) { service.MustRegister[adapter.CacheFile](ctx, cacheFile) internalServices = append(internalServices, cacheFile) } + if needClashAPI { + clashAPIOptions := sbCommon.PtrValueOrDefault(experimentalOptions.ClashAPI) + clashAPIOptions.ModeList = experimental.CalculateClashModeList(options.Options) + clashServer, err := experimental.NewClashServer(ctx, logFactory.(log.ObservableFactory), clashAPIOptions) + if err != nil { + return nil, common.NewError(err, "create clash-server") + } + router.AppendTracker(clashServer) + service.MustRegister[adapter.ClashServer](ctx, clashServer) + internalServices = append(internalServices, clashServer) + } + if needV2RayAPI { + v2rayServer, err := experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), sbCommon.PtrValueOrDefault(experimentalOptions.V2RayAPI)) + if err != nil { + return nil, common.NewError(err, "create v2ray-server") + } + if v2rayServer.StatsService() != nil { + router.AppendTracker(v2rayServer.StatsService()) + internalServices = append(internalServices, v2rayServer) + service.MustRegister[adapter.V2RayServer](ctx, v2rayServer) + } + } ntpOptions := sbCommon.PtrValueOrDefault(options.NTP) if ntpOptions.Enabled { ntpDialer, err := dialer.New(ctx, ntpOptions.DialerOptions, ntpOptions.ServerIsDomain()) @@ -405,7 +436,7 @@ func (s *Box) preStart() error { if err != nil { return common.NewError(err, "start logger") } - err = adapter.StartNamed(adapter.StartStateInitialize, s.internalService) // cache-file + err = adapter.StartNamed(adapter.StartStateInitialize, s.internalService) // cache-file clash-api v2ray-api if err != nil { return err } @@ -460,7 +491,7 @@ func (s *Box) Close() error { close(s.done) } err := sbCommon.Close( - s.endpoint, s.inbound, s.outbound, s.router, s.connection, s.dnsRouter, s.dnsTransport, s.network, + s.endpoint, s.inbound, s.outbound, s.router, s.connection, s.dnsRouter, s.dnsTransport, s.network, s.service, ) for _, lifecycleService := range s.internalService { err1 := lifecycleService.Close()