rpc

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: Apache-2.0 Imports: 28 Imported by: 0

Documentation

Overview

Package rpc serves the grant protocol (api/grant/v1) over gRPC on top of a core.Core, and optionally exposes a thin JSON gateway. It owns the mapping from core.StatusCode to gRPC codes and Miss details; the core stays transport-agnostic.

Index

Constants

View Source
const DefaultRetryAfter = time.Second

DefaultRetryAfter is what SHED tells the caller to wait.

View Source
const MaxChunk = 1 << 20

MaxChunk is the most data one Upload or Download message carries, well under gRPC's 4 MiB message limit.

Variables

This section is empty.

Functions

func AdmissionInterceptor

func AdmissionInterceptor() grpc.UnaryServerInterceptor

AdmissionInterceptor enforces admission completeness on the wire: a request carrying any field the schema does not define is rejected with InvalidArgument. Protobuf keeps unknown fields on decode instead of dropping them, so "the request struct has no field to bind it to" is a checkable property, not a silent one.

func AdmissionStreamInterceptor

func AdmissionStreamInterceptor() grpc.StreamServerInterceptor

AdmissionStreamInterceptor is AdmissionInterceptor for streaming calls. It checks every message the client sends, not only the first, so a later Upload chunk cannot carry an undefined field either.

func CallerFrom

func CallerFrom(ctx context.Context) (tlsconf.Caller, bool)

CallerFrom is the verified caller of the request. ok is false on a plaintext listener, where there is no caller identity.

func CallerInterceptor

func CallerInterceptor() grpc.UnaryServerInterceptor

CallerInterceptor puts the TLS peer's identity on every unary call's context. A peer whose certificate cannot name it is Unauthenticated.

func CallerStreamInterceptor

func CallerStreamInterceptor() grpc.StreamServerInterceptor

CallerStreamInterceptor is CallerInterceptor for streaming calls.

func ConnContext

func ConnContext(ctx context.Context, _ net.Conn) context.Context

ConnContext is the http.Server.ConnContext hook of a server that serves a Gateway. With it the gateway names a connection's peer once. A handler served without it names the peer on every request.

func FenceFromProto

func FenceFromProto(f *grantv1.Fence) core.Fence

FenceFromProto is the inverse of the fence mapping, for clients.

func HealthFunc

func HealthFunc(epoch func() uint64, health *core.SourceHealth, tier core.Tier, audit func() error) func() map[string]any

HealthFunc builds the standard /healthz body. It holds the epoch, the advertised tier, whether the issuer is reachable and the audit spool's state. An idle issuer is not down, only a stale one is. audit is "ok" or "poisoned". The fsync error is logged when it happens and never put in the body, which the gateway serves without authentication, since it names the spool's path. A nil health or audit omits its key.

func IsMiss

func IsMiss(err error) bool

IsMiss reports whether err is one of the two miss outcomes.

func IsNoWorkspace

func IsNoWorkspace(err error) bool

IsNoWorkspace reports whether err is the refusal of a file call on a fiber whose grant has no workspace.

func MissFromError

func MissFromError(err error) (*grantv1.Miss, bool)

MissFromError extracts the Miss detail from a gRPC error, for clients and the conformance suite.

func NewGRPCServer

func NewGRPCServer(s *Server, opts ...grpc.ServerOption) *grpc.Server

NewGRPCServer builds a grpc.Server with the caller and admission interceptors and the Fibers service registered. Pass grpc.Creds(rpc.ServerCreds(cfg)) for mutual TLS, so each connection's caller is named once at its handshake.

func RejectUnknown

func RejectUnknown(m protoreflect.Message) error

RejectUnknown walks the message and every nested message and fails on the first unknown field found.

func ServerCreds

func ServerCreds(cfg *tls.Config) credentials.TransportCredentials

ServerCreds are the TLS credentials of a server that names its callers. A connection's peer is named once, at its handshake, and the caller interceptors read that name on every call. The auth info of such a connection embeds credentials.TLSInfo and is not that type, so code that asserts credentials.TLSInfo does not match it.

func StatusToProto

func StatusToProto(st core.Status) *grantv1.Status

StatusToProto converts a ledger status to the wire message.

func WithCaller

func WithCaller(ctx context.Context, c tlsconf.Caller) context.Context

WithCaller records the verified caller on ctx.

func WithDraining

