big refactor. make compatible v2 and v1 interface
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
// Copyright 2015 Daniel Theophanes.
|
||||
// Use of this source code is governed by a zlib-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// simple does nothing except block while running the service.
|
||||
package main
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hiddify/libcore/admin_service"
|
||||
)
|
||||
|
||||
//export AdminServiceStart
|
||||
func AdminServiceStart(arg *C.char) *C.char {
|
||||
goArg := C.GoString(arg)
|
||||
exitCode, outMessage := admin_service.StartService(goArg)
|
||||
return C.CString(fmt.Sprintf("%d %s", exitCode, outMessage))
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package main
|
||||
|
||||
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"`
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
v2 "github.com/hiddify/libcore/v2"
|
||||
"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(pb.CoreState_STARTING)
|
||||
if commandServer != nil {
|
||||
commandServer.SetService(nil)
|
||||
commandServer = nil
|
||||
}
|
||||
if v2.Box != nil {
|
||||
v2.Box.Close()
|
||||
v2.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()
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sagernet/sing-box/experimental/libbox"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
)
|
||||
|
||||
var (
|
||||
statusClient *libbox.CommandClient
|
||||
groupClient *libbox.CommandClient
|
||||
groupInfoOnlyClient *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, //1000ms debounce
|
||||
},
|
||||
)
|
||||
return statusClient.Connect()
|
||||
case libbox.CommandGroup:
|
||||
groupClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{
|
||||
port: port,
|
||||
logger: logFactory.NewLogger("[Group Command Client]"),
|
||||
},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandGroup,
|
||||
StatusInterval: 300000000, //300ms debounce
|
||||
},
|
||||
)
|
||||
return groupClient.Connect()
|
||||
case libbox.CommandGroupInfoOnly:
|
||||
groupInfoOnlyClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{
|
||||
port: port,
|
||||
logger: logFactory.NewLogger("[GroupInfoOnly Command Client]"),
|
||||
},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandGroupInfoOnly,
|
||||
StatusInterval: 300000000, //300ms debounce
|
||||
},
|
||||
)
|
||||
return groupInfoOnlyClient.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
|
||||
case libbox.CommandGroupInfoOnly:
|
||||
err := groupInfoOnlyClient.Disconnect()
|
||||
groupInfoOnlyClient = nil
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package main
|
||||
|
||||
const (
|
||||
Stopped = "Stopped"
|
||||
Starting = "Starting"
|
||||
Started = "Started"
|
||||
Stopping = "Stopping"
|
||||
)
|
||||
|
||||
const (
|
||||
EmptyConfiguration = "EmptyConfiguration"
|
||||
StartCommandServer = "StartCommandServer"
|
||||
CreateService = "CreateService"
|
||||
StartService = "StartService"
|
||||
)
|
||||
309
custom/custom.go
309
custom/custom.go
@@ -7,10 +7,7 @@ import "C"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hiddify/libcore/bridge"
|
||||
@@ -18,16 +15,9 @@ import (
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
v2 "github.com/hiddify/libcore/v2"
|
||||
|
||||
"github.com/sagernet/sing-box/experimental/libbox"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
// var v2.Box *libbox.BoxService
|
||||
var configOptions *config.ConfigOptions
|
||||
var activeConfigPath *string
|
||||
var logFactory *log.Factory
|
||||
|
||||
//export setupOnce
|
||||
func setupOnce(api unsafe.Pointer) {
|
||||
bridge.InitializeDartApi(api)
|
||||
@@ -35,287 +25,146 @@ func setupOnce(api unsafe.Pointer) {
|
||||
|
||||
//export setup
|
||||
func setup(baseDir *C.char, workingDir *C.char, tempDir *C.char, statusPort C.longlong, debug bool) (CErr *C.char) {
|
||||
defer config.DeferPanicToError("setup", func(err error) {
|
||||
CErr = C.CString(err.Error())
|
||||
fmt.Printf("Error: %+v\n", err)
|
||||
})
|
||||
err := v2.Setup(C.GoString(baseDir), C.GoString(workingDir), C.GoString(tempDir), int64(statusPort), debug)
|
||||
|
||||
Setup(C.GoString(baseDir), C.GoString(workingDir), C.GoString(tempDir))
|
||||
statusPropagationPort = int64(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 C.CString(err.Error())
|
||||
}
|
||||
logFactory = &factory
|
||||
return C.CString("")
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export parse
|
||||
func parse(path *C.char, tempPath *C.char, debug bool) (CErr *C.char) {
|
||||
defer config.DeferPanicToError("parse", func(err error) {
|
||||
CErr = C.CString(err.Error())
|
||||
res, err := v2.Parse(&pb.ParseRequest{
|
||||
ConfigPath: C.GoString(path),
|
||||
TempPath: C.GoString(tempPath),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
|
||||
config, err := config.ParseConfig(C.GoString(tempPath), debug)
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
err = os.WriteFile(C.GoString(path), config, 0644)
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return C.CString("")
|
||||
err = os.WriteFile(C.GoString(path), []byte(res.Content), 0644)
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export changeConfigOptions
|
||||
func changeConfigOptions(configOptionsJson *C.char) (CErr *C.char) {
|
||||
defer config.DeferPanicToError("changeConfigOptions", func(err error) {
|
||||
CErr = C.CString(err.Error())
|
||||
|
||||
_, err := v2.ChangeConfigOptions(&pb.ChangeConfigOptionsRequest{
|
||||
ConfigOptionsJson: C.GoString(configOptionsJson),
|
||||
})
|
||||
|
||||
configOptions = &config.ConfigOptions{}
|
||||
err := json.Unmarshal([]byte(C.GoString(configOptionsJson)), configOptions)
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
if configOptions.Warp.WireguardConfigStr != "" {
|
||||
err := json.Unmarshal([]byte(configOptions.Warp.WireguardConfigStr), &configOptions.Warp.WireguardConfig)
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return C.CString("")
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export generateConfig
|
||||
func generateConfig(path *C.char) (res *C.char) {
|
||||
defer config.DeferPanicToError("generateConfig", func(err error) {
|
||||
res = C.CString("error" + err.Error())
|
||||
_, err := v2.GenerateConfig(&pb.GenerateConfigRequest{
|
||||
Path: C.GoString(path),
|
||||
})
|
||||
|
||||
config, err := generateConfigFromFile(C.GoString(path), *configOptions)
|
||||
if err != nil {
|
||||
return C.CString("error" + err.Error())
|
||||
}
|
||||
return C.CString(config)
|
||||
}
|
||||
|
||||
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
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export start
|
||||
func start(configPath *C.char, disableMemoryLimit bool) (CErr *C.char) {
|
||||
defer config.DeferPanicToError("start", func(err error) {
|
||||
stopAndAlert("Unexpected Error!", err)
|
||||
CErr = C.CString(err.Error())
|
||||
|
||||
_, err := v2.Start(&pb.StartRequest{
|
||||
ConfigPath: C.GoString(configPath),
|
||||
EnableOldCommandServer: true,
|
||||
DisableMemoryLimit: disableMemoryLimit,
|
||||
})
|
||||
|
||||
if v2.CoreState != pb.CoreState_STOPPED {
|
||||
return C.CString("")
|
||||
}
|
||||
propagateStatus(pb.CoreState_STARTING)
|
||||
|
||||
path := C.GoString(configPath)
|
||||
activeConfigPath = &path
|
||||
|
||||
libbox.SetMemoryLimit(!disableMemoryLimit)
|
||||
err := startService(false)
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return C.CString("")
|
||||
}
|
||||
|
||||
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 stopAndAlert("Error Building Config", err)
|
||||
}
|
||||
|
||||
config.SaveCurrentConfig(filepath.Join(sWorkingPath, "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)
|
||||
}
|
||||
v2.Box = instance
|
||||
commandServer.SetService(v2.Box)
|
||||
|
||||
propagateStatus(pb.CoreState_STARTED)
|
||||
return nil
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export stop
|
||||
func stop() (CErr *C.char) {
|
||||
defer config.DeferPanicToError("stop", func(err error) {
|
||||
stopAndAlert("Unexpected Error in Stop!", err)
|
||||
CErr = C.CString(err.Error())
|
||||
})
|
||||
|
||||
if v2.CoreState != pb.CoreState_STARTED {
|
||||
stopAndAlert("Already Stopped", nil)
|
||||
return C.CString("")
|
||||
}
|
||||
if v2.Box == nil {
|
||||
return C.CString("instance not found")
|
||||
}
|
||||
propagateStatus(pb.CoreState_STOPPING)
|
||||
config.DeactivateTunnelService()
|
||||
commandServer.SetService(nil)
|
||||
|
||||
err := v2.Box.Close()
|
||||
if err != nil {
|
||||
stopAndAlert("Unexpected Error in Close!", err)
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
v2.Box = nil
|
||||
err = commandServer.Close()
|
||||
if err != nil {
|
||||
stopAndAlert("Unexpected Error in Stop CommandServer/!", err)
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
commandServer = nil
|
||||
propagateStatus(pb.CoreState_STOPPED)
|
||||
return C.CString("")
|
||||
_, err := v2.Stop()
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export restart
|
||||
func restart(configPath *C.char, disableMemoryLimit bool) (CErr *C.char) {
|
||||
defer config.DeferPanicToError("restart", func(err error) {
|
||||
stopAndAlert("Unexpected Error!", err)
|
||||
CErr = C.CString(err.Error())
|
||||
|
||||
_, err := v2.Restart(&pb.StartRequest{
|
||||
ConfigPath: C.GoString(configPath),
|
||||
EnableOldCommandServer: true,
|
||||
DisableMemoryLimit: disableMemoryLimit,
|
||||
})
|
||||
log.Debug("[Service] Restarting")
|
||||
|
||||
if v2.CoreState != pb.CoreState_STARTED {
|
||||
return C.CString("")
|
||||
}
|
||||
if v2.Box == nil {
|
||||
return C.CString("instance not found")
|
||||
}
|
||||
|
||||
err := stop()
|
||||
if C.GoString(err) != "" {
|
||||
return err
|
||||
}
|
||||
|
||||
propagateStatus(pb.CoreState_STARTING)
|
||||
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
|
||||
path := C.GoString(configPath)
|
||||
activeConfigPath = &path
|
||||
libbox.SetMemoryLimit(!disableMemoryLimit)
|
||||
gErr := startService(false)
|
||||
if gErr != nil {
|
||||
return C.CString(gErr.Error())
|
||||
}
|
||||
return C.CString("")
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export startCommandClient
|
||||
func startCommandClient(command C.int, port C.longlong) *C.char {
|
||||
err := StartCommand(int32(command), int64(port), *logFactory)
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return C.CString("")
|
||||
err := v2.StartCommand(int32(command), int64(port))
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export stopCommandClient
|
||||
func stopCommandClient(command C.int) *C.char {
|
||||
err := StopCommand(int32(command))
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return C.CString("")
|
||||
err := v2.StopCommand(int32(command))
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export selectOutbound
|
||||
func selectOutbound(groupTag *C.char, outboundTag *C.char) (CErr *C.char) {
|
||||
defer config.DeferPanicToError("selectOutbound", func(err error) {
|
||||
CErr = C.CString(err.Error())
|
||||
|
||||
_, err := v2.SelectOutbound(&pb.SelectOutboundRequest{
|
||||
GroupTag: C.GoString(groupTag),
|
||||
OutboundTag: C.GoString(outboundTag),
|
||||
})
|
||||
|
||||
err := libbox.NewStandaloneCommandClient().SelectOutbound(C.GoString(groupTag), C.GoString(outboundTag))
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return C.CString("")
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
//export urlTest
|
||||
func urlTest(groupTag *C.char) (CErr *C.char) {
|
||||
defer config.DeferPanicToError("urlTest", func(err error) {
|
||||
CErr = C.CString(err.Error())
|
||||
_, err := v2.UrlTest(&pb.UrlTestRequest{
|
||||
GroupTag: C.GoString(groupTag),
|
||||
})
|
||||
|
||||
err := libbox.NewStandaloneCommandClient().URLTest(C.GoString(groupTag))
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
|
||||
func emptyOrErrorC(err error) *C.char {
|
||||
if err == nil {
|
||||
return C.CString("")
|
||||
}
|
||||
return C.CString("")
|
||||
log.Error(err.Error())
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
|
||||
//export generateWarpConfig
|
||||
func generateWarpConfig(licenseKey *C.char, accountId *C.char, accessToken *C.char) (CResp *C.char) {
|
||||
defer config.DeferPanicToError("generateWarpConfig", func(err error) {
|
||||
CResp = C.CString(fmt.Sprint("error: ", err.Error()))
|
||||
res, err := v2.GenerateWarpConfig(&pb.GenerateWarpConfigRequest{
|
||||
LicenseKey: C.GoString(licenseKey),
|
||||
AccountId: C.GoString(accountId),
|
||||
AccessToken: C.GoString(accessToken),
|
||||
})
|
||||
account, err := config.GenerateWarpAccount(C.GoString(licenseKey), C.GoString(accountId), C.GoString(accessToken))
|
||||
|
||||
if err != nil {
|
||||
return C.CString(fmt.Sprint("error: ", err.Error()))
|
||||
}
|
||||
return C.CString(account)
|
||||
warpAccount := config.WarpAccount{
|
||||
AccountID: res.Account.AccountId,
|
||||
AccessToken: res.Account.AccessToken,
|
||||
}
|
||||
warpConfig := config.WarpWireguardConfig{
|
||||
PrivateKey: res.Config.PrivateKey,
|
||||
LocalAddressIPv4: res.Config.LocalAddressIpv4,
|
||||
LocalAddressIPv6: res.Config.LocalAddressIpv6,
|
||||
PeerPublicKey: res.Config.PeerPublicKey,
|
||||
}
|
||||
log := res.Log
|
||||
response := &config.WarpGenerationResponse{
|
||||
WarpAccount: warpAccount,
|
||||
Log: log,
|
||||
Config: warpConfig,
|
||||
}
|
||||
|
||||
responseJson, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return C.CString("")
|
||||
}
|
||||
return C.CString(string(responseJson))
|
||||
|
||||
}
|
||||
|
||||
func main() {}
|
||||
|
||||
10
custom/grpc_interface.go
Normal file
10
custom/grpc_interface.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import "C"
|
||||
import v2 "github.com/hiddify/libcore/v2"
|
||||
|
||||
//export StartCoreGrpcServer
|
||||
func StartCoreGrpcServer(listenAddress *C.char) (CErr *C.char) {
|
||||
err := v2.StartCoreGrpcServer(C.GoString(listenAddress))
|
||||
return emptyOrErrorC(err)
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package main
|
||||
|
||||
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
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package main
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/hiddify/libcore/bridge"
|
||||
"github.com/hiddify/libcore/config"
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
v2 "github.com/hiddify/libcore/v2"
|
||||
)
|
||||
|
||||
var statusPropagationPort int64
|
||||
|
||||
// var status = Stopped
|
||||
|
||||
type StatusMessage struct {
|
||||
Status string `json:"status"`
|
||||
Alert *string `json:"alert"`
|
||||
Message *string `json:"message"`
|
||||
}
|
||||
|
||||
func propagateStatus(newStatus pb.CoreState) {
|
||||
v2.CoreState = newStatus
|
||||
|
||||
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(v2.CoreState)})
|
||||
bridge.SendStringToPort(statusPropagationPort, string(msg))
|
||||
}
|
||||
|
||||
func convert2OldState(newStatus pb.CoreState) string {
|
||||
if newStatus == pb.CoreState_STOPPED {
|
||||
return Stopped
|
||||
}
|
||||
if newStatus == pb.CoreState_STARTED {
|
||||
return Started
|
||||
}
|
||||
if newStatus == pb.CoreState_STARTING {
|
||||
return Starting
|
||||
}
|
||||
if newStatus == pb.CoreState_STOPPING {
|
||||
return Stopping
|
||||
}
|
||||
return "Invalid"
|
||||
}
|
||||
|
||||
func stopAndAlert(alert string, err error) (resultErr error) {
|
||||
defer config.DeferPanicToError("stopAndAlert", func(err error) {
|
||||
resultErr = err
|
||||
})
|
||||
v2.CoreState = pb.CoreState_STOPPED
|
||||
message := err.Error()
|
||||
fmt.Printf("Error: %s: %s\n", alert, message)
|
||||
msg, _ := json.Marshal(StatusMessage{Status: convert2OldState(v2.CoreState), Alert: &alert, Message: &message})
|
||||
bridge.SendStringToPort(statusPropagationPort, string(msg))
|
||||
|
||||
go config.DeactivateTunnelService()
|
||||
if commandServer != nil {
|
||||
commandServer.SetService(nil)
|
||||
}
|
||||
if v2.Box != nil {
|
||||
v2.Box.Close()
|
||||
v2.Box = nil
|
||||
}
|
||||
if commandServer != nil {
|
||||
commandServer.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user