1
0
世界 2 жил өмнө
parent
commit
55c34e3fb0

+ 2 - 0
experimental/libbox/command.go

@@ -11,4 +11,6 @@ const (
 	CommandGroupExpand
 	CommandClashMode
 	CommandSetClashMode
+	CommandGetSystemProxyStatus
+	CommandSetSystemProxyEnabled
 )

+ 17 - 1
experimental/libbox/command_client.go

@@ -5,6 +5,7 @@ import (
 	"net"
 	"os"
 	"path/filepath"
+	"time"
 
 	"github.com/sagernet/sing/common"
 	E "github.com/sagernet/sing/common/exceptions"
@@ -53,9 +54,24 @@ func (c *CommandClient) directConnect() (net.Conn, error) {
 	}
 }
 
+func (c *CommandClient) directConnectWithRetry() (net.Conn, error) {
+	var (
+		conn net.Conn
+		err  error
+	)
+	for i := 0; i < 10; i++ {
+		conn, err = c.directConnect()
+		if err == nil {
+			return conn, nil
+		}
+		time.Sleep(time.Duration(100+i*50) * time.Millisecond)
+	}
+	return nil, err
+}
+
 func (c *CommandClient) Connect() error {
 	common.Close(c.conn)
-	conn, err := c.directConnect()
+	conn, err := c.directConnectWithRetry()
 	if err != nil {
 		return err
 	}

+ 6 - 0
experimental/libbox/command_server.go

@@ -35,6 +35,8 @@ type CommandServer struct {
 
 type CommandServerHandler interface {
 	ServiceReload() error
+	GetSystemProxyStatus() *SystemProxyStatus
+	SetSystemProxyEnabled(isEnabled bool) error
 }
 
 func NewCommandServer(handler CommandServerHandler, maxLines int32) *CommandServer {
@@ -159,6 +161,10 @@ func (s *CommandServer) handleConnection(conn net.Conn) error {
 		return s.handleModeConn(conn)
 	case CommandSetClashMode:
 		return s.handleSetClashMode(conn)
+	case CommandGetSystemProxyStatus:
+		return s.handleGetSystemProxyStatus(conn)
+	case CommandSetSystemProxyEnabled:
+		return s.handleSetSystemProxyEnabled(conn)
 	default:
 		return E.New("unknown command: ", command)
 	}

+ 82 - 0
experimental/libbox/command_system_proxy.go

@@ -0,0 +1,82 @@
+package libbox
+
+import (
+	"encoding/binary"
+	"net"
+)
+
+type SystemProxyStatus struct {
+	Available bool
+	Enabled   bool
+}
+
+func (c *CommandClient) GetSystemProxyStatus() (*SystemProxyStatus, error) {
+	conn, err := c.directConnectWithRetry()
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+	err = binary.Write(conn, binary.BigEndian, uint8(CommandGetSystemProxyStatus))
+	if err != nil {
+		return nil, err
+	}
+	var status SystemProxyStatus
+	err = binary.Read(conn, binary.BigEndian, &status.Available)
+	if err != nil {
+		return nil, err
+	}
+	if status.Available {
+		err = binary.Read(conn, binary.BigEndian, &status.Enabled)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return &status, nil
+}
+
+func (s *CommandServer) handleGetSystemProxyStatus(conn net.Conn) error {
+	defer conn.Close()
+	status := s.handler.GetSystemProxyStatus()
+	err := binary.Write(conn, binary.BigEndian, status.Available)
+	if err != nil {
+		return err
+	}
+	if status.Available {
+		err = binary.Write(conn, binary.BigEndian, status.Enabled)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (c *CommandClient) SetSystemProxyEnabled(isEnabled bool) error {
+	conn, err := c.directConnect()
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+	err = binary.Write(conn, binary.BigEndian, uint8(CommandSetSystemProxyEnabled))
+	if err != nil {
+		return err
+	}
+	err = binary.Write(conn, binary.BigEndian, isEnabled)
+	if err != nil {
+		return err
+	}
+	return readError(conn)
+}
+
+func (s *CommandServer) handleSetSystemProxyEnabled(conn net.Conn) error {
+	defer conn.Close()
+	var isEnabled bool
+	err := binary.Read(conn, binary.BigEndian, &isEnabled)
+	if err != nil {
+		return err
+	}
+	err = s.handler.SetSystemProxyEnabled(isEnabled)
+	if err != nil {
+		return writeError(conn, err)
+	}
+	return writeError(conn, nil)
+}