Files
umbrix-libcore/config/admin_service_commander.go
2024-02-05 18:47:26 +01:00

117 lines
3.0 KiB
Go

package config
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"runtime"
"github.com/sagernet/sing-box/option"
dns "github.com/sagernet/sing-dns"
E "github.com/sagernet/sing/common/exceptions"
)
const (
serviceURL = "http://localhost:18020"
startEndpoint = "/start"
stopEndpoint = "/stop"
)
func isSupportedOS() bool {
return runtime.GOOS == "windows" || runtime.GOOS == "linux"
}
func ActivateTunnelService(opt ConfigOptions) (bool, error) {
if !isSupportedOS() {
return false, E.New("Unsupported OS: " + runtime.GOOS)
}
go startTunnelRequest(opt, true)
return true, nil
}
func DeactivateTunnelService() (bool, error) {
if !isSupportedOS() {
return true, nil
}
go stopTunnelRequest()
return true, nil
}
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)
if err != nil {
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)
if err != nil {
return false, fmt.Errorf("HTTP Request Error: %v", 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 runTunnelService(opt ConfigOptions) (bool, error) {
executablePath := getTunnelServicePath()
out, err := ExecuteCmd(executablePath, "install")
fmt.Println("Shell command executed:", out, err)
return startTunnelRequest(opt, false)
}
func getTunnelServicePath() string {
var fullPath string
binFolder := filepath.Dir(os.Args[0])
switch runtime.GOOS {
case "windows":
fullPath = "HiddifyService.exe"
case "darwin":
fallthrough
default:
fullPath = "HiddifyService"
}
return filepath.Join(binFolder, fullPath)
}