package v2 import ( "context" "io" "os" "runtime" runtimeDebug "runtime/debug" "time" "github.com/hiddify/hiddify-core/v2/service_manager" B "github.com/sagernet/sing-box" "github.com/sagernet/sing-box/common/urltest" "github.com/sagernet/sing-box/experimental/libbox" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/service" "github.com/sagernet/sing/service/filemanager" "github.com/sagernet/sing/service/pause" ) var ( sWorkingPath string sTempPath string sUserID int sGroupID int statusPropagationPort int64 ) func InitHiddifyService() error { return service_manager.StartServices() } func Setup(basePath string, workingPath string, tempPath string, statusPort int64, debug bool) error { statusPropagationPort = int64(statusPort) tcpConn := runtime.GOOS == "windows" // TODO add TVOS libbox.Setup(basePath, workingPath, tempPath, tcpConn) sWorkingPath = workingPath os.Chdir(sWorkingPath) sTempPath = tempPath sUserID = os.Getuid() sGroupID = os.Getgid() var defaultWriter io.Writer if !debug { defaultWriter = io.Discard } factory, err := log.New( log.Options{ DefaultWriter: defaultWriter, BaseTime: time.Now(), Observable: true, // Options: option.LogOptions{ // Disabled: false, // Level: "trace", // Output: "stdout", // }, }) coreLogFactory = factory if err != nil { return E.Cause(err, "create logger") } return InitHiddifyService() } func NewService(options option.Options) (*libbox.BoxService, error) { runtimeDebug.FreeOSMemory() ctx, cancel := context.WithCancel(context.Background()) ctx = filemanager.WithDefault(ctx, sWorkingPath, sTempPath, sUserID, sGroupID) urlTestHistoryStorage := urltest.NewHistoryStorage() ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage) instance, err := B.New(B.Options{ Context: ctx, Options: options, }) if err != nil { cancel() return nil, E.Cause(err, "create service") } runtimeDebug.FreeOSMemory() service := libbox.NewBoxService( ctx, cancel, instance, service.FromContext[pause.Manager](ctx), urlTestHistoryStorage, ) return &service, nil } func readOptions(configContent string) (option.Options, error) { var options option.Options err := options.UnmarshalJSON([]byte(configContent)) if err != nil { return option.Options{}, E.Cause(err, "decode config") } return options, nil }