Skip to content

Commit 4bfafe9

Browse files
mapleafgoclaude
andcommitted
refactor(core): 从 libbox 迁移到 box.New() 直接 API
移除 libbox CommandServer/Client gRPC 架构,Service 直接持有 *box.Box 实例。PlatformIO 直接实现 adapter.PlatformInterface, 桌面/mobile 通过 isMobile 字段分支。移除事件回调系统,改为 Query 轮询模式。删除 handler.go、callback.go 及旧设计文档。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 445c11f commit 4bfafe9

21 files changed

Lines changed: 836 additions & 3356 deletions

README.md

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,38 +85,23 @@ Desktop (c-shared) and Mobile (gomobile) FFI interfaces for integration with any
8585
### Capabilities
8686

8787
- **Service lifecycle** — init, start, stop, destroy with hot-reload support
88-
- **Config management** — validate, reload, TUN restart, VPN split-tunneling
88+
- **Config management** — validate, reload TUN, VPN split-tunneling
8989
- **Proxy control** — node selection, URL test delay, routing mode switch
90-
- **Real-time events** — traffic, logs, connections, proxy groups, mode changes via callback
91-
- **Connection tracking** — full lifecycle with per-connection metadata
90+
- **Query API** — proxies, traffic, logs, connections, memory stats via JSON
9291
- **Platform IO** — TUN fd, socket protector, WiFi state (mobile)
9392
- **Resource monitoring** — memory stats, goroutines, OOM protection
9493

95-
### Build
96-
97-
```bash
98-
# Desktop shared library
99-
task ffi-darwin-arm64
100-
task ffi-linux-amd64
101-
task ffi-windows-amd64
102-
103-
# Mobile SDK
104-
task mobile-android-arm64 # Android AAR
105-
task mobile-ios-arm64 # iOS xcframework
106-
```
107-
10894
### Quick Start (Desktop)
10995

11096
```c
11197
#include "cff_core.h"
11298

113-
CoreSetCallback(my_callback);
11499
CoreInit("{\"home_dir\":\"/tmp/singcast\"}");
115100
CoreStartWithContent(yaml_content, "");
116101

117102
// Query state
118-
char* traffic = CoreQueryTraffic(); // JSON with up/down/memory/started_at
119-
CoreFreeString(traffic);
103+
char* proxies = CoreQueryProxies();
104+
CoreFreeString(proxies);
120105

121106
CoreStop();
122107
CoreDestroy();
@@ -127,7 +112,7 @@ CoreDestroy();
127112
**Android (Kotlin):**
128113
```kotlin
129114
val singcast = Singcast()
130-
singcast.init("""{"home_dir":"$homeDir"}""")
115+
singcast.init("""{"home_dir":"$homeDir"}""}")
131116
132117
val fd = vpnService.Builder()
133118
.addAddress("172.18.0.1", 30)

README_zh.md

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ task ffi-ios-arm64
7676
task all
7777
```
7878

79-
构建标签:`with_clash_api,with_utls,with_quic,with_gvisor,with_v2ray_api`
79+
构建标签:`with_clash_api,with_utls,with_quic,with_gisor,with_v2ray_api`
8080

8181
## FFI 接口
8282

@@ -85,38 +85,23 @@ task all
8585
### 核心能力
8686

8787
- **服务生命周期** — 初始化、启动、停止、销毁,支持热重载
88-
- **配置管理** — 校验、重载、TUN 重启、VPN 分流
88+
- **配置管理** — 校验、TUN 重载、VPN 分流
8989
- **代理控制** — 节点选择、URL 延迟测试、路由模式切换
90-
- **实时事件** — 流量、日志、连接、代理组、模式变更回调
91-
- **连接追踪** — 全生命周期连接元数据
90+
- **查询 API** — 代理组、流量、日志、连接、内存统计,返回 JSON
9291
- **平台 IO** — TUN fd、Socket 保护、WiFi 状态(移动端)
9392
- **资源监控** — 内存统计、协程数、OOM 保护
9493

95-
### 构建
96-
97-
```bash
98-
# 桌面端动态库
99-
task ffi-darwin-arm64
100-
task ffi-linux-amd64
101-
task ffi-windows-amd64
102-
103-
# 移动端 SDK
104-
task mobile-android-arm64 # Android AAR
105-
task mobile-ios-arm64 # iOS xcframework
106-
```
107-
10894
### 快速上手(桌面端)
10995

11096
```c
11197
#include "cff_core.h"
11298

113-
CoreSetCallback(my_callback);
11499
CoreInit("{\"home_dir\":\"/tmp/singcast\"}");
115100
CoreStartWithContent(yaml_content, "");
116101

117102
// 查询状态
118-
char* traffic = CoreQueryTraffic(); // 包含 up/down/memory/started_at 的 JSON
119-
CoreFreeString(traffic);
103+
char* proxies = CoreQueryProxies();
104+
CoreFreeString(proxies);
120105

121106
CoreStop();
122107
CoreDestroy();
@@ -127,7 +112,7 @@ CoreDestroy();
127112
**Android(Kotlin):**
128113
```kotlin
129114
val singcast = Singcast()
130-
singcast.init("""{"home_dir":"$homeDir"}""")
115+
singcast.init("""{"home_dir":"$homeDir"}""}")
131116
132117
val fd = vpnService.Builder()
133118
.addAddress("172.18.0.1", 30)

cmd/lib/callback.go

Lines changed: 0 additions & 47 deletions
This file was deleted.

cmd/lib/exports.go

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import "C"
77

