Documentation
¶
Overview ¶
Package diag implements the agent-side debug surface that runs over the existing QUIC control channel to tunnelproxy.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ArgSpec ¶
type ArgSpec struct {
Type ArgType `json:"type"`
Required bool `json:"required,omitempty"`
Default any `json:"default,omitempty"`
Max any `json:"max,omitempty"`
Min any `json:"min,omitempty"`
Desc string `json:"description,omitempty"`
}
ArgSpec describes one argument of a Command. It is serialized into the manifest returned by the built-in `agent` command so an operator can discover the surface with a single GET.
type Command ¶
type Command interface {
// Spec returns the manifest entry for this command. It is called
// once at registration; the result must be safe to share.
Spec() Spec
// Run executes the command. args is the raw `args` field from the
// Request; implementations decode it as needed. ctx carries the
// dispatcher-imposed wall-clock ceiling and is cancelled when the
// stream goes away.
Run(ctx context.Context, args json.RawMessage, e Emitter) (result any, err error)
}
Command is the contract every probe implements. Non-streaming commands return a JSON-serializable Result and ignore the Emitter. Streaming commands return Result == nil and emit chunks via e until Run returns.
type Dispatcher ¶
type Dispatcher struct {
// MaxConcurrent caps in-flight commands. Excess Requests get
// ErrBusy. Default 1 — diag is interactive, not throughput-bound.
MaxConcurrent int
// DefaultCeiling is applied to commands whose Spec.CeilingMs is 0.
DefaultCeiling time.Duration
// contains filtered or unexported fields
}
Dispatcher reads Request frames from a downstream reader, runs each against its Registry, and writes Response frames to an upstream writer. One Dispatcher per agent ↔ tunnelproxy stream.
The dispatcher does not own the transport — the tunnel package opens the HTTP/3 stream and hands the read/write halves in. This keeps pkg/diag free of any QUIC dependency for testability.
func (*Dispatcher) Run ¶
Run drives the dispatch loop until ctx is cancelled or down returns EOF/error. It is safe to call once per stream; concurrent calls on the same Dispatcher share the registry but otherwise do not interact.
Frames on `down` MUST be Request; frames on `up` are written as Response. Both halves use newline-delimited JSON.
type Emitter ¶
Emitter is what a streaming Command writes its chunks to. It is supplied by the dispatcher; Commands MUST NOT retain a reference past their Run call.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds the set of registered commands. It is built once at startup and treated as immutable thereafter.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is the server-side handle for one connected agent's diag stream. It is built by the /diag/rpc handler and consumed by code that wants to drive commands against the agent.
Lifecycle: a Session is alive between Register and the moment the underlying agent stream closes (request body EOF or write failure). After Close, all in-flight Invoke calls receive a final Response frame with Error.Code = ErrInternal.
func (*Session) Close ¶
func (s *Session) Close()
Close terminates the session. Safe to call concurrently and repeatedly.
func (*Session) CloseErr ¶
CloseErr returns the terminal error after Done fires (io.EOF on clean close). Calling before Done is closed returns nil.
func (*Session) Done ¶
func (s *Session) Done() <-chan struct{}
Done returns a channel closed when the session terminates. Read CloseErr afterward to distinguish clean EOF from transport error.
func (*Session) Invoke ¶
func (s *Session) Invoke(ctx context.Context, command string, args json.RawMessage) (<-chan protocol.Response, error)
Invoke sends one Request to the agent and returns a channel that receives every Response frame for that id. The channel is closed after the terminal frame (Result, Error, or Done) or when the session terminates.
args may be nil. ctx cancellation removes the pending entry but does not interrupt the agent — the dispatcher honors its own per-command ceiling.
type Sessions ¶
type Sessions struct {
// contains filtered or unexported fields
}
Sessions is a process-scoped registry of agent diag sessions keyed by agent identifier (typically the TunnelNode UID).
func (*Sessions) Register ¶
Register inserts s into the registry under agentID. If an existing session is registered under the same id, it is closed and replaced.
func (*Sessions) Unregister ¶
Unregister removes the session for agentID iff it equals s. The equality check prevents a stale Unregister call (from a closing old session) from dropping a freshly registered one.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package commands holds the built-in diag commands.
|
Package commands holds the built-in diag commands. |
|
Package protocol defines the wire format for the agent diag channel: nd-json frames over one long-lived HTTP/3 stream, demuxed by Id so multiple commands can interleave.
|
Package protocol defines the wire format for the agent diag channel: nd-json frames over one long-lived HTTP/3 stream, demuxed by Id so multiple commands can interleave. |