release: version 0.17.7
This commit is contained in:
326
v2/commands.go
326
v2/commands.go
@@ -1,163 +1,163 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing-box/experimental/libbox"
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
)
|
||||
|
||||
var systemInfoObserver = observable.Observer[pb.SystemInfo]{}
|
||||
var outboundsInfoObserver = observable.Observer[pb.OutboundGroupList]{}
|
||||
var mainOutboundsInfoObserver = observable.Observer[pb.OutboundGroupList]{}
|
||||
|
||||
var (
|
||||
statusClient *libbox.CommandClient
|
||||
groupClient *libbox.CommandClient
|
||||
groupInfoOnlyClient *libbox.CommandClient
|
||||
)
|
||||
|
||||
func (s *server) GetSystemInfo(stream pb.Hiddify_GetSystemInfoServer) error {
|
||||
if statusClient == nil {
|
||||
statusClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandStatus,
|
||||
StatusInterval: 1000000000, //1000ms debounce
|
||||
},
|
||||
)
|
||||
|
||||
defer func() {
|
||||
statusClient.Disconnect()
|
||||
statusClient = nil
|
||||
}()
|
||||
statusClient.Connect()
|
||||
}
|
||||
|
||||
sub, _, _ := systemInfoObserver.Subscribe()
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-sub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(1000 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) OutboundsInfo(stream pb.Hiddify_OutboundsInfoServer) error {
|
||||
if groupClient == nil {
|
||||
groupClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandGroup,
|
||||
StatusInterval: 500000000, //500ms debounce
|
||||
},
|
||||
)
|
||||
|
||||
defer func() {
|
||||
groupClient.Disconnect()
|
||||
groupClient = nil
|
||||
}()
|
||||
groupClient.Connect()
|
||||
}
|
||||
|
||||
sub, _, _ := outboundsInfoObserver.Subscribe()
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-sub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) MainOutboundsInfo(stream pb.Hiddify_MainOutboundsInfoServer) error {
|
||||
if groupInfoOnlyClient == nil {
|
||||
groupInfoOnlyClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandGroupInfoOnly,
|
||||
StatusInterval: 500000000, //500ms debounce
|
||||
},
|
||||
)
|
||||
|
||||
defer func() {
|
||||
groupInfoOnlyClient.Disconnect()
|
||||
groupInfoOnlyClient = nil
|
||||
}()
|
||||
groupInfoOnlyClient.Connect()
|
||||
}
|
||||
|
||||
sub, _, _ := mainOutboundsInfoObserver.Subscribe()
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-sub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the SelectOutbound method
|
||||
func (s *server) SelectOutbound(ctx context.Context, in *pb.SelectOutboundRequest) (*pb.Response, error) {
|
||||
err := libbox.NewStandaloneCommandClient().SelectOutbound(in.GroupTag, in.OutboundTag)
|
||||
|
||||
if err != nil {
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Message: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Implement the UrlTest method
|
||||
func (s *server) UrlTest(ctx context.Context, in *pb.UrlTestRequest) (*pb.Response, error) {
|
||||
err := libbox.NewStandaloneCommandClient().URLTest(in.GroupTag)
|
||||
|
||||
if err != nil {
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Message: "",
|
||||
}, nil
|
||||
|
||||
}
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing-box/experimental/libbox"
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
)
|
||||
|
||||
var systemInfoObserver = observable.Observer[pb.SystemInfo]{}
|
||||
var outboundsInfoObserver = observable.Observer[pb.OutboundGroupList]{}
|
||||
var mainOutboundsInfoObserver = observable.Observer[pb.OutboundGroupList]{}
|
||||
|
||||
var (
|
||||
statusClient *libbox.CommandClient
|
||||
groupClient *libbox.CommandClient
|
||||
groupInfoOnlyClient *libbox.CommandClient
|
||||
)
|
||||
|
||||
func (s *server) GetSystemInfo(stream pb.Hiddify_GetSystemInfoServer) error {
|
||||
if statusClient == nil {
|
||||
statusClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandStatus,
|
||||
StatusInterval: 1000000000, //1000ms debounce
|
||||
},
|
||||
)
|
||||
|
||||
defer func() {
|
||||
statusClient.Disconnect()
|
||||
statusClient = nil
|
||||
}()
|
||||
statusClient.Connect()
|
||||
}
|
||||
|
||||
sub, _, _ := systemInfoObserver.Subscribe()
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-sub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(1000 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) OutboundsInfo(stream pb.Hiddify_OutboundsInfoServer) error {
|
||||
if groupClient == nil {
|
||||
groupClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandGroup,
|
||||
StatusInterval: 500000000, //500ms debounce
|
||||
},
|
||||
)
|
||||
|
||||
defer func() {
|
||||
groupClient.Disconnect()
|
||||
groupClient = nil
|
||||
}()
|
||||
groupClient.Connect()
|
||||
}
|
||||
|
||||
sub, _, _ := outboundsInfoObserver.Subscribe()
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-sub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) MainOutboundsInfo(stream pb.Hiddify_MainOutboundsInfoServer) error {
|
||||
if groupInfoOnlyClient == nil {
|
||||
groupInfoOnlyClient = libbox.NewCommandClient(
|
||||
&CommandClientHandler{},
|
||||
&libbox.CommandClientOptions{
|
||||
Command: libbox.CommandGroupInfoOnly,
|
||||
StatusInterval: 500000000, //500ms debounce
|
||||
},
|
||||
)
|
||||
|
||||
defer func() {
|
||||
groupInfoOnlyClient.Disconnect()
|
||||
groupInfoOnlyClient = nil
|
||||
}()
|
||||
groupInfoOnlyClient.Connect()
|
||||
}
|
||||
|
||||
sub, _, _ := mainOutboundsInfoObserver.Subscribe()
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-sub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the SelectOutbound method
|
||||
func (s *server) SelectOutbound(ctx context.Context, in *pb.SelectOutboundRequest) (*pb.Response, error) {
|
||||
err := libbox.NewStandaloneCommandClient().SelectOutbound(in.GroupTag, in.OutboundTag)
|
||||
|
||||
if err != nil {
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Message: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Implement the UrlTest method
|
||||
func (s *server) UrlTest(ctx context.Context, in *pb.UrlTestRequest) (*pb.Response, error) {
|
||||
err := libbox.NewStandaloneCommandClient().URLTest(in.GroupTag)
|
||||
|
||||
if err != nil {
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Message: "",
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
)
|
||||
|
||||
var coreInfoObserver = observable.Observer[pb.CoreInfoResponse]{}
|
||||
var CoreState = pb.CoreState_STOPPED
|
||||
|
||||
func SetCoreStatus(state pb.CoreState, msgType pb.MessageType, message string) pb.CoreInfoResponse {
|
||||
CoreState = state
|
||||
info := pb.CoreInfoResponse{
|
||||
CoreState: state,
|
||||
MessageType: msgType,
|
||||
Message: message,
|
||||
}
|
||||
coreInfoObserver.Emit(info)
|
||||
return info
|
||||
|
||||
}
|
||||
|
||||
func (s *server) CoreInfoListener(stream pb.Hiddify_CoreInfoListenerServer) error {
|
||||
coreSub, _, _ := coreInfoObserver.Subscribe()
|
||||
defer coreInfoObserver.UnSubscribe(coreSub)
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-coreSub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
package v2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
)
|
||||
|
||||
var coreInfoObserver = observable.Observer[pb.CoreInfoResponse]{}
|
||||
var CoreState = pb.CoreState_STOPPED
|
||||
|
||||
func SetCoreStatus(state pb.CoreState, msgType pb.MessageType, message string) pb.CoreInfoResponse {
|
||||
CoreState = state
|
||||
info := pb.CoreInfoResponse{
|
||||
CoreState: state,
|
||||
MessageType: msgType,
|
||||
Message: message,
|
||||
}
|
||||
coreInfoObserver.Emit(info)
|
||||
return info
|
||||
|
||||
}
|
||||
|
||||
func (s *server) CoreInfoListener(stream pb.Hiddify_CoreInfoListenerServer) error {
|
||||
coreSub, _, _ := coreInfoObserver.Subscribe()
|
||||
defer coreInfoObserver.UnSubscribe(coreSub)
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-coreSub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
464
v2/custom.go
464
v2/custom.go
@@ -1,232 +1,232 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/hiddify/libcore/config"
|
||||
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
|
||||
var configOptions *config.ConfigOptions
|
||||
var activeConfigPath *string
|
||||
var logFactory *log.Factory
|
||||
|
||||
func StopAndAlert(msgType pb.MessageType, message string) {
|
||||
SetCoreStatus(pb.CoreState_STOPPED, msgType, message)
|
||||
config.DeactivateTunnelService()
|
||||
// if commandServer != nil {
|
||||
// commandServer.SetService(nil)
|
||||
// }
|
||||
if Box != nil {
|
||||
Box.Close()
|
||||
Box = nil
|
||||
}
|
||||
// if commandServer != nil {
|
||||
// commandServer.Close()
|
||||
// }
|
||||
}
|
||||
|
||||
func (s *server) Start(ctx context.Context, in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
|
||||
defer config.DeferPanicToError("start", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
|
||||
if CoreState != pb.CoreState_STOPPED {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_STOPPED,
|
||||
}, fmt.Errorf("instance not stopped")
|
||||
}
|
||||
SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "")
|
||||
|
||||
libbox.SetMemoryLimit(!in.DisableMemoryLimit)
|
||||
resp, err := s.StartService(ctx, in)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Implement the StartService method
|
||||
func (s *server) StartService(ctx context.Context, in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
|
||||
|
||||
content := in.ConfigContent
|
||||
if content != "" {
|
||||
fileContent, err := os.ReadFile(*activeConfigPath)
|
||||
if err != nil {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_READING_CONFIG, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
content = string(fileContent)
|
||||
}
|
||||
|
||||
parsedContent, err := parseConfig(content)
|
||||
if err != nil {
|
||||
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 {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_BUILDING_CONFIG, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
config.SaveCurrentConfig(filepath.Join(sWorkingPath, "current-config.json"), *patchedOptions)
|
||||
|
||||
// err = startCommandServer(*logFactory)
|
||||
// if err != nil {
|
||||
// resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_START_COMMAND_SERVER, err.Error())
|
||||
// return &resp, err
|
||||
// }
|
||||
|
||||
instance, err := NewService(*patchedOptions)
|
||||
if err != nil {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_CREATE_SERVICE, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
if in.DelayStart {
|
||||
<-time.After(250 * time.Millisecond)
|
||||
}
|
||||
|
||||
err = instance.Start()
|
||||
if err != nil {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_START_SERVICE, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
Box = instance
|
||||
// commandServer.SetService(box)
|
||||
|
||||
resp := SetCoreStatus(pb.CoreState_STARTED, pb.MessageType_EMPTY, "")
|
||||
return &resp, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *server) Parse(ctx context.Context, in *pb.ParseRequest) (*pb.ParseResponse, error) {
|
||||
defer config.DeferPanicToError("parse", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CONFIG, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
|
||||
config, err := config.ParseConfigContent(in.Content, true)
|
||||
if err != nil {
|
||||
return &pb.ParseResponse{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
return &pb.ParseResponse{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Content: string(config),
|
||||
Message: "",
|
||||
}, err
|
||||
}
|
||||
|
||||
// func (s *server) ChangeConfigOptions(ctx context.Context, in *pb.ChangeConfigOptionsRequest) (*pb.CoreInfoResponse, error) {
|
||||
// // Implement your change config options logic
|
||||
// // Return a CoreInfoResponse
|
||||
// }
|
||||
|
||||
// func (s *server) GenerateConfig(ctx context.Context, in *pb.GenerateConfigRequest) (*pb.GenerateConfigResponse, error) {
|
||||
// defer config.DeferPanicToError("generateConfig", func(err error) {
|
||||
// Log(pb.LogLevel_FATAL, pb.LogType_CONFIG, err.Error())
|
||||
// StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
// })
|
||||
|
||||
// config, err := generateConfigFromFile(C.GoString(path), *configOptions)
|
||||
// if err != nil {
|
||||
// return C.CString("error" + err.Error())
|
||||
// }
|
||||
// return C.CString(config)
|
||||
// }
|
||||
|
||||
// Implement the Stop method
|
||||
func (s *server) Stop(ctx context.Context, empty *pb.Empty) (*pb.CoreInfoResponse, error) {
|
||||
defer config.DeferPanicToError("stop", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
config.DeactivateTunnelService()
|
||||
if CoreState != pb.CoreState_STARTED {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, "Core is not started")
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_STARTED,
|
||||
Message: "instance is not started",
|
||||
}, fmt.Errorf("instance not started")
|
||||
}
|
||||
if Box == nil {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_FOUND,
|
||||
Message: "instance is not found",
|
||||
}, fmt.Errorf("instance not found")
|
||||
}
|
||||
SetCoreStatus(pb.CoreState_STOPPING, pb.MessageType_EMPTY, "")
|
||||
// commandServer.SetService(nil)
|
||||
|
||||
err := Box.Close()
|
||||
if err != nil {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_UNEXPECTED_ERROR,
|
||||
Message: "Error while stopping the service.",
|
||||
}, fmt.Errorf("Error while stopping the service.")
|
||||
}
|
||||
Box = nil
|
||||
// err = commandServer.Close()
|
||||
// if err != nil {
|
||||
// return &pb.CoreInfoResponse{
|
||||
// CoreState: CoreState,
|
||||
// MessageType: pb.MessageType_UNEXPECTED_ERROR,
|
||||
// Message: "Error while Closing the comand server.",
|
||||
// }, fmt.Errorf("Error while Closing the comand server.")
|
||||
|
||||
// }
|
||||
// commandServer = nil
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_EMPTY, "")
|
||||
return &resp, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *server) Restart(ctx context.Context, in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
|
||||
defer config.DeferPanicToError("restart", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
log.Debug("[Service] Restarting")
|
||||
|
||||
if CoreState != pb.CoreState_STARTED {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_STARTED,
|
||||
Message: "instance is not started",
|
||||
}, fmt.Errorf("instance not started")
|
||||
}
|
||||
if Box == nil {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_FOUND,
|
||||
Message: "instance is not found",
|
||||
}, fmt.Errorf("instance not found")
|
||||
}
|
||||
|
||||
resp, err := s.Stop(ctx, &pb.Empty{})
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "")
|
||||
<-time.After(250 * time.Millisecond)
|
||||
|
||||
libbox.SetMemoryLimit(!in.DisableMemoryLimit)
|
||||
resp, gErr := s.StartService(ctx, in)
|
||||
return resp, gErr
|
||||
}
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/hiddify/libcore/config"
|
||||
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
|
||||
var configOptions *config.ConfigOptions
|
||||
var activeConfigPath *string
|
||||
var logFactory *log.Factory
|
||||
|
||||
func StopAndAlert(msgType pb.MessageType, message string) {
|
||||
SetCoreStatus(pb.CoreState_STOPPED, msgType, message)
|
||||
config.DeactivateTunnelService()
|
||||
// if commandServer != nil {
|
||||
// commandServer.SetService(nil)
|
||||
// }
|
||||
if Box != nil {
|
||||
Box.Close()
|
||||
Box = nil
|
||||
}
|
||||
// if commandServer != nil {
|
||||
// commandServer.Close()
|
||||
// }
|
||||
}
|
||||
|
||||
func (s *server) Start(ctx context.Context, in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
|
||||
defer config.DeferPanicToError("start", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
|
||||
if CoreState != pb.CoreState_STOPPED {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_STOPPED,
|
||||
}, fmt.Errorf("instance not stopped")
|
||||
}
|
||||
SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "")
|
||||
|
||||
libbox.SetMemoryLimit(!in.DisableMemoryLimit)
|
||||
resp, err := s.StartService(ctx, in)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Implement the StartService method
|
||||
func (s *server) StartService(ctx context.Context, in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
|
||||
|
||||
content := in.ConfigContent
|
||||
if content != "" {
|
||||
fileContent, err := os.ReadFile(*activeConfigPath)
|
||||
if err != nil {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_READING_CONFIG, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
content = string(fileContent)
|
||||
}
|
||||
|
||||
parsedContent, err := parseConfig(content)
|
||||
if err != nil {
|
||||
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 {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_ERROR_BUILDING_CONFIG, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
config.SaveCurrentConfig(filepath.Join(sWorkingPath, "current-config.json"), *patchedOptions)
|
||||
|
||||
// err = startCommandServer(*logFactory)
|
||||
// if err != nil {
|
||||
// resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_START_COMMAND_SERVER, err.Error())
|
||||
// return &resp, err
|
||||
// }
|
||||
|
||||
instance, err := NewService(*patchedOptions)
|
||||
if err != nil {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_CREATE_SERVICE, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
if in.DelayStart {
|
||||
<-time.After(250 * time.Millisecond)
|
||||
}
|
||||
|
||||
err = instance.Start()
|
||||
if err != nil {
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_START_SERVICE, err.Error())
|
||||
return &resp, err
|
||||
}
|
||||
Box = instance
|
||||
// commandServer.SetService(box)
|
||||
|
||||
resp := SetCoreStatus(pb.CoreState_STARTED, pb.MessageType_EMPTY, "")
|
||||
return &resp, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *server) Parse(ctx context.Context, in *pb.ParseRequest) (*pb.ParseResponse, error) {
|
||||
defer config.DeferPanicToError("parse", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CONFIG, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
|
||||
config, err := config.ParseConfigContent(in.Content, true)
|
||||
if err != nil {
|
||||
return &pb.ParseResponse{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
return &pb.ParseResponse{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Content: string(config),
|
||||
Message: "",
|
||||
}, err
|
||||
}
|
||||
|
||||
// func (s *server) ChangeConfigOptions(ctx context.Context, in *pb.ChangeConfigOptionsRequest) (*pb.CoreInfoResponse, error) {
|
||||
// // Implement your change config options logic
|
||||
// // Return a CoreInfoResponse
|
||||
// }
|
||||
|
||||
// func (s *server) GenerateConfig(ctx context.Context, in *pb.GenerateConfigRequest) (*pb.GenerateConfigResponse, error) {
|
||||
// defer config.DeferPanicToError("generateConfig", func(err error) {
|
||||
// Log(pb.LogLevel_FATAL, pb.LogType_CONFIG, err.Error())
|
||||
// StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
// })
|
||||
|
||||
// config, err := generateConfigFromFile(C.GoString(path), *configOptions)
|
||||
// if err != nil {
|
||||
// return C.CString("error" + err.Error())
|
||||
// }
|
||||
// return C.CString(config)
|
||||
// }
|
||||
|
||||
// Implement the Stop method
|
||||
func (s *server) Stop(ctx context.Context, empty *pb.Empty) (*pb.CoreInfoResponse, error) {
|
||||
defer config.DeferPanicToError("stop", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
config.DeactivateTunnelService()
|
||||
if CoreState != pb.CoreState_STARTED {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, "Core is not started")
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_STARTED,
|
||||
Message: "instance is not started",
|
||||
}, fmt.Errorf("instance not started")
|
||||
}
|
||||
if Box == nil {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_FOUND,
|
||||
Message: "instance is not found",
|
||||
}, fmt.Errorf("instance not found")
|
||||
}
|
||||
SetCoreStatus(pb.CoreState_STOPPING, pb.MessageType_EMPTY, "")
|
||||
// commandServer.SetService(nil)
|
||||
|
||||
err := Box.Close()
|
||||
if err != nil {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_UNEXPECTED_ERROR,
|
||||
Message: "Error while stopping the service.",
|
||||
}, fmt.Errorf("Error while stopping the service.")
|
||||
}
|
||||
Box = nil
|
||||
// err = commandServer.Close()
|
||||
// if err != nil {
|
||||
// return &pb.CoreInfoResponse{
|
||||
// CoreState: CoreState,
|
||||
// MessageType: pb.MessageType_UNEXPECTED_ERROR,
|
||||
// Message: "Error while Closing the comand server.",
|
||||
// }, fmt.Errorf("Error while Closing the comand server.")
|
||||
|
||||
// }
|
||||
// commandServer = nil
|
||||
resp := SetCoreStatus(pb.CoreState_STOPPED, pb.MessageType_EMPTY, "")
|
||||
return &resp, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *server) Restart(ctx context.Context, in *pb.StartRequest) (*pb.CoreInfoResponse, error) {
|
||||
defer config.DeferPanicToError("restart", func(err error) {
|
||||
Log(pb.LogLevel_FATAL, pb.LogType_CORE, err.Error())
|
||||
StopAndAlert(pb.MessageType_UNEXPECTED_ERROR, err.Error())
|
||||
})
|
||||
log.Debug("[Service] Restarting")
|
||||
|
||||
if CoreState != pb.CoreState_STARTED {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_STARTED,
|
||||
Message: "instance is not started",
|
||||
}, fmt.Errorf("instance not started")
|
||||
}
|
||||
if Box == nil {
|
||||
return &pb.CoreInfoResponse{
|
||||
CoreState: CoreState,
|
||||
MessageType: pb.MessageType_INSTANCE_NOT_FOUND,
|
||||
Message: "instance is not found",
|
||||
}, fmt.Errorf("instance not found")
|
||||
}
|
||||
|
||||
resp, err := s.Stop(ctx, &pb.Empty{})
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
SetCoreStatus(pb.CoreState_STARTING, pb.MessageType_EMPTY, "")
|
||||
<-time.After(250 * time.Millisecond)
|
||||
|
||||
libbox.SetMemoryLimit(!in.DisableMemoryLimit)
|
||||
resp, gErr := s.StartService(ctx, in)
|
||||
return resp, gErr
|
||||
}
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
const (
|
||||
address = "localhost:50051"
|
||||
defaultName = "world"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn, err := grpc.Dial(address, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
c := pb.NewHiddifyClient(conn)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
|
||||
// SayHello
|
||||
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: defaultName})
|
||||
if err != nil {
|
||||
log.Fatalf("could not greet: %v", err)
|
||||
}
|
||||
log.Printf("Greeting: %s", r.Message)
|
||||
|
||||
// SayHelloStream
|
||||
stream, err := c.SayHelloStream(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("could not stream: %v", err)
|
||||
}
|
||||
|
||||
names := []string{"Alice", "Bob", "Charlie"}
|
||||
|
||||
for _, name := range names {
|
||||
err := stream.Send(&pb.HelloRequest{Name: name})
|
||||
if err != nil {
|
||||
log.Fatalf("could not send: %v", err)
|
||||
}
|
||||
r, err := stream.Recv()
|
||||
if err != nil {
|
||||
log.Fatalf("could not receive: %v", err)
|
||||
}
|
||||
log.Printf("Received1: %s", r.Message)
|
||||
r2, err2 := stream.Recv()
|
||||
if err2 != nil {
|
||||
log.Fatalf("could not receive2: %v", err2)
|
||||
}
|
||||
log.Printf("Received: %s", r2.Message)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
}
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
const (
|
||||
address = "localhost:50051"
|
||||
defaultName = "world"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn, err := grpc.Dial(address, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
c := pb.NewHiddifyClient(conn)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
|
||||
// SayHello
|
||||
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: defaultName})
|
||||
if err != nil {
|
||||
log.Fatalf("could not greet: %v", err)
|
||||
}
|
||||
log.Printf("Greeting: %s", r.Message)
|
||||
|
||||
// SayHelloStream
|
||||
stream, err := c.SayHelloStream(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("could not stream: %v", err)
|
||||
}
|
||||
|
||||
names := []string{"Alice", "Bob", "Charlie"}
|
||||
|
||||
for _, name := range names {
|
||||
err := stream.Send(&pb.HelloRequest{Name: name})
|
||||
if err != nil {
|
||||
log.Fatalf("could not send: %v", err)
|
||||
}
|
||||
r, err := stream.Recv()
|
||||
if err != nil {
|
||||
log.Fatalf("could not receive: %v", err)
|
||||
}
|
||||
log.Printf("Received1: %s", r.Message)
|
||||
r2, err2 := stream.Recv()
|
||||
if err2 != nil {
|
||||
log.Fatalf("could not receive2: %v", err2)
|
||||
}
|
||||
log.Printf("Received: %s", r2.Message)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
v2 "github.com/hiddify/libcore/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// defer C.free(unsafe.Pointer(port))
|
||||
v2.StartGrpcServerGo("127.0.0.1:50051")
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
<-sigChan
|
||||
}
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
v2 "github.com/hiddify/libcore/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// defer C.free(unsafe.Pointer(port))
|
||||
v2.StartGrpcServerGo("127.0.0.1:50051")
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
<-sigChan
|
||||
}
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
package v2
|
||||
|
||||
/*
|
||||
#include "stdint.h"
|
||||
*/
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
pb.UnimplementedHiddifyServer
|
||||
}
|
||||
|
||||
//export StartGrpcServer
|
||||
func StartGrpcServer(listenAddress *C.char) (CErr *C.char) {
|
||||
//Example Listen Address: "127.0.0.1:50051"
|
||||
err := StartGrpcServerGo(C.GoString(listenAddress))
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartGrpcServerGo(listenAddressG string) error {
|
||||
//Example Listen Address: "127.0.0.1:50051"
|
||||
// defer C.free(unsafe.Pointer(CErr)) // free the C string when it's no longer needed
|
||||
// defer C.free(unsafe.Pointer(listenAddress)) // free the C string when it's no longer needed
|
||||
|
||||
lis, err := net.Listen("tcp", listenAddressG)
|
||||
if err != nil {
|
||||
log.Printf("failed to listen: %v", err)
|
||||
return err
|
||||
}
|
||||
s := grpc.NewServer()
|
||||
pb.RegisterHiddifyServer(s, &server{})
|
||||
log.Printf("Server listening on %s", listenAddressG)
|
||||
go func() {
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Printf("failed to serve: %v", err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
package v2
|
||||
|
||||
/*
|
||||
#include "stdint.h"
|
||||
*/
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
pb.UnimplementedHiddifyServer
|
||||
}
|
||||
|
||||
//export StartGrpcServer
|
||||
func StartGrpcServer(listenAddress *C.char) (CErr *C.char) {
|
||||
//Example Listen Address: "127.0.0.1:50051"
|
||||
err := StartGrpcServerGo(C.GoString(listenAddress))
|
||||
if err != nil {
|
||||
return C.CString(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartGrpcServerGo(listenAddressG string) error {
|
||||
//Example Listen Address: "127.0.0.1:50051"
|
||||
// defer C.free(unsafe.Pointer(CErr)) // free the C string when it's no longer needed
|
||||
// defer C.free(unsafe.Pointer(listenAddress)) // free the C string when it's no longer needed
|
||||
|
||||
lis, err := net.Listen("tcp", listenAddressG)
|
||||
if err != nil {
|
||||
log.Printf("failed to listen: %v", err)
|
||||
return err
|
||||
}
|
||||
s := grpc.NewServer()
|
||||
pb.RegisterHiddifyServer(s, &server{})
|
||||
log.Printf("Server listening on %s", listenAddressG)
|
||||
go func() {
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Printf("failed to serve: %v", err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
72
v2/hello.go
72
v2/hello.go
@@ -1,36 +1,36 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
)
|
||||
|
||||
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
|
||||
return &pb.HelloResponse{Message: "Hello, " + in.Name}, nil
|
||||
}
|
||||
func (s *server) SayHelloStream(stream pb.Hiddify_SayHelloStreamServer) error {
|
||||
|
||||
for {
|
||||
req, err := stream.Recv()
|
||||
if err != nil {
|
||||
log.Printf("stream.Recv() failed: %v", err)
|
||||
break
|
||||
}
|
||||
log.Printf("Received: %v", req.Name)
|
||||
time.Sleep(1 * time.Second)
|
||||
err = stream.Send(&pb.HelloResponse{Message: "Hello, " + req.Name})
|
||||
if err != nil {
|
||||
log.Printf("stream.Send() failed: %v", err)
|
||||
break
|
||||
}
|
||||
err = stream.Send(&pb.HelloResponse{Message: "Hello again, " + req.Name})
|
||||
if err != nil {
|
||||
log.Printf("stream.Send() failed: %v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
)
|
||||
|
||||
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
|
||||
return &pb.HelloResponse{Message: "Hello, " + in.Name}, nil
|
||||
}
|
||||
func (s *server) SayHelloStream(stream pb.Hiddify_SayHelloStreamServer) error {
|
||||
|
||||
for {
|
||||
req, err := stream.Recv()
|
||||
if err != nil {
|
||||
log.Printf("stream.Recv() failed: %v", err)
|
||||
break
|
||||
}
|
||||
log.Printf("Received: %v", req.Name)
|
||||
time.Sleep(1 * time.Second)
|
||||
err = stream.Send(&pb.HelloResponse{Message: "Hello, " + req.Name})
|
||||
if err != nil {
|
||||
log.Printf("stream.Send() failed: %v", err)
|
||||
break
|
||||
}
|
||||
err = stream.Send(&pb.HelloResponse{Message: "Hello again, " + req.Name})
|
||||
if err != nil {
|
||||
log.Printf("stream.Send() failed: %v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
)
|
||||
|
||||
var logObserver = observable.Observer[pb.LogMessage]{}
|
||||
|
||||
func Log(level pb.LogLevel, typ pb.LogType, message string) {
|
||||
logObserver.Emit(pb.LogMessage{
|
||||
Level: level,
|
||||
Type: typ,
|
||||
Message: message,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (s *server) LogListener(stream pb.Hiddify_LogListenerServer) error {
|
||||
logSub, _, _ := logObserver.Subscribe()
|
||||
defer logObserver.UnSubscribe(logSub)
|
||||
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-logSub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
package v2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing/common/observable"
|
||||
)
|
||||
|
||||
var logObserver = observable.Observer[pb.LogMessage]{}
|
||||
|
||||
func Log(level pb.LogLevel, typ pb.LogType, message string) {
|
||||
logObserver.Emit(pb.LogMessage{
|
||||
Level: level,
|
||||
Type: typ,
|
||||
Message: message,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (s *server) LogListener(stream pb.Hiddify_LogListenerServer) error {
|
||||
logSub, _, _ := logObserver.Subscribe()
|
||||
defer logObserver.UnSubscribe(logSub)
|
||||
|
||||
stopch := make(chan int)
|
||||
go func() {
|
||||
stream.Recv()
|
||||
close(stopch)
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
break
|
||||
case <-stopch:
|
||||
break
|
||||
case info := <-logSub:
|
||||
stream.Send(&info)
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
130
v2/warp.go
130
v2/warp.go
@@ -1,65 +1,65 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hiddify/libcore/config"
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing-box/experimental/libbox"
|
||||
)
|
||||
|
||||
func (s *server) GenerateWarpConfig(ctx context.Context, in *pb.GenerateWarpConfigRequest) (*pb.WarpGenerationResponse, error) {
|
||||
account, log, wg, err := config.GenerateWarpInfo(in.LicenseKey, in.AccountId, in.AccessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.WarpGenerationResponse{
|
||||
Account: &pb.WarpAccount{
|
||||
AccountId: account.AccountID,
|
||||
AccessToken: account.AccessToken,
|
||||
},
|
||||
Config: &pb.WarpWireguardConfig{
|
||||
PrivateKey: wg.PrivateKey,
|
||||
LocalAddressIpv4: wg.LocalAddressIPv4,
|
||||
LocalAddressIpv6: wg.LocalAddressIPv6,
|
||||
PeerPublicKey: wg.PeerPublicKey,
|
||||
},
|
||||
Log: log,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Implement the GetSystemProxyStatus method
|
||||
func (s *server) GetSystemProxyStatus(ctx context.Context, empty *pb.Empty) (*pb.SystemProxyStatus, error) {
|
||||
status, err := libbox.NewStandaloneCommandClient().GetSystemProxyStatus()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.SystemProxyStatus{
|
||||
Available: status.Available,
|
||||
Enabled: status.Enabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Implement the SetSystemProxyEnabled method
|
||||
func (s *server) SetSystemProxyEnabled(ctx context.Context, in *pb.SetSystemProxyEnabledRequest) (*pb.Response, error) {
|
||||
err := libbox.NewStandaloneCommandClient().SetSystemProxyEnabled(in.IsEnabled)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Message: "",
|
||||
}, nil
|
||||
|
||||
}
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hiddify/libcore/config"
|
||||
pb "github.com/hiddify/libcore/hiddifyrpc"
|
||||
"github.com/sagernet/sing-box/experimental/libbox"
|
||||
)
|
||||
|
||||
func (s *server) GenerateWarpConfig(ctx context.Context, in *pb.GenerateWarpConfigRequest) (*pb.WarpGenerationResponse, error) {
|
||||
account, log, wg, err := config.GenerateWarpInfo(in.LicenseKey, in.AccountId, in.AccessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.WarpGenerationResponse{
|
||||
Account: &pb.WarpAccount{
|
||||
AccountId: account.AccountID,
|
||||
AccessToken: account.AccessToken,
|
||||
},
|
||||
Config: &pb.WarpWireguardConfig{
|
||||
PrivateKey: wg.PrivateKey,
|
||||
LocalAddressIpv4: wg.LocalAddressIPv4,
|
||||
LocalAddressIpv6: wg.LocalAddressIPv6,
|
||||
PeerPublicKey: wg.PeerPublicKey,
|
||||
},
|
||||
Log: log,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Implement the GetSystemProxyStatus method
|
||||
func (s *server) GetSystemProxyStatus(ctx context.Context, empty *pb.Empty) (*pb.SystemProxyStatus, error) {
|
||||
status, err := libbox.NewStandaloneCommandClient().GetSystemProxyStatus()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.SystemProxyStatus{
|
||||
Available: status.Available,
|
||||
Enabled: status.Enabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Implement the SetSystemProxyEnabled method
|
||||
func (s *server) SetSystemProxyEnabled(ctx context.Context, in *pb.SetSystemProxyEnabledRequest) (*pb.Response, error) {
|
||||
err := libbox.NewStandaloneCommandClient().SetSystemProxyEnabled(in.IsEnabled)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_FAILED,
|
||||
Message: err.Error(),
|
||||
}, err
|
||||
}
|
||||
|
||||
return &pb.Response{
|
||||
ResponseCode: pb.ResponseCode_OK,
|
||||
Message: "",
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user