88
import (
99
"encoding/json"
10-
"unsafe"
1110

1211
"github.com/mapleafgo/singcast/ffi"
1312
)
@@ -60,16 +59,7 @@ func CoreSetOverridePackages(overrideJSON *C.char) *C.char {
6059
//export CoreSetLogLevel
6160
func CoreSetLogLevel(level C.int) { api.SetLogLevel(int32(level)) }
6261

63-
//export CoreSetError
64-
func CoreSetError(message *C.char) { api.SetError(goString(message)) }
65-
66-
// --- Pause / Wake / Network ---
67-
68-
//export CorePause
69-
func CorePause() { api.Pause() }
70-
71-
//export CoreWake
72-
func CoreWake() { api.Wake() }
62+
// --- Network ---
7363

7464
//export CoreResetNetwork
7565
func CoreResetNetwork() { api.ResetNetwork() }
@@ -107,9 +97,7 @@ func CoreQueryProxies() *C.char { return cString(api.QueryProxies()) }
10797
func CoreQueryTraffic() *C.char { return cString(api.QueryTraffic()) }
10898

10999
//export CoreQueryLogs
110-
func CoreQueryLogs(clear C.int) *C.char {
111-
return cString(api.QueryLogs(clear != 0))
112-
}
100+
func CoreQueryLogs() *C.char { return cString(api.QueryLogs()) }
113101

114102
//export CoreQueryConnections
115103
func CoreQueryConnections() *C.char { return cString(api.QueryConnections()) }
@@ -126,23 +114,7 @@ func CoreCloseAllConnections() *C.char {
126114
return resultJSON(api.CloseAllConnections())
127115
}
128116

129-
// --- Platform Queries ---
130-
131-
//export CoreNeedFindProcess
132-
func CoreNeedFindProcess() C.int {
133-
if api.NeedFindProcess() {
134-
return 1
135-
}
136-
return 0
137-
}
138-
139-
//export CoreWriteMessage
140-
func CoreWriteMessage(level C.int, message *C.char) {
141-
api.WriteMessage(int32(level), goString(message))
142-
}
143-
144-
//export CoreQueryTunOptions
145-
func CoreQueryTunOptions() *C.char { return cString(api.QueryTunOptions()) }
117+
// --- System ---
146118

147119
//export CoreFlushSystemDNS
148120
func CoreFlushSystemDNS() { api.FlushSystemDNS() }
@@ -162,16 +134,3 @@ func CoreSetMemoryLimit(bytes C.longlong) *C.char {
162134

163135
//export CoreGetVersion
164136
func CoreGetVersion() *C.char { return cString(api.Version()) }
165-
166-
// --- Events ---
167-
168-
//export CoreSetCallback
169-
func CoreSetCallback(cb unsafe.Pointer) { setCallback(cb) }
170-
171-
// --- Locale ---
172-
173-
//export CoreSetLocale
174-
func CoreSetLocale(localeID *C.char) { ffi.SetLocale(goString(localeID)) }
175-
176-
// --- System Proxy ---
177-
// System proxy management is handled by the GUI, not the core.

cmd/singcast/run.go

Lines changed: 2 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,6 @@ import (
1515
"github.com/mapleafgo/singcast/translator"
1616
)
1717

18-
func parseLogLevel(s string) int32 {
19-
switch s {
20-
case "panic":
21-
return 0
22-
case "fatal":
23-
return 1
24-
case "error":
25-
return 2
26-
case "warn", "warning":
27-
return 3
28-
case "info":
29-
return 4
30-
case "debug":
31-
return 5
32-
case "trace":
33-
return 6
34-
default:
35-
return 4
36-
}
37-
}
38-
3918
func runCommand() *cli.Command {
4019
return &cli.Command{
4120
Name: "run",
@@ -115,52 +94,21 @@ func runCommand() *cli.Command {
11594
}
11695
}
11796

118-
maxLevel := parseConfigLogLevel(jsonContent)
119-
12097
if daemon {
12198
return startDaemon(homeDir, outPath, proxyPrefix, apiAddr)
12299
}
123-
return runForeground(homeDir, outPath, maxLevel, jsonContent)
100+
return runForeground(homeDir, outPath, jsonContent)
124101
},
125102
}
126103
}
127104

128-
// parseConfigLogLevel parses the log.level field from sing-box JSON config string.
129-
func parseConfigLogLevel(jsonContent string) int32 {
130-
var cfg struct {
131-
Log struct {
132-
Level string `json:"level"`
133-
} `json:"log"`
134-
}
135-
if json.Unmarshal([]byte(jsonContent), &cfg) != nil {
136-
return 4
137-
}
138-
return parseLogLevel(cfg.Log.Level)
139-
}
140-
141-
func runForeground(homeDir, configPath string, maxLevel int32, jsonContent string) error {
105+
func runForeground(homeDir, configPath string, jsonContent string) error {
142106
svc := core.NewService()
143107
if err := svc.Init(`{"home_dir":"` + homeDir + `"}`); err != nil {
144108
return fmt.Errorf("init core: %w", err)
145109
}
146110
defer svc.Destroy()
147111

148-
svc.SetOnEvent(func(eventType int32, jsonPayload string) {
149-
if eventType != core.EventLogs {
150-
return
151-
}
152-
var entries []core.LogEntry
153-
if json.Unmarshal([]byte(jsonPayload), &entries) != nil {
154-
return
155-
}
156-
for _, e := range entries {
157-
if e.Level > maxLevel {
158-
continue
159-
}
160-
fmt.Println(e.Message)
161-
}
162-
})
163-
164112
data, err := os.ReadFile(configPath)
165113
if err != nil {
166114
return fmt.Errorf("read config: %w", err)

0 commit comments

Comments
 (0)