microsandbox_protocol/core.rs
1//! Core protocol message payloads.
2
3use serde::{Deserialize, Serialize};
4
5//--------------------------------------------------------------------------------------------------
6// Types
7//--------------------------------------------------------------------------------------------------
8
9/// Payload for `core.ready` messages.
10///
11/// Sent by the guest agent to signal that it has finished initialization
12/// and is ready to receive commands. Includes timing data for boot
13/// performance measurement.
14#[derive(Debug, Clone, Default, Serialize, Deserialize)]
15pub struct Ready {
16 /// `CLOCK_BOOTTIME` nanoseconds captured at the start of `main()`.
17 ///
18 /// Represents how long the kernel took to boot before userspace started.
19 pub boot_time_ns: u64,
20
21 /// Nanoseconds spent in `init::init()` (mounting filesystems).
22 pub init_time_ns: u64,
23
24 /// `CLOCK_BOOTTIME` nanoseconds captured just before sending this message.
25 ///
26 /// Represents total time from kernel boot to agent readiness.
27 pub ready_time_ns: u64,
28
29 /// The agent's package version (`CARGO_PKG_VERSION`), for diagnostics.
30 ///
31 /// Additive and optional: an older agent that predates this field decodes to
32 /// an empty string, and an older host ignores it. Empty means unknown. This
33 /// is the runtime's self-reported product version; the protocol generation is
34 /// carried separately in the message envelope's `v`.
35 #[serde(default, skip_serializing_if = "String::is_empty")]
36 pub agent_version: String,
37}
38
39/// Payload for `core.clock.sync` messages.
40///
41/// Sent by the host to ask the guest agent to step `CLOCK_REALTIME` to the
42/// host's current wall-clock time.
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct ClockSync {
45 /// Host Unix timestamp in nanoseconds.
46 pub unix_time_nanos: u64,
47}
48
49/// Payload for `core.error` messages.
50///
51/// Sent when a peer can identify a recoverable protocol error for a specific
52/// correlation ID. Unrecoverable frame-level errors, such as stream
53/// desynchronization or impossible frame lengths, should close the transport
54/// instead.
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct CoreError {
57 /// Machine-readable error kind.
58 pub kind: CoreErrorKind,
59
60 /// Human-readable diagnostic message.
61 pub message: String,
62
63 /// Wire message type involved in the error, when it could be determined.
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub offending_type: Option<String>,
66}
67
68/// Machine-readable `core.error` categories.
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
70#[serde(rename_all = "snake_case")]
71pub enum CoreErrorKind {
72 /// The protocol message envelope could not be decoded.
73 MalformedMessage,
74
75 /// The message type is unknown to the peer.
76 UnsupportedMessageType,
77
78 /// The message requires a newer protocol generation than the peer supports.
79 UnsupportedProtocolGeneration,
80
81 /// The frame flags do not match the message type.
82 InvalidFlags,
83
84 /// The message payload could not be decoded or failed validation.
85 InvalidPayload,
86
87 /// The message refers to an unknown, closed, or incompatible session.
88 InvalidSession,
89}
90
91/// Payload for `core.init.resolved` messages.
92///
93/// Sent by agentd after the guest rootfs is ready to resolve init-time facts,
94/// but before user volume mounts are attached. The host uses this to install
95/// early runtime state that depends on guest-resolved values.
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct InitResolved {
98 /// Default guest user for sandbox commands.
99 pub default_user: ResolvedUser,
100}
101
102/// A guest user and group resolved by agentd.
103#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
104pub struct ResolvedUser {
105 /// Effective default guest user id for sandbox commands.
106 pub uid: u32,
107
108 /// Effective default guest group id for sandbox commands.
109 pub gid: u32,
110}
111
112/// Payload for `core.init.ack` messages.
113///
114/// Sent by the host after it has consumed the init context and completed any
115/// dependent setup.
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct InitAck {}
118
119/// Payload for `core.relay.client.disconnected` messages.
120///
121/// Sent by the host relay when one SDK client socket disconnects. The
122/// guest agent uses the assigned correlation ID range to clean up resources
123/// owned by that client, such as open filesystem handles.
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct RelayClientDisconnected {
126 /// First correlation ID assigned to the disconnected client.
127 pub id_start: u32,
128
129 /// Exclusive upper bound of the disconnected client's ID range.
130 pub id_end_exclusive: u32,
131}