refactor global and admin service to use grpc

This commit is contained in:
Hiddify
2024-03-16 03:01:22 +01:00
parent 361419b95e
commit 6039baa313
20 changed files with 553 additions and 1337 deletions

View File

@@ -1,133 +0,0 @@
package admin_service
import (
"crypto/tls"
"fmt"
"net/http"
"os"
"strconv"
"github.com/hiddify/libcore/global"
"github.com/hiddify/libcore/utils"
)
const (
serverCertPath = "cert/server-cert.pem"
serverKeyPath = "cert/server-key.pem"
clientCertPath = "cert/client-cert.pem"
clientKeyPath = "cert/client-key.pem"
)
func StartWebServer(Port int, TLS bool) {
http.HandleFunc("/start", startHandler)
http.HandleFunc("/stop", StopHandler)
http.HandleFunc("/status", StatusHandler)
http.HandleFunc("/exit", ExitHandler)
server := &http.Server{
Addr: "127.0.0.1:" + fmt.Sprintf("%d", Port),
}
var err error
if TLS {
server.TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{utils.LoadCertificate(serverCertPath, serverKeyPath)},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: utils.LoadClientCA(clientCertPath),
}
err = server.ListenAndServeTLS(serverCertPath, serverKeyPath)
} else {
err = server.ListenAndServe()
}
if err != nil {
panic("Error: " + err.Error())
}
}
func startHandler(w http.ResponseWriter, r *http.Request) {
queryParams := r.URL.Query()
ipv6, err := strconv.ParseBool(queryParams.Get("Ipv6"))
if err != nil {
fmt.Printf("ipv6 Error: %v ==>using false\n", err)
ipv6 = false
}
serverPort, err := strconv.Atoi(queryParams.Get("ServerPort"))
if err != nil {
fmt.Printf("serverPort Error: %v ==>using 2334\n", err)
serverPort = 2334
}
strictRoute, err := strconv.ParseBool(queryParams.Get("StrictRoute"))
if err != nil {
fmt.Printf("strictRoute Error: %v ==>using false\n", err)
strictRoute = false
}
endpointIndependentNat, err := strconv.ParseBool(queryParams.Get("EndpointIndependentNat"))
if err != nil {
fmt.Printf("endpointIndependentNat Error: %v ==>using false\n", err)
endpointIndependentNat = false
}
theStack := GetStack(queryParams.Get("Stack"))
parameters := global.Parameters{Ipv6: ipv6, ServerPort: serverPort, StrictRoute: strictRoute, EndpointIndependentNat: endpointIndependentNat, Stack: theStack}
// err = global.WriteParameters(parameters.Ipv6, parameters.ServerPort, parameters.StrictRoute, parameters.EndpointIndependentNat, GetStringFromStack(parameters.Stack))
// if err != nil {
// http.Error(w, fmt.Sprintf("Error: %v", err), http.StatusBadRequest)
// return
// }
err = global.SetupC("./", "./", "./tmp", false)
if err != nil {
http.Error(w, fmt.Sprintf("Error: %v", err), http.StatusBadRequest)
return
}
err = global.StartServiceC(true, global.MakeConfig(parameters.Ipv6, parameters.ServerPort, parameters.StrictRoute, parameters.EndpointIndependentNat, GetStringFromStack(parameters.Stack)))
if err != nil {
http.Error(w, fmt.Sprintf("Error: %v", err), http.StatusBadRequest)
return
}
http.Error(w, fmt.Sprintf("Ok"), http.StatusOK)
}
func StatusHandler(w http.ResponseWriter, r *http.Request) {
}
func StopHandler(w http.ResponseWriter, r *http.Request) {
err := global.StopServiceC()
if err != nil {
http.Error(w, fmt.Sprintf("Error: %v", err), http.StatusBadRequest)
return
}
http.Error(w, fmt.Sprintf("Ok"), http.StatusOK)
}
func ExitHandler(w http.ResponseWriter, r *http.Request) {
global.StopServiceC()
os.Exit(0)
http.Error(w, fmt.Sprintf("Ok"), http.StatusOK)
}
func GetStack(stack string) global.Stack {
switch stack {
case "system":
return global.System
case "gvisor":
return global.GVisor
case "mixed":
return global.Mixed
// case "LWIP":
// return global.LWIP
default:
fmt.Printf("Stack Error: %s is not valid==> using GVisor\n", stack)
return global.GVisor
}
}
func GetStringFromStack(stack global.Stack) string {
switch stack {
case global.System:
return "system"
case global.GVisor:
return "gvisor"
case global.Mixed:
return "mixed"
// case global.LWIP:
// return "LWIP"
default:
return "UNKNOWN"
}
}

View File

@@ -1,7 +1,7 @@
package cmd
import (
"github.com/hiddify/libcore/global"
v2 "github.com/hiddify/libcore/v2"
"github.com/spf13/cobra"
)
@@ -29,5 +29,5 @@ func init() {
}
func runCommand(cmd *cobra.Command, args []string) {
global.RunStandalone(hiddifySettingPath, configPath)
v2.RunStandalone(hiddifySettingPath, configPath)
}

View File

@@ -3,7 +3,7 @@ package cmd
import (
"fmt"
"github.com/hiddify/libcore/admin_service"
v2 "github.com/hiddify/libcore/v2"
"github.com/spf13/cobra"
)
@@ -15,7 +15,7 @@ var commandService = &cobra.Command{
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
Run: func(cmd *cobra.Command, args []string) {
arg := args[0]
code, out := admin_service.StartService(arg)
code, out := v2.StartTunnelService(arg)
fmt.Printf("exitCode:%d msg=%s", code, out)
},
}

View File

