Files
ddhv/server/handlers.go
T
shishi 2f79b22936 feat: 系统调优 Go 版后端完整源码
- 19 个接口全部实测验收通过 (2026-08-08)
- 结构: main.go + core/consts + gsysctl + gtuner + server
- 含 build_go.sh 官方部署结构构建脚本 (amd64/arm64 交叉编译)
- 数据无缝衔接 Python 版遗留 (快照/state/审计日志)
- 备份自 156:/root/goddhv (2026-08-09)
2026-08-09 10:12:57 +08:00

258 lines
6.0 KiB
Go

// Package server 提供 GMSSH JSON-RPC 接口层(19 个接口)。
// 对应 Python 版 backend/app/server.py。
package server
import (
"encoding/json"
"strconv"
"github.com/DemonZack/simplejrpc-go/net/gsock"
"github.com/user_TGPJp0KLpNsa5TAo/ddhv/gsysctl"
"github.com/user_TGPJp0KLpNsa5TAo/ddhv/gtuner"
)
// Handler 聚合所有接口 handler
type Handler struct {
Sysctl *gsysctl.Manager
Tuner gtuner.TunerService
}
// NewHandler 构造 handler
func NewHandler() *Handler {
return &Handler{Sysctl: gsysctl.NewManager(), Tuner: gtuner.NewTuner()}
}
// params 提取请求参数为 map
func params(req *gsock.Request) map[string]any {
if req.RawRequest() == nil || req.RawRequest().Params == nil {
return map[string]any{}
}
raw, _ := json.Marshal(req.RawRequest().Params)
var m map[string]any
_ = json.Unmarshal(raw, &m)
return m
}
// str 取字符串参数
func str(p map[string]any, key string) string {
if v, ok := p[key]; ok {
switch t := v.(type) {
case string:
return t
case float64:
return strconv.FormatFloat(t, 'f', -1, 64)
default:
return ""
}
}
return ""
}
// boolP 取布尔参数
func boolP(p map[string]any, key string) bool {
if v, ok := p[key]; ok {
if b, ok := v.(bool); ok {
return b
}
if f, ok := v.(float64); ok {
return f != 0
}
if s, ok := v.(string); ok {
return s == "true" || s == "1"
}
}
return false
}
// trueP 取布尔参数(默认 true)
func trueP(p map[string]any, key string) bool {
if v, ok := p[key]; ok {
if b, ok := v.(bool); ok {
return b
}
if f, ok := v.(float64); ok {
return f != 0
}
if s, ok := v.(string); ok {
return s == "true" || s == "1"
}
return true
}
return true
}
// intP 取整数参数
func intP(p map[string]any, key string) int {
if v, ok := p[key]; ok {
if f, ok := v.(float64); ok {
return int(f)
}
if s, ok := v.(string); ok {
if i, err := strconv.Atoi(s); err == nil {
return i
}
}
}
return -1
}
// ========== 基础 ==========
// Hello 测试接口
func (h *Handler) Hello(req *gsock.Request) (any, error) {
return map[string]any{"message": "hello"}, nil
}
// Ping 健康检查(平台要求返回 pong)
func (h *Handler) Ping(req *gsock.Request) (any, error) {
return "pong", nil
}
// ========== 系统调优接口 ==========
func (h *Handler) TunerCheckRoot(req *gsock.Request) (any, error) {
return h.Tuner.CheckRoot()
}
func (h *Handler) TunerDetect(req *gsock.Request) (any, error) {
return h.Tuner.Detect()
}
func (h *Handler) TunerCurrentPreset(req *gsock.Request) (any, error) {
return h.Tuner.GetCurrentPreset()
}
func (h *Handler) TunerSnapshots(req *gsock.Request) (any, error) {
snaps := h.Sysctl.ListSnapshots()
list := make([]map[string]any, 0, len(snaps))
for _, s := range snaps {
list = append(list, map[string]any{
"name": s.Name, "created_at": s.CreatedAt, "reason": s.Reason,
"kind": s.Kind, "param_count": s.ParamCount,
})
}
return list, nil
}
func (h *Handler) TunerInitStatus(req *gsock.Request) (any, error) {
return h.Tuner.InitStatus()
}
func (h *Handler) TunerInit(req *gsock.Request) (any, error) {
return h.Tuner.InitSnapshot()
}
func (h *Handler) TunerCreateSnapshot(req *gsock.Request) (any, error) {
p := params(req)
reason := str(p, "reason")
if reason == "" {
reason = "手动备份"
}
return h.Sysctl.CreateSnapshot(reason, "manual")
}
func (h *Handler) TunerRestoreSnapshot(req *gsock.Request) (any, error) {
p := params(req)
name := str(p, "snapshot_name")
if name == "" {
return nil, errParam("缺少 snapshot_name 参数")
}
return h.Sysctl.RestoreSnapshot(name)
}
func (h *Handler) TunerPresets(req *gsock.Request) (any, error) {
return h.Tuner.GetPresets(), nil
}
func (h *Handler) TunerApplyPreset(req *gsock.Request) (any, error) {
p := params(req)
key := str(p, "preset_key")
if key == "" {
return nil, errParam("缺少 preset_key 参数")
}
return h.Tuner.ApplyPreset(key)
}
func (h *Handler) TunerSetSwappiness(req *gsock.Request) (any, error) {
p := params(req)
value := intP(p, "value")
if value < 0 {
return nil, errParam("缺少 value 参数")
}
persist := trueP(p, "persist")
return h.Tuner.SetSwappiness(value, persist)
}
func (h *Handler) TunerEnableBBR(req *gsock.Request) (any, error) {
return h.Tuner.EnableBBR()
}
func (h *Handler) TunerDisableBBR(req *gsock.Request) (any, error) {
return h.Tuner.DisableBBR()
}
func (h *Handler) TunerGetParam(req *gsock.Request) (any, error) {
p := params(req)
key := str(p, "key")
if key == "" {
return nil, errParam("缺少 key 参数")
}
value, err := gsysctl.GetValue(key)
if err != nil {
value = ""
}
return map[string]any{"key": key, "value": value}, nil
}
func (h *Handler) TunerSetParam(req *gsock.Request) (any, error) {
p := params(req)
key := str(p, "key")
value := str(p, "value")
if key == "" || value == "" {
return nil, errParam("缺少 key/value 参数")
}
unlocked := boolP(p, "unlocked")
// 危险参数必须解锁
if _, danger := h.Tuner.GetDangerousParams()[key]; danger && !unlocked {
return map[string]any{"need_unlock": true}, errNeedUnlock()
}
if err := gsysctl.SetValue(key, value, true); err != nil {
return nil, err
}
current, _ := gsysctl.GetValue(key)
h.Sysctl.LogAction("set_param", map[string]any{"key": key, "value": value, "unlocked": unlocked})
return map[string]any{"key": key, "value": value, "ok": true, "current": current}, nil
}
func (h *Handler) TunerDangerousParams(req *gsock.Request) (any, error) {
return h.Tuner.GetDangerousParams(), nil
}
func (h *Handler) TunerAuditLogs(req *gsock.Request) (any, error) {
p := params(req)
limit := intP(p, "limit")
if limit <= 0 || limit > 500 {
limit = 100
}
return h.Sysctl.AuditLogs(limit), nil
}
// ========== 辅助错误 ==========
// errParam 参数错误
func errParam(msg string) error {
return &handleError{code: 400, msg: msg}
}
// errNeedUnlock 需要解锁危险参数
func errNeedUnlock() error {
return &handleError{code: 403, msg: "危险参数需要先解锁才能修改"}
}
type handleError struct {
code int
msg string
}
func (e *handleError) Error() string { return e.msg }