ipc: the capability methods share one dispatch shape (V-575)

Thirteen arms of dispatch spelled out the same handler: nil check, unmarshal,
call, marshal, and a hand-written unknown-method error at the bottom of each.
callDirect, callDirectNoParams and callDirectVoid hold the three shapes those
arms come in, so the switch now says which Server field backs which method and
nothing else.

The nil check is the load-bearing part and it is unchanged: a nil field is the
capability being unconfigured on this box, and the wire still answers
ErrUnknownMethod. WrapKeyFn and UnlockFn keep their own arms because they take
apart the request rather than passing it through. No wire change.
This commit is contained in:
2026-08-06 01:31:03 +04:00
parent 43dc487113
commit 7262310fce
+82 -149
View File
@@ -583,180 +583,113 @@ func (s *Server) dispatch(ctx context.Context, req Request) (json.RawMessage, er
return marshalResult(PingResp{Alive: true, Locked: locked}), nil
case MethodAssertStepUp:
if s.StepUp != nil {
return marshalResult(nil), s.StepUp(ctx)
if s.StepUp == nil {
return nil, unknownMethod(req.Method)
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return marshalResult(nil), s.StepUp(ctx)
case MethodStoreEncryptionKey:
if s.WrapKeyFn != nil {
var p storeEncryptionKeyReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.WrapKeyFn(ctx, p.Secret, p.Explicit)
if s.WrapKeyFn == nil {
return nil, unknownMethod(req.Method)
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
var p storeEncryptionKeyReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.WrapKeyFn(ctx, p.Secret, p.Explicit)
case MethodUnlock:
if s.UnlockFn != nil {
var p unlockReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.UnlockFn(ctx, p.Secret)
if s.UnlockFn == nil {
return nil, unknownMethod(req.Method)
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
var p unlockReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
return marshalResult(nil), s.UnlockFn(ctx, p.Secret)
case MethodIngestMail:
if s.IngestMailFn != nil {
var p IngestMailReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.IngestMailFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.IngestMailFn)
case MethodSwapModel:
if s.SwapModelFn != nil {
var p SwapModelReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.SwapModelFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.SwapModelFn)
case MethodDescribeImage:
if s.DescribeImageFn != nil {
var p DescribeImageReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.DescribeImageFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.DescribeImageFn)
case MethodCaptureStart:
if s.CaptureStartFn != nil {
var p CaptureStartReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.CaptureStartFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.CaptureStartFn)
case MethodCaptureAppend:
if s.CaptureAppendFn != nil {
var p CaptureAppendReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.CaptureAppendFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.CaptureAppendFn)
case MethodCaptureStop:
if s.CaptureStopFn != nil {
var p CaptureStopReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.CaptureStopFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
case MethodCaptureStatus:
if s.CaptureStatusFn != nil {
resp, err := s.CaptureStatusFn(ctx)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.CaptureStopFn)
case MethodEnrollSpeaker:
if s.EnrollSpeakerFn != nil {
var p EnrollSpeakerReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
resp, err := s.EnrollSpeakerFn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirect(ctx, req, s.EnrollSpeakerFn)
case MethodCaptureStatus:
return callDirectNoParams(ctx, req, s.CaptureStatusFn)
case MethodListSpeakers:
if s.ListSpeakersFn != nil {
resp, err := s.ListSpeakersFn(ctx)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
case MethodForgetSpeaker:
if s.ForgetSpeakerFn != nil {
var p ForgetSpeakerReq
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
if err := s.ForgetSpeakerFn(ctx, p); err != nil {
return nil, err
}
return marshalResult(nil), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirectNoParams(ctx, req, s.ListSpeakersFn)
case MethodModelStatus:
if s.ModelStatusFn != nil {
resp, err := s.ModelStatusFn(ctx)
if err != nil {
return nil, err
}
return marshalResult(resp), nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return callDirectNoParams(ctx, req, s.ModelStatusFn)
case MethodForgetSpeaker:
return callDirectVoid(ctx, req, s.ForgetSpeakerFn)
}
h, ok := methodTable[req.Method]
if !ok {
return nil, fmt.Errorf("%w: %s", ErrUnknownMethod, req.Method)
return nil, unknownMethod(req.Method)
}
return h(ctx, api, req.Params)
}
// callDirect runs a daemon-supplied handler that bypasses CoreAPI: unmarshal
// the params, call it, marshal the reply. A nil handler is the capability being
// unconfigured on this box, and the wire says so as an unknown method.
func callDirect[P any, R any](ctx context.Context, req Request, fn func(context.Context, P) (R, error)) (json.RawMessage, error) {
if fn == nil {
return nil, unknownMethod(req.Method)
}
var p P
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
r, err := fn(ctx, p)
if err != nil {
return nil, err
}
return marshalResult(r), nil
}
// callDirectNoParams is callDirect for a handler that reads no params. Like
// withoutParams it never touches req.Params.
func callDirectNoParams[R any](ctx context.Context, req Request, fn func(context.Context) (R, error)) (json.RawMessage, error) {
if fn == nil {
return nil, unknownMethod(req.Method)
}
r, err := fn(ctx)
if err != nil {
return nil, err
}
return marshalResult(r), nil
}
// callDirectVoid is callDirect for a handler with nothing to report back. The
// wire reply is always null.
func callDirectVoid[P any](ctx context.Context, req Request, fn func(context.Context, P) error) (json.RawMessage, error) {
if fn == nil {
return nil, unknownMethod(req.Method)
}
var p P
if err := unmarshalParams(req.Params, &p); err != nil {
return nil, err
}
if err := fn(ctx, p); err != nil {
return nil, err
}
return marshalResult(nil), nil
}
func unknownMethod(m Method) error {
return fmt.Errorf("%w: %s", ErrUnknownMethod, m)
}
func unmarshalParams(raw json.RawMessage, v any) error {
if len(raw) == 0 {
raw = []byte("null")