@@ -1,17 +1,18 @@
package config
import (
context "context"
"fmt"
"io"
"net/http"
"net/url"
"log"
"os"
"path/filepath"
"runtime"
"time"
pb "github.com/hiddify/libcore/hiddifyrpc"
"github.com/sagernet/sing-box/option"
dns "github.com/sagernet/sing-dns"
grpc "google.golang.org/grpc"
)
const (
@@ -59,49 +60,46 @@ func startTunnelRequestWithFailover(opt ConfigOptions, installService bool) {
}
func startTunnelRequest(opt ConfigOptions, installService bool) (bool, error) {
params := map[string]interface{}{
"Ipv6": opt.IPv6Mode == option.DomainStrategy(dns.DomainStrategyUseIPv4),
"ServerPort": opt.InboundOptions.MixedPort,
"StrictRoute": opt.InboundOptions.StrictRoute,
"EndpointIndependentNat": true,
"Stack": opt.InboundOptions.TUNStack,
}
values := url.Values{}
for key, value := range params {
values.Add(key, fmt.Sprint(value))
}
url := fmt.Sprintf("%s%s?%s", serviceURL, startEndpoint, values.Encode())
fmt.Printf("URL: %s\n", url)
response, err := http.Get(url)
conn, err := grpc.Dial("127.0.0.1:18020", grpc.WithInsecure())
if err != nil {
log.Printf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewTunnelServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
_, err = c.Start(ctx, &pb.TunnelStartRequest{
Ipv6: opt.IPv6Mode == option.DomainStrategy(dns.DomainStrategyUseIPv4),
ServerPort: int32(opt.InboundOptions.MixedPort),
StrictRoute: opt.InboundOptions.StrictRoute,
EndpointIndependentNat: true,
Stack: opt.InboundOptions.TUNStack,
})
if err != nil {
log.Printf("could not greet: %v", err)
if installService {
return runTunnelService(opt)
}
return false, err
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
fmt.Printf("Response Code: %d %s. Response Body: %s Error:%v\n", response.StatusCode, response.Status, body, err)
if err != nil || response.StatusCode != http.StatusOK {
return false, fmt.Errorf("Unexpected Status Code: %d %s. Response Body: %s error:%v", response.StatusCode, response.Status, body, err)
}
return true, nil
}
func stopTunnelRequest() (bool, error) {
response, err := http.Get(serviceURL + stopEndpoint)
conn, err := grpc.Dial("127.0.0.1:18020", grpc.WithInsecure())
if err != nil {
return false, fmt.Errorf("HTTP Request Error: %v", err)
log.Printf("did not connect: %v", err)
}
defer response.Body.Close()
defer conn.Close()
c := pb.NewTunnelServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
body, err := io.ReadAll(response.Body)
// fmt.Printf("Response Code: %d %s. Response Body: %s Error:%v\n", response.StatusCode, response.Status, body, err)
if err != nil || response.StatusCode != http.StatusOK {
return false, fmt.Errorf("unexpected Status Code: %d %s. Response Body: %s error:%v", response.StatusCode, response.Status, body, err)
_, err = c.Stop(ctx, &pb.Empty{})
if err != nil {
return false, err
}
return true, nil

View File

@@ -1,102 +0,0 @@
package global
import (
"encoding/json"
"fmt"
"github.com/hiddify/libcore/bridge"
"github.com/sagernet/sing-box/experimental/libbox"
"github.com/sagernet/sing-box/log"
)
type CommandClientHandler struct {
port int64
logger log.Logger
}
func (cch *CommandClientHandler) Connected() {
cch.logger.Debug("CONNECTED")
}
func (cch *CommandClientHandler) Disconnected(message string) {
cch.logger.Debug("DISCONNECTED: ", message)
}
func (cch *CommandClientHandler) ClearLog() {
cch.logger.Debug("clear log")
}
func (cch *CommandClientHandler) WriteLog(message string) {
cch.logger.Debug("log: ", message)
}
func (cch *CommandClientHandler) WriteStatus(message *libbox.StatusMessage) {
msg, err := json.Marshal(
map[string]int64{
"connections-in": int64(message.ConnectionsIn),
"connections-out": int64(message.ConnectionsOut),
"uplink": message.Uplink,
"downlink": message.Downlink,
"uplink-total": message.UplinkTotal,
"downlink-total": message.DownlinkTotal,
},
)
cch.logger.Debug("Memory: ", libbox.FormatBytes(message.Memory), ", Goroutines: ", message.Goroutines)
if err != nil {
bridge.SendStringToPort(cch.port, fmt.Sprintf("error: %e", err))
} else {
bridge.SendStringToPort(cch.port, string(msg))
}
}
func (cch *CommandClientHandler) WriteGroups(message libbox.OutboundGroupIterator) {
if message == nil {
return
}
groups := []*OutboundGroup{}
for message.HasNext() {
group := message.Next()
items := group.GetItems()
groupItems := []*OutboundGroupItem{}
for items.HasNext() {
item := items.Next()
groupItems = append(groupItems,
&OutboundGroupItem{
Tag: item.Tag,
Type: item.Type,
URLTestTime: item.URLTestTime,
URLTestDelay: item.URLTestDelay,
},
)
}
groups = append(groups, &OutboundGroup{Tag: group.Tag, Type: group.Type, Selected: group.Selected, Items: groupItems})
}
response, err := json.Marshal(groups)
if err != nil {
bridge.SendStringToPort(cch.port, fmt.Sprintf("error: %e", err))
} else {
bridge.SendStringToPort(cch.port, string(response))
}
}
func (cch *CommandClientHandler) InitializeClashMode(modeList libbox.StringIterator, currentMode string) {
cch.logger.Debug("initial clash mode: ", currentMode)
}
func (cch *CommandClientHandler) UpdateClashMode(newMode string) {
cch.logger.Debug("update clash mode: ", newMode)
}
type OutboundGroup struct {
Tag string `json:"tag"`
Type string `json:"type"`
Selected string `json:"selected"`
Items []*OutboundGroupItem `json:"items"`
}
type OutboundGroupItem struct {
Tag string `json:"tag"`
Type string `json:"type"`
URLTestTime int64 `json:"url-test-time"`
URLTestDelay int32 `json:"url-test-delay"`
}

View File

@@ -1,43 +0,0 @@
package global
import (
"github.com/sagernet/sing-box/experimental/libbox"
"github.com/sagernet/sing-box/log"
)
var commandServer *libbox.CommandServer
type CommandServerHandler struct {
logger log.Logger
}
func (csh *CommandServerHandler) ServiceReload() error {
csh.logger.Trace("Reloading service")
propagateStatus(Starting)
if commandServer != nil {
commandServer.SetService(nil)
commandServer = nil
}
if box != nil {
box.Close()
box = nil
}
return startService(true)
}
func (csh *CommandServerHandler) GetSystemProxyStatus() *libbox.SystemProxyStatus {
csh.logger.Trace("Getting system proxy status")
return &libbox.SystemProxyStatus{Available: true, Enabled: false}
}
func (csh *CommandServerHandler) SetSystemProxyEnabled(isEnabled bool) error {
csh.logger.Trace("Setting system proxy status, enabled? ", isEnabled)
return csh.ServiceReload()
}
func startCommandServer(logFactory log.Factory) error {
logger := logFactory.NewLogger("[Command Server Handler]")
logger.Trace("Starting command server")
commandServer = libbox.NewCommandServer(&CommandServerHandler{logger: logger}, 300)
return commandServer.Start()
}

View File

@@ -1,55 +0,0 @@
package global
import (
"github.com/sagernet/sing-box/experimental/libbox"
"github.com/sagernet/sing-box/log"
)
var (
statusClient *libbox.CommandClient
groupClient *libbox.CommandClient
)
func StartCommand(command int32, port int64, logFactory log.Factory) error {
switch command {
case libbox.CommandStatus:
statusClient = libbox.NewCommandClient(
&CommandClientHandler{
port: port,
logger: logFactory.NewLogger("[Status Command Client]"),
},
&libbox.CommandClientOptions{
Command: libbox.CommandStatus,
StatusInterval: 1000000000,
},
)
return statusClient.Connect()
case libbox.CommandGroup:
groupClient = libbox.NewCommandClient(
&CommandClientHandler{
port: port,
logger: logFactory.NewLogger("[Group Command Client]"),
},
&libbox.CommandClientOptions{
Command: libbox.CommandGroup,
StatusInterval: 1000000000,
},
)
return groupClient.Connect()
}
return nil
}
func StopCommand(command int32) error {
switch command {
case libbox.CommandStatus:
err := statusClient.Disconnect()
statusClient = nil
return err
case libbox.CommandGroup:
err := groupClient.Disconnect()
groupClient = nil
return err
}
return nil
}

View File

@@ -1,15 +0,0 @@
package global
const (
Stopped = "Stopped"
Starting = "Starting"
Started = "Started"
Stopping = "Stopping"
)
const (
EmptyConfiguration = "EmptyConfiguration"
StartCommandServer = "StartCommandServer"
CreateService = "CreateService"
StartService = "StartService"
)

View File

@@ -1,405 +0,0 @@
package global
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/hiddify/libcore/config"
"github.com/sagernet/sing-box/experimental/libbox"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
)
var box *libbox.BoxService
var configOptions *config.ConfigOptions
var activeConfigPath *string
var logFactory *log.Factory
func setup(baseDir string, workingDir string, tempDir string, statusPort int64, debug bool) error {
Setup(baseDir, workingDir, tempDir)
statusPropagationPort = statusPort
var defaultWriter io.Writer
if !debug {
defaultWriter = io.Discard
}
factory, err := log.New(
log.Options{
DefaultWriter: defaultWriter,
BaseTime: time.Now(),
Observable: false,
})
if err != nil {
return err
}
logFactory = &factory
return nil
}
func parse(path string, tempPath string, debug bool) error {
config, err := config.ParseConfig(tempPath, debug)
if err != nil {
return err
}
err = os.WriteFile(path, config, 0644)
if err != nil {
return err
}
return nil
}
func changeConfigOptions(configOptionsJson string) error {
configOptions = &config.ConfigOptions{}
err := json.Unmarshal([]byte(configOptionsJson), configOptions)
if err != nil {
return err
}
if configOptions.Warp.WireguardConfigStr != "" {
err := json.Unmarshal([]byte(configOptions.Warp.WireguardConfigStr), &configOptions.Warp.WireguardConfig)
if err != nil {
return err
}
}
return nil
}
func generateConfig(path string) (string, error) {
config, err := generateConfigFromFile(path, *configOptions)
if err != nil {
return "", err
}
return config, nil
}
func generateConfigFromFile(path string, configOpt config.ConfigOptions) (string, error) {
os.Chdir(filepath.Dir(path))
content, err := os.ReadFile(path)
if err != nil {
return "", err
}
options, err := parseConfig(string(content))
if err != nil {
return "", err
}
config, err := config.BuildConfigJson(configOpt, options)
if err != nil {
return "", err
}
return config, nil
}
func start(configPath string, disableMemoryLimit bool) error {
if status != Stopped {
return nil
}
propagateStatus(Starting)
activeConfigPath = &configPath
libbox.SetMemoryLimit(!disableMemoryLimit)
err := startService(false)
if err != nil {
return err
}
return nil
}
func startService(delayStart bool) error {
content, err := os.ReadFile(*activeConfigPath)
if err != nil {
return stopAndAlert(EmptyConfiguration, err)
}
options, err := parseConfig(string(content))
if err != nil {
return stopAndAlert(EmptyConfiguration, err)
}
os.Chdir(filepath.Dir(*activeConfigPath))
var patchedOptions *option.Options
patchedOptions, err = config.BuildConfig(*configOptions, options)
if err != nil {
return fmt.Errorf("error building config: %w", err)
}
config.SaveCurrentConfig(filepath.Join(sWorkingPath, "tunnel-current-config.json"), *patchedOptions)
err = startCommandServer(*logFactory)
if err != nil {
return stopAndAlert(StartCommandServer, err)
}
instance, err := NewService(*patchedOptions)
if err != nil {
return stopAndAlert(CreateService, err)
}
if delayStart {
time.Sleep(250 * time.Millisecond)
}
err = instance.Start()
if err != nil {
return stopAndAlert(StartService, err)
}
box = instance
commandServer.SetService(box)
propagateStatus(Started)
return nil
}
func stop() error {
if status != Started {
return nil
}
if box == nil {
return errors.New("instance not found")
}
config.DeactivateTunnelService()
propagateStatus(Stopping)
commandServer.SetService(nil)
err := box.Close()
if err != nil {
return err
}
box = nil
err = commandServer.Close()
if err != nil {
return err
}
commandServer = nil
propagateStatus(Stopped)
return nil
}
func restart(configPath string, disableMemoryLimit bool) error {
log.Debug("[Service] Restarting")
if status != Started {
return nil
}
if box == nil {
return errors.New("instance not found")
}
err := stop()
if err != nil {
return err
}
propagateStatus(Starting)
time.Sleep(250 * time.Millisecond)
activeConfigPath = &configPath
libbox.SetMemoryLimit(!disableMemoryLimit)
gErr := startService(false)
if gErr != nil {
return gErr
}
return nil
}
func startCommandClient(command int, port int64) error {
err := StartCommand(int32(command), port, *logFactory)
if err != nil {
return err
}
return nil
}
func stopCommandClient(command int) error {
err := StopCommand(int32(command))
if err != nil {
return err
}
return nil
}
func selectOutbound(groupTag string, outboundTag string) error {
err := libbox.NewStandaloneCommandClient().SelectOutbound(groupTag, outboundTag)
if err != nil {
return err
}
return nil
}
func urlTest(groupTag string) error {
err := libbox.NewStandaloneCommandClient().URLTest(groupTag)
if err != nil {
return err
}
return nil
}
func StartServiceC(delayStart bool, content string) error {
if box != nil {
return errors.New("instance already started")
}
options, err := parseConfig(content)
// if err != nil {
// return stopAndAlert(EmptyConfiguration, err)
// }
// configOptions = &config.ConfigOptions{}
// patchedOptions, err := config.BuildConfig(*configOptions, options)
// options = *patchedOptions
// config.SaveCurrentConfig(filepath.Join(sWorkingPath, "custom-current-config.json"), options)
// if err != nil {
// fmt.Printf("Error in saving config: %v\n", err)
// return err
// }
// err = startCommandServer(*logFactory)
// if err != nil {
// return err
// }
instance, err := NewService(options)
if err != nil {
// return stopAndAlert(CreateService, err)
return err
}
// if delayStart {
// time.Sleep(250 * time.Millisecond)
// }
err = instance.Start()
if err != nil {
// return stopAndAlert(StartService, err)
fmt.Printf("String Service Error: %v\n", err)
return err
}
box = instance
// commandServer.SetService(box)
status = Started
return nil
}
func StopServiceC() error {
// if status != Started {
// return errors.New("instance not started")
// }
config.DeactivateTunnelService()
if box == nil {
return errors.New("instance not found")
}
// propagateStatus(Stopping)
err := box.Close()
// commandServer.SetService(nil)
if err != nil {
return err
}
box = nil
// err = commandServer.Close()
// if err != nil {
// return err
// }
commandServer = nil
status = Stopped
return nil
}
func SetupC(baseDir string, workDir string, tempDir string, debug bool) error {
err := os.MkdirAll(baseDir, 0644)
if err != nil {
return err
}
err = os.MkdirAll(workDir, 0644)
if err != nil {
return err
}
err = os.MkdirAll(tempDir, 0644)
if err != nil {
return err
}
Setup(baseDir, workDir, tempDir)
var defaultWriter io.Writer
if !debug {
defaultWriter = io.Discard
}
factory, err := log.New(
log.Options{
DefaultWriter: defaultWriter,
BaseTime: time.Now(),
Observable: false,
})
if err != nil {
return err
}
logFactory = &factory
return nil
}
func MakeConfig(Ipv6 bool, ServerPort int, StrictRoute bool, EndpointIndependentNat bool, Stack string) string {
var ipv6 string
if Ipv6 {
ipv6 = ` "inet6_address": "fdfe:dcba:9876::1/126",`
} else {
ipv6 = ""
}
base := `{
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"interface_name": "HiddifyTunnel",
"inet4_address": "172.19.0.1/30",
` + ipv6 + `
"mtu": 9000,
"auto_route": true,
"strict_route": ` + fmt.Sprintf("%t", StrictRoute) + `,
"endpoint_independent_nat": ` + fmt.Sprintf("%t", EndpointIndependentNat) + `,
"stack": "` + Stack + `"
}
],
"outbounds": [
{
"type": "socks",
"tag": "socks-out",
"server": "127.0.0.1",
"server_port": ` + fmt.Sprintf("%d", ServerPort) + `,
"version": "5"
}
]
}`
return base
}
func WriteParameters(Ipv6 bool, ServerPort int, StrictRoute bool, EndpointIndependentNat bool, Stack string) error {
parameters := fmt.Sprintf("%t,%d,%t,%t,%s", Ipv6, ServerPort, StrictRoute, EndpointIndependentNat, Stack)
err := os.WriteFile("parameters.config", []byte(parameters), 0644)
if err != nil {
return err
}
return nil
}
func ReadParameters() (bool, int, bool, bool, string, error) {
Data, err := os.ReadFile("parameters.config")
if err != nil {
return false, 0, false, false, "", err
}
DataSlice := strings.Split(string(Data), ",")
Ipv6, _ := strconv.ParseBool(DataSlice[0])
ServerPort, _ := strconv.Atoi(DataSlice[1])
StrictRoute, _ := strconv.ParseBool(DataSlice[2])
EndpointIndependentNat, _ := strconv.ParseBool(DataSlice[3])
stack := DataSlice[4]
return Ipv6, ServerPort, StrictRoute, EndpointIndependentNat, stack, nil
}

View File

@@ -1,18 +0,0 @@
package global
type Stack string
const (
System Stack = "system"
GVisor Stack = "gvisor"
Mixed Stack = "mixed"
// LWIP Stack = "LWIP"
)
type Parameters struct {
Ipv6 bool
ServerPort int
StrictRoute bool
EndpointIndependentNat bool
Stack Stack
}

View File

@@ -1,68 +0,0 @@
package global
import (
"context"
"os"
"runtime"
runtimeDebug "runtime/debug"
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/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
)
func Setup(basePath string, workingPath string, tempPath string) {
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()
}
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 parseConfig(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
}

View File

@@ -1,32 +0,0 @@
package global
import (
"encoding/json"
"github.com/hiddify/libcore/bridge"
)
var statusPropagationPort int64
var status = Stopped
type StatusMessage struct {
Status string `json:"status"`
Alert *string `json:"alert"`
Message *string `json:"message"`
}
func propagateStatus(newStatus string) {
status = newStatus
msg, _ := json.Marshal(StatusMessage{Status: status})
bridge.SendStringToPort(statusPropagationPort, string(msg))
}
func stopAndAlert(alert string, err error) error {
status = Stopped
message := err.Error()
msg, _ := json.Marshal(StatusMessage{Status: status, Alert: &alert, Message: &message})
bridge.SendStringToPort(statusPropagationPort, string(msg))
return nil
}

View File

@@ -199,34 +199,6 @@ func (LogType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_b52c484803f63ee3, []int{4}
}
type StackType int32
const (
StackType_SYSTEM StackType = 0
StackType_GVISOR StackType = 1
StackType_MIXED StackType = 2
)
var StackType_name = map[int32]string{
0: "SYSTEM",
1: "GVISOR",
2: "MIXED",
}
var StackType_value = map[string]int32{
"SYSTEM": 0,
"GVISOR": 1,
"MIXED": 2,
}
func (x StackType) String() string {
return proto.EnumName(StackType_name, int32(x))
}
func (StackType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_b52c484803f63ee3, []int{5}
}
type CoreInfoResponse struct {
CoreState CoreState `protobuf:"varint,1,opt,name=core_state,json=coreState,proto3,enum=hiddifyrpc.CoreState" json:"core_state,omitempty"`
MessageType MessageType `protobuf:"varint,2,opt,name=message_type,json=messageType,proto3,enum=hiddifyrpc.MessageType" json:"message_type,omitempty"`
@@ -288,6 +260,7 @@ type StartRequest struct {
DisableMemoryLimit bool `protobuf:"varint,3,opt,name=disable_memory_limit,json=disableMemoryLimit,proto3" json:"disable_memory_limit,omitempty"`
DelayStart bool `protobuf:"varint,4,opt,name=delay_start,json=delayStart,proto3" json:"delay_start,omitempty"`
EnableOldCommandServer bool `protobuf:"varint,5,opt,name=enable_old_command_server,json=enableOldCommandServer,proto3" json:"enable_old_command_server,omitempty"`
EnableRawConfig bool `protobuf:"varint,6,opt,name=enable_raw_config,json=enableRawConfig,proto3" json:"enable_raw_config,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -353,6 +326,13 @@ func (m *StartRequest) GetEnableOldCommandServer() bool {
return false
}
func (m *StartRequest) GetEnableRawConfig() bool {
if m != nil {
return m.EnableRawConfig
}
return false
}
type SetupRequest struct {
BasePath string `protobuf:"bytes,1,opt,name=base_path,json=basePath,proto3" json:"base_path,omitempty"`
WorkingPath string `protobuf:"bytes,2,opt,name=working_path,json=workingPath,proto3" json:"working_path,omitempty"`
@@ -1562,14 +1542,14 @@ func (m *StopRequest) XXX_DiscardUnknown() {
var xxx_messageInfo_StopRequest proto.InternalMessageInfo
type TunnelStartRequest struct {
Ipv6 bool `protobuf:"varint,1,opt,name=ipv6,proto3" json:"ipv6,omitempty"`
ServerPort int32 `protobuf:"varint,2,opt,name=server_port,json=serverPort,proto3" json:"server_port,omitempty"`
StrictRoute bool `protobuf:"varint,3,opt,name=strict_route,json=strictRoute,proto3" json:"strict_route,omitempty"`
EndpointIndependentNat bool `protobuf:"varint,4,opt,name=endpoint_independent_nat,json=endpointIndependentNat,proto3" json:"endpoint_independent_nat,omitempty"`
Stack StackType `protobuf:"varint,5,opt,name=stack,proto3,enum=hiddifyrpc.StackType" json:"stack,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
Ipv6 bool `protobuf:"varint,1,opt,name=ipv6,proto3" json:"ipv6,omitempty"`
ServerPort int32 `protobuf:"varint,2,opt,name=server_port,json=serverPort,proto3" json:"server_port,omitempty"`
StrictRoute bool `protobuf:"varint,3,opt,name=strict_route,json=strictRoute,proto3" json:"strict_route,omitempty"`
EndpointIndependentNat bool `protobuf:"varint,4,opt,name=endpoint_independent_nat,json=endpointIndependentNat,proto3" json:"endpoint_independent_nat,omitempty"`
Stack string `protobuf:"bytes,5,opt,name=stack,proto3" json:"stack,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TunnelStartRequest) Reset() { *m = TunnelStartRequest{} }
@@ -1625,11 +1605,11 @@ func (m *TunnelStartRequest) GetEndpointIndependentNat() bool {
return false
}
func (m *TunnelStartRequest) GetStack() StackType {
func (m *TunnelStartRequest) GetStack() string {
if m != nil {
return m.Stack
}
return StackType_SYSTEM
return ""
}
type TunnelResponse struct {
@@ -1677,7 +1657,6 @@ func init() {
proto.RegisterEnum("hiddifyrpc.MessageType", MessageType_name, MessageType_value)
proto.RegisterEnum("hiddifyrpc.LogLevel", LogLevel_name, LogLevel_value)
proto.RegisterEnum("hiddifyrpc.LogType", LogType_name, LogType_value)
proto.RegisterEnum("hiddifyrpc.StackType", StackType_name, StackType_value)
proto.RegisterType((*CoreInfoResponse)(nil), "hiddifyrpc.CoreInfoResponse")
proto.RegisterType((*StartRequest)(nil), "hiddifyrpc.StartRequest")
proto.RegisterType((*SetupRequest)(nil), "hiddifyrpc.SetupRequest")
@@ -1711,132 +1690,131 @@ func init() {
func init() { proto.RegisterFile("hiddifyrpc/hiddify.proto", fileDescriptor_b52c484803f63ee3) }
var fileDescriptor_b52c484803f63ee3 = []byte{
// 2025 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xdd, 0x72, 0xdb, 0xc6,
0x15, 0x36, 0x28, 0x52, 0x24, 0x0f, 0x49, 0x19, 0x5a, 0xc9, 0x32, 0xad, 0xd8, 0xb5, 0x83, 0x69,
0x12, 0x55, 0x4d, 0xe5, 0x54, 0x71, 0xe3, 0xfe, 0x79, 0x3c, 0x14, 0x09, 0x29, 0xac, 0x28, 0x92,
0x03, 0x40, 0x71, 0xdc, 0xce, 0x14, 0x03, 0x01, 0x2b, 0x1a, 0x15, 0x88, 0x45, 0x81, 0xa5, 0x12,
0x4e, 0x3b, 0xbd, 0x68, 0x67, 0xfa, 0x02, 0x9d, 0xe9, 0x65, 0x1f, 0xa4, 0x37, 0x7d, 0x82, 0x5e,
0xf5, 0x0d, 0x3a, 0x7d, 0x85, 0xde, 0x77, 0xf6, 0x07, 0x24, 0x40, 0x91, 0x56, 0x9a, 0xe4, 0x6e,
0xf7, 0x9c, 0xb3, 0x07, 0xe7, 0x7f, 0xbf, 0x05, 0x34, 0xdf, 0xf8, 0x9e, 0xe7, 0x5f, 0x4e, 0xe3,
0xc8, 0x7d, 0x2a, 0x97, 0x07, 0x51, 0x4c, 0x28, 0x41, 0x30, 0xe7, 0x68, 0x7f, 0x53, 0x40, 0x6d,
0x93, 0x18, 0x77, 0xc3, 0x4b, 0x62, 0xe0, 0x24, 0x22, 0x61, 0x82, 0xd1, 0x33, 0x00, 0x97, 0xc4,
0xd8, 0x4e, 0xa8, 0x43, 0x71, 0x53, 0x79, 0xa2, 0xec, 0x6d, 0x1c, 0xde, 0x3b, 0x98, 0x9f, 0x3a,
0x60, 0x27, 0x4c, 0xc6, 0x34, 0xaa, 0x6e, 0xba, 0x44, 0x3f, 0x85, 0xfa, 0x18, 0x27, 0x89, 0x33,
0xc2, 0x36, 0x9d, 0x46, 0xb8, 0x59, 0xe0, 0xe7, 0xee, 0x67, 0xcf, 0x9d, 0x09, 0xbe, 0x35, 0x8d,
0xb0, 0x51, 0x1b, 0xcf, 0x37, 0xa8, 0x09, 0x65, 0xb9, 0x6d, 0xae, 0x3d, 0x51, 0xf6, 0xaa, 0x46,
0xba, 0xd5, 0xfe, 0xa3, 0x40, 0xdd, 0xa4, 0x4e, 0x4c, 0x0d, 0xfc, 0xdb, 0x09, 0x4e, 0x28, 0x7a,
0x0c, 0x35, 0x97, 0x84, 0x97, 0xfe, 0xc8, 0x8e, 0x1c, 0xfa, 0x86, 0x5b, 0x57, 0x35, 0x40, 0x90,
0x86, 0x0e, 0x7d, 0x83, 0xde, 0x83, 0x0d, 0x29, 0xe0, 0x92, 0x90, 0xe2, 0x90, 0x72, 0x4b, 0xaa,
0x46, 0x43, 0x50, 0xdb, 0x82, 0x88, 0x3e, 0x82, 0x6d, 0xcf, 0x4f, 0x9c, 0x8b, 0x00, 0xdb, 0x63,
0x3c, 0x26, 0xf1, 0xd4, 0x0e, 0xfc, 0xb1, 0x4f, 0xf9, 0xf7, 0x2b, 0x06, 0x92, 0xbc, 0x33, 0xce,
0xea, 0x31, 0x0e, 0xfb, 0xb2, 0x87, 0x03, 0x67, 0xca, 0xe2, 0x12, 0xd3, 0x66, 0x91, 0x0b, 0x02,
0x27, 0x71, 0x0b, 0xd1, 0x4f, 0xe0, 0x01, 0x0e, 0xb9, 0x46, 0x12, 0x78, 0xb6, 0x4b, 0xc6, 0x63,
0x27, 0xf4, 0xec, 0x04, 0xc7, 0xd7, 0x38, 0x6e, 0x96, 0xb8, 0xf8, 0x8e, 0x10, 0x18, 0x04, 0x5e,
0x5b, 0xb0, 0x4d, 0xce, 0xd5, 0xae, 0xa0, 0x6e, 0x62, 0x3a, 0x89, 0x52, 0x2f, 0xdf, 0x81, 0xea,
0x85, 0x93, 0xe0, 0xac, 0x8f, 0x15, 0x46, 0xe0, 0x1e, 0xbe, 0x0b, 0xf5, 0x2f, 0x48, 0x7c, 0xe5,
0x87, 0x32, 0x06, 0xc2, 0xbf, 0x9a, 0xa4, 0x71, 0x91, 0x77, 0xa0, 0x4a, 0xf1, 0x38, 0x12, 0x7c,
0x11, 0xd2, 0x0a, 0x23, 0x30, 0xa6, 0xe6, 0x42, 0x65, 0x96, 0xeb, 0x17, 0xd0, 0x88, 0xe5, 0xda,
0x76, 0x89, 0x97, 0xa6, 0xbb, 0x99, 0x4d, 0x5b, 0x2a, 0xdc, 0x26, 0x1e, 0x36, 0xea, 0x71, 0x66,
0x97, 0x4d, 0x5c, 0x21, 0x9f, 0x38, 0x0d, 0xea, 0x9f, 0xe2, 0x20, 0x20, 0xa9, 0x47, 0x08, 0x8a,
0xa1, 0x33, 0xc6, 0xd2, 0x19, 0xbe, 0xd6, 0xbe, 0x07, 0x0d, 0x29, 0x23, 0xad, 0xc9, 0xa8, 0x53,
0xf2, 0xea, 0xca, 0x50, 0xd2, 0xc7, 0x11, 0x9d, 0x6a, 0xff, 0x28, 0x00, 0x98, 0xd3, 0x84, 0xe2,
0x31, 0xab, 0x59, 0xb4, 0x03, 0xeb, 0x22, 0x7d, 0xfc, 0xc0, 0x9a, 0x21, 0x77, 0xe8, 0x3b, 0x00,
0x23, 0x12, 0x93, 0x09, 0xf5, 0x43, 0x9c, 0x70, 0xdb, 0x4a, 0x46, 0x86, 0x22, 0xab, 0x24, 0xc4,
0x2e, 0xf5, 0x49, 0x98, 0xd8, 0x7e, 0xc8, 0xa3, 0x54, 0xe2, 0x55, 0x92, 0x52, 0xbb, 0x21, 0xfa,
0x00, 0xee, 0x66, 0xc5, 0xc8, 0x44, 0xe4, 0xbd, 0x64, 0x64, 0x4f, 0x0f, 0x26, 0x14, 0x7d, 0x1f,
0x36, 0x69, 0xec, 0x5c, 0x5e, 0xfa, 0xae, 0xed, 0x5c, 0x3b, 0x7e, 0xc0, 0xb2, 0x2c, 0x73, 0xae,
0x4a, 0x46, 0x2b, 0xa5, 0x33, 0xa3, 0x27, 0x51, 0xe0, 0x87, 0x57, 0xcd, 0x75, 0x61, 0xb4, 0xd8,
0xa1, 0x5d, 0xa8, 0x78, 0xe4, 0x8b, 0x90, 0x73, 0xca, 0x9c, 0x33, 0xdb, 0xb3, 0xa4, 0x0b, 0x29,
0x9b, 0x12, 0xea, 0x04, 0xcd, 0x0a, 0xe7, 0xd7, 0x04, 0xcd, 0x62, 0x24, 0xe6, 0x53, 0x2a, 0x2e,
0x85, 0xaa, 0x5c, 0xa8, 0x91, 0x52, 0xb9, 0x98, 0xf6, 0x27, 0x05, 0x36, 0x07, 0x13, 0x7a, 0x41,
0x26, 0xa1, 0x77, 0x12, 0x93, 0x49, 0xd4, 0xa5, 0x78, 0x8c, 0x54, 0x58, 0xa3, 0xce, 0x48, 0x86,
0x9d, 0x2d, 0x59, 0xc6, 0x66, 0x8d, 0x5c, 0x35, 0xf8, 0x1a, 0x69, 0xd0, 0x98, 0xc4, 0x81, 0x4d,
0x71, 0x42, 0x6d, 0xea, 0x8f, 0x45, 0xbb, 0x32, 0x33, 0xe2, 0xc0, 0xc2, 0x09, 0xb5, 0xfc, 0x31,
0x46, 0xdf, 0x85, 0x8d, 0x99, 0x0c, 0xef, 0x0e, 0x19, 0xb2, 0xba, 0x14, 0xea, 0x30, 0x9a, 0xf6,
0x67, 0x05, 0x1a, 0x39, 0x2b, 0xbe, 0xa2, 0x05, 0xbb, 0x50, 0x49, 0x70, 0x80, 0x5d, 0x8a, 0xbd,
0xb4, 0xb0, 0xd3, 0x3d, 0xfa, 0x18, 0x4a, 0x3e, 0xc5, 0xe3, 0xa4, 0x59, 0x7c, 0xb2, 0xb6, 0x57,
0x3b, 0x7c, 0x94, 0x2d, 0xe2, 0x1b, 0x1e, 0x1b, 0x42, 0x56, 0xeb, 0x2c, 0x44, 0xa3, 0xe7, 0x27,
0x14, 0x3d, 0x4d, 0x35, 0x29, 0x5c, 0xd3, 0x83, 0x95, 0x9a, 0x52, 0x2d, 0x03, 0xa8, 0xbd, 0x72,
0xe2, 0xa8, 0xe5, 0xba, 0x64, 0x12, 0x52, 0xf4, 0x08, 0xc0, 0x11, 0x4b, 0xdb, 0xf7, 0xa4, 0x4b,
0x55, 0x49, 0xe9, 0x7a, 0x2c, 0x99, 0x8e, 0xeb, 0xe2, 0x24, 0xb1, 0x29, 0xb9, 0xc2, 0x61, 0xda,
0xc1, 0x82, 0x66, 0x31, 0x92, 0xf6, 0x77, 0x05, 0xb6, 0x98, 0xc6, 0x57, 0x7e, 0x8c, 0x47, 0x13,
0x27, 0xf6, 0xda, 0x7c, 0x7c, 0xb1, 0x29, 0x14, 0xc5, 0xfe, 0xb5, 0x43, 0xb1, 0x7d, 0x85, 0xa7,
0xe9, 0xfc, 0x93, 0xa4, 0x53, 0x3c, 0x45, 0x1f, 0x02, 0x0a, 0x88, 0xeb, 0x04, 0xb6, 0xe3, 0x79,
0x31, 0xfb, 0x84, 0x1f, 0x5d, 0x3f, 0x93, 0x5f, 0x50, 0x39, 0xa7, 0x25, 0x18, 0xdd, 0xe8, 0xfa,
0xd9, 0x52, 0xe9, 0x4f, 0x64, 0x60, 0x17, 0xa5, 0x3f, 0x41, 0xef, 0xc3, 0xdd, 0x08, 0xe3, 0xd8,
0x8e, 0x26, 0x17, 0x81, 0xef, 0x72, 0x03, 0x8a, 0x62, 0xb8, 0x32, 0xf2, 0x90, 0x53, 0x4f, 0xf1,
0x54, 0xfb, 0xab, 0x02, 0x3b, 0xcc, 0xf8, 0x13, 0x1c, 0xe2, 0xd8, 0x61, 0x4d, 0x32, 0x6b, 0xf1,
0x1f, 0x42, 0x59, 0xc6, 0x81, 0xdb, 0x5e, 0xcb, 0xdf, 0x10, 0x99, 0x18, 0x1a, 0xa9, 0x1c, 0x2b,
0x8c, 0x80, 0x8c, 0xa4, 0x0b, 0x6c, 0x89, 0x9e, 0xc3, 0xba, 0x98, 0xe6, 0xdc, 0xd2, 0xda, 0xe1,
0xe3, 0x45, 0x1d, 0x0b, 0x51, 0x33, 0xa4, 0xb8, 0x76, 0x0a, 0x9b, 0x62, 0x78, 0x0c, 0x63, 0xf2,
0x25, 0x1b, 0xdb, 0x74, 0x92, 0xa0, 0x87, 0x50, 0x9d, 0xf7, 0xac, 0xc2, 0x7b, 0x76, 0x4e, 0x60,
0x33, 0x49, 0x0c, 0x6d, 0x8f, 0x5b, 0x50, 0x31, 0xd2, 0xad, 0xf6, 0x7b, 0xa8, 0x0f, 0x9d, 0x38,
0xc1, 0xe9, 0x88, 0x6b, 0x42, 0x39, 0xbd, 0x72, 0xe4, 0xf4, 0x92, 0xdb, 0xc5, 0x4b, 0xab, 0x70,
0xe3, 0xd2, 0x7a, 0xdb, 0xbc, 0x46, 0xdb, 0x50, 0xf2, 0xf0, 0xc5, 0x64, 0x24, 0xaf, 0x1c, 0xb1,
0xd1, 0xfe, 0xa8, 0x40, 0x43, 0x7e, 0xfe, 0x5b, 0x9b, 0xe5, 0xf9, 0x1b, 0x73, 0x66, 0xfe, 0xea,
0xeb, 0xb9, 0x07, 0xbb, 0xed, 0x37, 0x4e, 0x38, 0xc2, 0x22, 0xce, 0x83, 0x88, 0x0f, 0xc4, 0x34,
0x20, 0x07, 0xb0, 0x25, 0xdd, 0x26, 0x82, 0x61, 0xff, 0x26, 0x21, 0xa1, 0x0c, 0xce, 0xa6, 0x9b,
0x3d, 0xf2, 0x8b, 0x84, 0x84, 0xda, 0xaf, 0xe1, 0x9e, 0xac, 0x18, 0xa9, 0x2f, 0x73, 0x79, 0x64,
0x6e, 0x42, 0xbe, 0xce, 0x87, 0xac, 0xb0, 0x2a, 0x64, 0x6b, 0xd9, 0x90, 0xbd, 0x84, 0x9d, 0x45,
0xfd, 0x32, 0x74, 0x37, 0x41, 0x83, 0xb2, 0x04, 0x34, 0x68, 0xaf, 0xe0, 0x9e, 0xc9, 0x87, 0x4d,
0x3a, 0x03, 0x32, 0xf7, 0xf5, 0x88, 0x8d, 0x03, 0x7b, 0x3e, 0xc1, 0x2a, 0x9c, 0x60, 0x39, 0x23,
0xd6, 0xed, 0x44, 0xca, 0x73, 0xbe, 0xec, 0xf6, 0x94, 0x66, 0x39, 0x23, 0xed, 0x07, 0xb0, 0x71,
0x2e, 0xa6, 0xe3, 0x57, 0xd1, 0xa8, 0xfd, 0x01, 0x1e, 0xa4, 0x8e, 0xb0, 0x6a, 0xcf, 0x07, 0xeb,
0x31, 0xd4, 0x02, 0xdf, 0xc5, 0xac, 0x0a, 0x32, 0x13, 0x42, 0x92, 0xd8, 0x84, 0xc8, 0x0f, 0xa7,
0xc2, 0x6d, 0xc3, 0x69, 0xed, 0xe6, 0x70, 0x7a, 0x01, 0x0f, 0x4d, 0x4c, 0x33, 0x9d, 0xa4, 0x8b,
0x96, 0x48, 0x4d, 0x78, 0x04, 0xe0, 0x27, 0x76, 0xda, 0x36, 0xb2, 0xa5, 0xfc, 0x44, 0x4a, 0x69,
0xbf, 0x03, 0xe8, 0x91, 0x91, 0x44, 0x83, 0x68, 0x1f, 0x4a, 0x01, 0xbe, 0xc6, 0x81, 0x2c, 0xd7,
0xed, 0x6c, 0xb9, 0xf6, 0xc8, 0xa8, 0xc7, 0x78, 0x86, 0x10, 0x41, 0x1f, 0x64, 0x6e, 0x84, 0x8d,
0xc3, 0xad, 0x05, 0x51, 0x0e, 0x2c, 0xc5, 0x35, 0xb1, 0xba, 0x64, 0x1b, 0x50, 0x33, 0x29, 0x49,
0x91, 0x96, 0xf6, 0x2f, 0x05, 0x90, 0x35, 0x09, 0x43, 0x1c, 0xe4, 0x60, 0x26, 0x82, 0x22, 0x9f,
0x84, 0xc2, 0x76, 0xbe, 0x66, 0x81, 0x15, 0x60, 0xce, 0x8e, 0x48, 0x4c, 0x53, 0x50, 0x21, 0x48,
0x43, 0x12, 0x53, 0x16, 0xb9, 0x84, 0xc6, 0xbe, 0x4b, 0x6d, 0x86, 0x33, 0xb0, 0x2c, 0xbe, 0x9a,
0xa0, 0x19, 0x8c, 0x84, 0x7e, 0x0c, 0x4d, 0x1c, 0x7a, 0x11, 0xf1, 0x59, 0xf0, 0x43, 0x0f, 0x47,
0x38, 0xf4, 0x70, 0x48, 0xed, 0xd0, 0x49, 0x11, 0xe5, 0x4e, 0xca, 0xef, 0xce, 0xd9, 0x7d, 0x87,
0x21, 0x8c, 0x52, 0x42, 0x1d, 0xf7, 0x8a, 0xa3, 0x8a, 0x05, 0x40, 0x6e, 0x32, 0x06, 0xf7, 0x5e,
0xc8, 0x68, 0xfb, 0xb0, 0x21, 0x9c, 0xba, 0x1d, 0x5a, 0xed, 0x6b, 0x50, 0xcf, 0x4e, 0x05, 0xb4,
0x0e, 0x85, 0xc1, 0xa9, 0x7a, 0x07, 0x01, 0xac, 0x1f, 0xb7, 0xba, 0x3d, 0xbd, 0xa3, 0x2a, 0xfb,
0x2d, 0xa8, 0xce, 0x40, 0x3f, 0xaa, 0x41, 0xd9, 0xb4, 0x06, 0xc3, 0xa1, 0xde, 0x51, 0xef, 0xa0,
0x3a, 0x54, 0x4c, 0xab, 0x65, 0x58, 0xdd, 0xfe, 0x89, 0xaa, 0x08, 0x56, 0xcb, 0xb0, 0xf4, 0x8e,
0x5a, 0x10, 0xac, 0xc1, 0x70, 0xc8, 0x58, 0x6b, 0xfb, 0xff, 0x2c, 0x40, 0x2d, 0xf3, 0x00, 0x40,
0x55, 0x28, 0xe9, 0x67, 0x43, 0xeb, 0xb5, 0x7a, 0x07, 0xdd, 0x87, 0x2d, 0xbe, 0xb4, 0xdb, 0x83,
0xfe, 0x71, 0xf7, 0xe4, 0xdc, 0x68, 0x59, 0xdd, 0x41, 0x5f, 0x55, 0x50, 0x13, 0xb6, 0xb9, 0x3a,
0xbb, 0x3d, 0x38, 0x3b, 0x6b, 0xf5, 0x3b, 0xb6, 0xa9, 0x1b, 0x9f, 0xe9, 0x86, 0x5a, 0x40, 0x08,
0x36, 0xda, 0x86, 0xde, 0xb2, 0x74, 0x4e, 0xea, 0xb6, 0x75, 0x75, 0x0d, 0x6d, 0x42, 0x43, 0x48,
0xa7, 0xa4, 0x22, 0xda, 0x06, 0xf5, 0xbc, 0xaf, 0x7f, 0x3e, 0xd4, 0xdb, 0x96, 0xde, 0xb1, 0x75,
0xc3, 0x18, 0x18, 0x6a, 0x09, 0x6d, 0xc1, 0xdd, 0x56, 0xcf, 0xd0, 0x5b, 0x9d, 0xd7, 0x76, 0x6a,
0xed, 0x7a, 0x9e, 0x28, 0xbc, 0x2b, 0xa3, 0x1d, 0x40, 0xdd, 0xbe, 0x69, 0xb5, 0xfa, 0x6d, 0xdd,
0xee, 0x0f, 0x2c, 0xfb, 0x78, 0x70, 0xde, 0xef, 0xa8, 0x15, 0x66, 0x58, 0x8e, 0x9e, 0x9e, 0xa8,
0x2e, 0xe1, 0x88, 0x0f, 0x00, 0x7a, 0x00, 0xf7, 0xb8, 0x01, 0xf6, 0xd1, 0x79, 0xb7, 0xd7, 0xe9,
0xf6, 0x4f, 0xa4, 0xbb, 0x6a, 0x8d, 0x1d, 0x12, 0xac, 0x61, 0xcb, 0x30, 0x33, 0x9c, 0xfa, 0x9c,
0xc3, 0x2c, 0xcb, 0x70, 0x1a, 0xfb, 0x47, 0x50, 0x49, 0xbb, 0x83, 0xc5, 0xb2, 0xa3, 0x1f, 0x9d,
0x9f, 0xa8, 0x77, 0x50, 0x05, 0x8a, 0xdd, 0xfe, 0xf1, 0x40, 0xe4, 0xe2, 0x55, 0xcb, 0xe8, 0xb3,
0xe8, 0x17, 0x78, 0xb4, 0xb9, 0xf7, 0x6b, 0x6c, 0x79, 0xdc, 0xb2, 0x5a, 0x3d, 0xb5, 0xb8, 0xff,
0x21, 0x94, 0x65, 0xdb, 0xb0, 0x73, 0xed, 0x81, 0xa1, 0xab, 0x77, 0x78, 0x0e, 0x65, 0x00, 0x15,
0x56, 0x04, 0xf2, 0x8b, 0x85, 0xfd, 0x03, 0xa8, 0xce, 0x0a, 0x8d, 0x31, 0xcc, 0xd7, 0xa6, 0xa5,
0x9f, 0x89, 0x4a, 0x39, 0xf9, 0xac, 0x6b, 0x0e, 0x0c, 0x55, 0x61, 0xda, 0xcf, 0xba, 0x9f, 0xb3,
0xfc, 0x1f, 0xfe, 0x45, 0x81, 0x12, 0xc7, 0xf7, 0xe8, 0x25, 0x54, 0x4c, 0x67, 0x2a, 0xd6, 0xb9,
0xeb, 0x28, 0xfb, 0x44, 0xd8, 0x7d, 0xb0, 0x84, 0x23, 0xab, 0xb7, 0x0b, 0x1b, 0xa9, 0x02, 0x93,
0xc6, 0xd8, 0x19, 0x7f, 0x2d, 0x35, 0x7b, 0xca, 0x47, 0xca, 0xe1, 0xbf, 0xab, 0x50, 0x64, 0xb5,
0x8c, 0x5e, 0x42, 0x49, 0xbc, 0xdb, 0x9a, 0x0b, 0xad, 0x34, 0x9b, 0x02, 0xbb, 0x0f, 0x17, 0x5f,
0xbd, 0xb9, 0x77, 0xf2, 0xd9, 0xfc, 0xed, 0xcc, 0x40, 0x23, 0x1b, 0xc8, 0xe8, 0x7e, 0x5e, 0xd7,
0x6c, 0xce, 0xbc, 0x5d, 0x15, 0x33, 0x0c, 0x9d, 0xce, 0x01, 0x71, 0xc2, 0xdf, 0x36, 0x2b, 0x75,
0xad, 0x06, 0xb6, 0xcc, 0x0e, 0xae, 0x6c, 0x00, 0x9b, 0x67, 0x8e, 0x1f, 0x7e, 0x7b, 0x0a, 0x3b,
0xd0, 0x38, 0x49, 0x47, 0xfe, 0xdb, 0x95, 0xed, 0xe4, 0x18, 0xb3, 0x03, 0x5c, 0xcb, 0x73, 0x28,
0xf1, 0x77, 0xee, 0x42, 0xcc, 0x33, 0x4f, 0xdf, 0xdd, 0xed, 0x65, 0x70, 0x05, 0xfd, 0x1c, 0x4a,
0x1c, 0xec, 0xe4, 0x0f, 0x66, 0xe1, 0x57, 0x3e, 0xef, 0x79, 0x64, 0xf4, 0x2b, 0xd8, 0x5a, 0x02,
0x53, 0xd0, 0xfb, 0xb9, 0x9c, 0xac, 0xc4, 0x31, 0xb7, 0x94, 0xc1, 0xb1, 0xfc, 0x43, 0xc1, 0x9e,
0xf2, 0xbe, 0x8b, 0xbf, 0x76, 0x39, 0x3d, 0x87, 0x22, 0x0b, 0x23, 0xda, 0xcc, 0x4a, 0xf1, 0x47,
0xef, 0x2d, 0x07, 0x5b, 0x50, 0x36, 0x70, 0xf2, 0x8d, 0x4a, 0x99, 0xf5, 0x57, 0x0e, 0xd8, 0xa0,
0x77, 0xf3, 0x09, 0x5a, 0x02, 0x7a, 0x56, 0x64, 0xea, 0x67, 0x50, 0x96, 0x50, 0x06, 0xed, 0x66,
0x05, 0xf2, 0xf8, 0x66, 0xc5, 0x61, 0x1b, 0xd0, 0x4d, 0x60, 0x83, 0xde, 0xcb, 0xca, 0xae, 0x04,
0x3e, 0xbb, 0xda, 0xe2, 0x2b, 0x60, 0xc9, 0xf3, 0xe3, 0x53, 0xd8, 0x3e, 0xc9, 0x21, 0x17, 0xf9,
0x06, 0x58, 0x12, 0xf4, 0x47, 0x37, 0xeb, 0x38, 0x7b, 0x82, 0x63, 0xc1, 0x25, 0x18, 0x08, 0xed,
0x2d, 0x94, 0xf6, 0x4a, 0x98, 0xb4, 0x22, 0x06, 0x47, 0x50, 0x63, 0x83, 0xfd, 0xd6, 0x89, 0xb2,
0xb3, 0x80, 0x7e, 0xe4, 0xe5, 0xca, 0x87, 0xdc, 0x7f, 0x15, 0x68, 0x48, 0x54, 0x23, 0xab, 0xf2,
0xc5, 0xed, 0xd3, 0x2e, 0x97, 0xae, 0x05, 0xf8, 0xf0, 0xa3, 0xd5, 0xc5, 0xf9, 0xb6, 0x63, 0xcf,
0x61, 0x7d, 0x75, 0x80, 0x6f, 0xf9, 0x9e, 0xfe, 0xa5, 0x4f, 0xff, 0xcf, 0x63, 0x47, 0x1b, 0xbf,
0xac, 0x1f, 0x3c, 0x9d, 0xb3, 0x2f, 0xd6, 0xf9, 0x2f, 0xcf, 0x8f, 0xff, 0x17, 0x00, 0x00, 0xff,
0xff, 0x17, 0x3d, 0x94, 0x57, 0x0e, 0x15, 0x00, 0x00,
// 2014 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xdd, 0x6e, 0xe3, 0xc6,
0x15, 0x5e, 0xea, 0xc7, 0x92, 0x8e, 0x24, 0x2f, 0x3d, 0xf6, 0x7a, 0x65, 0x65, 0x37, 0xbb, 0x21,
0x9a, 0xc4, 0x75, 0x53, 0x6f, 0xea, 0x6c, 0xb3, 0xfd, 0x0b, 0x16, 0xb2, 0x44, 0x3b, 0xaa, 0x65,
0x49, 0xa0, 0xe8, 0x6e, 0xd3, 0x02, 0x25, 0x68, 0x72, 0xac, 0x65, 0x4d, 0x71, 0x58, 0x72, 0xe4,
0x8d, 0xd0, 0xa2, 0x17, 0x2d, 0xd0, 0xeb, 0x02, 0x05, 0x7a, 0xd9, 0x07, 0x29, 0x0a, 0xf4, 0x09,
0xfa, 0x12, 0x7d, 0x8d, 0xde, 0x14, 0xf3, 0x43, 0x89, 0x94, 0xa5, 0x75, 0x9a, 0xe6, 0x6e, 0xe6,
0xfc, 0xf1, 0xcc, 0x37, 0x67, 0xce, 0x7c, 0x43, 0x68, 0xbc, 0xf6, 0x5c, 0xd7, 0xbb, 0x9a, 0x45,
0xa1, 0xf3, 0x4c, 0x0e, 0x0f, 0xc3, 0x88, 0x50, 0x82, 0x60, 0xa1, 0xd1, 0xfe, 0xa6, 0x80, 0xda,
0x26, 0x11, 0xee, 0x06, 0x57, 0xc4, 0xc0, 0x71, 0x48, 0x82, 0x18, 0xa3, 0xe7, 0x00, 0x0e, 0x89,
0xb0, 0x15, 0x53, 0x9b, 0xe2, 0x86, 0xf2, 0x54, 0xd9, 0xdf, 0x3c, 0x7a, 0x70, 0xb8, 0xf0, 0x3a,
0x64, 0x1e, 0x23, 0xa6, 0x34, 0x2a, 0x4e, 0x32, 0x44, 0x3f, 0x82, 0xda, 0x04, 0xc7, 0xb1, 0x3d,
0xc6, 0x16, 0x9d, 0x85, 0xb8, 0x91, 0xe3, 0x7e, 0x0f, 0xd3, 0x7e, 0xe7, 0x42, 0x6f, 0xce, 0x42,
0x6c, 0x54, 0x27, 0x8b, 0x09, 0x6a, 0x40, 0x49, 0x4e, 0x1b, 0xf9, 0xa7, 0xca, 0x7e, 0xc5, 0x48,
0xa6, 0xda, 0x9f, 0x73, 0x50, 0x1b, 0x51, 0x3b, 0xa2, 0x06, 0xfe, 0xcd, 0x14, 0xc7, 0x14, 0x3d,
0x81, 0xaa, 0x43, 0x82, 0x2b, 0x6f, 0x6c, 0x85, 0x36, 0x7d, 0xcd, 0xb3, 0xab, 0x18, 0x20, 0x44,
0x43, 0x9b, 0xbe, 0x46, 0xef, 0xc3, 0xa6, 0x34, 0x70, 0x48, 0x40, 0x71, 0x40, 0x79, 0x26, 0x15,
0xa3, 0x2e, 0xa4, 0x6d, 0x21, 0x44, 0x1f, 0xc3, 0x8e, 0xeb, 0xc5, 0xf6, 0xa5, 0x8f, 0xad, 0x09,
0x9e, 0x90, 0x68, 0x66, 0xf9, 0xde, 0xc4, 0xa3, 0xfc, 0xfb, 0x65, 0x03, 0x49, 0xdd, 0x39, 0x57,
0xf5, 0x98, 0x86, 0x7d, 0xd9, 0xc5, 0xbe, 0x3d, 0x63, 0xb8, 0x44, 0xb4, 0x51, 0xe0, 0x86, 0xc0,
0x45, 0x3c, 0x43, 0xf4, 0x43, 0xd8, 0xc3, 0x01, 0x8f, 0x48, 0x7c, 0xd7, 0x72, 0xc8, 0x64, 0x62,
0x07, 0xae, 0x15, 0xe3, 0xe8, 0x06, 0x47, 0x8d, 0x22, 0x37, 0xdf, 0x15, 0x06, 0x03, 0xdf, 0x6d,
0x0b, 0xf5, 0x88, 0x6b, 0xd1, 0x01, 0x6c, 0x49, 0xd7, 0xc8, 0x7e, 0x63, 0x89, 0x4c, 0x1b, 0x1b,
0xdc, 0xe5, 0xbe, 0x50, 0x18, 0xf6, 0x9b, 0x36, 0x17, 0x6b, 0xd7, 0x50, 0x1b, 0x61, 0x3a, 0x0d,
0x13, 0x44, 0xde, 0x81, 0xca, 0xa5, 0x1d, 0xe3, 0x34, 0x1e, 0x65, 0x26, 0xe0, 0x68, 0xbc, 0x07,
0xb5, 0x37, 0x24, 0xba, 0xf6, 0x02, 0x89, 0x97, 0xc0, 0xa2, 0x2a, 0x65, 0xdc, 0xe4, 0x1d, 0xa8,
0x50, 0x3c, 0x09, 0x85, 0x5e, 0xc0, 0x5f, 0x66, 0x02, 0xa6, 0xd4, 0x1c, 0x28, 0xcf, 0xeb, 0xe2,
0x33, 0xa8, 0x47, 0x72, 0x6c, 0x39, 0xc4, 0x4d, 0x4a, 0xa3, 0x91, 0xde, 0xe2, 0xc4, 0xb8, 0x4d,
0x5c, 0x6c, 0xd4, 0xa2, 0xd4, 0x2c, 0xbd, 0xc9, 0xb9, 0xec, 0x26, 0x6b, 0x50, 0xfb, 0x1c, 0xfb,
0x3e, 0x49, 0x56, 0x84, 0xa0, 0x10, 0xd8, 0x13, 0x2c, 0x17, 0xc3, 0xc7, 0xda, 0xb7, 0xa1, 0x2e,
0x6d, 0x64, 0x36, 0xa9, 0x70, 0x4a, 0x36, 0x5c, 0x09, 0x8a, 0xfa, 0x24, 0xa4, 0x33, 0xed, 0x9f,
0x39, 0x80, 0xd1, 0x2c, 0xa6, 0x78, 0xc2, 0xea, 0x1b, 0xed, 0xc2, 0x86, 0xd8, 0x6a, 0xee, 0x90,
0x37, 0xe4, 0x0c, 0xbd, 0x0b, 0x30, 0x26, 0x11, 0x99, 0x52, 0x2f, 0xc0, 0x31, 0xcf, 0xad, 0x68,
0xa4, 0x24, 0xb2, 0xa2, 0x02, 0xec, 0x50, 0x8f, 0x04, 0xb1, 0xe5, 0x05, 0x1c, 0xa5, 0x22, 0xaf,
0xa8, 0x44, 0xda, 0x0d, 0xd0, 0x87, 0x70, 0x3f, 0x6d, 0x46, 0xa6, 0xa2, 0x46, 0x8a, 0x46, 0xda,
0x7b, 0x30, 0xa5, 0xe8, 0x3b, 0xb0, 0x45, 0x23, 0xfb, 0xea, 0xca, 0x73, 0x2c, 0xfb, 0xc6, 0xf6,
0x7c, 0xb6, 0xbd, 0xb2, 0x3e, 0x54, 0xa9, 0x68, 0x25, 0x72, 0x96, 0xf4, 0x34, 0xf4, 0xbd, 0xe0,
0x9a, 0x97, 0x43, 0xde, 0x90, 0x33, 0xd4, 0x84, 0xb2, 0x4b, 0xde, 0x04, 0x5c, 0x53, 0xe2, 0x9a,
0xf9, 0x9c, 0x6d, 0xba, 0xb0, 0xb2, 0x28, 0xa1, 0xb6, 0xdf, 0x28, 0x73, 0x7d, 0x55, 0xc8, 0x4c,
0x26, 0x62, 0x6b, 0x4a, 0xcc, 0xa5, 0x51, 0x85, 0x1b, 0xd5, 0x13, 0x29, 0x37, 0xd3, 0xfe, 0xa8,
0xc0, 0xd6, 0x60, 0x4a, 0x2f, 0xc9, 0x34, 0x70, 0x4f, 0x23, 0x32, 0x0d, 0xbb, 0x14, 0x4f, 0x90,
0x0a, 0x79, 0x6a, 0x8f, 0x25, 0xec, 0x6c, 0xc8, 0x76, 0x6c, 0x7e, 0xe8, 0x2b, 0x06, 0x1f, 0x23,
0x0d, 0xea, 0xd3, 0xc8, 0xb7, 0x28, 0x8e, 0xa9, 0x45, 0xbd, 0x89, 0x38, 0xda, 0x2c, 0x8d, 0xc8,
0x37, 0x71, 0x4c, 0x4d, 0x6f, 0x82, 0xd1, 0xb7, 0x60, 0x73, 0x6e, 0xc3, 0x4f, 0x92, 0x84, 0xac,
0x26, 0x8d, 0x3a, 0x4c, 0xa6, 0xfd, 0x49, 0x81, 0x7a, 0x26, 0x8b, 0xaf, 0x98, 0x41, 0x13, 0xca,
0x31, 0xf6, 0xb1, 0x43, 0xb1, 0x9b, 0x14, 0x76, 0x32, 0x47, 0x9f, 0x40, 0xd1, 0xa3, 0x78, 0x12,
0x37, 0x0a, 0x4f, 0xf3, 0xfb, 0xd5, 0xa3, 0xc7, 0xe9, 0x22, 0xbe, 0xb5, 0x62, 0x43, 0xd8, 0x6a,
0x9d, 0x25, 0x34, 0x7a, 0x5e, 0x4c, 0xd1, 0xb3, 0x24, 0x92, 0xc2, 0x23, 0xed, 0xad, 0x8d, 0x94,
0x44, 0x19, 0x40, 0xf5, 0x95, 0x1d, 0x85, 0x2d, 0xc7, 0x21, 0xd3, 0x80, 0xa2, 0xc7, 0x00, 0xb6,
0x18, 0x5a, 0x9e, 0x2b, 0x97, 0x54, 0x91, 0x92, 0xae, 0xcb, 0x36, 0xd3, 0x76, 0x1c, 0x1c, 0xc7,
0x16, 0x25, 0xd7, 0x38, 0x48, 0x4e, 0xb0, 0x90, 0x99, 0x4c, 0xa4, 0xfd, 0x5d, 0x81, 0x6d, 0x16,
0xf1, 0x95, 0x17, 0xe1, 0xf1, 0xd4, 0x8e, 0x5c, 0xd1, 0x29, 0x58, 0xc7, 0x0a, 0x23, 0xef, 0xc6,
0xa6, 0xd8, 0xba, 0xc6, 0xb3, 0xa4, 0x57, 0x4a, 0xd1, 0x19, 0x9e, 0xa1, 0x8f, 0x00, 0xf9, 0xc4,
0xb1, 0x7d, 0xcb, 0x76, 0xdd, 0x88, 0x7d, 0xc2, 0x0b, 0x6f, 0x9e, 0xcb, 0x2f, 0xa8, 0x5c, 0xd3,
0x12, 0x8a, 0x6e, 0x78, 0xf3, 0x7c, 0xa5, 0xf5, 0xa7, 0x12, 0xd8, 0x65, 0xeb, 0x4f, 0xd1, 0x07,
0x70, 0x3f, 0xc4, 0x38, 0xb2, 0xc2, 0xe9, 0xa5, 0xef, 0x39, 0x3c, 0x81, 0x82, 0x68, 0xc4, 0x4c,
0x3c, 0xe4, 0xd2, 0x33, 0x3c, 0xd3, 0xfe, 0xaa, 0xc0, 0x2e, 0x4b, 0xfe, 0x14, 0x07, 0x38, 0xb2,
0xd9, 0x21, 0x99, 0x1f, 0xf1, 0xef, 0x41, 0x49, 0xe2, 0xc0, 0x73, 0xaf, 0x66, 0x6f, 0x93, 0x14,
0x86, 0x46, 0x62, 0xc7, 0x0a, 0xc3, 0x27, 0x63, 0xb9, 0x04, 0x36, 0x44, 0x2f, 0x60, 0x43, 0xf6,
0xd3, 0x3c, 0x8f, 0xf1, 0x64, 0x39, 0xc6, 0x12, 0x6a, 0x86, 0x34, 0xd7, 0xce, 0x60, 0x4b, 0x34,
0x8f, 0x61, 0x44, 0xbe, 0x64, 0x2d, 0x9e, 0x4e, 0x63, 0xf4, 0x08, 0x2a, 0x8b, 0x33, 0xab, 0xf0,
0x33, 0xbb, 0x10, 0xb0, 0x9e, 0x24, 0xba, 0xb5, 0xcb, 0x33, 0x28, 0x1b, 0xc9, 0x54, 0xfb, 0x1d,
0xd4, 0x86, 0x76, 0x14, 0xe3, 0xa4, 0xc5, 0x35, 0xa0, 0x94, 0x5c, 0x4f, 0xb2, 0x7b, 0xc9, 0xe9,
0xf2, 0x05, 0x97, 0xbb, 0x75, 0xc1, 0xbd, 0xad, 0x5f, 0xa3, 0x1d, 0x28, 0xba, 0xf8, 0x72, 0x3a,
0x96, 0xd7, 0x93, 0x98, 0x68, 0x7f, 0x50, 0xa0, 0x2e, 0x3f, 0xff, 0x8d, 0xf5, 0xf2, 0xec, 0xed,
0x3a, 0x4f, 0x7f, 0xfd, 0x55, 0xde, 0x83, 0x66, 0xfb, 0xb5, 0x1d, 0x8c, 0xb1, 0xc0, 0x79, 0x10,
0xf2, 0x86, 0x98, 0x00, 0x72, 0x08, 0xdb, 0x72, 0xd9, 0x44, 0x28, 0xac, 0x5f, 0xc7, 0x24, 0x90,
0xe0, 0x6c, 0x39, 0x69, 0x97, 0x9f, 0xc6, 0x24, 0xd0, 0x7e, 0x05, 0x0f, 0x64, 0xc5, 0xc8, 0x78,
0xa9, 0xcb, 0x23, 0x75, 0x13, 0xf2, 0x71, 0x16, 0xb2, 0xdc, 0x3a, 0xc8, 0xf2, 0x69, 0xc8, 0x5e,
0xc2, 0xee, 0x72, 0x7c, 0x09, 0xdd, 0x6d, 0x82, 0xa1, 0xac, 0x20, 0x18, 0xda, 0x2b, 0x78, 0x30,
0xe2, 0xcd, 0x26, 0xe9, 0x01, 0xa9, 0xfb, 0x7a, 0xcc, 0xda, 0x81, 0xb5, 0xe8, 0x60, 0x65, 0x2e,
0x30, 0xed, 0x31, 0x3b, 0xed, 0x44, 0xda, 0x73, 0xbd, 0x3c, 0xed, 0x89, 0xcc, 0xb4, 0xc7, 0xda,
0x77, 0x61, 0xf3, 0x42, 0x74, 0xc7, 0xaf, 0x12, 0x51, 0xfb, 0x3d, 0xec, 0x25, 0x0b, 0x61, 0xd5,
0x9e, 0x05, 0xeb, 0x09, 0x54, 0x7d, 0xcf, 0xc1, 0xac, 0x0a, 0x52, 0x1d, 0x42, 0x8a, 0x58, 0x87,
0xc8, 0x36, 0xa7, 0xdc, 0x5d, 0xcd, 0x29, 0x7f, 0xbb, 0x39, 0x7d, 0x06, 0x8f, 0x46, 0x98, 0xa6,
0x4e, 0x92, 0x2e, 0x8e, 0x44, 0x92, 0xc2, 0x63, 0x00, 0x2f, 0xb6, 0x92, 0x63, 0x23, 0x8f, 0x94,
0x17, 0x4b, 0x2b, 0xed, 0xb7, 0x00, 0x3d, 0x32, 0x96, 0xcc, 0x11, 0x1d, 0x40, 0xd1, 0xc7, 0x37,
0xd8, 0x97, 0xe5, 0xba, 0x93, 0x2e, 0xd7, 0x1e, 0x19, 0xf7, 0x98, 0xce, 0x10, 0x26, 0xe8, 0xc3,
0xd4, 0x8d, 0xb0, 0x79, 0xb4, 0xbd, 0x64, 0xca, 0x49, 0xa8, 0xb8, 0x26, 0xd6, 0x97, 0x6c, 0x1d,
0xaa, 0x23, 0x4a, 0x12, 0xa6, 0xa5, 0xfd, 0x43, 0x01, 0x64, 0x4e, 0x83, 0x00, 0xfb, 0x19, 0x4a,
0x8a, 0xa0, 0xc0, 0x3b, 0xa1, 0xc8, 0x9d, 0x8f, 0x19, 0xb0, 0x82, 0xf8, 0x59, 0x21, 0x89, 0x68,
0x42, 0x2a, 0x84, 0x68, 0x48, 0x22, 0xca, 0x90, 0x8b, 0x69, 0xe4, 0x39, 0xd4, 0x62, 0x3c, 0x03,
0xcb, 0xe2, 0xab, 0x0a, 0x99, 0xc1, 0x44, 0xe8, 0x07, 0xd0, 0xc0, 0x81, 0x1b, 0x12, 0x8f, 0x81,
0x1f, 0xb8, 0x38, 0xc4, 0x81, 0x8b, 0x03, 0x6a, 0x05, 0x76, 0xc2, 0x3e, 0x77, 0x13, 0x7d, 0x77,
0xa1, 0xee, 0xdb, 0x94, 0x95, 0x74, 0x4c, 0x6d, 0xe7, 0x9a, 0xb3, 0x8a, 0x8a, 0x21, 0x26, 0xda,
0x01, 0x6c, 0x8a, 0xec, 0xef, 0xe6, 0x50, 0x07, 0x1a, 0xd4, 0xd2, 0xc7, 0x1f, 0x6d, 0x40, 0x6e,
0x70, 0xa6, 0xde, 0x43, 0x00, 0x1b, 0x27, 0xad, 0x6e, 0x4f, 0xef, 0xa8, 0xca, 0x41, 0x0b, 0x2a,
0xf3, 0x97, 0x00, 0xaa, 0x42, 0x69, 0x64, 0x0e, 0x86, 0x43, 0xbd, 0xa3, 0xde, 0x43, 0x35, 0x28,
0x8f, 0xcc, 0x96, 0x61, 0x76, 0xfb, 0xa7, 0xaa, 0x22, 0x54, 0x2d, 0xc3, 0xd4, 0x3b, 0x6a, 0x4e,
0xa8, 0x06, 0xc3, 0x21, 0x53, 0xe5, 0x0f, 0xfe, 0x95, 0x83, 0x6a, 0xea, 0x55, 0x80, 0x2a, 0x50,
0xd4, 0xcf, 0x87, 0xe6, 0x17, 0xea, 0x3d, 0xf4, 0x10, 0xb6, 0xf9, 0xd0, 0x6a, 0x0f, 0xfa, 0x27,
0xdd, 0xd3, 0x0b, 0xa3, 0x65, 0x76, 0x07, 0x7d, 0x55, 0x41, 0x0d, 0xd8, 0xe1, 0xe1, 0xac, 0xf6,
0xe0, 0xfc, 0xbc, 0xd5, 0xef, 0x58, 0x23, 0xdd, 0xf8, 0x99, 0x6e, 0xa8, 0x39, 0x84, 0x60, 0xb3,
0x6d, 0xe8, 0x2d, 0x53, 0xe7, 0xa2, 0x6e, 0x5b, 0x57, 0xf3, 0x68, 0x0b, 0xea, 0xc2, 0x3a, 0x11,
0x15, 0xd0, 0x0e, 0xa8, 0x17, 0x7d, 0xfd, 0xe7, 0x43, 0xbd, 0x6d, 0xea, 0x1d, 0x4b, 0x37, 0x8c,
0x81, 0xa1, 0x16, 0xd1, 0x36, 0xdc, 0x6f, 0xf5, 0x0c, 0xbd, 0xd5, 0xf9, 0xc2, 0x4a, 0xb2, 0xdd,
0xc8, 0x0a, 0xc5, 0xea, 0x4a, 0x68, 0x17, 0x50, 0xb7, 0x3f, 0x32, 0x5b, 0xfd, 0xb6, 0x6e, 0xf5,
0x07, 0xa6, 0x75, 0x32, 0xb8, 0xe8, 0x77, 0xd4, 0x32, 0x4b, 0x2c, 0x23, 0x4f, 0x3c, 0x2a, 0x2b,
0x34, 0xe2, 0x03, 0x80, 0xf6, 0xe0, 0x01, 0x4f, 0xc0, 0x3a, 0xbe, 0xe8, 0xf6, 0x3a, 0xdd, 0xfe,
0xa9, 0x5c, 0xae, 0x5a, 0x65, 0x4e, 0x42, 0x35, 0x6c, 0x19, 0xa3, 0x94, 0xa6, 0xb6, 0xd0, 0xb0,
0xcc, 0x52, 0x9a, 0xfa, 0xc1, 0x31, 0x94, 0x93, 0x63, 0xc0, 0xb0, 0xec, 0xe8, 0xc7, 0x17, 0xa7,
0xea, 0x3d, 0x54, 0x86, 0x42, 0xb7, 0x7f, 0x32, 0x10, 0x7b, 0xf1, 0xaa, 0x65, 0xf4, 0x19, 0xfa,
0x39, 0x8e, 0x36, 0x5f, 0x7d, 0x9e, 0x0d, 0x4f, 0x5a, 0x66, 0xab, 0xa7, 0x16, 0x0e, 0x3e, 0x82,
0x92, 0x3c, 0x1f, 0xcc, 0xaf, 0x3d, 0x30, 0x74, 0xf5, 0x1e, 0xdf, 0x43, 0x09, 0xa0, 0xc2, 0x8a,
0x40, 0x7e, 0x31, 0x77, 0xf4, 0x17, 0x05, 0x8a, 0x9c, 0x98, 0xa3, 0x97, 0x50, 0x1e, 0xd9, 0x33,
0x31, 0xce, 0xdc, 0x23, 0x69, 0x6e, 0xdf, 0xdc, 0x5b, 0xa1, 0x91, 0xd5, 0xd8, 0x85, 0xcd, 0x24,
0xc0, 0x88, 0x46, 0xd8, 0x9e, 0x7c, 0xad, 0x30, 0xfb, 0xca, 0xc7, 0xca, 0xd1, 0xbf, 0x2b, 0x50,
0x60, 0xb5, 0x89, 0x5e, 0x42, 0x51, 0x3c, 0xce, 0x32, 0xa1, 0xd2, 0xc7, 0xb7, 0xf9, 0x68, 0xf9,
0x69, 0x9b, 0x79, 0x0c, 0x9f, 0x2f, 0x1e, 0xc8, 0x8c, 0xed, 0xb1, 0x4e, 0x8a, 0x1e, 0x66, 0x63,
0xcd, 0x1b, 0xc4, 0xdb, 0x43, 0xb1, 0xc4, 0xd0, 0xd9, 0x82, 0xc9, 0xc6, 0xfc, 0x51, 0xb2, 0x36,
0xd6, 0x7a, 0x46, 0xca, 0xf2, 0xe0, 0xc1, 0x06, 0xb0, 0x75, 0x6e, 0x7b, 0xc1, 0x37, 0x17, 0xb0,
0x03, 0xf5, 0xd3, 0xa4, 0x57, 0xbf, 0x3d, 0xd8, 0x6e, 0x46, 0x31, 0x77, 0xe0, 0x51, 0x5e, 0x40,
0x91, 0x3f, 0x50, 0x97, 0x30, 0x4f, 0xbd, 0x59, 0x9b, 0x3b, 0xab, 0x78, 0x06, 0xfa, 0x09, 0x14,
0x39, 0x4b, 0xc9, 0x3a, 0xa6, 0x79, 0x53, 0x76, 0xdf, 0xb3, 0x94, 0xe6, 0x97, 0xb0, 0xbd, 0x82,
0x5f, 0xa0, 0x0f, 0x32, 0x7b, 0xb2, 0x96, 0x80, 0xdc, 0x51, 0x06, 0x27, 0xf2, 0x37, 0x04, 0x7b,
0xaf, 0x7b, 0x0e, 0xfe, 0xda, 0xe5, 0xf4, 0x02, 0x0a, 0x0c, 0x46, 0xb4, 0x95, 0xb6, 0xe2, 0xaf,
0xd5, 0x3b, 0x1c, 0x5b, 0x50, 0x32, 0x70, 0xfc, 0x7f, 0x95, 0x32, 0x3b, 0x5f, 0x19, 0x46, 0x82,
0xde, 0xcb, 0x6e, 0xd0, 0x0a, 0xb6, 0xb2, 0x66, 0xa7, 0x7e, 0x0c, 0x25, 0xc9, 0x41, 0x50, 0x33,
0x6d, 0x90, 0x25, 0x26, 0x6b, 0x9c, 0x2d, 0x40, 0xb7, 0x19, 0x09, 0x7a, 0x3f, 0x6d, 0xbb, 0x96,
0xb1, 0x34, 0xb5, 0x65, 0xfa, 0xbe, 0xe2, 0xdd, 0xf0, 0x39, 0xec, 0x9c, 0x66, 0x28, 0x87, 0x24,
0xef, 0x2b, 0x40, 0x7f, 0x7c, 0xbb, 0x8e, 0xd3, 0x1e, 0x9c, 0xc4, 0xad, 0x20, 0x2f, 0x68, 0x7f,
0xa9, 0xb4, 0xd7, 0xf2, 0x9b, 0x35, 0x18, 0x1c, 0x43, 0x95, 0x35, 0xea, 0x3b, 0x3b, 0xca, 0xee,
0x12, 0x6d, 0x91, 0x97, 0x25, 0x6f, 0x72, 0xff, 0x51, 0xa0, 0x2e, 0xe9, 0x88, 0xac, 0xca, 0x76,
0xd2, 0xed, 0xde, 0x4d, 0xbb, 0xdd, 0xa6, 0x2c, 0xcd, 0xe6, 0x6d, 0xfd, 0x3c, 0xb5, 0xef, 0xaf,
0x2f, 0xd1, 0xb7, 0xb9, 0xbd, 0x80, 0x8d, 0xf5, 0x30, 0xdf, 0xf1, 0x3d, 0xfd, 0x4b, 0x8f, 0xfe,
0x8f, 0x6e, 0xc7, 0x9b, 0xbf, 0xa8, 0x1d, 0x3e, 0x5b, 0xa8, 0x2f, 0x37, 0xf8, 0xdf, 0xcd, 0x4f,
0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x2e, 0xae, 0xf7, 0x33, 0xf9, 0x14, 0x00, 0x00,
}

View File

@@ -45,6 +45,7 @@ message StartRequest {
bool disable_memory_limit = 3;
bool delay_start = 4;
bool enable_old_command_server = 5;
bool enable_raw_config = 6;
}
message SetupRequest {
@@ -193,19 +194,14 @@ message StopRequest{
}
enum StackType {
SYSTEM = 0;
GVISOR = 1;
MIXED = 2;
}
message TunnelStartRequest {
bool ipv6 = 1;
int32 server_port = 2;
bool strict_route = 3;
bool endpoint_independent_nat = 4;
StackType stack = 5;
string stack = 5;
}
message TunnelResponse {
@@ -240,7 +236,7 @@ service Core {
service TunnelService {
rpc Start(StartRequest) returns (TunnelResponse);
rpc Start(TunnelStartRequest ) returns (TunnelResponse);
rpc Stop(Empty) returns (TunnelResponse);
rpc Status(Empty) returns (TunnelResponse);
rpc Exit(Empty) returns (TunnelResponse);

View File

@@ -1034,7 +1034,7 @@ const (
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type TunnelServiceClient interface {
Start(ctx context.Context, in *StartRequest, opts ...grpc.CallOption) (*TunnelResponse, error)
Start(ctx context.Context, in *TunnelStartRequest, opts ...grpc.CallOption) (*TunnelResponse, error)
Stop(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TunnelResponse, error)
Status(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TunnelResponse, error)
Exit(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TunnelResponse, error)
@@ -1048,7 +1048,7 @@ func NewTunnelServiceClient(cc grpc.ClientConnInterface) TunnelServiceClient {
return &tunnelServiceClient{cc}
}
func (c *tunnelServiceClient) Start(ctx context.Context, in *StartRequest, opts ...grpc.CallOption) (*TunnelResponse, error) {
func (c *tunnelServiceClient) Start(ctx context.Context, in *TunnelStartRequest, opts ...grpc.CallOption) (*TunnelResponse, error) {
out := new(TunnelResponse)
err := c.cc.Invoke(ctx, TunnelService_Start_FullMethodName, in, out, opts...)
if err != nil {
@@ -1088,7 +1088,7 @@ func (c *tunnelServiceClient) Exit(ctx context.Context, in *Empty, opts ...grpc.
// All implementations must embed UnimplementedTunnelServiceServer
// for forward compatibility
type TunnelServiceServer interface {
Start(context.Context, *StartRequest) (*TunnelResponse, error)
Start(context.Context, *TunnelStartRequest) (*TunnelResponse, error)
Stop(context.Context, *Empty) (*TunnelResponse, error)
Status(context.Context, *Empty) (*TunnelResponse, error)
Exit(context.Context, *Empty) (*TunnelResponse, error)
@@ -1099,7 +1099,7 @@ type TunnelServiceServer interface {
type UnimplementedTunnelServiceServer struct {
}
func (UnimplementedTunnelServiceServer) Start(context.Context, *StartRequest) (*TunnelResponse, error) {
func (UnimplementedTunnelServiceServer) Start(context.Context, *TunnelStartRequest) (*TunnelResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Start not implemented")
}
func (UnimplementedTunnelServiceServer) Stop(context.Context, *Empty) (*TunnelResponse, error) {
@@ -1125,7 +1125,7 @@ func RegisterTunnelServiceServer(s grpc.ServiceRegistrar, srv TunnelServiceServe
}
func _TunnelService_Start_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StartRequest)
in := new(TunnelStartRequest)
if err := dec(in); err != nil {
return nil, err
}
@@ -1137,7 +1137,7 @@ func _TunnelService_Start_Handler(srv interface{}, ctx context.Context, dec func
FullMethod: TunnelService_Start_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TunnelServiceServer).Start(ctx, req.(*StartRequest))
return srv.(TunnelServiceServer).Start(ctx, req.(*TunnelStartRequest))
}
return interceptor(ctx, in, info, handler)
}

View File

@@ -8,6 +8,7 @@ import (
pb "github.com/hiddify/libcore/hiddifyrpc"
)
var EnableBridge = true
var coreInfoObserver = NewObserver[pb.CoreInfoResponse](10)
var CoreState = pb.CoreState_STOPPED
@@ -20,8 +21,10 @@ func SetCoreStatus(state pb.CoreState, msgType pb.MessageType, message string) p
Message: message,
}
coreInfoObserver.Emit(info)
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState)})
bridge.SendStringToPort(statusPropagationPort, string(msg))
if EnableBridge {
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState)})
bridge.SendStringToPort(statusPropagationPort, string(msg))
}
return info
}

View File

@@ -13,7 +13,6 @@ import (
pb "github.com/hiddify/libcore/hiddifyrpc"
"github.com/sagernet/sing-box/experimental/libbox"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
)
var Box *libbox.BoxService
@@ -34,9 +33,11 @@ func StopAndAlert(msgType pb.MessageType, message string) {
if commandServer != nil {
commandServer.Close()
}
alert := msgType.String()
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState), Alert: &alert, Message: &message})
bridge.SendStringToPort(statusPropagationPort, string(msg))
if EnableBridge {
alert := msgType.String()
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(CoreState), Alert: &alert, Message: &message})
bridge.SendStringToPort(statusPropagationPort, string(msg))
}
}
func (s *CoreService) Start(ctx context.Context, in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
@@ -48,15 +49,17 @@ func Start(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
})
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting")
if CoreState != pb.CoreState_STOPPED {
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting0000")
return &pb.CoreInfoResponse{
CoreState: CoreState,
MessageType: pb.MessageType_INSTANCE_NOT_STOPPED,
}, fmt.Errorf("instance not stopped")
}
SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "")
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting1111")
SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "Starting222")
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting2")
libbox.SetMemoryLimit(!in.DisableMemoryLimit)
resp, err := StartService(in)
return resp, err
@@ -65,7 +68,7 @@ func (s *CoreService) StartService(ctx context.Context, in *pb.StartRequest) (*p
return StartService(in)
}
func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting3")
content := in.ConfigContent
if content == "" {
@@ -80,22 +83,28 @@ func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
}
content = string(fileContent)
}
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Starting4")
Log(pb.LogLevel_INFO, pb.LogType_CORE, content)
parsedContent, err := parseConfig(content)
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Parsed")
if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_PARSING_CONFIG, err.Error())
return &resp, err
}
var patchedOptions *option.Options
patchedOptions, err = config.BuildConfig(*configOptions, parsedContent)
if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_BUILDING_CONFIG, err.Error())
return &resp, err
if !in.EnableRawConfig {
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Building config")
parsedContent_tmp, err := config.BuildConfig(*configOptions, parsedContent)
parsedContent = *parsedContent_tmp
if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_BUILDING_CONFIG, err.Error())
return &resp, err
}
}
config.SaveCurrentConfig(filepath.Join(sWorkingPath, "current-config.json"), *patchedOptions)
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Saving Contnet")
config.SaveCurrentConfig(filepath.Join(sWorkingPath, "current-config.json"), parsedContent)
if in.EnableOldCommandServer {
err = startCommandServer(*logFactory)
if err != nil {
@@ -105,13 +114,15 @@ func StartService(in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
}
}
instance, err := NewService(*patchedOptions)
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Stating Service ")
instance, err := NewService(parsedContent)
if err != nil {
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_CREATE_SERVICE, err.Error())
return &resp, err
}
Log(pb.LogLevel_INFO, pb.LogType_CORE, "Service.. started")
if in.DelayStart {
<-time.After(250 * time.Millisecond)
}

View File

@@ -1,223 +1,233 @@
package global
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/signal"
"runtime"
"strconv"
"strings"
"syscall"
"time"
"github.com/hiddify/libcore/config"
"github.com/sagernet/sing-box/option"
)
func RunStandalone(hiddifySettingPath string, configPath string) error {
fmt.Println("Running in standalone mode")
current, err := readAndBuildConfig(hiddifySettingPath, configPath)
if err != nil {
fmt.Printf("Error in read and build config %v", err)
return err
}
go StartServiceC(false, current.Config)
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)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
<-sigChan
err = StopServiceC()
return err
}
type ConfigResult struct {
Config string
RefreshInterval int
}
func readAndBuildConfig(hiddifySettingPath string, configPath string) (ConfigResult, error) {
var result ConfigResult
result, err := readConfigContent(configPath)
if err != nil {
return result, err
}
hiddifyconfig := config.DefaultConfigOptions()
if hiddifySettingPath != "" {
hiddifyconfig, err = readConfigOptionsAt(hiddifySettingPath)
if err != nil {
return result, err
}
}
result.Config, err = buildConfig(result.Config, *hiddifyconfig)
if err != nil {
return result, err
}
return result, nil
}
func readConfigContent(configPath string) (ConfigResult, error) {
var content string
var refreshInterval int
if strings.HasPrefix(configPath, "http://") || strings.HasPrefix(configPath, "https://") {
client := &http.Client{}
// Create a new request
req, err := http.NewRequest("GET", configPath, nil)
if err != nil {
fmt.Println("Error creating request:", err)
return ConfigResult{}, err
}
req.Header.Set("User-Agent", "HiddifyNext/17.5.0 ("+runtime.GOOS+") like ClashMeta v2ray sing-box")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error making GET request:", err)
return ConfigResult{}, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ConfigResult{}, fmt.Errorf("failed to read config body: %w", err)
}
content = string(body)
refreshInterval, _ = extractRefreshInterval(resp.Header, content)
fmt.Printf("Refresh interval: %d\n", refreshInterval)
} else {
data, err := ioutil.ReadFile(configPath)
if err != nil {
return ConfigResult{}, fmt.Errorf("failed to read config file: %w", err)
}
content = string(data)
}
return ConfigResult{
Config: content,
RefreshInterval: refreshInterval,
}, nil
}
func extractRefreshInterval(header http.Header, bodyStr string) (int, error) {
refreshIntervalStr := header.Get("profile-update-interval")
if refreshIntervalStr != "" {
refreshInterval, err := strconv.Atoi(refreshIntervalStr)
if err != nil {
return 0, fmt.Errorf("failed to parse refresh interval from header: %w", err)
}
return refreshInterval, nil
}
lines := strings.Split(bodyStr, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "//profile-update-interval:") || strings.HasPrefix(line, "#profile-update-interval:") {
parts := strings.SplitN(line, ":", 2)
str := strings.TrimSpace(parts[1])
refreshInterval, err := strconv.Atoi(str)
if err != nil {
return 0, fmt.Errorf("failed to parse refresh interval from body: %w", err)
}
return refreshInterval, nil
}
}
return 0, nil
}
func buildConfig(configContent string, options config.ConfigOptions) (string, error) {
parsedContent, err := config.ParseConfigContent(configContent, true)
if err != nil {
return "", fmt.Errorf("failed to parse config content: %w", err)
}
singconfigs, err := readConfigBytes([]byte(parsedContent))
if err != nil {
return "", err
}
finalconfig, err := config.BuildConfig(options, *singconfigs)
if err != nil {
return "", fmt.Errorf("failed to build config: %w", err)
}
finalconfig.Log.Output = ""
finalconfig.Experimental.ClashAPI.ExternalUI = "webui"
if options.AllowConnectionFromLAN {
finalconfig.Experimental.ClashAPI.ExternalController = "0.0.0.0:6756"
} else {
finalconfig.Experimental.ClashAPI.ExternalController = "127.0.0.1:6756"
}
if finalconfig.Experimental.ClashAPI.Secret == "" {
// finalconfig.Experimental.ClashAPI.Secret = "hiddify"
}
if err := SetupC("./", "./", "./tmp", false); err != nil {
return "", fmt.Errorf("failed to set up global configuration: %w", err)
}
configStr, err := config.ToJson(*finalconfig)
if err != nil {
return "", fmt.Errorf("failed to convert config to JSON: %w", err)
}
return configStr, nil
}
func updateConfigInterval(current ConfigResult, hiddifySettingPath string, configPath string) {
if current.RefreshInterval <= 0 {
return
}
for {
<-time.After(time.Duration(current.RefreshInterval) * time.Hour)
new, err := readAndBuildConfig(hiddifySettingPath, configPath)
if err != nil {
continue
}
if new.Config != current.Config {
go StopServiceC()
go StartServiceC(false, new.Config)
}
current = new
}
}
func readConfigBytes(content []byte) (*option.Options, error) {
var options option.Options
err := options.UnmarshalJSON(content)
if err != nil {
return nil, err
}
return &options, nil
}
func readConfigOptionsAt(path string) (*config.ConfigOptions, error) {
content, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var options config.ConfigOptions
err = json.Unmarshal(content, &options)
if err != nil {
return nil, err
}
if options.Warp.WireguardConfigStr != "" {
err := json.Unmarshal([]byte(options.Warp.WireguardConfigStr), &options.Warp.WireguardConfig)
if err != nil {
return nil, err
}
}
return &options, nil
}
package v2
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/signal"
"runtime"
"strconv"
"strings"
"syscall"
"time"
"github.com/hiddify/libcore/config"
pb "github.com/hiddify/libcore/hiddifyrpc"
"github.com/sagernet/sing-box/option"
)
func RunStandalone(hiddifySettingPath string, configPath string) error {
fmt.Println("Running in standalone mode")
current, err := readAndBuildConfig(hiddifySettingPath, configPath)
if err != nil {
fmt.Printf("Error in read and build config %v", err)
return err
}
go StartService(&pb.StartRequest{
ConfigPath: configPath,
EnableOldCommandServer: false,
DelayStart: false,
})
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)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
<-sigChan
_, err = Stop()
return err
}
type ConfigResult struct {
Config string
RefreshInterval int
}
func readAndBuildConfig(hiddifySettingPath string, configPath string) (ConfigResult, error) {
var result ConfigResult
result, err := readConfigContent(configPath)
if err != nil {
return result, err
}
hiddifyconfig := config.DefaultConfigOptions()
if hiddifySettingPath != "" {
hiddifyconfig, err = readConfigOptionsAt(hiddifySettingPath)
if err != nil {
return result, err
}
}
result.Config, err = buildConfig(result.Config, *hiddifyconfig)
if err != nil {
return result, err
}
return result, nil
}
func readConfigContent(configPath string) (ConfigResult, error) {
var content string
var refreshInterval int
if strings.HasPrefix(configPath, "http://") || strings.HasPrefix(configPath, "https://") {
client := &http.Client{}
// Create a new request
req, err := http.NewRequest("GET", configPath, nil)
if err != nil {
fmt.Println("Error creating request:", err)
return ConfigResult{}, err
}
req.Header.Set("User-Agent", "HiddifyNext/17.5.0 ("+runtime.GOOS+") like ClashMeta v2ray sing-box")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error making GET request:", err)
return ConfigResult{}, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ConfigResult{}, fmt.Errorf("failed to read config body: %w", err)
}
content = string(body)
refreshInterval, _ = extractRefreshInterval(resp.Header, content)
fmt.Printf("Refresh interval: %d\n", refreshInterval)
} else {
data, err := ioutil.ReadFile(configPath)
if err != nil {
return ConfigResult{}, fmt.Errorf("failed to read config file: %w", err)
}
content = string(data)
}
return ConfigResult{
Config: content,
RefreshInterval: refreshInterval,
}, nil
}
func extractRefreshInterval(header http.Header, bodyStr string) (int, error) {
refreshIntervalStr := header.Get("profile-update-interval")
if refreshIntervalStr != "" {
refreshInterval, err := strconv.Atoi(refreshIntervalStr)
if err != nil {
return 0, fmt.Errorf("failed to parse refresh interval from header: %w", err)
}
return refreshInterval, nil
}
lines := strings.Split(bodyStr, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "//profile-update-interval:") || strings.HasPrefix(line, "#profile-update-interval:") {
parts := strings.SplitN(line, ":", 2)
str := strings.TrimSpace(parts[1])
refreshInterval, err := strconv.Atoi(str)
if err != nil {
return 0, fmt.Errorf("failed to parse refresh interval from body: %w", err)
}
return refreshInterval, nil
}
}
return 0, nil
}
func buildConfig(configContent string, options config.ConfigOptions) (string, error) {
parsedContent, err := config.ParseConfigContent(configContent, true)
if err != nil {
return "", fmt.Errorf("failed to parse config content: %w", err)
}
singconfigs, err := readConfigBytes([]byte(parsedContent))
if err != nil {
return "", err
}
finalconfig, err := config.BuildConfig(options, *singconfigs)
if err != nil {
return "", fmt.Errorf("failed to build config: %w", err)
}
finalconfig.Log.Output = ""
finalconfig.Experimental.ClashAPI.ExternalUI = "webui"
if options.AllowConnectionFromLAN {
finalconfig.Experimental.ClashAPI.ExternalController = "0.0.0.0:6756"
} else {
finalconfig.Experimental.ClashAPI.ExternalController = "127.0.0.1:6756"
}
if finalconfig.Experimental.ClashAPI.Secret == "" {
// finalconfig.Experimental.ClashAPI.Secret = "hiddify"
}
if err := Setup("./", "./", "./tmp", 0, false); err != nil {
return "", fmt.Errorf("failed to set up global configuration: %w", err)
}
configStr, err := config.ToJson(*finalconfig)
if err != nil {
return "", fmt.Errorf("failed to convert config to JSON: %w", err)
}
return configStr, nil
}
func updateConfigInterval(current ConfigResult, hiddifySettingPath string, configPath string) {
if current.RefreshInterval <= 0 {
return
}
for {
<-time.After(time.Duration(current.RefreshInterval) * time.Hour)
new, err := readAndBuildConfig(hiddifySettingPath, configPath)
if err != nil {
continue
}
if new.Config != current.Config {
go Stop()
go StartService(&pb.StartRequest{
ConfigContent: new.Config,
DelayStart: false,
EnableOldCommandServer: false,
DisableMemoryLimit: false,
})
}
current = new
}
}
func readConfigBytes(content []byte) (*option.Options, error) {
var options option.Options
err := options.UnmarshalJSON(content)
if err != nil {
return nil, err
}
return &options, nil
}
func readConfigOptionsAt(path string) (*config.ConfigOptions, error) {
content, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var options config.ConfigOptions
err = json.Unmarshal(content, &options)
if err != nil {
return nil, err
}
if options.Warp.WireguardConfigStr != "" {
err := json.Unmarshal([]byte(options.Warp.WireguardConfigStr), &options.Warp.WireguardConfig)
if err != nil {
return nil, err
}
}
return &options, nil
}

View File

@@ -1,4 +1,4 @@
package admin_service
package v2
import (
"fmt"
@@ -6,7 +6,6 @@ import (
"os"
"path/filepath"
"github.com/hiddify/libcore/global"
"github.com/kardianos/service"
)
@@ -17,11 +16,11 @@ type hiddifyNext struct{}
var port int = 18020
func (m *hiddifyNext) Start(s service.Service) error {
go StartWebServer(port, false)
go StartTunnelGrpcServer(fmt.Sprintf("127.0.0.1:%d", port))
return nil
}
func (m *hiddifyNext) Stop(s service.Service) error {
err := global.StopServiceC()
_, err := Stop()
if err != nil {
return nil
}
@@ -41,7 +40,7 @@ func getCurrentExecutableDirectory() string {
return executableDirectory
}
func StartService(goArg string) (int, string) {
func StartTunnelService(goArg string) (int, string) {
svcConfig := &service.Config{
Name: "HiddifyTunnelService",
DisplayName: "Hiddify Tunnel Service",

92
v2/tunnel_service.go Normal file
View File

@@ -0,0 +1,92 @@
package v2
import (
"context"
"fmt"
"os"
pb "github.com/hiddify/libcore/hiddifyrpc"
)
func (s *TunnelService) Start(ctx context.Context, in *pb.TunnelStartRequest) (*pb.TunnelResponse, error) {
if in.ServerPort == 0 {
in.ServerPort = 2334
}
EnableBridge = false
res, err := Start(&pb.StartRequest{
ConfigContent: makeTunnelConfig(in.Ipv6, in.ServerPort, in.StrictRoute, in.EndpointIndependentNat, in.Stack),
EnableOldCommandServer: false,
DisableMemoryLimit: false,
EnableRawConfig: true,
})
fmt.Printf("Start Result: %+v\n", res)
if err != nil {
return &pb.TunnelResponse{
Message: err.Error(),
}, err
}
return &pb.TunnelResponse{
Message: "OK",
}, err
}
func makeTunnelConfig(Ipv6 bool, ServerPort int32, StrictRoute bool, EndpointIndependentNat bool, Stack string) string {
var ipv6 string
if Ipv6 {
ipv6 = ` "inet6_address": "fdfe:dcba:9876::1/126",`
} else {
ipv6 = ""
}
base := `{
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"interface_name": "HiddifyTunnel",
"inet4_address": "172.19.0.1/30",
` + ipv6 + `
"mtu": 9000,
"auto_route": true,
"strict_route": ` + fmt.Sprintf("%t", StrictRoute) + `,
"endpoint_independent_nat": ` + fmt.Sprintf("%t", EndpointIndependentNat) + `,
"stack": "` + Stack + `"
}
],
"outbounds": [
{
"type": "socks",
"tag": "socks-out",
"server": "127.0.0.1",
"server_port": ` + fmt.Sprintf("%d", ServerPort) + `,
"version": "5"
}
]
}`
return base
}
func (s *TunnelService) Stop(ctx context.Context, _ *pb.Empty) (*pb.TunnelResponse, error) {
_, err := Stop()
if err != nil {
return &pb.TunnelResponse{
Message: err.Error(),
}, err
}
return &pb.TunnelResponse{
Message: "OK",
}, err
}
func (s *TunnelService) Status(ctx context.Context, _ *pb.Empty) (*pb.TunnelResponse, error) {
return &pb.TunnelResponse{
Message: "Not Implemented",
}, nil
}
func (s *TunnelService) Exit(ctx context.Context, _ *pb.Empty) (*pb.TunnelResponse, error) {
Stop()
os.Exit(0)
return &pb.TunnelResponse{
Message: "OK",
}, nil
}