1use crate::generated_protocol::v1 as generated_protocol;
2use serde::de::{self, SeqAccess, Visitor};
3use serde::ser::SerializeTuple;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_json::Value;
6use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
7use std::error::Error;
8use std::fmt;
9
10pub use crate::wire::{OwnershipRequirement, ProtocolCodecError, RequestDirection};
11
12pub const PROTOCOL_NAME: &str = crate::wire::PROTOCOL_NAME;
13pub const PROTOCOL_VERSION: u16 = crate::wire::PROTOCOL_VERSION;
14pub const DEFAULT_MAX_FRAME_BYTES: usize = crate::wire::DEFAULT_MAX_FRAME_BYTES;
15pub const DEFAULT_COMPLETED_RESPONSE_CAP: usize = 10_000;
16pub type RequestId = crate::wire::RequestId;
17pub type ExtEnvelope = crate::wire::ExtEnvelope;
18
19fn serialize_bare_newtype_tag<S, T>(serializer: S, tag: u64, payload: &T) -> Result<S::Ok, S::Error>
20where
21 S: Serializer,
22 T: Serialize,
23{
24 let mut tuple = serializer.serialize_tuple(2)?;
25 tuple.serialize_element(&serde_bare::Uint(tag))?;
26 tuple.serialize_element(payload)?;
27 tuple.end()
28}
29
30pub fn to_generated_protocol_frame(
32 frame: &ProtocolFrame,
33) -> Result<generated_protocol::ProtocolFrame, ProtocolCodecError> {
34 Ok(match frame {
35 ProtocolFrame::Request(frame) => {
36 generated_protocol::ProtocolFrame::RequestFrame(generated_protocol::RequestFrame {
37 schema: to_generated_protocol_schema(&frame.schema),
38 request_id: frame.request_id,
39 ownership: to_generated_ownership_scope(&frame.ownership),
40 payload: to_generated_request_payload(&frame.payload)?,
41 })
42 }
43 ProtocolFrame::Response(frame) => {
44 generated_protocol::ProtocolFrame::ResponseFrame(generated_protocol::ResponseFrame {
45 schema: to_generated_protocol_schema(&frame.schema),
46 request_id: frame.request_id,
47 ownership: to_generated_ownership_scope(&frame.ownership),
48 payload: to_generated_response_payload(&frame.payload)?,
49 })
50 }
51 ProtocolFrame::Event(frame) => {
52 generated_protocol::ProtocolFrame::EventFrame(generated_protocol::EventFrame {
53 schema: to_generated_protocol_schema(&frame.schema),
54 ownership: to_generated_ownership_scope(&frame.ownership),
55 payload: to_generated_event_payload(&frame.payload),
56 })
57 }
58 ProtocolFrame::SidecarRequest(frame) => {
59 generated_protocol::ProtocolFrame::SidecarRequestFrame(
60 generated_protocol::SidecarRequestFrame {
61 schema: to_generated_protocol_schema(&frame.schema),
62 request_id: frame.request_id,
63 ownership: to_generated_ownership_scope(&frame.ownership),
64 payload: to_generated_sidecar_request_payload(&frame.payload)?,
65 },
66 )
67 }
68 ProtocolFrame::SidecarResponse(frame) => {
69 generated_protocol::ProtocolFrame::SidecarResponseFrame(
70 generated_protocol::SidecarResponseFrame {
71 schema: to_generated_protocol_schema(&frame.schema),
72 request_id: frame.request_id,
73 ownership: to_generated_ownership_scope(&frame.ownership),
74 payload: to_generated_sidecar_response_payload(&frame.payload)?,
75 },
76 )
77 }
78 })
79}
80
81pub fn from_generated_protocol_frame(
83 frame: generated_protocol::ProtocolFrame,
84) -> Result<ProtocolFrame, ProtocolCodecError> {
85 Ok(match frame {
86 generated_protocol::ProtocolFrame::RequestFrame(frame) => {
87 ProtocolFrame::Request(RequestFrame {
88 schema: from_generated_protocol_schema(frame.schema),
89 request_id: frame.request_id,
90 ownership: from_generated_ownership_scope(frame.ownership),
91 payload: from_generated_request_payload(frame.payload)?,
92 })
93 }
94 generated_protocol::ProtocolFrame::ResponseFrame(frame) => {
95 ProtocolFrame::Response(ResponseFrame {
96 schema: from_generated_protocol_schema(frame.schema),
97 request_id: frame.request_id,
98 ownership: from_generated_ownership_scope(frame.ownership),
99 payload: from_generated_response_payload(frame.payload)?,
100 })
101 }
102 generated_protocol::ProtocolFrame::EventFrame(frame) => ProtocolFrame::Event(EventFrame {
103 schema: from_generated_protocol_schema(frame.schema),
104 ownership: from_generated_ownership_scope(frame.ownership),
105 payload: from_generated_event_payload(frame.payload),
106 }),
107 generated_protocol::ProtocolFrame::SidecarRequestFrame(frame) => {
108 ProtocolFrame::SidecarRequest(SidecarRequestFrame {
109 schema: from_generated_protocol_schema(frame.schema),
110 request_id: frame.request_id,
111 ownership: from_generated_ownership_scope(frame.ownership),
112 payload: from_generated_sidecar_request_payload(frame.payload)?,
113 })
114 }
115 generated_protocol::ProtocolFrame::SidecarResponseFrame(frame) => {
116 ProtocolFrame::SidecarResponse(SidecarResponseFrame {
117 schema: from_generated_protocol_schema(frame.schema),
118 request_id: frame.request_id,
119 ownership: from_generated_ownership_scope(frame.ownership),
120 payload: from_generated_sidecar_response_payload(frame.payload)?,
121 })
122 }
123 })
124}
125
126fn to_generated_protocol_schema(schema: &ProtocolSchema) -> generated_protocol::ProtocolSchema {
127 schema.clone()
128}
129
130fn from_generated_protocol_schema(schema: generated_protocol::ProtocolSchema) -> ProtocolSchema {
131 schema
132}
133
134pub(crate) fn to_generated_ownership_scope(
139 ownership: &OwnershipScope,
140) -> generated_protocol::OwnershipScope {
141 ownership.clone()
142}
143
144pub(crate) fn from_generated_ownership_scope(
145 ownership: generated_protocol::OwnershipScope,
146) -> OwnershipScope {
147 ownership
148}
149
150fn to_generated_dispose_reason(reason: &DisposeReason) -> generated_protocol::DisposeReason {
151 match reason {
152 DisposeReason::Requested => generated_protocol::DisposeReason::Requested,
153 DisposeReason::ConnectionClosed => generated_protocol::DisposeReason::ConnectionClosed,
154 DisposeReason::HostShutdown => generated_protocol::DisposeReason::HostShutdown,
155 }
156}
157
158fn from_generated_dispose_reason(reason: generated_protocol::DisposeReason) -> DisposeReason {
159 match reason {
160 generated_protocol::DisposeReason::Requested => DisposeReason::Requested,
161 generated_protocol::DisposeReason::ConnectionClosed => DisposeReason::ConnectionClosed,
162 generated_protocol::DisposeReason::HostShutdown => DisposeReason::HostShutdown,
163 }
164}
165
166fn to_generated_filesystem_operation(
167 operation: &FilesystemOperation,
168) -> generated_protocol::FilesystemOperation {
169 match operation {
170 FilesystemOperation::Read => generated_protocol::FilesystemOperation::Read,
171 FilesystemOperation::Write => generated_protocol::FilesystemOperation::Write,
172 FilesystemOperation::Stat => generated_protocol::FilesystemOperation::Stat,
173 FilesystemOperation::ReadDir => generated_protocol::FilesystemOperation::ReadDir,
174 FilesystemOperation::Mkdir => generated_protocol::FilesystemOperation::Mkdir,
175 FilesystemOperation::Remove => generated_protocol::FilesystemOperation::Remove,
176 FilesystemOperation::Rename => generated_protocol::FilesystemOperation::Rename,
177 }
178}
179
180fn from_generated_filesystem_operation(
181 operation: generated_protocol::FilesystemOperation,
182) -> FilesystemOperation {
183 match operation {
184 generated_protocol::FilesystemOperation::Read => FilesystemOperation::Read,
185 generated_protocol::FilesystemOperation::Write => FilesystemOperation::Write,
186 generated_protocol::FilesystemOperation::Stat => FilesystemOperation::Stat,
187 generated_protocol::FilesystemOperation::ReadDir => FilesystemOperation::ReadDir,
188 generated_protocol::FilesystemOperation::Mkdir => FilesystemOperation::Mkdir,
189 generated_protocol::FilesystemOperation::Remove => FilesystemOperation::Remove,
190 generated_protocol::FilesystemOperation::Rename => FilesystemOperation::Rename,
191 }
192}
193
194fn to_generated_guest_filesystem_operation(
195 operation: &GuestFilesystemOperation,
196) -> generated_protocol::GuestFilesystemOperation {
197 match operation {
198 GuestFilesystemOperation::ReadFile => {
199 generated_protocol::GuestFilesystemOperation::ReadFile
200 }
201 GuestFilesystemOperation::WriteFile => {
202 generated_protocol::GuestFilesystemOperation::WriteFile
203 }
204 GuestFilesystemOperation::CreateDir => {
205 generated_protocol::GuestFilesystemOperation::CreateDir
206 }
207 GuestFilesystemOperation::Mkdir => generated_protocol::GuestFilesystemOperation::Mkdir,
208 GuestFilesystemOperation::Exists => generated_protocol::GuestFilesystemOperation::Exists,
209 GuestFilesystemOperation::Stat => generated_protocol::GuestFilesystemOperation::Stat,
210 GuestFilesystemOperation::Lstat => generated_protocol::GuestFilesystemOperation::Lstat,
211 GuestFilesystemOperation::ReadDir => generated_protocol::GuestFilesystemOperation::ReadDir,
212 GuestFilesystemOperation::RemoveFile => {
213 generated_protocol::GuestFilesystemOperation::RemoveFile
214 }
215 GuestFilesystemOperation::RemoveDir => {
216 generated_protocol::GuestFilesystemOperation::RemoveDir
217 }
218 GuestFilesystemOperation::Rename => generated_protocol::GuestFilesystemOperation::Rename,
219 GuestFilesystemOperation::Realpath => {
220 generated_protocol::GuestFilesystemOperation::Realpath
221 }
222 GuestFilesystemOperation::Symlink => generated_protocol::GuestFilesystemOperation::Symlink,
223 GuestFilesystemOperation::ReadLink => {
224 generated_protocol::GuestFilesystemOperation::ReadLink
225 }
226 GuestFilesystemOperation::Link => generated_protocol::GuestFilesystemOperation::Link,
227 GuestFilesystemOperation::Chmod => generated_protocol::GuestFilesystemOperation::Chmod,
228 GuestFilesystemOperation::Chown => generated_protocol::GuestFilesystemOperation::Chown,
229 GuestFilesystemOperation::Utimes => generated_protocol::GuestFilesystemOperation::Utimes,
230 GuestFilesystemOperation::Truncate => {
231 generated_protocol::GuestFilesystemOperation::Truncate
232 }
233 GuestFilesystemOperation::Pread => generated_protocol::GuestFilesystemOperation::Pread,
234 GuestFilesystemOperation::Pwrite => generated_protocol::GuestFilesystemOperation::Pwrite,
235 }
236}
237
238fn from_generated_guest_filesystem_operation(
239 operation: generated_protocol::GuestFilesystemOperation,
240) -> GuestFilesystemOperation {
241 match operation {
242 generated_protocol::GuestFilesystemOperation::ReadFile => {
243 GuestFilesystemOperation::ReadFile
244 }
245 generated_protocol::GuestFilesystemOperation::WriteFile => {
246 GuestFilesystemOperation::WriteFile
247 }
248 generated_protocol::GuestFilesystemOperation::CreateDir => {
249 GuestFilesystemOperation::CreateDir
250 }
251 generated_protocol::GuestFilesystemOperation::Mkdir => GuestFilesystemOperation::Mkdir,
252 generated_protocol::GuestFilesystemOperation::Exists => GuestFilesystemOperation::Exists,
253 generated_protocol::GuestFilesystemOperation::Stat => GuestFilesystemOperation::Stat,
254 generated_protocol::GuestFilesystemOperation::Lstat => GuestFilesystemOperation::Lstat,
255 generated_protocol::GuestFilesystemOperation::ReadDir => GuestFilesystemOperation::ReadDir,
256 generated_protocol::GuestFilesystemOperation::RemoveFile => {
257 GuestFilesystemOperation::RemoveFile
258 }
259 generated_protocol::GuestFilesystemOperation::RemoveDir => {
260 GuestFilesystemOperation::RemoveDir
261 }
262 generated_protocol::GuestFilesystemOperation::Rename => GuestFilesystemOperation::Rename,
263 generated_protocol::GuestFilesystemOperation::Realpath => {
264 GuestFilesystemOperation::Realpath
265 }
266 generated_protocol::GuestFilesystemOperation::Symlink => GuestFilesystemOperation::Symlink,
267 generated_protocol::GuestFilesystemOperation::ReadLink => {
268 GuestFilesystemOperation::ReadLink
269 }
270 generated_protocol::GuestFilesystemOperation::Link => GuestFilesystemOperation::Link,
271 generated_protocol::GuestFilesystemOperation::Chmod => GuestFilesystemOperation::Chmod,
272 generated_protocol::GuestFilesystemOperation::Chown => GuestFilesystemOperation::Chown,
273 generated_protocol::GuestFilesystemOperation::Utimes => GuestFilesystemOperation::Utimes,
274 generated_protocol::GuestFilesystemOperation::Truncate => {
275 GuestFilesystemOperation::Truncate
276 }
277 generated_protocol::GuestFilesystemOperation::Pread => GuestFilesystemOperation::Pread,
278 generated_protocol::GuestFilesystemOperation::Pwrite => GuestFilesystemOperation::Pwrite,
279 }
280}
281
282fn to_generated_permission_mode(mode: &PermissionMode) -> generated_protocol::PermissionMode {
283 mode.clone()
284}
285
286fn from_generated_permission_mode(mode: generated_protocol::PermissionMode) -> PermissionMode {
287 mode
288}
289
290fn to_generated_root_filesystem_entry_encoding(
291 encoding: &RootFilesystemEntryEncoding,
292) -> generated_protocol::RootFilesystemEntryEncoding {
293 match encoding {
294 RootFilesystemEntryEncoding::Utf8 => generated_protocol::RootFilesystemEntryEncoding::Utf8,
295 RootFilesystemEntryEncoding::Base64 => {
296 generated_protocol::RootFilesystemEntryEncoding::Base64
297 }
298 }
299}
300
301fn from_generated_root_filesystem_entry_encoding(
302 encoding: generated_protocol::RootFilesystemEntryEncoding,
303) -> RootFilesystemEntryEncoding {
304 match encoding {
305 generated_protocol::RootFilesystemEntryEncoding::Utf8 => RootFilesystemEntryEncoding::Utf8,
306 generated_protocol::RootFilesystemEntryEncoding::Base64 => {
307 RootFilesystemEntryEncoding::Base64
308 }
309 }
310}
311
312fn to_generated_stream_channel(channel: &StreamChannel) -> generated_protocol::StreamChannel {
313 match channel {
314 StreamChannel::Stdout => generated_protocol::StreamChannel::Stdout,
315 StreamChannel::Stderr => generated_protocol::StreamChannel::Stderr,
316 }
317}
318
319fn from_generated_stream_channel(channel: generated_protocol::StreamChannel) -> StreamChannel {
320 match channel {
321 generated_protocol::StreamChannel::Stdout => StreamChannel::Stdout,
322 generated_protocol::StreamChannel::Stderr => StreamChannel::Stderr,
323 }
324}
325
326fn to_generated_vm_lifecycle_state(
327 state: &VmLifecycleState,
328) -> generated_protocol::VmLifecycleState {
329 match state {
330 VmLifecycleState::Creating => generated_protocol::VmLifecycleState::Creating,
331 VmLifecycleState::Ready => generated_protocol::VmLifecycleState::Ready,
332 VmLifecycleState::Disposing => generated_protocol::VmLifecycleState::Disposing,
333 VmLifecycleState::Disposed => generated_protocol::VmLifecycleState::Disposed,
334 VmLifecycleState::Failed => generated_protocol::VmLifecycleState::Failed,
335 }
336}
337
338fn from_generated_vm_lifecycle_state(
339 state: generated_protocol::VmLifecycleState,
340) -> VmLifecycleState {
341 match state {
342 generated_protocol::VmLifecycleState::Creating => VmLifecycleState::Creating,
343 generated_protocol::VmLifecycleState::Ready => VmLifecycleState::Ready,
344 generated_protocol::VmLifecycleState::Disposing => VmLifecycleState::Disposing,
345 generated_protocol::VmLifecycleState::Disposed => VmLifecycleState::Disposed,
346 generated_protocol::VmLifecycleState::Failed => VmLifecycleState::Failed,
347 }
348}
349
350fn to_generated_guest_filesystem_stat(
351 stat: &GuestFilesystemStat,
352) -> generated_protocol::GuestFilesystemStat {
353 stat.clone()
354}
355
356fn from_generated_guest_filesystem_stat(
357 stat: generated_protocol::GuestFilesystemStat,
358) -> GuestFilesystemStat {
359 stat
360}
361
362fn to_generated_process_snapshot_entry(
363 entry: &ProcessSnapshotEntry,
364) -> generated_protocol::ProcessSnapshotEntry {
365 entry.clone()
366}
367
368fn from_generated_process_snapshot_entry(
369 entry: generated_protocol::ProcessSnapshotEntry,
370) -> ProcessSnapshotEntry {
371 entry
372}
373
374fn to_generated_ext_envelope(envelope: &ExtEnvelope) -> generated_protocol::ExtEnvelope {
375 envelope.clone()
376}
377
378fn from_generated_ext_envelope(envelope: generated_protocol::ExtEnvelope) -> ExtEnvelope {
379 envelope
380}
381
382fn to_generated_request_payload(
383 payload: &RequestPayload,
384) -> Result<generated_protocol::RequestPayload, ProtocolCodecError> {
385 Ok(match payload {
386 RequestPayload::Authenticate(inner) => {
387 generated_protocol::RequestPayload::AuthenticateRequest(inner.clone())
388 }
389 RequestPayload::OpenSession(inner) => {
390 generated_protocol::RequestPayload::OpenSessionRequest(inner.clone())
391 }
392 RequestPayload::CreateVm(inner) => {
393 generated_protocol::RequestPayload::CreateVmRequest(inner.clone())
394 }
395 RequestPayload::DisposeVm(inner) => generated_protocol::RequestPayload::DisposeVmRequest(
396 generated_protocol::DisposeVmRequest {
397 reason: to_generated_dispose_reason(&inner.reason),
398 },
399 ),
400 RequestPayload::BootstrapRootFilesystem(inner) => {
401 generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner.clone())
402 }
403 RequestPayload::ConfigureVm(inner) => {
404 generated_protocol::RequestPayload::ConfigureVmRequest(inner.clone())
405 }
406 RequestPayload::RegisterHostCallbacks(inner) => {
407 generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner.clone())
408 }
409 RequestPayload::CreateLayer(_) => generated_protocol::RequestPayload::CreateLayerRequest,
410 RequestPayload::SealLayer(inner) => {
411 generated_protocol::RequestPayload::SealLayerRequest(inner.clone())
412 }
413 RequestPayload::ImportSnapshot(inner) => {
414 generated_protocol::RequestPayload::ImportSnapshotRequest(inner.clone())
415 }
416 RequestPayload::ExportSnapshot(inner) => {
417 generated_protocol::RequestPayload::ExportSnapshotRequest(inner.clone())
418 }
419 RequestPayload::CreateOverlay(inner) => {
420 generated_protocol::RequestPayload::CreateOverlayRequest(inner.clone())
421 }
422 RequestPayload::GuestFilesystemCall(inner) => {
423 generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner.clone())
424 }
425 RequestPayload::SnapshotRootFilesystem(_) => {
426 generated_protocol::RequestPayload::SnapshotRootFilesystemRequest
427 }
428 RequestPayload::Execute(inner) => {
429 generated_protocol::RequestPayload::ExecuteRequest(inner.clone())
430 }
431 RequestPayload::WriteStdin(inner) => {
432 generated_protocol::RequestPayload::WriteStdinRequest(inner.clone())
433 }
434 RequestPayload::CloseStdin(inner) => {
435 generated_protocol::RequestPayload::CloseStdinRequest(inner.clone())
436 }
437 RequestPayload::KillProcess(inner) => {
438 generated_protocol::RequestPayload::KillProcessRequest(inner.clone())
439 }
440 RequestPayload::GetProcessSnapshot(_) => {
441 generated_protocol::RequestPayload::GetProcessSnapshotRequest
442 }
443 RequestPayload::GetResourceSnapshot(_) => {
444 generated_protocol::RequestPayload::GetResourceSnapshotRequest
445 }
446 RequestPayload::FindListener(inner) => {
447 generated_protocol::RequestPayload::FindListenerRequest(inner.clone())
448 }
449 RequestPayload::FindBoundUdp(inner) => {
450 generated_protocol::RequestPayload::FindBoundUdpRequest(inner.clone())
451 }
452 RequestPayload::VmFetch(inner) => {
453 generated_protocol::RequestPayload::VmFetchRequest(inner.clone())
454 }
455 RequestPayload::GetSignalState(inner) => {
456 generated_protocol::RequestPayload::GetSignalStateRequest(inner.clone())
457 }
458 RequestPayload::GetZombieTimerCount(_) => {
459 generated_protocol::RequestPayload::GetZombieTimerCountRequest
460 }
461 RequestPayload::HostFilesystemCall(inner) => {
462 generated_protocol::RequestPayload::HostFilesystemCallRequest(
463 generated_protocol::HostFilesystemCallRequest {
464 operation: to_generated_filesystem_operation(&inner.operation),
465 path: inner.path.clone(),
466 payload_size_bytes: inner.payload_size_bytes,
467 },
468 )
469 }
470 RequestPayload::PersistenceLoad(inner) => {
471 generated_protocol::RequestPayload::PersistenceLoadRequest(inner.clone())
472 }
473 RequestPayload::PersistenceFlush(inner) => {
474 generated_protocol::RequestPayload::PersistenceFlushRequest(inner.clone())
475 }
476 RequestPayload::Ext(inner) => {
477 generated_protocol::RequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
478 }
479 RequestPayload::GuestKernelCall(inner) => {
480 generated_protocol::RequestPayload::GuestKernelCallRequest(inner.clone())
481 }
482 RequestPayload::ResizePty(inner) => {
483 generated_protocol::RequestPayload::ResizePtyRequest(inner.clone())
484 }
485 RequestPayload::LinkPackage(inner) => {
486 generated_protocol::RequestPayload::LinkPackageRequest(inner.clone())
487 }
488 })
489}
490
491fn from_generated_request_payload(
492 payload: generated_protocol::RequestPayload,
493) -> Result<RequestPayload, ProtocolCodecError> {
494 Ok(match payload {
495 generated_protocol::RequestPayload::AuthenticateRequest(inner) => {
496 RequestPayload::Authenticate(inner)
497 }
498 generated_protocol::RequestPayload::OpenSessionRequest(inner) => {
499 RequestPayload::OpenSession(inner)
500 }
501 generated_protocol::RequestPayload::CreateVmRequest(inner) => {
502 RequestPayload::CreateVm(inner)
503 }
504 generated_protocol::RequestPayload::DisposeVmRequest(inner) => {
505 RequestPayload::DisposeVm(DisposeVmRequest {
506 reason: from_generated_dispose_reason(inner.reason),
507 })
508 }
509 generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner) => {
510 RequestPayload::BootstrapRootFilesystem(inner)
511 }
512 generated_protocol::RequestPayload::ConfigureVmRequest(inner) => {
513 RequestPayload::ConfigureVm(inner)
514 }
515 generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner) => {
516 RequestPayload::RegisterHostCallbacks(inner)
517 }
518 generated_protocol::RequestPayload::CreateLayerRequest => {
519 RequestPayload::CreateLayer(CreateLayerRequest {})
520 }
521 generated_protocol::RequestPayload::SealLayerRequest(inner) => {
522 RequestPayload::SealLayer(inner)
523 }
524 generated_protocol::RequestPayload::ImportSnapshotRequest(inner) => {
525 RequestPayload::ImportSnapshot(inner)
526 }
527 generated_protocol::RequestPayload::ExportSnapshotRequest(inner) => {
528 RequestPayload::ExportSnapshot(inner)
529 }
530 generated_protocol::RequestPayload::CreateOverlayRequest(inner) => {
531 RequestPayload::CreateOverlay(inner)
532 }
533 generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner) => {
534 RequestPayload::GuestFilesystemCall(inner)
535 }
536 generated_protocol::RequestPayload::SnapshotRootFilesystemRequest => {
537 RequestPayload::SnapshotRootFilesystem(SnapshotRootFilesystemRequest {})
538 }
539 generated_protocol::RequestPayload::ExecuteRequest(inner) => RequestPayload::Execute(inner),
540 generated_protocol::RequestPayload::WriteStdinRequest(inner) => {
541 RequestPayload::WriteStdin(inner)
542 }
543 generated_protocol::RequestPayload::CloseStdinRequest(inner) => {
544 RequestPayload::CloseStdin(inner)
545 }
546 generated_protocol::RequestPayload::KillProcessRequest(inner) => {
547 RequestPayload::KillProcess(inner)
548 }
549 generated_protocol::RequestPayload::GetProcessSnapshotRequest => {
550 RequestPayload::GetProcessSnapshot(GetProcessSnapshotRequest {})
551 }
552 generated_protocol::RequestPayload::GetResourceSnapshotRequest => {
553 RequestPayload::GetResourceSnapshot(GetResourceSnapshotRequest {})
554 }
555 generated_protocol::RequestPayload::FindListenerRequest(inner) => {
556 RequestPayload::FindListener(inner)
557 }
558 generated_protocol::RequestPayload::FindBoundUdpRequest(inner) => {
559 RequestPayload::FindBoundUdp(inner)
560 }
561 generated_protocol::RequestPayload::VmFetchRequest(inner) => RequestPayload::VmFetch(inner),
562 generated_protocol::RequestPayload::GetSignalStateRequest(inner) => {
563 RequestPayload::GetSignalState(inner)
564 }
565 generated_protocol::RequestPayload::GetZombieTimerCountRequest => {
566 RequestPayload::GetZombieTimerCount(GetZombieTimerCountRequest {})
567 }
568 generated_protocol::RequestPayload::HostFilesystemCallRequest(inner) => {
569 RequestPayload::HostFilesystemCall(HostFilesystemCallRequest {
570 operation: from_generated_filesystem_operation(inner.operation),
571 path: inner.path,
572 payload_size_bytes: inner.payload_size_bytes,
573 })
574 }
575 generated_protocol::RequestPayload::PersistenceLoadRequest(inner) => {
576 RequestPayload::PersistenceLoad(inner)
577 }
578 generated_protocol::RequestPayload::PersistenceFlushRequest(inner) => {
579 RequestPayload::PersistenceFlush(inner)
580 }
581 generated_protocol::RequestPayload::ExtEnvelope(inner) => {
582 RequestPayload::Ext(from_generated_ext_envelope(inner))
583 }
584 generated_protocol::RequestPayload::GuestKernelCallRequest(inner) => {
585 RequestPayload::GuestKernelCall(inner)
586 }
587 generated_protocol::RequestPayload::ResizePtyRequest(inner) => {
588 RequestPayload::ResizePty(inner)
589 }
590 generated_protocol::RequestPayload::LinkPackageRequest(inner) => {
591 RequestPayload::LinkPackage(inner)
592 }
593 })
594}
595
596fn to_generated_response_payload(
597 payload: &ResponsePayload,
598) -> Result<generated_protocol::ResponsePayload, ProtocolCodecError> {
599 Ok(match payload {
600 ResponsePayload::Authenticated(inner) => {
601 generated_protocol::ResponsePayload::AuthenticatedResponse(inner.clone())
602 }
603 ResponsePayload::SessionOpened(inner) => {
604 generated_protocol::ResponsePayload::SessionOpenedResponse(inner.clone())
605 }
606 ResponsePayload::VmCreated(inner) => {
607 generated_protocol::ResponsePayload::VmCreatedResponse(inner.clone())
608 }
609 ResponsePayload::VmDisposed(inner) => {
610 generated_protocol::ResponsePayload::VmDisposedResponse(inner.clone())
611 }
612 ResponsePayload::RootFilesystemBootstrapped(inner) => {
613 generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner.clone())
614 }
615 ResponsePayload::VmConfigured(inner) => {
616 generated_protocol::ResponsePayload::VmConfiguredResponse(inner.clone())
617 }
618 ResponsePayload::HostCallbacksRegistered(inner) => {
619 generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner.clone())
620 }
621 ResponsePayload::LayerCreated(inner) => {
622 generated_protocol::ResponsePayload::LayerCreatedResponse(inner.clone())
623 }
624 ResponsePayload::LayerSealed(inner) => {
625 generated_protocol::ResponsePayload::LayerSealedResponse(inner.clone())
626 }
627 ResponsePayload::SnapshotImported(inner) => {
628 generated_protocol::ResponsePayload::SnapshotImportedResponse(inner.clone())
629 }
630 ResponsePayload::SnapshotExported(inner) => {
631 generated_protocol::ResponsePayload::SnapshotExportedResponse(
632 generated_protocol::SnapshotExportedResponse {
633 layer_id: inner.layer_id.clone(),
634 entries: inner.entries.clone(),
635 },
636 )
637 }
638 ResponsePayload::OverlayCreated(inner) => {
639 generated_protocol::ResponsePayload::OverlayCreatedResponse(inner.clone())
640 }
641 ResponsePayload::GuestFilesystemResult(inner) => {
642 generated_protocol::ResponsePayload::GuestFilesystemResultResponse(
643 generated_protocol::GuestFilesystemResultResponse {
644 operation: to_generated_guest_filesystem_operation(&inner.operation),
645 path: inner.path.clone(),
646 content: inner.content.clone(),
647 encoding: inner
648 .encoding
649 .as_ref()
650 .map(to_generated_root_filesystem_entry_encoding),
651 entries: inner.entries.clone(),
652 stat: inner.stat.as_ref().map(to_generated_guest_filesystem_stat),
653 exists: inner.exists,
654 target: inner.target.clone(),
655 },
656 )
657 }
658 ResponsePayload::RootFilesystemSnapshot(inner) => {
659 generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(
660 generated_protocol::RootFilesystemSnapshotResponse {
661 entries: inner.entries.clone(),
662 },
663 )
664 }
665 ResponsePayload::ProcessStarted(inner) => {
666 generated_protocol::ResponsePayload::ProcessStartedResponse(inner.clone())
667 }
668 ResponsePayload::StdinWritten(inner) => {
669 generated_protocol::ResponsePayload::StdinWrittenResponse(inner.clone())
670 }
671 ResponsePayload::StdinClosed(inner) => {
672 generated_protocol::ResponsePayload::StdinClosedResponse(inner.clone())
673 }
674 ResponsePayload::ProcessKilled(inner) => {
675 generated_protocol::ResponsePayload::ProcessKilledResponse(inner.clone())
676 }
677 ResponsePayload::ProcessSnapshot(inner) => {
678 generated_protocol::ResponsePayload::ProcessSnapshotResponse(
679 generated_protocol::ProcessSnapshotResponse {
680 processes: inner
681 .processes
682 .iter()
683 .map(to_generated_process_snapshot_entry)
684 .collect(),
685 },
686 )
687 }
688 ResponsePayload::ResourceSnapshot(inner) => {
689 generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner.clone())
690 }
691 ResponsePayload::ListenerSnapshot(inner) => {
692 generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner.clone())
693 }
694 ResponsePayload::BoundUdpSnapshot(inner) => {
695 generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner.clone())
696 }
697 ResponsePayload::VmFetchResult(inner) => {
698 generated_protocol::ResponsePayload::VmFetchResponse(inner.clone())
699 }
700 ResponsePayload::SignalState(inner) => {
701 generated_protocol::ResponsePayload::SignalStateResponse(inner.clone())
702 }
703 ResponsePayload::ZombieTimerCount(inner) => {
704 generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner.clone())
705 }
706 ResponsePayload::FilesystemResult(inner) => {
707 generated_protocol::ResponsePayload::FilesystemResultResponse(
708 generated_protocol::FilesystemResultResponse {
709 operation: to_generated_filesystem_operation(&inner.operation),
710 status: inner.status.clone(),
711 payload_size_bytes: inner.payload_size_bytes,
712 },
713 )
714 }
715 ResponsePayload::PermissionDecision(inner) => {
716 generated_protocol::ResponsePayload::PermissionDecisionResponse(
717 generated_protocol::PermissionDecisionResponse {
718 capability: inner.capability.clone(),
719 decision: to_generated_permission_mode(&inner.decision),
720 },
721 )
722 }
723 ResponsePayload::PersistenceState(inner) => {
724 generated_protocol::ResponsePayload::PersistenceStateResponse(inner.clone())
725 }
726 ResponsePayload::PersistenceFlushed(inner) => {
727 generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner.clone())
728 }
729 ResponsePayload::Rejected(inner) => {
730 generated_protocol::ResponsePayload::RejectedResponse(inner.clone())
731 }
732 ResponsePayload::ExtResult(inner) => {
733 generated_protocol::ResponsePayload::ExtEnvelope(to_generated_ext_envelope(inner))
734 }
735 ResponsePayload::GuestKernelResult(inner) => {
736 generated_protocol::ResponsePayload::GuestKernelResultResponse(inner.clone())
737 }
738 ResponsePayload::PtyResized(inner) => {
739 generated_protocol::ResponsePayload::PtyResizedResponse(inner.clone())
740 }
741 ResponsePayload::PackageLinked(inner) => {
742 generated_protocol::ResponsePayload::PackageLinkedResponse(inner.clone())
743 }
744 })
745}
746
747fn from_generated_response_payload(
748 payload: generated_protocol::ResponsePayload,
749) -> Result<ResponsePayload, ProtocolCodecError> {
750 Ok(match payload {
751 generated_protocol::ResponsePayload::AuthenticatedResponse(inner) => {
752 ResponsePayload::Authenticated(inner)
753 }
754 generated_protocol::ResponsePayload::SessionOpenedResponse(inner) => {
755 ResponsePayload::SessionOpened(inner)
756 }
757 generated_protocol::ResponsePayload::VmCreatedResponse(inner) => {
758 ResponsePayload::VmCreated(inner)
759 }
760 generated_protocol::ResponsePayload::VmDisposedResponse(inner) => {
761 ResponsePayload::VmDisposed(inner)
762 }
763 generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner) => {
764 ResponsePayload::RootFilesystemBootstrapped(inner)
765 }
766 generated_protocol::ResponsePayload::VmConfiguredResponse(inner) => {
767 ResponsePayload::VmConfigured(inner)
768 }
769 generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner) => {
770 ResponsePayload::HostCallbacksRegistered(inner)
771 }
772 generated_protocol::ResponsePayload::LayerCreatedResponse(inner) => {
773 ResponsePayload::LayerCreated(inner)
774 }
775 generated_protocol::ResponsePayload::LayerSealedResponse(inner) => {
776 ResponsePayload::LayerSealed(inner)
777 }
778 generated_protocol::ResponsePayload::SnapshotImportedResponse(inner) => {
779 ResponsePayload::SnapshotImported(inner)
780 }
781 generated_protocol::ResponsePayload::SnapshotExportedResponse(inner) => {
782 ResponsePayload::SnapshotExported(SnapshotExportedResponse {
783 layer_id: inner.layer_id,
784 entries: inner.entries,
785 })
786 }
787 generated_protocol::ResponsePayload::OverlayCreatedResponse(inner) => {
788 ResponsePayload::OverlayCreated(inner)
789 }
790 generated_protocol::ResponsePayload::GuestFilesystemResultResponse(inner) => {
791 ResponsePayload::GuestFilesystemResult(GuestFilesystemResultResponse {
792 operation: from_generated_guest_filesystem_operation(inner.operation),
793 path: inner.path,
794 content: inner.content,
795 encoding: inner
796 .encoding
797 .map(from_generated_root_filesystem_entry_encoding),
798 entries: inner.entries,
799 stat: inner.stat.map(from_generated_guest_filesystem_stat),
800 exists: inner.exists,
801 target: inner.target,
802 })
803 }
804 generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(inner) => {
805 ResponsePayload::RootFilesystemSnapshot(RootFilesystemSnapshotResponse {
806 entries: inner.entries,
807 })
808 }
809 generated_protocol::ResponsePayload::ProcessStartedResponse(inner) => {
810 ResponsePayload::ProcessStarted(inner)
811 }
812 generated_protocol::ResponsePayload::StdinWrittenResponse(inner) => {
813 ResponsePayload::StdinWritten(inner)
814 }
815 generated_protocol::ResponsePayload::StdinClosedResponse(inner) => {
816 ResponsePayload::StdinClosed(inner)
817 }
818 generated_protocol::ResponsePayload::ProcessKilledResponse(inner) => {
819 ResponsePayload::ProcessKilled(inner)
820 }
821 generated_protocol::ResponsePayload::ProcessSnapshotResponse(inner) => {
822 ResponsePayload::ProcessSnapshot(ProcessSnapshotResponse {
823 processes: inner
824 .processes
825 .into_iter()
826 .map(from_generated_process_snapshot_entry)
827 .collect(),
828 })
829 }
830 generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner) => {
831 ResponsePayload::ResourceSnapshot(inner)
832 }
833 generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner) => {
834 ResponsePayload::ListenerSnapshot(inner)
835 }
836 generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner) => {
837 ResponsePayload::BoundUdpSnapshot(inner)
838 }
839 generated_protocol::ResponsePayload::VmFetchResponse(inner) => {
840 ResponsePayload::VmFetchResult(inner)
841 }
842 generated_protocol::ResponsePayload::SignalStateResponse(inner) => {
843 ResponsePayload::SignalState(inner)
844 }
845 generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner) => {
846 ResponsePayload::ZombieTimerCount(inner)
847 }
848 generated_protocol::ResponsePayload::FilesystemResultResponse(inner) => {
849 ResponsePayload::FilesystemResult(FilesystemResultResponse {
850 operation: from_generated_filesystem_operation(inner.operation),
851 status: inner.status,
852 payload_size_bytes: inner.payload_size_bytes,
853 })
854 }
855 generated_protocol::ResponsePayload::PermissionDecisionResponse(inner) => {
856 ResponsePayload::PermissionDecision(PermissionDecisionResponse {
857 capability: inner.capability,
858 decision: from_generated_permission_mode(inner.decision),
859 })
860 }
861 generated_protocol::ResponsePayload::PersistenceStateResponse(inner) => {
862 ResponsePayload::PersistenceState(inner)
863 }
864 generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner) => {
865 ResponsePayload::PersistenceFlushed(inner)
866 }
867 generated_protocol::ResponsePayload::RejectedResponse(inner) => {
868 ResponsePayload::Rejected(inner)
869 }
870 generated_protocol::ResponsePayload::ExtEnvelope(inner) => {
871 ResponsePayload::ExtResult(from_generated_ext_envelope(inner))
872 }
873 generated_protocol::ResponsePayload::GuestKernelResultResponse(inner) => {
874 ResponsePayload::GuestKernelResult(inner)
875 }
876 generated_protocol::ResponsePayload::PtyResizedResponse(inner) => {
877 ResponsePayload::PtyResized(inner)
878 }
879 generated_protocol::ResponsePayload::PackageLinkedResponse(inner) => {
880 ResponsePayload::PackageLinked(inner)
881 }
882 })
883}
884
885fn to_generated_event_payload(payload: &EventPayload) -> generated_protocol::EventPayload {
886 match payload {
887 EventPayload::VmLifecycle(inner) => generated_protocol::EventPayload::VmLifecycleEvent(
888 generated_protocol::VmLifecycleEvent {
889 state: to_generated_vm_lifecycle_state(&inner.state),
890 },
891 ),
892 EventPayload::ProcessOutput(inner) => generated_protocol::EventPayload::ProcessOutputEvent(
893 generated_protocol::ProcessOutputEvent {
894 process_id: inner.process_id.clone(),
895 channel: to_generated_stream_channel(&inner.channel),
896 chunk: inner.chunk.clone(),
897 },
898 ),
899 EventPayload::ProcessExited(inner) => {
900 generated_protocol::EventPayload::ProcessExitedEvent(inner.clone())
901 }
902 EventPayload::Structured(inner) => {
903 generated_protocol::EventPayload::StructuredEvent(inner.clone())
904 }
905 EventPayload::Ext(inner) => {
906 generated_protocol::EventPayload::ExtEnvelope(to_generated_ext_envelope(inner))
907 }
908 }
909}
910
911fn from_generated_event_payload(payload: generated_protocol::EventPayload) -> EventPayload {
912 match payload {
913 generated_protocol::EventPayload::VmLifecycleEvent(inner) => {
914 EventPayload::VmLifecycle(VmLifecycleEvent {
915 state: from_generated_vm_lifecycle_state(inner.state),
916 })
917 }
918 generated_protocol::EventPayload::ProcessOutputEvent(inner) => {
919 EventPayload::ProcessOutput(ProcessOutputEvent {
920 process_id: inner.process_id,
921 channel: from_generated_stream_channel(inner.channel),
922 chunk: inner.chunk,
923 })
924 }
925 generated_protocol::EventPayload::ProcessExitedEvent(inner) => {
926 EventPayload::ProcessExited(inner)
927 }
928 generated_protocol::EventPayload::StructuredEvent(inner) => EventPayload::Structured(inner),
929 generated_protocol::EventPayload::ExtEnvelope(inner) => {
930 EventPayload::Ext(from_generated_ext_envelope(inner))
931 }
932 }
933}
934
935fn to_generated_sidecar_request_payload(
936 payload: &SidecarRequestPayload,
937) -> Result<generated_protocol::SidecarRequestPayload, ProtocolCodecError> {
938 Ok(match payload {
939 SidecarRequestPayload::HostCallback(inner) => {
940 generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner.clone())
941 }
942 SidecarRequestPayload::JsBridgeCall(inner) => {
943 generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner.clone())
944 }
945 SidecarRequestPayload::Ext(inner) => {
946 generated_protocol::SidecarRequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
947 }
948 })
949}
950
951fn from_generated_sidecar_request_payload(
952 payload: generated_protocol::SidecarRequestPayload,
953) -> Result<SidecarRequestPayload, ProtocolCodecError> {
954 Ok(match payload {
955 generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner) => {
956 SidecarRequestPayload::HostCallback(inner)
957 }
958 generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner) => {
959 SidecarRequestPayload::JsBridgeCall(inner)
960 }
961 generated_protocol::SidecarRequestPayload::ExtEnvelope(inner) => {
962 SidecarRequestPayload::Ext(from_generated_ext_envelope(inner))
963 }
964 })
965}
966
967fn to_generated_sidecar_response_payload(
968 payload: &SidecarResponsePayload,
969) -> Result<generated_protocol::SidecarResponsePayload, ProtocolCodecError> {
970 Ok(match payload {
971 SidecarResponsePayload::HostCallbackResult(inner) => {
972 generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner.clone())
973 }
974 SidecarResponsePayload::JsBridgeResult(inner) => {
975 generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner.clone())
976 }
977 SidecarResponsePayload::ExtResult(inner) => {
978 generated_protocol::SidecarResponsePayload::ExtEnvelope(to_generated_ext_envelope(
979 inner,
980 ))
981 }
982 })
983}
984
985fn from_generated_sidecar_response_payload(
986 payload: generated_protocol::SidecarResponsePayload,
987) -> Result<SidecarResponsePayload, ProtocolCodecError> {
988 Ok(match payload {
989 generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner) => {
990 SidecarResponsePayload::HostCallbackResult(inner)
991 }
992 generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner) => {
993 SidecarResponsePayload::JsBridgeResult(inner)
994 }
995 generated_protocol::SidecarResponsePayload::ExtEnvelope(inner) => {
996 SidecarResponsePayload::ExtResult(from_generated_ext_envelope(inner))
997 }
998 })
999}
1000
1001macro_rules! impl_bare_newtype_union_enum {
1002 (
1003 $name:ident,
1004 $json_name:ident,
1005 $(#[$json_attr:meta])*
1006 {
1007 $($variant:ident($ty:ty) = $tag:literal),+ $(,)?
1008 }
1009 ) => {
1010 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1011 $(#[$json_attr])*
1012 enum $json_name {
1013 $($variant($ty)),+
1014 }
1015
1016 impl From<&$name> for $json_name {
1017 fn from(value: &$name) -> Self {
1018 match value {
1019 $($name::$variant(inner) => Self::$variant(inner.clone()),)+
1020 }
1021 }
1022 }
1023
1024 impl From<$json_name> for $name {
1025 fn from(value: $json_name) -> Self {
1026 match value {
1027 $($json_name::$variant(inner) => Self::$variant(inner),)+
1028 }
1029 }
1030 }
1031
1032 impl Serialize for $name {
1033 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1034 where
1035 S: Serializer,
1036 {
1037 if serializer.is_human_readable() {
1038 $json_name::from(self).serialize(serializer)
1039 } else {
1040 match self {
1041 $(Self::$variant(inner) => serialize_bare_newtype_tag(serializer, $tag, inner),)+
1042 }
1043 }
1044 }
1045 }
1046
1047 impl<'de> Deserialize<'de> for $name {
1048 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1049 where
1050 D: Deserializer<'de>,
1051 {
1052 if deserializer.is_human_readable() {
1053 Ok($json_name::deserialize(deserializer)?.into())
1054 } else {
1055 struct UnionVisitor;
1056
1057 impl<'de> Visitor<'de> for UnionVisitor {
1058 type Value = $name;
1059
1060 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1061 write!(formatter, "a {} BARE union", stringify!($name))
1062 }
1063
1064 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1065 where
1066 A: SeqAccess<'de>,
1067 {
1068 let serde_bare::Uint(tag) = seq
1069 .next_element()?
1070 .ok_or_else(|| de::Error::custom(concat!("missing ", stringify!($name), " tag")))?;
1071 match tag {
1072 $(
1073 $tag => {
1074 let payload = seq.next_element::<$ty>()?.ok_or_else(|| {
1075 de::Error::custom(format!(
1076 "missing {} payload for tag {}",
1077 stringify!($variant),
1078 $tag
1079 ))
1080 })?;
1081 Ok($name::$variant(payload))
1082 }
1083 )+
1084 _ => Err(de::Error::custom(format!(
1085 "unknown {} tag: {}",
1086 stringify!($name),
1087 tag
1088 ))),
1089 }
1090 }
1091 }
1092
1093 deserializer.deserialize_tuple(2, UnionVisitor)
1094 }
1095 }
1096 }
1097 };
1098}
1099
1100pub type ProtocolSchema = crate::wire::ProtocolSchema;
1101
1102pub type OwnershipScope = crate::wire::OwnershipScope;
1103
1104#[derive(Debug, Clone, PartialEq, Eq)]
1105pub enum ProtocolFrame {
1106 Request(RequestFrame),
1107 Response(ResponseFrame),
1108 Event(EventFrame),
1109 SidecarRequest(SidecarRequestFrame),
1110 SidecarResponse(SidecarResponseFrame),
1111}
1112
1113#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1114pub struct RequestFrame {
1115 pub schema: ProtocolSchema,
1116 pub request_id: RequestId,
1117 pub ownership: OwnershipScope,
1118 pub payload: RequestPayload,
1119}
1120
1121impl RequestFrame {
1122 pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: RequestPayload) -> Self {
1123 Self {
1124 schema: ProtocolSchema::current(),
1125 request_id,
1126 ownership,
1127 payload,
1128 }
1129 }
1130}
1131
1132#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1133pub struct ResponseFrame {
1134 pub schema: ProtocolSchema,
1135 pub request_id: RequestId,
1136 pub ownership: OwnershipScope,
1137 pub payload: ResponsePayload,
1138}
1139
1140impl ResponseFrame {
1141 pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: ResponsePayload) -> Self {
1142 Self {
1143 schema: ProtocolSchema::current(),
1144 request_id,
1145 ownership,
1146 payload,
1147 }
1148 }
1149}
1150
1151#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1152pub struct SidecarRequestFrame {
1153 pub schema: ProtocolSchema,
1154 pub request_id: RequestId,
1155 pub ownership: OwnershipScope,
1156 pub payload: SidecarRequestPayload,
1157}
1158
1159impl SidecarRequestFrame {
1160 pub fn new(
1161 request_id: RequestId,
1162 ownership: OwnershipScope,
1163 payload: SidecarRequestPayload,
1164 ) -> Self {
1165 Self {
1166 schema: ProtocolSchema::current(),
1167 request_id,
1168 ownership,
1169 payload,
1170 }
1171 }
1172}
1173
1174#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1175pub struct SidecarResponseFrame {
1176 pub schema: ProtocolSchema,
1177 pub request_id: RequestId,
1178 pub ownership: OwnershipScope,
1179 pub payload: SidecarResponsePayload,
1180}
1181
1182impl SidecarResponseFrame {
1183 pub fn new(
1184 request_id: RequestId,
1185 ownership: OwnershipScope,
1186 payload: SidecarResponsePayload,
1187 ) -> Self {
1188 Self {
1189 schema: ProtocolSchema::current(),
1190 request_id,
1191 ownership,
1192 payload,
1193 }
1194 }
1195}
1196
1197#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1198pub struct EventFrame {
1199 pub schema: ProtocolSchema,
1200 pub ownership: OwnershipScope,
1201 pub payload: EventPayload,
1202}
1203
1204impl EventFrame {
1205 pub fn new(ownership: OwnershipScope, payload: EventPayload) -> Self {
1206 Self {
1207 schema: ProtocolSchema::current(),
1208 ownership,
1209 payload,
1210 }
1211 }
1212}
1213
1214#[derive(Debug, Clone, PartialEq, Eq)]
1215pub enum RequestPayload {
1216 Authenticate(AuthenticateRequest),
1217 OpenSession(OpenSessionRequest),
1218 CreateVm(CreateVmRequest),
1219 DisposeVm(DisposeVmRequest),
1220 BootstrapRootFilesystem(BootstrapRootFilesystemRequest),
1221 ConfigureVm(ConfigureVmRequest),
1222 RegisterHostCallbacks(RegisterHostCallbacksRequest),
1223 CreateLayer(CreateLayerRequest),
1224 SealLayer(SealLayerRequest),
1225 ImportSnapshot(ImportSnapshotRequest),
1226 ExportSnapshot(ExportSnapshotRequest),
1227 CreateOverlay(CreateOverlayRequest),
1228 GuestFilesystemCall(GuestFilesystemCallRequest),
1229 SnapshotRootFilesystem(SnapshotRootFilesystemRequest),
1230 Execute(ExecuteRequest),
1231 WriteStdin(WriteStdinRequest),
1232 CloseStdin(CloseStdinRequest),
1233 KillProcess(KillProcessRequest),
1234 GetProcessSnapshot(GetProcessSnapshotRequest),
1235 FindListener(FindListenerRequest),
1236 FindBoundUdp(FindBoundUdpRequest),
1237 VmFetch(VmFetchRequest),
1238 GetSignalState(GetSignalStateRequest),
1239 GetZombieTimerCount(GetZombieTimerCountRequest),
1240 HostFilesystemCall(HostFilesystemCallRequest),
1241 PersistenceLoad(PersistenceLoadRequest),
1242 PersistenceFlush(PersistenceFlushRequest),
1243 Ext(ExtEnvelope),
1244 GuestKernelCall(GuestKernelCallRequest),
1245 ResizePty(ResizePtyRequest),
1246 GetResourceSnapshot(GetResourceSnapshotRequest),
1247 LinkPackage(LinkPackageRequest),
1248}
1249
1250#[derive(Debug, Clone, PartialEq, Eq)]
1251pub enum ResponsePayload {
1252 Authenticated(AuthenticatedResponse),
1253 SessionOpened(SessionOpenedResponse),
1254 VmCreated(VmCreatedResponse),
1255 VmDisposed(VmDisposedResponse),
1256 RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse),
1257 VmConfigured(VmConfiguredResponse),
1258 HostCallbacksRegistered(HostCallbacksRegisteredResponse),
1259 LayerCreated(LayerCreatedResponse),
1260 LayerSealed(LayerSealedResponse),
1261 SnapshotImported(SnapshotImportedResponse),
1262 SnapshotExported(SnapshotExportedResponse),
1263 OverlayCreated(OverlayCreatedResponse),
1264 GuestFilesystemResult(GuestFilesystemResultResponse),
1265 RootFilesystemSnapshot(RootFilesystemSnapshotResponse),
1266 ProcessStarted(ProcessStartedResponse),
1267 StdinWritten(StdinWrittenResponse),
1268 StdinClosed(StdinClosedResponse),
1269 ProcessKilled(ProcessKilledResponse),
1270 ProcessSnapshot(ProcessSnapshotResponse),
1271 ListenerSnapshot(ListenerSnapshotResponse),
1272 BoundUdpSnapshot(BoundUdpSnapshotResponse),
1273 VmFetchResult(VmFetchResponse),
1274 SignalState(SignalStateResponse),
1275 ZombieTimerCount(ZombieTimerCountResponse),
1276 FilesystemResult(FilesystemResultResponse),
1277 PermissionDecision(PermissionDecisionResponse),
1278 PersistenceState(PersistenceStateResponse),
1279 PersistenceFlushed(PersistenceFlushedResponse),
1280 Rejected(RejectedResponse),
1281 ExtResult(ExtEnvelope),
1282 GuestKernelResult(GuestKernelResultResponse),
1283 PtyResized(PtyResizedResponse),
1284 ResourceSnapshot(ResourceSnapshotResponse),
1285 PackageLinked(PackageLinkedResponse),
1286}
1287
1288#[derive(Debug, Clone, PartialEq, Eq)]
1289pub enum SidecarRequestPayload {
1290 HostCallback(HostCallbackRequest),
1291 JsBridgeCall(JsBridgeCallRequest),
1292 Ext(ExtEnvelope),
1293}
1294
1295#[derive(Debug, Clone, PartialEq, Eq)]
1296pub enum SidecarResponsePayload {
1297 HostCallbackResult(HostCallbackResultResponse),
1298 JsBridgeResult(JsBridgeResultResponse),
1299 ExtResult(ExtEnvelope),
1300}
1301
1302#[derive(Debug, Clone, PartialEq, Eq)]
1303pub enum EventPayload {
1304 VmLifecycle(VmLifecycleEvent),
1305 ProcessOutput(ProcessOutputEvent),
1306 ProcessExited(ProcessExitedEvent),
1307 Structured(StructuredEvent),
1308 Ext(ExtEnvelope),
1309}
1310
1311pub type SidecarPlacement = crate::wire::SidecarPlacement;
1312
1313pub type SidecarPlacementShared = crate::wire::SidecarPlacementShared;
1314
1315pub type SidecarPlacementExplicit = crate::wire::SidecarPlacementExplicit;
1316
1317pub type GuestRuntimeKind = crate::wire::GuestRuntimeKind;
1318
1319pub type DisposeReason = crate::wire::DisposeReason;
1320
1321pub type FilesystemOperation = crate::wire::FilesystemOperation;
1322
1323pub type GuestFilesystemOperation = crate::wire::GuestFilesystemOperation;
1324
1325pub type PermissionMode = crate::wire::PermissionMode;
1326
1327pub type FsPermissionRule = crate::wire::FsPermissionRule;
1328
1329pub type PatternPermissionRule = crate::wire::PatternPermissionRule;
1330
1331pub type FsPermissionRuleSet = crate::wire::FsPermissionRuleSet;
1332
1333pub type PatternPermissionRuleSet = crate::wire::PatternPermissionRuleSet;
1334
1335pub type FsPermissionScope = crate::wire::FsPermissionScope;
1336
1337pub type PatternPermissionScope = crate::wire::PatternPermissionScope;
1338
1339pub type PermissionsPolicy = crate::wire::PermissionsPolicy;
1340
1341pub type RootFilesystemEntryKind = crate::wire::RootFilesystemEntryKind;
1342
1343pub type RootFilesystemMode = crate::wire::RootFilesystemMode;
1344
1345pub type RootFilesystemLowerDescriptor = crate::wire::RootFilesystemLowerDescriptor;
1346
1347pub type SnapshotRootFilesystemLower = crate::wire::SnapshotRootFilesystemLower;
1348
1349pub type StreamChannel = crate::wire::StreamChannel;
1350
1351pub type VmLifecycleState = crate::wire::VmLifecycleState;
1352
1353pub type AuthenticateRequest = crate::wire::AuthenticateRequest;
1354
1355pub type OpenSessionRequest = crate::wire::OpenSessionRequest;
1356
1357pub type CreateVmRequest = crate::wire::CreateVmRequest;
1358
1359#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1360pub struct DisposeVmRequest {
1361 pub reason: DisposeReason,
1362}
1363
1364pub type BootstrapRootFilesystemRequest = crate::wire::BootstrapRootFilesystemRequest;
1365
1366pub type RootFilesystemDescriptor = crate::wire::RootFilesystemDescriptor;
1367
1368pub type RootFilesystemEntryEncoding = crate::wire::RootFilesystemEntryEncoding;
1369
1370pub type RootFilesystemEntry = crate::wire::RootFilesystemEntry;
1371
1372pub type ConfigureVmRequest = crate::wire::ConfigureVmRequest;
1373
1374#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1375pub struct CreateLayerRequest {}
1376
1377pub type SealLayerRequest = crate::wire::SealLayerRequest;
1378
1379pub type ImportSnapshotRequest = crate::wire::ImportSnapshotRequest;
1380
1381pub type ExportSnapshotRequest = crate::wire::ExportSnapshotRequest;
1382
1383pub type CreateOverlayRequest = crate::wire::CreateOverlayRequest;
1384
1385pub type GuestFilesystemCallRequest = crate::wire::GuestFilesystemCallRequest;
1386
1387pub type GuestKernelCallRequest = crate::wire::GuestKernelCallRequest;
1388pub type ResizePtyRequest = crate::wire::ResizePtyRequest;
1389pub type PackageDescriptor = crate::wire::PackageDescriptor;
1390pub type LinkPackageRequest = crate::wire::LinkPackageRequest;
1391
1392pub type GuestKernelResultResponse = crate::wire::GuestKernelResultResponse;
1393pub type PtyResizedResponse = crate::wire::PtyResizedResponse;
1394pub type PackageLinkedResponse = crate::wire::PackageLinkedResponse;
1395
1396#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1397pub struct SnapshotRootFilesystemRequest {}
1398
1399pub type MountDescriptor = crate::wire::MountDescriptor;
1400
1401pub type MountPluginDescriptor = crate::wire::MountPluginDescriptor;
1402
1403pub type SoftwareDescriptor = crate::wire::SoftwareDescriptor;
1404
1405pub type ProjectedModuleDescriptor = crate::wire::ProjectedModuleDescriptor;
1406
1407pub type WasmPermissionTier = crate::wire::WasmPermissionTier;
1408
1409pub type ExecuteRequest = crate::wire::ExecuteRequest;
1410
1411pub type WriteStdinRequest = crate::wire::WriteStdinRequest;
1412
1413pub type CloseStdinRequest = crate::wire::CloseStdinRequest;
1414
1415pub type KillProcessRequest = crate::wire::KillProcessRequest;
1416
1417#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1418pub struct GetProcessSnapshotRequest {}
1419
1420#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1421pub struct GetResourceSnapshotRequest {}
1422
1423pub type FindListenerRequest = crate::wire::FindListenerRequest;
1424
1425pub type FindBoundUdpRequest = crate::wire::FindBoundUdpRequest;
1426
1427pub type VmFetchRequest = crate::wire::VmFetchRequest;
1428
1429pub type GetSignalStateRequest = crate::wire::GetSignalStateRequest;
1430
1431#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1432pub struct GetZombieTimerCountRequest {}
1433
1434pub type HostFilesystemCallRequest = crate::wire::HostFilesystemCallRequest;
1435
1436pub type PersistenceLoadRequest = crate::wire::PersistenceLoadRequest;
1437
1438pub type PersistenceFlushRequest = crate::wire::PersistenceFlushRequest;
1439
1440pub type RegisterHostCallbacksRequest = crate::wire::RegisterHostCallbacksRequest;
1441
1442pub type RegisteredHostCallbackDefinition = crate::wire::RegisteredHostCallbackDefinition;
1443
1444pub type RegisteredHostCallbackExample = crate::wire::RegisteredHostCallbackExample;
1445
1446pub type HostCallbackRequest = crate::wire::HostCallbackRequest;
1447
1448pub type JsBridgeCallRequest = crate::wire::JsBridgeCallRequest;
1449
1450pub type AuthenticatedResponse = crate::wire::AuthenticatedResponse;
1451
1452pub type SessionOpenedResponse = crate::wire::SessionOpenedResponse;
1453
1454pub type VmCreatedResponse = crate::wire::VmCreatedResponse;
1455
1456pub type VmDisposedResponse = crate::wire::VmDisposedResponse;
1457
1458pub type RootFilesystemBootstrappedResponse = crate::wire::RootFilesystemBootstrappedResponse;
1459
1460pub type VmConfiguredResponse = crate::wire::VmConfiguredResponse;
1461
1462pub type HostCallbacksRegisteredResponse = crate::wire::HostCallbacksRegisteredResponse;
1463
1464pub type GuestFilesystemStat = crate::wire::GuestFilesystemStat;
1465
1466pub type GuestDirEntry = crate::wire::GuestDirEntry;
1467
1468pub type GuestFilesystemResultResponse = crate::wire::GuestFilesystemResultResponse;
1469
1470pub type RootFilesystemSnapshotResponse = crate::wire::RootFilesystemSnapshotResponse;
1471
1472pub type LayerCreatedResponse = crate::wire::LayerCreatedResponse;
1473
1474pub type LayerSealedResponse = crate::wire::LayerSealedResponse;
1475
1476pub type SnapshotImportedResponse = crate::wire::SnapshotImportedResponse;
1477
1478pub type SnapshotExportedResponse = crate::wire::SnapshotExportedResponse;
1479
1480pub type OverlayCreatedResponse = crate::wire::OverlayCreatedResponse;
1481
1482pub type ProcessStartedResponse = crate::wire::ProcessStartedResponse;
1483
1484pub type StdinWrittenResponse = crate::wire::StdinWrittenResponse;
1485
1486pub type StdinClosedResponse = crate::wire::StdinClosedResponse;
1487
1488pub type ProcessKilledResponse = crate::wire::ProcessKilledResponse;
1489
1490pub type ProcessSnapshotStatus = crate::wire::ProcessSnapshotStatus;
1491
1492pub type ProcessSnapshotEntry = crate::wire::ProcessSnapshotEntry;
1493
1494pub type ProcessSnapshotResponse = crate::wire::ProcessSnapshotResponse;
1495
1496pub type QueueSnapshotEntry = crate::wire::QueueSnapshotEntry;
1497
1498pub type ResourceSnapshotResponse = crate::wire::ResourceSnapshotResponse;
1499
1500pub type SocketStateEntry = crate::wire::SocketStateEntry;
1501
1502pub type ListenerSnapshotResponse = crate::wire::ListenerSnapshotResponse;
1503
1504pub type BoundUdpSnapshotResponse = crate::wire::BoundUdpSnapshotResponse;
1505
1506pub type VmFetchResponse = crate::wire::VmFetchResponse;
1507
1508pub type SignalDispositionAction = crate::wire::SignalDispositionAction;
1509
1510pub type SignalHandlerRegistration = crate::wire::SignalHandlerRegistration;
1511
1512pub type SignalStateResponse = crate::wire::SignalStateResponse;
1513
1514pub type ZombieTimerCountResponse = crate::wire::ZombieTimerCountResponse;
1515
1516pub type FilesystemResultResponse = crate::wire::FilesystemResultResponse;
1517
1518pub type PermissionDecisionResponse = crate::wire::PermissionDecisionResponse;
1519
1520pub type PersistenceStateResponse = crate::wire::PersistenceStateResponse;
1521
1522pub type PersistenceFlushedResponse = crate::wire::PersistenceFlushedResponse;
1523
1524pub type HostCallbackResultResponse = crate::wire::HostCallbackResultResponse;
1525
1526pub type JsBridgeResultResponse = crate::wire::JsBridgeResultResponse;
1527
1528pub type RejectedResponse = crate::wire::RejectedResponse;
1529
1530pub type VmLifecycleEvent = crate::wire::VmLifecycleEvent;
1531
1532pub type ProcessOutputEvent = crate::wire::ProcessOutputEvent;
1533
1534pub type ProcessExitedEvent = crate::wire::ProcessExitedEvent;
1535
1536pub type StructuredEvent = crate::wire::StructuredEvent;
1537
1538impl_bare_newtype_union_enum!(
1539 ProtocolFrame,
1540 JsonProtocolFrame,
1541 #[serde(tag = "frame_type", rename_all = "snake_case")]
1542 {
1543 Request(RequestFrame) = 0,
1544 Response(ResponseFrame) = 1,
1545 Event(EventFrame) = 2,
1546 SidecarRequest(SidecarRequestFrame) = 3,
1547 SidecarResponse(SidecarResponseFrame) = 4,
1548 }
1549);
1550
1551impl_bare_newtype_union_enum!(
1552 RequestPayload,
1553 JsonRequestPayload,
1554 #[serde(tag = "type", rename_all = "snake_case")]
1555 {
1556 Authenticate(AuthenticateRequest) = 0,
1557 OpenSession(OpenSessionRequest) = 1,
1558 CreateVm(CreateVmRequest) = 2,
1559 DisposeVm(DisposeVmRequest) = 3,
1560 BootstrapRootFilesystem(BootstrapRootFilesystemRequest) = 4,
1561 ConfigureVm(ConfigureVmRequest) = 5,
1562 RegisterHostCallbacks(RegisterHostCallbacksRequest) = 6,
1563 CreateLayer(CreateLayerRequest) = 7,
1564 SealLayer(SealLayerRequest) = 8,
1565 ImportSnapshot(ImportSnapshotRequest) = 9,
1566 ExportSnapshot(ExportSnapshotRequest) = 10,
1567 CreateOverlay(CreateOverlayRequest) = 11,
1568 GuestFilesystemCall(GuestFilesystemCallRequest) = 12,
1569 SnapshotRootFilesystem(SnapshotRootFilesystemRequest) = 13,
1570 Execute(ExecuteRequest) = 14,
1571 WriteStdin(WriteStdinRequest) = 15,
1572 CloseStdin(CloseStdinRequest) = 16,
1573 KillProcess(KillProcessRequest) = 17,
1574 GetProcessSnapshot(GetProcessSnapshotRequest) = 18,
1575 FindListener(FindListenerRequest) = 19,
1576 FindBoundUdp(FindBoundUdpRequest) = 20,
1577 GetSignalState(GetSignalStateRequest) = 21,
1578 GetZombieTimerCount(GetZombieTimerCountRequest) = 22,
1579 HostFilesystemCall(HostFilesystemCallRequest) = 23,
1580 PersistenceLoad(PersistenceLoadRequest) = 24,
1581 PersistenceFlush(PersistenceFlushRequest) = 25,
1582 VmFetch(VmFetchRequest) = 26,
1583 Ext(ExtEnvelope) = 27,
1584 GuestKernelCall(GuestKernelCallRequest) = 28,
1585 ResizePty(ResizePtyRequest) = 29,
1586 GetResourceSnapshot(GetResourceSnapshotRequest) = 30,
1587 LinkPackage(LinkPackageRequest) = 31,
1588 }
1589);
1590
1591impl_bare_newtype_union_enum!(
1592 ResponsePayload,
1593 JsonResponsePayload,
1594 #[serde(tag = "type", rename_all = "snake_case")]
1595 {
1596 Authenticated(AuthenticatedResponse) = 0,
1597 SessionOpened(SessionOpenedResponse) = 1,
1598 VmCreated(VmCreatedResponse) = 2,
1599 VmDisposed(VmDisposedResponse) = 3,
1600 RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse) = 4,
1601 VmConfigured(VmConfiguredResponse) = 5,
1602 HostCallbacksRegistered(HostCallbacksRegisteredResponse) = 6,
1603 LayerCreated(LayerCreatedResponse) = 7,
1604 LayerSealed(LayerSealedResponse) = 8,
1605 SnapshotImported(SnapshotImportedResponse) = 9,
1606 SnapshotExported(SnapshotExportedResponse) = 10,
1607 OverlayCreated(OverlayCreatedResponse) = 11,
1608 GuestFilesystemResult(GuestFilesystemResultResponse) = 12,
1609 RootFilesystemSnapshot(RootFilesystemSnapshotResponse) = 13,
1610 ProcessStarted(ProcessStartedResponse) = 14,
1611 StdinWritten(StdinWrittenResponse) = 15,
1612 StdinClosed(StdinClosedResponse) = 16,
1613 ProcessKilled(ProcessKilledResponse) = 17,
1614 ProcessSnapshot(ProcessSnapshotResponse) = 18,
1615 ListenerSnapshot(ListenerSnapshotResponse) = 19,
1616 BoundUdpSnapshot(BoundUdpSnapshotResponse) = 20,
1617 SignalState(SignalStateResponse) = 21,
1618 ZombieTimerCount(ZombieTimerCountResponse) = 22,
1619 FilesystemResult(FilesystemResultResponse) = 23,
1620 PermissionDecision(PermissionDecisionResponse) = 24,
1621 PersistenceState(PersistenceStateResponse) = 25,
1622 PersistenceFlushed(PersistenceFlushedResponse) = 26,
1623 Rejected(RejectedResponse) = 27,
1624 VmFetchResult(VmFetchResponse) = 28,
1625 ExtResult(ExtEnvelope) = 29,
1626 GuestKernelResult(GuestKernelResultResponse) = 30,
1627 PtyResized(PtyResizedResponse) = 31,
1628 ResourceSnapshot(ResourceSnapshotResponse) = 32,
1629 PackageLinked(PackageLinkedResponse) = 33,
1630 }
1631);
1632
1633impl_bare_newtype_union_enum!(
1634 SidecarRequestPayload,
1635 JsonSidecarRequestPayload,
1636 #[serde(tag = "type", rename_all = "snake_case")]
1637 {
1638 HostCallback(HostCallbackRequest) = 0,
1639 JsBridgeCall(JsBridgeCallRequest) = 1,
1640 Ext(ExtEnvelope) = 2,
1641 }
1642);
1643
1644impl_bare_newtype_union_enum!(
1645 SidecarResponsePayload,
1646 JsonSidecarResponsePayload,
1647 #[allow(clippy::enum_variant_names)]
1648 #[serde(tag = "type", rename_all = "snake_case")]
1649 {
1650 HostCallbackResult(HostCallbackResultResponse) = 0,
1651 JsBridgeResult(JsBridgeResultResponse) = 1,
1652 ExtResult(ExtEnvelope) = 2,
1653 }
1654);
1655
1656impl_bare_newtype_union_enum!(
1657 EventPayload,
1658 JsonEventPayload,
1659 #[serde(tag = "type", rename_all = "snake_case")]
1660 {
1661 VmLifecycle(VmLifecycleEvent) = 0,
1662 ProcessOutput(ProcessOutputEvent) = 1,
1663 ProcessExited(ProcessExitedEvent) = 2,
1664 Structured(StructuredEvent) = 3,
1665 Ext(ExtEnvelope) = 4,
1666 }
1667);
1668
1669fn serialize_payload(
1670 frame: &ProtocolFrame,
1671 payload_codec: NativePayloadCodec,
1672) -> Result<Vec<u8>, ProtocolCodecError> {
1673 match payload_codec {
1674 NativePayloadCodec::Json => serde_json::to_vec(frame)
1675 .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
1676 NativePayloadCodec::Bare => serde_bare::to_vec(&to_generated_protocol_frame(frame)?)
1677 .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
1678 }
1679}
1680
1681fn deserialize_payload(
1682 payload: &[u8],
1683 payload_codec: NativePayloadCodec,
1684) -> Result<ProtocolFrame, ProtocolCodecError> {
1685 match payload_codec {
1686 NativePayloadCodec::Json => serde_json::from_slice(payload)
1687 .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string())),
1688 NativePayloadCodec::Bare => {
1689 let frame: generated_protocol::ProtocolFrame = serde_bare::from_slice(payload)
1690 .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string()))?;
1691 from_generated_protocol_frame(frame)
1692 }
1693 }
1694}
1695
1696#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1697pub enum NativePayloadCodec {
1698 Json,
1699 Bare,
1700}
1701
1702impl NativePayloadCodec {
1703 pub fn sniff(payload: &[u8]) -> Self {
1704 match payload.first() {
1705 Some(b'{') => Self::Json,
1706 _ => Self::Bare,
1707 }
1708 }
1709
1710 pub fn alternate(self) -> Self {
1711 match self {
1712 Self::Json => Self::Bare,
1713 Self::Bare => Self::Json,
1714 }
1715 }
1716}
1717
1718#[derive(Debug, Clone)]
1719pub struct NativeFrameCodec {
1720 max_frame_bytes: usize,
1721 payload_codec: NativePayloadCodec,
1722}
1723
1724impl NativeFrameCodec {
1725 pub fn new(max_frame_bytes: usize) -> Self {
1726 Self::with_payload_codec(max_frame_bytes, NativePayloadCodec::Json)
1727 }
1728
1729 pub fn with_payload_codec(max_frame_bytes: usize, payload_codec: NativePayloadCodec) -> Self {
1730 Self {
1731 max_frame_bytes,
1732 payload_codec,
1733 }
1734 }
1735
1736 pub fn max_frame_bytes(&self) -> usize {
1737 self.max_frame_bytes
1738 }
1739
1740 pub fn payload_codec(&self) -> NativePayloadCodec {
1741 self.payload_codec
1742 }
1743
1744 pub fn encode(&self, frame: &ProtocolFrame) -> Result<Vec<u8>, ProtocolCodecError> {
1745 self.encode_with_codec(frame, self.payload_codec)
1746 }
1747
1748 pub fn encode_with_codec(
1749 &self,
1750 frame: &ProtocolFrame,
1751 payload_codec: NativePayloadCodec,
1752 ) -> Result<Vec<u8>, ProtocolCodecError> {
1753 validate_frame(frame)?;
1754
1755 let payload = serialize_payload(frame, payload_codec)?;
1756 if payload.len() > self.max_frame_bytes {
1757 return Err(ProtocolCodecError::FrameTooLarge {
1758 size: payload.len(),
1759 max: self.max_frame_bytes,
1760 });
1761 }
1762
1763 let length =
1764 u32::try_from(payload.len()).map_err(|_| ProtocolCodecError::FrameTooLarge {
1765 size: payload.len(),
1766 max: u32::MAX as usize,
1767 })?;
1768
1769 let mut encoded = Vec::with_capacity(4 + payload.len());
1770 encoded.extend_from_slice(&length.to_be_bytes());
1771 encoded.extend_from_slice(&payload);
1772 Ok(encoded)
1773 }
1774
1775 pub fn decode(&self, bytes: &[u8]) -> Result<ProtocolFrame, ProtocolCodecError> {
1776 self.decode_detected(bytes).map(|(frame, _)| frame)
1777 }
1778
1779 pub fn decode_with_codec(
1780 &self,
1781 bytes: &[u8],
1782 payload_codec: NativePayloadCodec,
1783 ) -> Result<ProtocolFrame, ProtocolCodecError> {
1784 let payload = self.checked_payload(bytes)?;
1785 let frame = deserialize_payload(payload, payload_codec)?;
1786 validate_frame(&frame)?;
1787 Ok(frame)
1788 }
1789
1790 pub fn decode_detected(
1791 &self,
1792 bytes: &[u8],
1793 ) -> Result<(ProtocolFrame, NativePayloadCodec), ProtocolCodecError> {
1794 let payload = self.checked_payload(bytes)?;
1795 let primary = NativePayloadCodec::sniff(payload);
1796
1797 match deserialize_payload(payload, primary) {
1798 Ok(frame) => {
1799 validate_frame(&frame)?;
1800 Ok((frame, primary))
1801 }
1802 Err(primary_error) => {
1803 let alternate = primary.alternate();
1804 let frame = deserialize_payload(payload, alternate).map_err(|_| primary_error)?;
1805 validate_frame(&frame)?;
1806 Ok((frame, alternate))
1807 }
1808 }
1809 }
1810
1811 fn checked_payload<'a>(&self, bytes: &'a [u8]) -> Result<&'a [u8], ProtocolCodecError> {
1812 if bytes.len() < 4 {
1813 return Err(ProtocolCodecError::TruncatedFrame {
1814 actual: bytes.len(),
1815 });
1816 }
1817
1818 let declared =
1819 u32::from_be_bytes(bytes[..4].try_into().expect("length prefix is four bytes"))
1820 as usize;
1821 if declared > self.max_frame_bytes {
1822 return Err(ProtocolCodecError::FrameTooLarge {
1823 size: declared,
1824 max: self.max_frame_bytes,
1825 });
1826 }
1827
1828 let actual = bytes.len() - 4;
1829 if declared != actual {
1830 return Err(ProtocolCodecError::LengthPrefixMismatch { declared, actual });
1831 }
1832 Ok(&bytes[4..])
1833 }
1834}
1835
1836impl Default for NativeFrameCodec {
1837 fn default() -> Self {
1838 Self::new(DEFAULT_MAX_FRAME_BYTES)
1839 }
1840}
1841
1842#[derive(Debug)]
1843pub struct ResponseTracker {
1844 pending: HashMap<RequestId, PendingRequest>,
1845 completed: HashSet<RequestId>,
1846 completed_order: VecDeque<RequestId>,
1847 completed_cap: usize,
1848}
1849
1850#[derive(Debug)]
1851pub struct SidecarResponseTracker {
1852 pending: HashMap<RequestId, PendingSidecarRequest>,
1853 completed: HashSet<RequestId>,
1854 completed_order: VecDeque<RequestId>,
1855 completed_cap: usize,
1856}
1857
1858impl ResponseTracker {
1859 pub fn with_completed_cap(completed_cap: usize) -> Self {
1860 Self {
1861 pending: HashMap::new(),
1862 completed: HashSet::new(),
1863 completed_order: VecDeque::new(),
1864 completed_cap: completed_cap.max(1),
1865 }
1866 }
1867
1868 pub fn completed_count(&self) -> usize {
1869 self.completed.len()
1870 }
1871
1872 pub fn register_request(&mut self, request: &RequestFrame) -> Result<(), ResponseTrackerError> {
1873 if self.pending.contains_key(&request.request_id)
1874 || self.completed.contains(&request.request_id)
1875 {
1876 return Err(ResponseTrackerError::DuplicateRequestId {
1877 request_id: request.request_id,
1878 });
1879 }
1880
1881 self.pending.insert(
1882 request.request_id,
1883 PendingRequest {
1884 ownership: request.ownership.clone(),
1885 expected_response: request.payload.expected_response(),
1886 },
1887 );
1888 Ok(())
1889 }
1890
1891 pub fn accept_response(
1892 &mut self,
1893 response: &ResponseFrame,
1894 ) -> Result<(), ResponseTrackerError> {
1895 if self.completed.contains(&response.request_id) {
1896 return Err(ResponseTrackerError::DuplicateResponse {
1897 request_id: response.request_id,
1898 });
1899 }
1900
1901 let pending = self.pending.get(&response.request_id).ok_or(
1902 ResponseTrackerError::UnmatchedResponse {
1903 request_id: response.request_id,
1904 },
1905 )?;
1906
1907 if pending.ownership != response.ownership {
1908 return Err(ResponseTrackerError::OwnershipMismatch {
1909 request_id: response.request_id,
1910 expected: Box::new(pending.ownership.clone()),
1911 actual: Box::new(response.ownership.clone()),
1912 });
1913 }
1914
1915 if !pending.expected_response.matches(&response.payload) {
1916 return Err(ResponseTrackerError::ResponseKindMismatch {
1917 request_id: response.request_id,
1918 expected: pending.expected_response.as_str().to_string(),
1919 actual: response.payload.kind_name().to_string(),
1920 });
1921 }
1922
1923 self.pending
1924 .remove(&response.request_id)
1925 .expect("pending response should still exist after validation");
1926 self.completed.insert(response.request_id);
1927 self.completed_order.push_back(response.request_id);
1928 while self.completed.len() > self.completed_cap {
1929 if let Some(evicted) = self.completed_order.pop_front() {
1930 self.completed.remove(&evicted);
1931 }
1932 }
1933 Ok(())
1934 }
1935}
1936
1937impl Default for ResponseTracker {
1938 fn default() -> Self {
1939 Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
1940 }
1941}
1942
1943impl SidecarResponseTracker {
1944 pub fn with_completed_cap(completed_cap: usize) -> Self {
1945 Self {
1946 pending: HashMap::new(),
1947 completed: HashSet::new(),
1948 completed_order: VecDeque::new(),
1949 completed_cap: completed_cap.max(1),
1950 }
1951 }
1952
1953 pub fn pending_count(&self) -> usize {
1954 self.pending.len()
1955 }
1956
1957 pub fn completed_count(&self) -> usize {
1958 self.completed.len()
1959 }
1960
1961 pub fn register_request(
1962 &mut self,
1963 request: &SidecarRequestFrame,
1964 ) -> Result<(), SidecarResponseTrackerError> {
1965 if self.pending.contains_key(&request.request_id)
1966 || self.completed.contains(&request.request_id)
1967 {
1968 return Err(SidecarResponseTrackerError::DuplicateRequestId {
1969 request_id: request.request_id,
1970 });
1971 }
1972
1973 self.pending.insert(
1974 request.request_id,
1975 PendingSidecarRequest {
1976 ownership: request.ownership.clone(),
1977 expected_response: request.payload.expected_response(),
1978 },
1979 );
1980 Ok(())
1981 }
1982
1983 pub fn accept_response(
1984 &mut self,
1985 response: &SidecarResponseFrame,
1986 ) -> Result<(), SidecarResponseTrackerError> {
1987 if self.completed.contains(&response.request_id) {
1988 return Err(SidecarResponseTrackerError::DuplicateResponse {
1989 request_id: response.request_id,
1990 });
1991 }
1992
1993 let pending = self.pending.get(&response.request_id).ok_or(
1994 SidecarResponseTrackerError::UnmatchedResponse {
1995 request_id: response.request_id,
1996 },
1997 )?;
1998
1999 if pending.ownership != response.ownership {
2000 return Err(SidecarResponseTrackerError::OwnershipMismatch {
2001 request_id: response.request_id,
2002 expected: Box::new(pending.ownership.clone()),
2003 actual: Box::new(response.ownership.clone()),
2004 });
2005 }
2006
2007 if !pending.expected_response.matches(&response.payload) {
2008 return Err(SidecarResponseTrackerError::ResponseKindMismatch {
2009 request_id: response.request_id,
2010 expected: pending.expected_response.as_str().to_string(),
2011 actual: response.payload.kind_name().to_string(),
2012 });
2013 }
2014
2015 self.pending
2016 .remove(&response.request_id)
2017 .expect("pending sidecar response should still exist after validation");
2018 self.completed.insert(response.request_id);
2019 self.completed_order.push_back(response.request_id);
2020 while self.completed.len() > self.completed_cap {
2021 if let Some(evicted) = self.completed_order.pop_front() {
2022 self.completed.remove(&evicted);
2023 }
2024 }
2025 Ok(())
2026 }
2027}
2028
2029impl Default for SidecarResponseTracker {
2030 fn default() -> Self {
2031 Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
2032 }
2033}
2034
2035#[derive(Debug, Clone, PartialEq, Eq)]
2036pub enum ResponseTrackerError {
2037 DuplicateRequestId {
2038 request_id: RequestId,
2039 },
2040 UnmatchedResponse {
2041 request_id: RequestId,
2042 },
2043 DuplicateResponse {
2044 request_id: RequestId,
2045 },
2046 OwnershipMismatch {
2047 request_id: RequestId,
2048 expected: Box<OwnershipScope>,
2049 actual: Box<OwnershipScope>,
2050 },
2051 ResponseKindMismatch {
2052 request_id: RequestId,
2053 expected: String,
2054 actual: String,
2055 },
2056}
2057
2058impl fmt::Display for ResponseTrackerError {
2059 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2060 match self {
2061 Self::DuplicateRequestId { request_id } => {
2062 write!(f, "request id {request_id} is already tracked")
2063 }
2064 Self::UnmatchedResponse { request_id } => {
2065 write!(
2066 f,
2067 "response id {request_id} does not match any pending request"
2068 )
2069 }
2070 Self::DuplicateResponse { request_id } => {
2071 write!(f, "response id {request_id} has already been completed")
2072 }
2073 Self::OwnershipMismatch {
2074 request_id,
2075 expected,
2076 actual,
2077 } => write!(
2078 f,
2079 "response id {request_id} used ownership {:?}, expected {:?}",
2080 actual, expected
2081 ),
2082 Self::ResponseKindMismatch {
2083 request_id,
2084 expected,
2085 actual,
2086 } => write!(
2087 f,
2088 "response id {request_id} carried {actual}, expected {expected}",
2089 ),
2090 }
2091 }
2092}
2093
2094impl Error for ResponseTrackerError {}
2095
2096#[derive(Debug, Clone, PartialEq, Eq)]
2097pub enum SidecarResponseTrackerError {
2098 DuplicateRequestId {
2099 request_id: RequestId,
2100 },
2101 UnmatchedResponse {
2102 request_id: RequestId,
2103 },
2104 DuplicateResponse {
2105 request_id: RequestId,
2106 },
2107 OwnershipMismatch {
2108 request_id: RequestId,
2109 expected: Box<OwnershipScope>,
2110 actual: Box<OwnershipScope>,
2111 },
2112 ResponseKindMismatch {
2113 request_id: RequestId,
2114 expected: String,
2115 actual: String,
2116 },
2117}
2118
2119impl fmt::Display for SidecarResponseTrackerError {
2120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2121 match self {
2122 Self::DuplicateRequestId { request_id } => {
2123 write!(f, "sidecar request id {request_id} is already tracked")
2124 }
2125 Self::UnmatchedResponse { request_id } => {
2126 write!(
2127 f,
2128 "sidecar response id {request_id} does not match any pending request"
2129 )
2130 }
2131 Self::DuplicateResponse { request_id } => {
2132 write!(
2133 f,
2134 "sidecar response id {request_id} has already been completed"
2135 )
2136 }
2137 Self::OwnershipMismatch {
2138 request_id,
2139 expected,
2140 actual,
2141 } => write!(
2142 f,
2143 "sidecar response id {request_id} used ownership {:?}, expected {:?}",
2144 actual, expected
2145 ),
2146 Self::ResponseKindMismatch {
2147 request_id,
2148 expected,
2149 actual,
2150 } => write!(
2151 f,
2152 "sidecar response id {request_id} carried {actual}, expected {expected}",
2153 ),
2154 }
2155 }
2156}
2157
2158impl Error for SidecarResponseTrackerError {}
2159
2160#[derive(Debug, Clone, PartialEq, Eq)]
2161struct PendingRequest {
2162 ownership: OwnershipScope,
2163 expected_response: ExpectedResponseKind,
2164}
2165
2166#[derive(Debug, Clone, PartialEq, Eq)]
2167struct PendingSidecarRequest {
2168 ownership: OwnershipScope,
2169 expected_response: ExpectedSidecarResponseKind,
2170}
2171
2172#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2173enum ExpectedResponseKind {
2174 Authenticated,
2175 SessionOpened,
2176 VmCreated,
2177 VmDisposed,
2178 RootFilesystemBootstrapped,
2179 VmConfigured,
2180 HostCallbacksRegistered,
2181 LayerCreated,
2182 LayerSealed,
2183 SnapshotImported,
2184 SnapshotExported,
2185 OverlayCreated,
2186 GuestFilesystemResult,
2187 RootFilesystemSnapshot,
2188 ProcessStarted,
2189 StdinWritten,
2190 StdinClosed,
2191 ProcessKilled,
2192 ProcessSnapshot,
2193 ResourceSnapshot,
2194 ListenerSnapshot,
2195 BoundUdpSnapshot,
2196 VmFetchResult,
2197 SignalState,
2198 ZombieTimerCount,
2199 FilesystemResult,
2200 #[allow(dead_code)]
2203 PermissionDecision,
2204 PersistenceState,
2205 PersistenceFlushed,
2206 ExtResult,
2207 GuestKernelResult,
2208 PtyResized,
2209 PackageLinked,
2210}
2211
2212#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2213enum ExpectedSidecarResponseKind {
2214 HostCallback,
2215 JsBridge,
2216 Ext,
2217}
2218
2219impl ExpectedResponseKind {
2220 fn as_str(self) -> &'static str {
2221 match self {
2222 Self::Authenticated => "authenticated",
2223 Self::SessionOpened => "session_opened",
2224 Self::VmCreated => "vm_created",
2225 Self::VmDisposed => "vm_disposed",
2226 Self::RootFilesystemBootstrapped => "root_filesystem_bootstrapped",
2227 Self::VmConfigured => "vm_configured",
2228 Self::HostCallbacksRegistered => "host_callbacks_registered",
2229 Self::LayerCreated => "layer_created",
2230 Self::LayerSealed => "layer_sealed",
2231 Self::SnapshotImported => "snapshot_imported",
2232 Self::SnapshotExported => "snapshot_exported",
2233 Self::OverlayCreated => "overlay_created",
2234 Self::GuestFilesystemResult => "guest_filesystem_result",
2235 Self::RootFilesystemSnapshot => "root_filesystem_snapshot",
2236 Self::ProcessStarted => "process_started",
2237 Self::StdinWritten => "stdin_written",
2238 Self::StdinClosed => "stdin_closed",
2239 Self::ProcessKilled => "process_killed",
2240 Self::ProcessSnapshot => "process_snapshot",
2241 Self::ResourceSnapshot => "resource_snapshot",
2242 Self::ListenerSnapshot => "listener_snapshot",
2243 Self::BoundUdpSnapshot => "bound_udp_snapshot",
2244 Self::VmFetchResult => "vm_fetch_result",
2245 Self::SignalState => "signal_state",
2246 Self::ZombieTimerCount => "zombie_timer_count",
2247 Self::FilesystemResult => "filesystem_result",
2248 Self::PermissionDecision => "permission_decision",
2249 Self::PersistenceState => "persistence_state",
2250 Self::PersistenceFlushed => "persistence_flushed",
2251 Self::ExtResult => "ext_result",
2252 Self::GuestKernelResult => "guest_kernel_result",
2253 Self::PtyResized => "pty_resized",
2254 Self::PackageLinked => "package_linked",
2255 }
2256 }
2257
2258 fn matches(self, payload: &ResponsePayload) -> bool {
2259 match payload {
2260 ResponsePayload::Rejected(_) => true,
2261 _ => payload.kind_name() == self.as_str(),
2262 }
2263 }
2264}
2265
2266impl ExpectedSidecarResponseKind {
2267 fn as_str(self) -> &'static str {
2268 match self {
2269 Self::HostCallback => "host_callback_result",
2270 Self::JsBridge => "js_bridge_result",
2271 Self::Ext => "ext_result",
2272 }
2273 }
2274
2275 fn matches(self, payload: &SidecarResponsePayload) -> bool {
2276 payload.kind_name() == self.as_str()
2277 }
2278}
2279
2280impl RequestPayload {
2281 fn ownership_requirement(&self) -> OwnershipRequirement {
2282 match self {
2283 Self::Authenticate(_) | Self::OpenSession(_) => OwnershipRequirement::Connection,
2284 Self::CreateVm(_) | Self::PersistenceLoad(_) | Self::PersistenceFlush(_) => {
2285 OwnershipRequirement::Session
2286 }
2287 Self::DisposeVm(_)
2288 | Self::BootstrapRootFilesystem(_)
2289 | Self::ConfigureVm(_)
2290 | Self::RegisterHostCallbacks(_)
2291 | Self::CreateLayer(_)
2292 | Self::SealLayer(_)
2293 | Self::ImportSnapshot(_)
2294 | Self::ExportSnapshot(_)
2295 | Self::CreateOverlay(_)
2296 | Self::GuestFilesystemCall(_)
2297 | Self::SnapshotRootFilesystem(_)
2298 | Self::Execute(_)
2299 | Self::WriteStdin(_)
2300 | Self::CloseStdin(_)
2301 | Self::KillProcess(_)
2302 | Self::GetProcessSnapshot(_)
2303 | Self::GetResourceSnapshot(_)
2304 | Self::FindListener(_)
2305 | Self::FindBoundUdp(_)
2306 | Self::VmFetch(_)
2307 | Self::GetSignalState(_)
2308 | Self::GetZombieTimerCount(_)
2309 | Self::GuestKernelCall(_)
2310 | Self::ResizePty(_)
2311 | Self::LinkPackage(_)
2312 | Self::HostFilesystemCall(_) => OwnershipRequirement::Vm,
2313 Self::Ext(_) => OwnershipRequirement::Any,
2314 }
2315 }
2316
2317 fn expected_response(&self) -> ExpectedResponseKind {
2318 match self {
2319 Self::Authenticate(_) => ExpectedResponseKind::Authenticated,
2320 Self::OpenSession(_) => ExpectedResponseKind::SessionOpened,
2321 Self::CreateVm(_) => ExpectedResponseKind::VmCreated,
2322 Self::DisposeVm(_) => ExpectedResponseKind::VmDisposed,
2323 Self::BootstrapRootFilesystem(_) => ExpectedResponseKind::RootFilesystemBootstrapped,
2324 Self::ConfigureVm(_) => ExpectedResponseKind::VmConfigured,
2325 Self::RegisterHostCallbacks(_) => ExpectedResponseKind::HostCallbacksRegistered,
2326 Self::CreateLayer(_) => ExpectedResponseKind::LayerCreated,
2327 Self::SealLayer(_) => ExpectedResponseKind::LayerSealed,
2328 Self::ImportSnapshot(_) => ExpectedResponseKind::SnapshotImported,
2329 Self::ExportSnapshot(_) => ExpectedResponseKind::SnapshotExported,
2330 Self::CreateOverlay(_) => ExpectedResponseKind::OverlayCreated,
2331 Self::GuestFilesystemCall(_) => ExpectedResponseKind::GuestFilesystemResult,
2332 Self::SnapshotRootFilesystem(_) => ExpectedResponseKind::RootFilesystemSnapshot,
2333 Self::Execute(_) => ExpectedResponseKind::ProcessStarted,
2334 Self::WriteStdin(_) => ExpectedResponseKind::StdinWritten,
2335 Self::CloseStdin(_) => ExpectedResponseKind::StdinClosed,
2336 Self::KillProcess(_) => ExpectedResponseKind::ProcessKilled,
2337 Self::GetProcessSnapshot(_) => ExpectedResponseKind::ProcessSnapshot,
2338 Self::GetResourceSnapshot(_) => ExpectedResponseKind::ResourceSnapshot,
2339 Self::FindListener(_) => ExpectedResponseKind::ListenerSnapshot,
2340 Self::FindBoundUdp(_) => ExpectedResponseKind::BoundUdpSnapshot,
2341 Self::VmFetch(_) => ExpectedResponseKind::VmFetchResult,
2342 Self::GetSignalState(_) => ExpectedResponseKind::SignalState,
2343 Self::GetZombieTimerCount(_) => ExpectedResponseKind::ZombieTimerCount,
2344 Self::HostFilesystemCall(_) => ExpectedResponseKind::FilesystemResult,
2345 Self::PersistenceLoad(_) => ExpectedResponseKind::PersistenceState,
2346 Self::PersistenceFlush(_) => ExpectedResponseKind::PersistenceFlushed,
2347 Self::Ext(_) => ExpectedResponseKind::ExtResult,
2348 Self::GuestKernelCall(_) => ExpectedResponseKind::GuestKernelResult,
2349 Self::ResizePty(_) => ExpectedResponseKind::PtyResized,
2350 Self::LinkPackage(_) => ExpectedResponseKind::PackageLinked,
2351 }
2352 }
2353}
2354
2355impl SidecarRequestPayload {
2356 fn ownership_requirement(&self) -> OwnershipRequirement {
2357 OwnershipRequirement::Vm
2358 }
2359
2360 fn expected_response(&self) -> ExpectedSidecarResponseKind {
2361 match self {
2362 Self::HostCallback(_) => ExpectedSidecarResponseKind::HostCallback,
2363 Self::JsBridgeCall(_) => ExpectedSidecarResponseKind::JsBridge,
2364 Self::Ext(_) => ExpectedSidecarResponseKind::Ext,
2365 }
2366 }
2367}
2368
2369impl ResponsePayload {
2370 fn ownership_requirement(&self) -> OwnershipRequirement {
2371 match self {
2372 Self::Authenticated(_) | Self::SessionOpened(_) => OwnershipRequirement::Connection,
2373 Self::VmCreated(_) | Self::PersistenceState(_) | Self::PersistenceFlushed(_) => {
2374 OwnershipRequirement::Session
2375 }
2376 Self::Rejected(_) => OwnershipRequirement::Any,
2377 Self::VmDisposed(_)
2378 | Self::RootFilesystemBootstrapped(_)
2379 | Self::VmConfigured(_)
2380 | Self::HostCallbacksRegistered(_)
2381 | Self::LayerCreated(_)
2382 | Self::LayerSealed(_)
2383 | Self::SnapshotImported(_)
2384 | Self::SnapshotExported(_)
2385 | Self::OverlayCreated(_)
2386 | Self::GuestFilesystemResult(_)
2387 | Self::RootFilesystemSnapshot(_)
2388 | Self::ProcessStarted(_)
2389 | Self::StdinWritten(_)
2390 | Self::StdinClosed(_)
2391 | Self::ProcessKilled(_)
2392 | Self::ProcessSnapshot(_)
2393 | Self::ResourceSnapshot(_)
2394 | Self::ListenerSnapshot(_)
2395 | Self::BoundUdpSnapshot(_)
2396 | Self::VmFetchResult(_)
2397 | Self::SignalState(_)
2398 | Self::ZombieTimerCount(_)
2399 | Self::FilesystemResult(_)
2400 | Self::PermissionDecision(_)
2401 | Self::GuestKernelResult(_)
2402 | Self::PtyResized(_)
2403 | Self::PackageLinked(_) => OwnershipRequirement::Vm,
2404 Self::ExtResult(_) => OwnershipRequirement::Any,
2405 }
2406 }
2407
2408 fn kind_name(&self) -> &'static str {
2409 match self {
2410 Self::Authenticated(_) => "authenticated",
2411 Self::SessionOpened(_) => "session_opened",
2412 Self::VmCreated(_) => "vm_created",
2413 Self::VmDisposed(_) => "vm_disposed",
2414 Self::RootFilesystemBootstrapped(_) => "root_filesystem_bootstrapped",
2415 Self::VmConfigured(_) => "vm_configured",
2416 Self::HostCallbacksRegistered(_) => "host_callbacks_registered",
2417 Self::LayerCreated(_) => "layer_created",
2418 Self::LayerSealed(_) => "layer_sealed",
2419 Self::SnapshotImported(_) => "snapshot_imported",
2420 Self::SnapshotExported(_) => "snapshot_exported",
2421 Self::OverlayCreated(_) => "overlay_created",
2422 Self::GuestFilesystemResult(_) => "guest_filesystem_result",
2423 Self::RootFilesystemSnapshot(_) => "root_filesystem_snapshot",
2424 Self::ProcessStarted(_) => "process_started",
2425 Self::StdinWritten(_) => "stdin_written",
2426 Self::StdinClosed(_) => "stdin_closed",
2427 Self::ProcessKilled(_) => "process_killed",
2428 Self::ProcessSnapshot(_) => "process_snapshot",
2429 Self::ResourceSnapshot(_) => "resource_snapshot",
2430 Self::ListenerSnapshot(_) => "listener_snapshot",
2431 Self::BoundUdpSnapshot(_) => "bound_udp_snapshot",
2432 Self::VmFetchResult(_) => "vm_fetch_result",
2433 Self::SignalState(_) => "signal_state",
2434 Self::ZombieTimerCount(_) => "zombie_timer_count",
2435 Self::FilesystemResult(_) => "filesystem_result",
2436 Self::PermissionDecision(_) => "permission_decision",
2437 Self::PersistenceState(_) => "persistence_state",
2438 Self::PersistenceFlushed(_) => "persistence_flushed",
2439 Self::Rejected(_) => "rejected",
2440 Self::ExtResult(_) => "ext_result",
2441 Self::GuestKernelResult(_) => "guest_kernel_result",
2442 Self::PtyResized(_) => "pty_resized",
2443 Self::PackageLinked(_) => "package_linked",
2444 }
2445 }
2446}
2447
2448impl SidecarResponsePayload {
2449 fn ownership_requirement(&self) -> OwnershipRequirement {
2450 OwnershipRequirement::Vm
2451 }
2452
2453 fn kind_name(&self) -> &'static str {
2454 match self {
2455 Self::HostCallbackResult(_) => "host_callback_result",
2456 Self::JsBridgeResult(_) => "js_bridge_result",
2457 Self::ExtResult(_) => "ext_result",
2458 }
2459 }
2460}
2461
2462impl EventPayload {
2463 fn ownership_requirement(&self) -> OwnershipRequirement {
2464 match self {
2465 Self::Structured(_) => OwnershipRequirement::SessionOrVm,
2466 Self::VmLifecycle(_) | Self::ProcessOutput(_) | Self::ProcessExited(_) => {
2467 OwnershipRequirement::Vm
2468 }
2469 Self::Ext(_) => OwnershipRequirement::Any,
2470 }
2471 }
2472}
2473
2474pub fn validate_frame(frame: &ProtocolFrame) -> Result<(), ProtocolCodecError> {
2475 match frame {
2476 ProtocolFrame::Request(request) => validate_request(request),
2477 ProtocolFrame::Response(response) => validate_response(response),
2478 ProtocolFrame::Event(event) => validate_event(event),
2479 ProtocolFrame::SidecarRequest(request) => validate_sidecar_request(request),
2480 ProtocolFrame::SidecarResponse(response) => validate_sidecar_response(response),
2481 }
2482}
2483
2484fn validate_request(request: &RequestFrame) -> Result<(), ProtocolCodecError> {
2485 validate_schema(&request.schema)?;
2486 validate_request_id_direction(request.request_id, RequestDirection::Host)?;
2487
2488 validate_ownership(&request.ownership)?;
2489 validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
2490 if let RequestPayload::Authenticate(authenticate) = &request.payload {
2491 if authenticate.auth_token.is_empty() {
2492 return Err(ProtocolCodecError::EmptyAuthToken);
2493 }
2494 }
2495
2496 Ok(())
2497}
2498
2499fn validate_response(response: &ResponseFrame) -> Result<(), ProtocolCodecError> {
2500 validate_schema(&response.schema)?;
2501 validate_request_id_direction(response.request_id, RequestDirection::Host)?;
2502
2503 validate_ownership(&response.ownership)?;
2504 validate_requirement(
2505 response.payload.ownership_requirement(),
2506 &response.ownership,
2507 )?;
2508 Ok(())
2509}
2510
2511fn validate_sidecar_request(request: &SidecarRequestFrame) -> Result<(), ProtocolCodecError> {
2512 validate_schema(&request.schema)?;
2513 validate_request_id_direction(request.request_id, RequestDirection::Sidecar)?;
2514 validate_ownership(&request.ownership)?;
2515 validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
2516 Ok(())
2517}
2518
2519fn validate_sidecar_response(response: &SidecarResponseFrame) -> Result<(), ProtocolCodecError> {
2520 validate_schema(&response.schema)?;
2521 validate_request_id_direction(response.request_id, RequestDirection::Sidecar)?;
2522 validate_ownership(&response.ownership)?;
2523 validate_requirement(
2524 response.payload.ownership_requirement(),
2525 &response.ownership,
2526 )?;
2527 Ok(())
2528}
2529
2530fn validate_event(event: &EventFrame) -> Result<(), ProtocolCodecError> {
2531 validate_schema(&event.schema)?;
2532 validate_ownership(&event.ownership)?;
2533 validate_requirement(event.payload.ownership_requirement(), &event.ownership)?;
2534 Ok(())
2535}
2536
2537fn validate_schema(schema: &ProtocolSchema) -> Result<(), ProtocolCodecError> {
2538 if schema.name != PROTOCOL_NAME || schema.version != PROTOCOL_VERSION {
2539 return Err(ProtocolCodecError::UnsupportedSchema {
2540 name: schema.name.clone(),
2541 version: schema.version,
2542 });
2543 }
2544
2545 Ok(())
2546}
2547
2548fn validate_ownership(ownership: &OwnershipScope) -> Result<(), ProtocolCodecError> {
2549 match ownership {
2550 OwnershipScope::ConnectionOwnership(inner) => {
2551 validate_non_empty("connection_id", &inner.connection_id)
2552 }
2553 OwnershipScope::SessionOwnership(inner) => {
2554 validate_non_empty("connection_id", &inner.connection_id)?;
2555 validate_non_empty("session_id", &inner.session_id)
2556 }
2557 OwnershipScope::VmOwnership(inner) => {
2558 validate_non_empty("connection_id", &inner.connection_id)?;
2559 validate_non_empty("session_id", &inner.session_id)?;
2560 validate_non_empty("vm_id", &inner.vm_id)
2561 }
2562 }
2563}
2564
2565fn validate_non_empty(field: &'static str, value: &str) -> Result<(), ProtocolCodecError> {
2566 if value.is_empty() {
2567 return Err(ProtocolCodecError::EmptyOwnershipField { field });
2568 }
2569
2570 Ok(())
2571}
2572
2573fn validate_request_id_direction(
2574 request_id: RequestId,
2575 direction: RequestDirection,
2576) -> Result<(), ProtocolCodecError> {
2577 if request_id == 0 {
2578 return Err(ProtocolCodecError::InvalidRequestId);
2579 }
2580
2581 let matches_direction = match direction {
2582 RequestDirection::Host => request_id > 0,
2583 RequestDirection::Sidecar => request_id < 0,
2584 };
2585 if matches_direction {
2586 Ok(())
2587 } else {
2588 Err(ProtocolCodecError::InvalidRequestDirection {
2589 request_id,
2590 expected: direction,
2591 })
2592 }
2593}
2594
2595fn validate_requirement(
2596 required: OwnershipRequirement,
2597 ownership: &OwnershipScope,
2598) -> Result<(), ProtocolCodecError> {
2599 let actual = match ownership {
2600 OwnershipScope::ConnectionOwnership(..) => OwnershipRequirement::Connection,
2601 OwnershipScope::SessionOwnership(..) => OwnershipRequirement::Session,
2602 OwnershipScope::VmOwnership(..) => OwnershipRequirement::Vm,
2603 };
2604
2605 let valid = match required {
2606 OwnershipRequirement::Any => true,
2607 OwnershipRequirement::Connection => {
2608 matches!(ownership, OwnershipScope::ConnectionOwnership(..))
2609 }
2610 OwnershipRequirement::Session => matches!(ownership, OwnershipScope::SessionOwnership(..)),
2611 OwnershipRequirement::Vm => matches!(ownership, OwnershipScope::VmOwnership(..)),
2612 OwnershipRequirement::SessionOrVm => {
2613 matches!(
2614 ownership,
2615 OwnershipScope::SessionOwnership(..) | OwnershipScope::VmOwnership(..)
2616 )
2617 }
2618 };
2619
2620 if valid {
2621 Ok(())
2622 } else {
2623 Err(ProtocolCodecError::InvalidOwnershipScope { required, actual })
2624 }
2625}
2626
2627#[derive(Debug, Deserialize, Default)]
2632pub struct JavascriptChildProcessSpawnOptions {
2633 #[serde(default)]
2634 pub cwd: Option<String>,
2635 #[serde(default)]
2636 pub env: BTreeMap<String, String>,
2637 #[serde(rename = "internalBootstrapEnv", default)]
2638 pub internal_bootstrap_env: BTreeMap<String, String>,
2639 #[serde(default)]
2640 pub input: Option<Value>,
2641 #[serde(default)]
2642 pub shell: bool,
2643 #[serde(default)]
2644 pub detached: bool,
2645 #[serde(default)]
2646 pub stdio: Vec<String>,
2647 #[serde(default)]
2648 pub timeout: Option<u64>,
2649 #[serde(rename = "killSignal", default)]
2650 pub kill_signal: Option<String>,
2651}
2652
2653#[derive(Debug, Deserialize)]
2654pub struct JavascriptChildProcessSpawnRequest {
2655 pub command: String,
2656 #[serde(default)]
2657 pub args: Vec<String>,
2658 #[serde(default)]
2659 pub options: JavascriptChildProcessSpawnOptions,
2660}
2661
2662#[derive(Debug, Deserialize)]
2663pub struct JavascriptNetConnectRequest {
2664 #[serde(default)]
2665 pub host: Option<String>,
2666 #[serde(default)]
2667 pub port: Option<u16>,
2668 #[serde(default)]
2669 pub path: Option<String>,
2670 #[serde(rename = "localAddress", default)]
2671 pub local_address: Option<String>,
2672 #[serde(rename = "localPort", default)]
2673 pub local_port: Option<u16>,
2674 #[serde(rename = "localReservation", default)]
2675 pub local_reservation: Option<String>,
2676}
2677
2678#[derive(Debug, Deserialize)]
2679pub struct JavascriptNetReserveTcpPortRequest {
2680 #[serde(default)]
2681 pub host: Option<String>,
2682 #[serde(default)]
2683 pub port: Option<u16>,
2684}
2685
2686#[derive(Debug, Deserialize)]
2687pub struct JavascriptNetListenRequest {
2688 #[serde(default)]
2689 pub host: Option<String>,
2690 #[serde(default)]
2691 pub port: Option<u16>,
2692 #[serde(default)]
2693 pub path: Option<String>,
2694 #[serde(default)]
2695 pub backlog: Option<u32>,
2696 #[serde(rename = "localReservation", default)]
2697 pub local_reservation: Option<String>,
2698}
2699
2700#[derive(Debug, Deserialize)]
2701pub struct JavascriptDgramCreateSocketRequest {
2702 #[serde(rename = "type")]
2703 pub socket_type: String,
2704}
2705
2706#[derive(Debug, Deserialize)]
2707pub struct JavascriptDgramBindRequest {
2708 #[serde(default)]
2709 pub address: Option<String>,
2710 #[serde(default)]
2711 pub port: u16,
2712}
2713
2714#[derive(Debug, Deserialize)]
2715pub struct JavascriptDgramSendRequest {
2716 #[serde(default)]
2717 pub address: Option<String>,
2718 pub port: u16,
2719}
2720
2721#[derive(Debug, Deserialize)]
2722pub struct JavascriptDnsLookupRequest {
2723 pub hostname: String,
2724 #[serde(default)]
2725 pub family: Option<u8>,
2726}
2727
2728#[derive(Debug, Deserialize)]
2729pub struct JavascriptDnsResolveRequest {
2730 pub hostname: String,
2731 #[serde(default)]
2732 pub rrtype: Option<String>,
2733}