fix; standalone issue and add secret

This commit is contained in:
Hiddify
2024-03-18 20:38:09 +01:00
parent 3c8c2d4aa5
commit cd07df9b8f
7 changed files with 54 additions and 37 deletions

View File

@@ -73,7 +73,9 @@ func BuildConfig(opt ConfigOptions, input option.Options) (*option.Options, erro
options.Experimental = &option.ExperimentalOptions{ options.Experimental = &option.ExperimentalOptions{
ClashAPI: &option.ClashAPIOptions{ ClashAPI: &option.ClashAPIOptions{
ExternalController: fmt.Sprintf("%s:%d", "127.0.0.1", opt.ClashApiPort), ExternalController: fmt.Sprintf("%s:%d", "127.0.0.1", opt.ClashApiPort),
Secret: opt.ClashApiSecret,
}, },
CacheFile: &option.CacheFileOptions{ CacheFile: &option.CacheFileOptions{
Enabled: true, Enabled: true,
Path: "clash.db", Path: "clash.db",

View File

@@ -9,6 +9,7 @@ type ConfigOptions struct {
LogLevel string `json:"log-level"` LogLevel string `json:"log-level"`
EnableClashApi bool `json:"enable-clash-api"` EnableClashApi bool `json:"enable-clash-api"`
ClashApiPort uint16 `json:"clash-api-port"` ClashApiPort uint16 `json:"clash-api-port"`
ClashApiSecret string `json:"clash-api-secret"`
GeoIPPath string `json:"geoip-path"` GeoIPPath string `json:"geoip-path"`
GeoSitePath string `json:"geosite-path"` GeoSitePath string `json:"geosite-path"`
Rules []Rule `json:"rules"` Rules []Rule `json:"rules"`
@@ -117,9 +118,10 @@ func DefaultConfigOptions() *ConfigOptions {
BypassLAN: false, BypassLAN: false,
AllowConnectionFromLAN: false, AllowConnectionFromLAN: false,
}, },
LogLevel: "info", LogLevel: "warn",
EnableClashApi: true, EnableClashApi: true,
ClashApiPort: 6756, ClashApiPort: 6756,
ClashApiSecret: "hiddify",
GeoIPPath: "geoip.db", GeoIPPath: "geoip.db",
GeoSitePath: "geosite.db", GeoSitePath: "geosite.db",
Rules: []Rule{}, Rules: []Rule{},

View File

@@ -9,12 +9,15 @@ import (
pb "github.com/hiddify/libcore/hiddifyrpc" pb "github.com/hiddify/libcore/hiddifyrpc"
) )
var EnableBridge = true
var coreInfoObserver = NewObserver[pb.CoreInfoResponse](10) var coreInfoObserver = NewObserver[pb.CoreInfoResponse](10)
var CoreState = pb.CoreState_STOPPED var CoreState = pb.CoreState_STOPPED
func SetCoreStatus(state pb.CoreState, msgType pb.MessageType, message string) pb.CoreInfoResponse { func SetCoreStatus(state pb.CoreState, msgType pb.MessageType, message string) pb.CoreInfoResponse {
Log(pb.LogLevel_INFO, pb.LogType_CORE, fmt.Sprintf("%s: %s %s", state.String(), msgType.String(), message)) msg := fmt.Sprintf("%s: %s %s", state.String(), msgType.String(), message)
if msgType == pb.MessageType_EMPTY {
msg = fmt.Sprintf("%s: %s", state.String(), message)
}
Log(pb.LogLevel_INFO, pb.LogType_CORE, msg)
CoreState = state CoreState = state
info := pb.CoreInfoResponse{ info := pb.CoreInfoResponse{
CoreState: state, CoreState: state,
@@ -22,7 +25,7 @@ func SetCoreStatus(state pb.CoreState, msgType pb.MessageType, message string) p
Message: message, Message: message,
} }
coreInfoObserver.Emit(info) coreInfoObserver.Emit(info)
if EnableBridge { if useFlutterBridge {
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState)}) msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState)})
bridge.SendStringToPort(statusPropagationPort, string(msg)) bridge.SendStringToPort(statusPropagationPort, string(msg))
} }
@@ -41,9 +44,9 @@ func (s *CoreService) CoreInfoListener(stream pb.Core_CoreInfoListenerServer) er
for { for {
select { select {
case <-stream.Context().Done(): case <-stream.Context().Done():
break return nil
case <-stopch: case <-stopch:
break return nil
case info := <-coreSub: case info := <-coreSub:
stream.Send(&info) stream.Send(&info)
case <-time.After(500 * time.Millisecond): case <-time.After(500 * time.Millisecond):

View File

@@ -15,10 +15,13 @@ import (
"github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/log"
) )
var Box *libbox.BoxService var (
var configOptions *config.ConfigOptions Box *libbox.BoxService
var activeConfigPath *string configOptions *config.ConfigOptions
var coreLogFactory log.Factory activeConfigPath string
coreLogFactory log.Factory
useFlutterBridge bool = true
)
func StopAndAlert(msgType pb.MessageType, message string) { func StopAndAlert(msgType pb.MessageType, message string) {
SetCoreStatus(pb.CoreState_STOPPED, msgType, message) SetCoreStatus(pb.CoreState_STOPPED, msgType, message)
@@ -33,7 +36,7 @@ func StopAndAlert(msgType pb.MessageType, message string) {
if oldCommandServer != nil { if oldCommandServer != nil {
oldCommandServer.Close() oldCommandServer.Close()
} }
if EnableBridge { if useFlutterBridge {
alert := msgType.String() alert := msgType.String()
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState), Alert: &alert, Message: &message}) msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState), Alert: &alert, Message: &message})
bridge.SendStringToPort(statusPropagationPort, string(msg)) bridge.SendStringToPort(statusPropagationPort, string(msg))
@@ -57,9 +60,8 @@ func Start(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
MessageType: pb.MessageType_INSTANCE_NOT_STOPPED, MessageType: pb.MessageType_INSTANCE_NOT_STOPPED,
}, fmt.Errorf("instance not stopped") }, fmt.Errorf("instance not stopped")
} }
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting1111") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Starting Core")
SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "Starting222") SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "")
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting2")
libbox.SetMemoryLimit(!in.DisableMemoryLimit) libbox.SetMemoryLimit(!in.DisableMemoryLimit)
resp, err := StartService(in) resp, err := StartService(in)
return resp, err return resp, err
@@ -68,14 +70,12 @@ func (s *CoreService) StartService(ctx context.Context, in *pb.StartRequest) (*p
return StartService(in) return StartService(in)
} }
func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) { func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting3") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Starting Core Service")
content := in.ConfigContent content := in.ConfigContent
if content == "" { if content == "" {
if in.ConfigPath != "" { activeConfigPath = in.ConfigPath
activeConfigPath = &in.ConfigPath fileContent, err := os.ReadFile(activeConfigPath)
}
fileContent, err := os.ReadFile(*activeConfigPath)
if err != nil { if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error()) Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_READING_CONFIG, err.Error()) resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_READING_CONFIG, err.Error())
@@ -84,10 +84,10 @@ func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
} }
content = string(fileContent) content = string(fileContent)
} }
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting4") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Parsing Config")
Log(pb.LogLevel_INFO, pb.LogType_CORE, content)
parsedContent, err := parseConfig(content) parsedContent, err := parseConfig(content)
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Parsed") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Parsed")
if err != nil { if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error()) Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
@@ -96,20 +96,24 @@ func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
return &resp, err return &resp, err
} }
if !in.EnableRawConfig { if !in.EnableRawConfig {
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Building config") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Building config")
parsedContent_tmp, err := config.BuildConfig(*configOptions, parsedContent) parsedContent_tmp, err := config.BuildConfig(*configOptions, parsedContent)
parsedContent = *parsedContent_tmp
if err != nil { if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error()) Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_BUILDING_CONFIG, err.Error()) resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_BUILDING_CONFIG, err.Error())
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error()) StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
return &resp, err return &resp, err
} }
parsedContent = *parsedContent_tmp
}
Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Saving config")
currentBuildConfigPath := filepath.Join(sWorkingPath, "current-config.json")
config.SaveCurrentConfig(currentBuildConfigPath, parsedContent)
if activeConfigPath == "" {
activeConfigPath = currentBuildConfigPath
} }
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Saving Contnet")
config.SaveCurrentConfig(filepath.Join(sWorkingPath, "current-config.json"), parsedContent)
if in.EnableOldCommandServer { if in.EnableOldCommandServer {
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting Command Server") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Starting Command Server")
err = startCommandServer() err = startCommandServer()
if err != nil { if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error()) Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
@@ -119,7 +123,7 @@ func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
} }
} }
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Stating Service ") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Stating Service ")
instance, err := NewService(parsedContent) instance, err := NewService(parsedContent)
if err != nil { if err != nil {
@@ -128,7 +132,7 @@ func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error()) StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
return &resp, err return &resp, err
} }
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Service.. started") Log(pb.LogLevel_DEBUG, pb.LogType_CORE, "Service.. started")
if in.DelayStart { if in.DelayStart {
<-time.After(250 * time.Millisecond) <-time.After(250 * time.Millisecond)
} }

View File

@@ -15,7 +15,10 @@ func NewObserver[T any](listenerBufferSize int) *observable.Observer[T] {
var logObserver = NewObserver[pb.LogMessage](10) var logObserver = NewObserver[pb.LogMessage](10)
func Log(level pb.LogLevel, typ pb.LogType, message string) { func Log(level pb.LogLevel, typ pb.LogType, message string) {
fmt.Printf("%s %s %s\n", level, typ, message) if level != pb.LogLevel_DEBUG {
fmt.Printf("%s %s %s\n", level, typ, message)
}
logObserver.Emit(pb.LogMessage{ logObserver.Emit(pb.LogMessage{
Level: level, Level: level,
Type: typ, Type: typ,

View File

@@ -21,6 +21,7 @@ import (
func RunStandalone(hiddifySettingPath string, configPath string) error { func RunStandalone(hiddifySettingPath string, configPath string) error {
fmt.Println("Running in standalone mode") fmt.Println("Running in standalone mode")
useFlutterBridge = false
current, err := readAndBuildConfig(hiddifySettingPath, configPath) current, err := readAndBuildConfig(hiddifySettingPath, configPath)
if err != nil { if err != nil {
fmt.Printf("Error in read and build config %v", err) fmt.Printf("Error in read and build config %v", err)
@@ -28,17 +29,19 @@ func RunStandalone(hiddifySettingPath string, configPath string) error {
} }
go StartService(&pb.StartRequest{ go StartService(&pb.StartRequest{
ConfigPath: configPath, ConfigContent: current.Config,
EnableOldCommandServer: false, EnableOldCommandServer: false,
DelayStart: false, DelayStart: false,
EnableRawConfig: true,
}) })
go updateConfigInterval(current, hiddifySettingPath, configPath) go updateConfigInterval(current, hiddifySettingPath, configPath)
fmt.Printf("Press CTRL+C to stop\n")
fmt.Printf("Open http://localhost:6756/?secret=hiddify in your browser\n")
sigChan := make(chan os.Signal, 1) sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
fmt.Printf("Waiting for CTRL+C to stop\n")
<-sigChan <-sigChan
fmt.Printf("CTRL+C recived-->stopping\n")
_, err = Stop() _, err = Stop()
return err return err
@@ -63,6 +66,7 @@ func readAndBuildConfig(hiddifySettingPath string, configPath string) (ConfigRes
return result, err return result, err
} }
} }
configOptions = hiddifyconfig
result.Config, err = buildConfig(result.Config, *hiddifyconfig) result.Config, err = buildConfig(result.Config, *hiddifyconfig)
if err != nil { if err != nil {
return result, err return result, err
@@ -161,9 +165,7 @@ func buildConfig(configContent string, options config.ConfigOptions) (string, er
finalconfig.Experimental.ClashAPI.ExternalController = "127.0.0.1:6756" finalconfig.Experimental.ClashAPI.ExternalController = "127.0.0.1:6756"
} }
if finalconfig.Experimental.ClashAPI.Secret == "" { fmt.Printf("Open http://localhost:6756/ui/?secret=%s in your browser\n", finalconfig.Experimental.ClashAPI.Secret)
// finalconfig.Experimental.ClashAPI.Secret = "hiddify"
}
if err := Setup("./", "./", "./tmp", 0, false); err != nil { if err := Setup("./", "./", "./tmp", 0, false); err != nil {
return "", fmt.Errorf("failed to set up global configuration: %w", err) return "", fmt.Errorf("failed to set up global configuration: %w", err)
@@ -195,6 +197,7 @@ func updateConfigInterval(current ConfigResult, hiddifySettingPath string, confi
DelayStart: false, DelayStart: false,
EnableOldCommandServer: false, EnableOldCommandServer: false,
DisableMemoryLimit: false, DisableMemoryLimit: false,
EnableRawConfig: true,
}) })
} }
current = new current = new

View File

@@ -13,7 +13,7 @@ func (s *TunnelService) Start(ctx context.Context, in *pb.TunnelStartRequest) (*
if in.ServerPort == 0 { if in.ServerPort == 0 {
in.ServerPort = 2334 in.ServerPort = 2334
} }
EnableBridge = false useFlutterBridge = false
res, err := Start(&pb.StartRequest{ res, err := Start(&pb.StartRequest{
ConfigContent: makeTunnelConfig(in.Ipv6, in.ServerPort, in.StrictRoute, in.EndpointIndependentNat, in.Stack), ConfigContent: makeTunnelConfig(in.Ipv6, in.ServerPort, in.StrictRoute, in.EndpointIndependentNat, in.Stack),
EnableOldCommandServer: false, EnableOldCommandServer: false,