func WithDraining(health func() map[string]any, draining func() bool) func() map[string]any

WithDraining adds "draining": true to what health returns while draining reports true, for a readiness check. WriteHealth answers that body with 503, so a readiness probe takes the home out of its endpoints while it parks its sessions before it stops. A liveness check keeps health unwrapped, since a 503 there means restart fiberd.

func WriteHealth

func WriteHealth(w http.ResponseWriter, body map[string]any)

WriteHealth writes a /healthz body. The status is 503 when the audit spool is poisoned, because every Sync operation fails until fiberd restarts. A probe that sees it restarts the home or drains it. A readiness body from WithDraining is 503 too while fiberd drains before it stops. An unreachable issuer stays 200, since fiberd fences it and recovers on its own.

func WrongHomeFromError

func WrongHomeFromError(err error) (*grantv1.WrongHome, bool)

WrongHomeFromError extracts the WrongHome detail from a gRPC error, for clients and the conformance suite. Its home is the node id of the home that refused the grant.

Types

type Gateway

type Gateway struct {
	Server *Server
	// Health is served at GET /healthz for readiness polling, with the
	// status WriteHealth picks.
	Health func() map[string]any
}

Gateway is the thin JSON-over-HTTP face of the same service, mounted only when fiberd is started with -http. Requests are protobuf JSON (protojson) of the same messages; unknown fields are rejected exactly as on gRPC. Errors are the google.rpc.Status JSON with the Miss detail embedded, and the HTTP code follows the gRPC code.

func (*Gateway) Handler

func (g *Gateway) Handler() http.Handler

type Server

type Server struct {
	grantv1.UnimplementedFibersServer

	Core *core.Core
	// Issuer is reported in every Miss so a DEFERRED caller knows which
	// control plane to fall back through.
	Issuer     string
	RetryAfter time.Duration
}

Server implements grantv1.FibersServer.

func (*Server) Clone

func (*Server) Discard

func (s *Server) Discard(ctx context.Context, req *grantv1.DiscardRequest) (*emptypb.Empty, error)

Discard deletes a parked session by name. Like Clone it carries the grant, so the caller is checked against the grant's binding from the TLS peer, not through owns. Another tenant's session is not filed under this grant's tenant, so it answers NotFound.

func (*Server) Download

Download reads one regular file from a fiber's workspace. The first chunk carries the file's info, and every chunk at most MaxChunk bytes.

func (*Server) ListFiles

ListFiles lists one directory of a fiber's workspace. An empty dir is the workspace itself.

func (*Server) Park

func (s *Server) Park(ctx context.Context, req *grantv1.ParkRequest) (*emptypb.Empty, error)

Park and Release answer NotFound, never PermissionDenied, for another caller's fiber, so a fiber ID reveals nothing about who holds it.

func (*Server) Release

func (s *Server) Release(ctx context.Context, req *grantv1.ReleaseRequest) (*emptypb.Empty, error)

func (*Server) ToError

func (s *Server) ToError(code core.StatusCode, err error) error

Miss policy: every miss carries a grantv1.Miss detail. Never a bare code.

core.Shed             -> ResourceExhausted + Miss{SHED, retry_after_s}
core.DeferredFallback -> Unavailable       + Miss{DEFERRED_FALLBACK, issuer}
core.NeedsTier        -> FailedPrecondition
core.Invalid          -> InvalidArgument (ErrAnonymousPark, ErrSessionRunning)
core.Unauthenticated  -> Unauthenticated
                         + WrongHome{home} when the cause is core.ErrWrongAudience and the home has a node id
core.NotFound         -> NotFound (ErrFiberUnknown, ErrSessionUnknown)
core.NoWorkspace      -> FailedPrecondition + NoWorkspace
core.OverBudget       -> ResourceExhausted, no Miss
core.Internal         -> Internal

func (*Server) Upload

func (s *Server) Upload(stream grantv1.Fibers_UploadServer) error

Upload writes one file into a fiber's workspace. The first message is the header, which declares the size, so an oversize file is refused before any data is read. Every later message is a chunk of at most MaxChunk bytes, and the chunks add up to the declared size. The file appears only once every byte and the optional sha256 checked out.

func (*Server) Watch

func (s *Server) Watch(_ *emptypb.Empty, stream grantv1.Fibers_WatchServer) error

Watch streams one Status per admitted grant of the caller on every change and at least every status interval, until the client goes away.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL