// 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 }