new: make tunnel service working

This commit is contained in:
Hiddify
2024-02-02 13:47:41 +01:00
parent ad764a86b1
commit 7bdfee5459
14 changed files with 232 additions and 94 deletions

View File

@@ -0,0 +1,17 @@
<?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="hiddify-service.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>

Binary file not shown.

56
admin_service/cmd/main.go Normal file
View File

@@ -0,0 +1,56 @@
package main
/*
#cgo LDFLAGS: bin/libcore.dll
#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
// Check if there is at least one command-line argument
if len(args) < 2 {
println("Usage: hiddify-service.exe empty/start/stop/uninstall/install")
// os.Exit(1)
args = append(args, "")
}
// fmt.Printf("os.Args: %+v", args)
os.Chdir(os.Args[0])
// Convert the Go string to a C string
arg := C.CString(args[1])
// defer C.free(unsafe.Pointer(arg))
// Call AdminServiceStart with the C string
result := C.AdminServiceStart(arg)
goRes := C.GoString(result)
defer C.free(unsafe.Pointer(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(int(parsedExitCode))
}
}

View File

@@ -1,7 +1,10 @@
package admin_service
import (
"fmt"
"log"
"os"
"path/filepath"
"github.com/hiddify/libcore/global"
"github.com/kardianos/service"
@@ -18,7 +21,7 @@ func (m *hiddifyNext) Start(s service.Service) error {
return nil
}
func (m *hiddifyNext) Stop(s service.Service) error {
err := global.StopService()
err := global.StopServiceC()
if err != nil {
return err
}
@@ -30,45 +33,115 @@ func (m *hiddifyNext) run() {
StartWebServer(port, false)
}
func StartService(goArg string) {
func getCurrentExecutableDirectory() string {
executablePath, err := os.Executable()
if err != nil {
return ""
}
// Extract the directory (folder) containing the executable
executableDirectory := filepath.Dir(executablePath)
return executableDirectory
}
func StartService(goArg string) (int, string) {
svcConfig := &service.Config{
Name: "Hiddify Tunnel Service",
DisplayName: "Hiddify Tunnel Service",
Description: "This is a bridge for tunnel",
Option: map[string]interface{}{
"RunAtLoad": true,
"WorkingDirectory": getCurrentExecutableDirectory(),
},
}
prg := &hiddifyNext{}
s, err := service.New(prg, svcConfig)
if err != nil {
log.Fatal(err)
// log.Printf("Error: %v", err)
return 1, fmt.Sprintf("Error: %v", err)
}
if len(goArg) > 0 {
if goArg == "uninstall" {
err = s.Stop()
if err != nil {
log.Fatal(err)
}
}
err = service.Control(s, goArg)
if err != nil {
log.Fatal(err)
}
if goArg == "install" {
err = s.Start()
if err != nil {
log.Fatal(err)
}
}
return
if len(goArg) > 0 {
return control(s, goArg)
}
logger, err = s.Logger(nil)
if err != nil {
log.Fatal(err)
log.Printf("Error: %v", err)
}
err = s.Run()
if err != nil {
logger.Error(err)
return 3, fmt.Sprintf("Error: %v", err)
}
return 0, ""
}
func control(s service.Service, goArg string) (int, string) {
dolog := false
var err error
status, serr := s.Status()
if dolog {
fmt.Printf("Current Status: %+v %+v!\n", status, serr)
}
switch goArg {
case "uninstall":
if status == service.StatusRunning {
s.Stop()
}
if dolog {
fmt.Printf("Tunnel Service Uninstalled Successfully.\n")
}
err = s.Uninstall()
case "start":
if status == service.StatusRunning {
if dolog {
fmt.Printf("Tunnel Service Already Running.\n")
}
return 0, "Tunnel Service Already Running."
} else if status == service.StatusUnknown {
s.Install()
status, serr = s.Status()
if dolog {
fmt.Printf("Check status again: %+v %+v!", status, serr)
}
}
if status != service.StatusRunning {
err = s.Start()
}
case "install":
err = s.Install()
status, serr = s.Status()
if dolog {
fmt.Printf("Check Status Again: %+v %+v", status, serr)
}
if status != service.StatusRunning {
err = s.Start()
}
case "stop":
if status == service.StatusStopped {
if dolog {
fmt.Printf("Tunnel Service Already Stopped.\n")
}
return 0, "Tunnel Service Already Stopped."
}
err = s.Stop()
default:
err = service.Control(s, goArg)
}
if err == nil {
out := fmt.Sprintf("Tunnel Service %sed Successfully.", goArg)
if dolog {
fmt.Printf(out)
}
return 0, out
} else {
out := fmt.Sprintf("Error: %v", err)
if dolog {
log.Printf(out)
}
return 2, out
}
}

View File

@@ -65,11 +65,11 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
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.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 {
@@ -84,11 +84,12 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, fmt.Sprintf("Ok"), http.StatusOK)
}
func StopHandler(w http.ResponseWriter, r *http.Request) {
err := global.StopService()
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 GetStack(stack string) global.Stack {