Documentation
¶
Overview ¶
Package holdwire is the protocol between the daemon and a session holder: framing here, message shapes in msg.go. It is deliberately tiny and version 1 is meant to stay the only version for a long time — a holder keeps running the binary that spawned it across daemon updates, so every verb added here is a compatibility promise to every holder already alive.
Index ¶
Constants ¶
const ( TJSON byte = 1 TChunk byte = 2 )
Frame types. Control connections carry only TJSON; an attach connection carries one TJSON header and then TChunk frames of raw session output.
const MaxFrame = 8 << 20
MaxFrame bounds a single frame's payload. The largest legitimate frame is a spawn request carrying a revived ring (2 MiB by default) inside JSON base64, so 8 MiB clears every real message while keeping a corrupt or hostile length prefix from turning into an allocation.
const Proto = 1
Proto is the protocol version a holder reports in its hello. A daemon that meets a version it does not know must surface the holder as unreachable, never guess at it.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Event ¶
type Event struct {
Event string `json:"event"` // exit | title | active
Code int `json:"code,omitempty"`
At time.Time `json:"at,omitempty"`
Title string `json:"title,omitempty"`
}
Event is pushed by the holder on a control connection, unprompted and without an ID. exit arrives once; title on every change; active at most once per second while output flows, so a list's LastActive ordering stays honest without a round trip per chunk.
type Hello ¶
type Hello struct {
Proto int `json:"proto"`
Version string `json:"version"` // flue version the holder runs
Pid int `json:"pid"` // the child's pid, 0 before spawn
// Info is a session.Info, raw for the same reason as SpawnReq.Restore.
Info json.RawMessage `json:"info,omitempty"`
BaseSeq uint64 `json:"baseSeq"`
EndSeq uint64 `json:"endSeq"`
}
Hello is the holder's self-description: enough for a daemon that has just started to rebuild its registry entry from the socket alone.
type Req ¶
type Req struct {
ID uint64 `json:"id"`
Verb string `json:"verb"` // hello | spawn | write | resize | signal | tail | close | attach
Spawn *SpawnReq `json:"spawn,omitempty"`
// Data carries write payloads. encoding/json base64s []byte, which is
// what keeps arbitrary terminal input inside a JSON frame.
Data []byte `json:"data,omitempty"`
Cols uint16 `json:"cols,omitempty"`
Rows uint16 `json:"rows,omitempty"`
// Sig is the raw signal number. Daemon and holder are always the same
// machine and build architecture, so the number is unambiguous.
Sig int `json:"sig,omitempty"`
N int `json:"n,omitempty"`
// FromSeq is attach's resume point, Sub semantics exactly.
FromSeq uint64 `json:"fromSeq,omitempty"`
}
Req is one request on a control connection, or the attach header on an attach connection. Requests are serialized per connection and every one is answered; ID ties the reply back when a caller pipelines.
type Resp ¶
type Resp struct {
ID uint64 `json:"id"`
Err string `json:"err,omitempty"`
Hello *Hello `json:"hello,omitempty"`
// Data, Cols, Rows answer tail.
Data []byte `json:"data,omitempty"`
Cols uint16 `json:"cols,omitempty"`
Rows uint16 `json:"rows,omitempty"`
// StartSeq and Truncated head an attach stream, mirroring session.Sub.
StartSeq uint64 `json:"startSeq,omitempty"`
Truncated bool `json:"truncated,omitempty"`
}
Resp answers one Req. Err is the whole error contract: empty is success, anything else is a message for the daemon's log and the caller's error.
type SpawnReq ¶
type SpawnReq struct {
ID string `json:"id"`
Run []string `json:"run"`
Argv []string `json:"argv"`
Env []string `json:"env"`
Cwd string `json:"cwd"`
Cols uint16 `json:"cols"`
Rows uint16 `json:"rows"`
RingSize int `json:"ringSize,omitempty"`
Preload []byte `json:"preload,omitempty"`
// Restore is a session.Info, carried raw: this package sits below the
// session package (which imports it from the daemon side), so it cannot
// name the type without a cycle. Both ends marshal the same struct.
Restore json.RawMessage `json:"restore,omitempty"`
Group string `json:"group,omitempty"`
Ephemeral bool `json:"ephemeral,omitempty"`
}
SpawnReq is a fully resolved spawn: the daemon has already decided the login shell, environment and working directory, and the holder execs exactly what it is told. Run is what execs; Argv is what Info reports — the same split registry.start keeps, for the same reason.