new: add cli interface with basic webui
This commit is contained in:
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -74,7 +74,7 @@ jobs:
|
||||
rm -f /*.h
|
||||
rm ./hiddify-libcore*sources* ||echo "no source"
|
||||
rm ./hiddify-libcore-macos-a*.dylib || echo "no macos arm and amd"
|
||||
files=$(ls | grep -E '^(libcore\.(dll|so|dylib|aar)|Libcore.xcframework|HiddifyService(\.exe)?)$')
|
||||
files=$(ls | grep -E '^(libcore\.(dll|so|dylib|aar)|webui|Libcore.xcframework|HiddifyCli(\.exe)?)$')
|
||||
echo tar -czvf hiddify-core-${{ matrix.job.target }}.tar.gz $files
|
||||
tar -czvf hiddify-core-${{ matrix.job.target }}.tar.gz $files
|
||||
|
||||
|
||||
31
Makefile
31
Makefile
@@ -2,7 +2,7 @@ PRODUCT_NAME=libcore
|
||||
BASENAME=$(PRODUCT_NAME)
|
||||
BINDIR=bin
|
||||
LIBNAME=$(PRODUCT_NAME)
|
||||
SRVNAME=HiddifyService
|
||||
CLINAME=HiddifyCli
|
||||
|
||||
BRANCH=$(shell git branch --show-current)
|
||||
VERSION=$(shell git describe --tags || echo "unknown version")
|
||||
@@ -35,24 +35,36 @@ ios: lib_install
|
||||
cp Info.plist $(BINDIR)/Libcore.xcframework/
|
||||
|
||||
|
||||
webui:
|
||||
curl -L -o webui.zip https://github.com/hiddify/Yacd-meta/archive/gh-pages.zip
|
||||
unzip -d ./ -q webui.zip
|
||||
rm webui.zip
|
||||
rm -rf bin/webui
|
||||
mv Yacd-meta-gh-pages bin/webui
|
||||
|
||||
|
||||
windows-amd64:
|
||||
curl http://localhost:18020/exit || echo "exited"
|
||||
env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc $(GOBUILDLIB) -o $(BINDIR)/$(LIBNAME).dll ./custom
|
||||
go get github.com/akavel/rsrc
|
||||
go install github.com/akavel/rsrc
|
||||
# go get github.com/akavel/rsrc
|
||||
# go install github.com/akavel/rsrc
|
||||
cp $(BINDIR)/$(LIBNAME).dll ./$(LIBNAME).dll
|
||||
$$(go env GOPATH)/bin/rsrc -manifest admin_service/cmd/admin_service.manifest -ico ./assets/hiddify-service.ico -o admin_service/cmd/admin_service.syso
|
||||
env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="$(LIBNAME).dll" $(GOBUILDSRV) -o $(BINDIR)/$(SRVNAME).exe ./admin_service/cmd
|
||||
# $$(go env GOPATH)/bin/rsrc -manifest admin_service/cmd/admin_service.manifest -ico ./assets/hiddify-service.ico -o admin_service/cmd/admin_service.syso
|
||||
|
||||
$$(go env GOPATH)/bin/rsrc -ico ./assets/hiddify-cli.ico -o ./cli/bydll/cli.syso
|
||||
env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CGO_LDFLAGS="$(LIBNAME).dll" $(GOBUILDSRV) -o $(BINDIR)/$(CLINAME).exe ./cli/bydll
|
||||
rm ./$(LIBNAME).dll
|
||||
make webui
|
||||
|
||||
|
||||
linux-amd64:
|
||||
env GOOS=linux GOARCH=amd64 $(GOBUILDLIB) -o $(BINDIR)/$(LIBNAME).so ./custom
|
||||
mkdir lib
|
||||
cp $(BINDIR)/$(LIBNAME).so ./lib/$(LIBNAME).so
|
||||
env GOOS=linux GOARCH=amd64 CGO_LDFLAGS="./lib/$(LIBNAME).so" $(GOBUILDSRV) -o $(BINDIR)/$(SRVNAME) ./admin_service/cmd
|
||||
env GOOS=linux GOARCH=amd64 CGO_LDFLAGS="./lib/$(LIBNAME).so" $(GOBUILDSRV) -o $(BINDIR)/$(CLINAME) ./cli/bydll
|
||||
rm -rf ./lib
|
||||
chmod +x $(BINDIR)/$(SRVNAME)
|
||||
chmod +x $(BINDIR)/$(CLINAME)
|
||||
make webui
|
||||
|
||||
macos-amd64:
|
||||
env GOOS=darwin GOARCH=amd64 CGO_CFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="-mmacosx-version-min=10.11" CGO_ENABLED=1 go build -trimpath -tags $(TAGS),$(IOS_ADD_TAGS) -buildmode=c-shared -o $(BINDIR)/$(LIBNAME)-amd64.dylib ./custom
|
||||
@@ -62,9 +74,9 @@ macos-arm64:
|
||||
macos-universal: macos-amd64 macos-arm64
|
||||
lipo -create $(BINDIR)/$(LIBNAME)-amd64.dylib $(BINDIR)/$(LIBNAME)-arm64.dylib -output $(BINDIR)/$(LIBNAME).dylib
|
||||
cp $(BINDIR)/$(LIBNAME).dylib ./$(LIBNAME).dylib
|
||||
env GOOS=darwin GOARCH=amd64 CGO_CFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="bin/$(LIBNAME).dylib" CGO_ENABLED=1 $(GOBUILDSRV) -o $(BINDIR)/$(SRVNAME) ./admin_service/cmd
|
||||
env GOOS=darwin GOARCH=amd64 CGO_CFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="bin/$(LIBNAME).dylib" CGO_ENABLED=1 $(GOBUILDSRV) -o $(BINDIR)/$(CLINAME) ./admin_service/cmd
|
||||
rm ./$(LIBNAME).dylib
|
||||
chmod +x $(BINDIR)/$(SRVNAME)
|
||||
chmod +x $(BINDIR)/$(CLINAME)
|
||||
|
||||
clean:
|
||||
rm $(BINDIR)/*
|
||||
@@ -73,6 +85,7 @@ build_protobuf:
|
||||
protoc --go_out=. --go-grpc_out=. hiddifyrpc/hiddify.proto
|
||||
|
||||
|
||||
|
||||
release: # Create a new tag for release.
|
||||
@echo "previous version was $$(git describe --tags $$(git rev-list --tags --max-count=1))"
|
||||
@echo "WARNING: This operation will creates version tag and push to github"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<!-- <assemblyIdentity
|
||||
version="1.0.0.0"
|
||||
processorArchitecture="*"
|
||||
name="HiddifyService.exe"
|
||||
type="win32"
|
||||
/> -->
|
||||
<description>Hiddify Tunnel Service</description>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
@@ -1,50 +0,0 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Import the function from the DLL
|
||||
char* AdminServiceStart(const char* arg);
|
||||
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
args := os.Args
|
||||
if len(args) < 2 {
|
||||
fmt.Println("Usage: HiddifyService.exe empty/start/stop/uninstall/install")
|
||||
args = append(args, "")
|
||||
}
|
||||
|
||||
arg := C.CString(args[1])
|
||||
defer C.free(unsafe.Pointer(arg))
|
||||
|
||||
result := C.AdminServiceStart(arg)
|
||||
defer C.free(unsafe.Pointer(result))
|
||||
|
||||
goRes := C.GoString(result)
|
||||
|
||||
parts := strings.SplitN(goRes, " ", 2)
|
||||
|
||||
var parsedExitCode int
|
||||
_, err := fmt.Sscanf(parts[0], "%d", &parsedExitCode)
|
||||
parsedOutMessage := parts[1]
|
||||
if err != nil {
|
||||
fmt.Println("Error parsing the string:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%d %s", parsedExitCode, parsedOutMessage)
|
||||
|
||||
if parsedExitCode != 0 {
|
||||
os.Exit(parsedExitCode)
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,7 @@ func StartService(goArg string) (int, string) {
|
||||
svcConfig := &service.Config{
|
||||
Name: "HiddifyTunnelService",
|
||||
DisplayName: "Hiddify Tunnel Service",
|
||||
Arguments: []string{"tunnel", "run"},
|
||||
Description: "This is a bridge for tunnel",
|
||||
Option: map[string]interface{}{
|
||||
"RunAtLoad": true,
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@@ -4,15 +4,15 @@ set GOARCH=amd64
|
||||
set CC=x86_64-w64-mingw32-gcc
|
||||
set CGO_ENABLED=1
|
||||
curl http://localhost:18020/exit || echo "Exited"
|
||||
del bin\libcore.dll bin\HiddifyService.exe
|
||||
del bin\libcore.dll bin\HiddifyCli.exe
|
||||
set CGO_LDFLAGS=
|
||||
go build -trimpath -tags with_gvisor,with_quic,with_wireguard,with_ech,with_utls,with_clash_api,with_grpc -ldflags="-w -s" -buildmode=c-shared -o bin/libcore.dll ./custom
|
||||
go get github.com/akavel/rsrc
|
||||
go install github.com/akavel/rsrc
|
||||
|
||||
rsrc -manifest admin_service\cmd\admin_service.manifest -ico ..\assets\images\tray_icon_connected.ico -o admin_service\cmd\admin_service.syso
|
||||
rsrc -ico .\assets\images\hiddify-cli.ico -o cli\bydll\cli.syso
|
||||
|
||||
copy bin\libcore.dll .
|
||||
set CGO_LDFLAGS="libcore.dll"
|
||||
go build -o bin/HiddifyService.exe ./admin_service/cmd/
|
||||
go build -o bin/HiddifyCli.exe ./cli/bydll/
|
||||
del libcore.dll
|
||||
|
||||
35
cli/bydll/clibydll.go
Normal file
35
cli/bydll/clibydll.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Import the function from the DLL
|
||||
char* parseCli(int argc, char** argv);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
args := os.Args
|
||||
|
||||
// Convert []string to []*C.char
|
||||
var cArgs []*C.char
|
||||
for _, arg := range args {
|
||||
cArgs = append(cArgs, C.CString(arg))
|
||||
}
|
||||
defer func() {
|
||||
for _, arg := range cArgs {
|
||||
C.free(unsafe.Pointer(arg))
|
||||
}
|
||||
}()
|
||||
|
||||
// Call the C function
|
||||
result := C.parseCli(C.int(len(cArgs)), (**C.char)(unsafe.Pointer(&cArgs[0])))
|
||||
fmt.Println(C.GoString(result))
|
||||
}
|
||||
11
cli/main.go
Normal file
11
cli/main.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/hiddify/libcore/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd.ParseCli(os.Args[1:])
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hiddify/libcore/admin_service"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var commandService = &cobra.Command{
|
||||
Use: "admin-service",
|
||||
Short: "Sign box service start/stop/install/uninstall",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
arg := ""
|
||||
if len(args) > 1 {
|
||||
arg = args[1]
|
||||
}
|
||||
code, out := admin_service.StartService(arg)
|
||||
fmt.Printf("exitCode:%d msg=%s", code, out)
|
||||
|
||||
},
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -109,6 +109,15 @@ func readConfigAt(path string) (*option.Options, error) {
|
||||
return &options, nil
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
@@ -1,65 +1,33 @@
|
||||
package main
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/hiddify/libcore/config"
|
||||
"github.com/hiddify/libcore/global"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var commandRunInputPath string
|
||||
var (
|
||||
hiddifySettingPath string
|
||||
configPath string
|
||||
)
|
||||
|
||||
var commandRun = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "run",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := runSingbox(commandRunInputPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
Args: cobra.OnlyValidArgs,
|
||||
Run: runCommand,
|
||||
}
|
||||
|
||||
func init() {
|
||||
commandRun.Flags().StringVarP(&commandRunInputPath, "config", "c", "", "read config")
|
||||
commandRun.PersistentFlags().BoolP("help", "", false, "help for this command")
|
||||
commandRun.Flags().StringVarP(&hiddifySettingPath, "hiddify", "h", "", "Hiddify Setting JSON Path")
|
||||
commandRun.Flags().StringVarP(&configPath, "config", "c", "", "proxy config path or url")
|
||||
|
||||
commandRun.MarkFlagRequired("config")
|
||||
|
||||
mainCommand.AddCommand(commandRun)
|
||||
|
||||
}
|
||||
|
||||
func runSingbox(configPath string) error {
|
||||
options, err := readConfigAt(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options.Log = &option.LogOptions{}
|
||||
options.Log.Disabled = false
|
||||
options.Log.Level = "trace"
|
||||
options.Log.Output = ""
|
||||
options.Log.DisableColor = false
|
||||
|
||||
err = global.SetupC("./", "./", "./tmp", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
configStr, err := config.ToJson(*options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go global.StartServiceC(false, configStr)
|
||||
fmt.Printf("Waiting for 30 seconds\n")
|
||||
// <-time.After(time.Second * 30)
|
||||
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
<-sigChan
|
||||
|
||||
return err
|
||||
func runCommand(cmd *cobra.Command, args []string) {
|
||||
global.RunStandalone(hiddifySettingPath, configPath)
|
||||
}
|
||||
|
||||
21
cmd/cmd_tunnel_service.go
Normal file
21
cmd/cmd_tunnel_service.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hiddify/libcore/admin_service"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var commandService = &cobra.Command{
|
||||
Use: "tunnel run/start/stop/install/uninstall",
|
||||
Short: "Tunnel Service run/start/stop/install/uninstall",
|
||||
ValidArgs: []string{"run", "start", "stop", "install", "uninstall"},
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
arg := args[0]
|
||||
code, out := admin_service.StartService(arg)
|
||||
fmt.Printf("exitCode:%d msg=%s", code, out)
|
||||
},
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -17,7 +17,7 @@ var (
|
||||
)
|
||||
|
||||
var mainCommand = &cobra.Command{
|
||||
Use: "hiddify-next",
|
||||
Use: "HiddifyCli",
|
||||
PersistentPreRun: preRun,
|
||||
}
|
||||
|
||||
@@ -30,10 +30,13 @@ func init() {
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := mainCommand.Execute(); err != nil {
|
||||
func ParseCli(args []string) error {
|
||||
mainCommand.SetArgs(args)
|
||||
err := mainCommand.Execute()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func preRun(cmd *cobra.Command, args []string) {
|
||||
@@ -7,54 +7,43 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ExecuteCmd(executablePath, args string, background bool) (string, error) {
|
||||
func ExecuteCmd(executablePath string, background bool, args ...string) (string, error) {
|
||||
cwd := filepath.Dir(executablePath)
|
||||
if appimage := os.Getenv("APPIMAGE"); appimage != "" {
|
||||
executablePath = appimage + " HiddifyService"
|
||||
executablePath = appimage
|
||||
if !background {
|
||||
return "Fail", fmt.Errorf("Appimage can not have service")
|
||||
return "Fail", fmt.Errorf("Appimage cannot have service")
|
||||
}
|
||||
}
|
||||
|
||||
if err := execCmdImp([]string{"cocoasudo", "--prompt=Hiddify needs root for tunneling.", executablePath, args}, cwd, background); err == nil {
|
||||
return "Ok", nil
|
||||
}
|
||||
if err := execCmdImp([]string{"gksu", executablePath, args}, cwd, background); err == nil {
|
||||
return "Ok", nil
|
||||
}
|
||||
if err := execCmdImp([]string{"pkexec", executablePath, args}, cwd, background); err == nil {
|
||||
return "Ok", nil
|
||||
}
|
||||
if err := execCmdImp([]string{"xterm", "-e", "sudo " + executablePath + " " + args}, cwd, background); err == nil {
|
||||
return "Ok", nil
|
||||
commands := [][]string{
|
||||
{"cocoasudo", "--prompt=Hiddify needs root for tunneling.", executablePath},
|
||||
{"gksu", executablePath},
|
||||
{"pkexec", executablePath},
|
||||
{"xterm", "-e", "sudo", executablePath, strings.Join(args, " ")},
|
||||
{"sudo", executablePath},
|
||||
}
|
||||
|
||||
if err := execCmdImp([]string{"sudo", executablePath, args}, cwd, background); err == nil {
|
||||
return "Ok", nil
|
||||
var err error
|
||||
var cmd *exec.Cmd
|
||||
for _, command := range commands {
|
||||
cmd = exec.Command(command[0], command[1:]...)
|
||||
cmd.Dir = cwd
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
fmt.Printf("Running command: %v\n", command)
|
||||
if background {
|
||||
err = cmd.Start()
|
||||
} else {
|
||||
err = cmd.Run()
|
||||
}
|
||||
if err == nil {
|
||||
return "Ok", nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Error executing run as root shell command")
|
||||
|
||||
}
|
||||
|
||||
func execCmdImp(commands []string, cwd string, background bool) error {
|
||||
cmd := exec.Command(commands[0], commands[1:]...)
|
||||
cmd.Dir = cwd
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
fmt.Printf("Running command: %v", commands)
|
||||
if background {
|
||||
if err := cmd.Start(); err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -9,18 +9,30 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func ExecuteCmd(exe string, args string, background bool) (string, error) {
|
||||
func ExecuteCmd(exe string, background bool, args ...string) (string, error) {
|
||||
verb := "runas"
|
||||
cwd, _ := os.Getwd()
|
||||
cwd, err := os.Getwd() // Error handling added
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
verbPtr, _ := syscall.UTF16PtrFromString(verb)
|
||||
exePtr, _ := syscall.UTF16PtrFromString(exe)
|
||||
cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
|
||||
argPtr, _ := syscall.UTF16PtrFromString(args)
|
||||
|
||||
var showCmd int32 = 1 //SW_NORMAL
|
||||
// Convert args to UTF16Ptr slice
|
||||
var argsPtr []*uint16
|
||||
for _, arg := range args {
|
||||
argPtr, err := syscall.UTF16PtrFromString(arg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
argsPtr = append(argsPtr, argPtr)
|
||||
}
|
||||
|
||||
err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd)
|
||||
var showCmd int32 = 1 // SW_NORMAL
|
||||
|
||||
err = windows.ShellExecute(0, verbPtr, exePtr, nil, cwdPtr, showCmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ func stopTunnelRequest() (bool, error) {
|
||||
func runTunnelService(opt ConfigOptions) (bool, error) {
|
||||
executablePath := getTunnelServicePath()
|
||||
fmt.Printf("Executable path is %s", executablePath)
|
||||
out, err := ExecuteCmd(executablePath, "install", false)
|
||||
out, err := ExecuteCmd(executablePath, false, "tunnel", "install")
|
||||
fmt.Println("Shell command executed:", out, err)
|
||||
if err != nil {
|
||||
out, err = ExecuteCmd(executablePath, "", true)
|
||||
out, err = ExecuteCmd(executablePath, true, "tunnel", "run")
|
||||
fmt.Println("Shell command executed without flag:", out, err)
|
||||
}
|
||||
if err == nil {
|
||||
@@ -112,11 +112,11 @@ func getTunnelServicePath() string {
|
||||
binFolder := filepath.Dir(exePath)
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
fullPath = "HiddifyService.exe"
|
||||
fullPath = "HiddifyCli.exe"
|
||||
case "darwin":
|
||||
fallthrough
|
||||
default:
|
||||
fullPath = "HiddifyService"
|
||||
fullPath = "HiddifyCli"
|
||||
}
|
||||
|
||||
abspath, _ := filepath.Abs(filepath.Join(binFolder, fullPath))
|
||||
|
||||
@@ -61,7 +61,7 @@ func BuildConfig(opt ConfigOptions, input option.Options) (*option.Options, erro
|
||||
fmt.Printf("config options: %+v\n", opt)
|
||||
|
||||
var options option.Options
|
||||
directDNSDomains := []string{}
|
||||
directDNSDomains := make(map[string]bool)
|
||||
dnsRules := []option.DefaultDNSRule{}
|
||||
|
||||
var bind string
|
||||
@@ -221,7 +221,7 @@ func BuildConfig(opt ConfigOptions, input option.Options) (*option.Options, erro
|
||||
}
|
||||
parsedUrl, err := url.Parse(fmt.Sprintf("https://%s", remoteDNSAddress))
|
||||
if err == nil && net.ParseIP(parsedUrl.Host) == nil {
|
||||
directDNSDomains = append(directDNSDomains, fmt.Sprintf("full:%s", parsedUrl.Host))
|
||||
directDNSDomains["full:"+parsedUrl.Host] = true
|
||||
//TODO: IS it really needed
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ func BuildConfig(opt ConfigOptions, input option.Options) (*option.Options, erro
|
||||
}
|
||||
|
||||
if serverDomain != "" {
|
||||
directDNSDomains = append(directDNSDomains, serverDomain)
|
||||
directDNSDomains[serverDomain] = true
|
||||
}
|
||||
out = *outbound
|
||||
|
||||
@@ -518,7 +518,12 @@ func BuildConfig(opt ConfigOptions, input option.Options) (*option.Options, erro
|
||||
// trickDnsRule.Server = DNSTricksDirectTag
|
||||
// options.DNS.Rules = append([]option.DNSRule{{Type: C.RuleTypeDefault, DefaultOptions: trickDnsRule}}, options.DNS.Rules...)
|
||||
|
||||
domains := strings.Join(directDNSDomains, ",")
|
||||
directDNSDomainskeys := make([]string, 0, len(directDNSDomains))
|
||||
for key := range directDNSDomains {
|
||||
directDNSDomainskeys = append(directDNSDomainskeys, key)
|
||||
}
|
||||
|
||||
domains := strings.Join(directDNSDomainskeys, ",")
|
||||
directRule := Rule{Domains: domains, Outbound: OutboundBypassTag}
|
||||
dnsRule := directRule.MakeDNSRule()
|
||||
dnsRule.Server = DNSDirectTag
|
||||
|
||||
@@ -96,7 +96,7 @@ func DefaultConfigOptions() *ConfigOptions {
|
||||
EnableDNSRouting: false,
|
||||
},
|
||||
InboundOptions: InboundOptions{
|
||||
EnableTun: true,
|
||||
EnableTun: false,
|
||||
SetSystemProxy: true,
|
||||
MixedPort: 2334,
|
||||
LocalDnsPort: 16450,
|
||||
@@ -117,12 +117,12 @@ func DefaultConfigOptions() *ConfigOptions {
|
||||
},
|
||||
LogLevel: "info",
|
||||
EnableClashApi: true,
|
||||
ClashApiPort: 16756,
|
||||
ClashApiPort: 6756,
|
||||
GeoIPPath: "geoip.db",
|
||||
GeoSitePath: "geosite.db",
|
||||
Rules: []Rule{},
|
||||
MuxOptions: MuxOptions{
|
||||
EnableMux: true,
|
||||
EnableMux: false,
|
||||
MuxPadding: true,
|
||||
MaxStreams: 8,
|
||||
MuxProtocol: "h2mux",
|
||||
|
||||
27
custom/cmd_interface.go
Normal file
27
custom/cmd_interface.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hiddify/libcore/cmd"
|
||||
)
|
||||
|
||||
//export parseCli
|
||||
func parseCli(argc C.int, argv **C.char) *C.char {
|
||||
args := make([]string, argc)
|
||||
for i := 0; i < int(argc); i++ {
|
||||
fmt.Println("parseCli", C.GoString(*argv))
|
||||
args[i] = C.GoString(*argv)
|
||||
argv = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + uintptr(unsafe.Sizeof(*argv))))
|
||||
}
|
||||
err := cmd.ParseCli(args[1:])
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return C.CString("Ok")
|
||||
}
|
||||
@@ -16,9 +16,6 @@ import (
|
||||
func AdminServiceStart(arg *C.char) *C.char {
|
||||
goArg := C.GoString(arg)
|
||||
exitCode, outMessage := admin_service.StartService(goArg)
|
||||
|
||||
// Allocate memory for the message and copy the string content
|
||||
|
||||
return C.CString(fmt.Sprintf("%d %s", exitCode, outMessage))
|
||||
|
||||
}
|
||||
|
||||
203
global/standalone.go
Normal file
203
global/standalone.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package global
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hiddify/libcore/config"
|
||||
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
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://") {
|
||||
resp, err := http.Get(configPath)
|
||||
if err != nil {
|
||||
return ConfigResult{}, fmt.Errorf("failed to get config from URL: %w", 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"
|
||||
finalconfig.Experimental.ClashAPI.ExternalController = "0.0.0.0: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 RunStandalone(hiddifySettingPath string, configPath string) error {
|
||||
current, err := readAndBuildConfig(hiddifySettingPath, configPath)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
10
go.mod
10
go.mod
@@ -4,6 +4,7 @@ go 1.21.5
|
||||
|
||||
require (
|
||||
github.com/bepass-org/wireguard-go v0.0.16-alpha
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/hiddify/ray2sing v0.0.0-20240221185915-96fae128815c
|
||||
github.com/kardianos/service v1.2.2
|
||||
github.com/sagernet/gomobile v0.1.3
|
||||
@@ -11,18 +12,20 @@ require (
|
||||
github.com/sagernet/sing-box v1.8.4
|
||||
github.com/sagernet/sing-dns v0.1.12
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/urfave/cli/v2 v2.27.1
|
||||
github.com/xmdhs/clash2singbox v0.0.2
|
||||
golang.org/x/sys v0.17.0
|
||||
google.golang.org/grpc v1.62.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
berty.tech/go-libtor v1.0.385 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/akavel/rsrc v0.10.2 // indirect
|
||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||
github.com/caddyserver/certmagic v0.20.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/cretz/bine v0.2.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gaukas/godicttls v0.0.4 // indirect
|
||||
@@ -34,7 +37,6 @@ require (
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.0.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
@@ -66,6 +68,7 @@ require (
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/quic-go/quic-go v0.40.1 // indirect
|
||||
github.com/refraction-networking/utls v1.6.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect
|
||||
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e // indirect
|
||||
@@ -88,6 +91,7 @@ require (
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
@@ -99,8 +103,8 @@ require (
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 // indirect
|
||||
google.golang.org/grpc v1.62.0 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
lukechampine.com/blake3 v1.2.1 // indirect
|
||||
)
|
||||
|
||||
12
go.sum
12
go.sum
@@ -2,14 +2,13 @@ berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
|
||||
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=
|
||||
github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
|
||||
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
||||
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
|
||||
@@ -129,6 +128,7 @@ github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1
|
||||
github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
|
||||
github.com/refraction-networking/utls v1.6.1 h1:n1JG5karzdGWsI6iZmGrOv3SNzR4c+4M8J6KWGsk3lA=
|
||||
github.com/refraction-networking/utls v1.6.1/go.mod h1:+EbcQOvQvXoFV9AEKbuGlljt1doLRKAVY1jJHe9EtDo=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
|
||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
||||
@@ -190,10 +190,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
|
||||
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/xmdhs/clash2singbox v0.0.2 h1:/gxaFm8fmv+UcUZzK508Z0yR01wg1LHrrq872Qibk1I=
|
||||
github.com/xmdhs/clash2singbox v0.0.2/go.mod h1:B5pbJCwIHhJg6YRPCT04EXw6XXNIIOllMfL3XyJ7ob8=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
@@ -284,8 +288,8 @@ golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 h1:DKU1r6Tj5s1vlU/moGhuGz7E3xRfwjdAfDzbsaQJtEY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
|
||||
|
||||
Reference in New Issue
Block a user