hyperlight_js/sandbox/sandbox_builder.rs
1#[cfg(target_os = "linux")]
2use std::time::Duration;
3
4use hyperlight_host::sandbox::{is_hypervisor_present, SandboxConfiguration};
5use hyperlight_host::{GuestBinary, HyperlightError, Result};
6
7use super::proto_js_sandbox::ProtoJSSandbox;
8use crate::HostPrintFn;
9
10/// A builder for a ProtoJSSandbox
11pub struct SandboxBuilder {
12 config: SandboxConfiguration,
13 host_print_fn: Option<HostPrintFn>,
14}
15
16const MIN_STACK_SIZE: u64 = 256 * 1024;
17// The minimum heap size is 4096KB.
18const MIN_HEAP_SIZE: u64 = 4096 * 1024;
19
20impl SandboxBuilder {
21 /// Create a new SandboxBuilder
22 pub fn new() -> Self {
23 let mut config = SandboxConfiguration::default();
24 config.set_stack_size(MIN_STACK_SIZE);
25 config.set_heap_size(MIN_HEAP_SIZE);
26
27 Self {
28 config,
29 host_print_fn: None,
30 }
31 }
32
33 /// Set the host print function
34 pub fn with_host_print_fn(mut self, host_print_fn: HostPrintFn) -> Self {
35 self.host_print_fn = Some(host_print_fn);
36 self
37 }
38
39 /// Set the guest output buffer size
40 pub fn with_guest_output_buffer_size(mut self, guest_output_buffer_size: usize) -> Self {
41 self.config.set_output_data_size(guest_output_buffer_size);
42 self
43 }
44
45 /// Set the guest input buffer size
46 /// This is the size of the buffer that the guest can write to
47 /// to send data to the host
48 /// The host can read from this buffer
49 /// The guest can write to this buffer
50 pub fn with_guest_input_buffer_size(mut self, guest_input_buffer_size: usize) -> Self {
51 self.config.set_input_data_size(guest_input_buffer_size);
52 self
53 }
54
55 /// Set the guest stack size
56 /// This is the size of the stack that code executing in the guest can use.
57 /// If this value is too small then the guest will fail with a stack overflow error
58 /// The default value (and minimum) is set to the value of the MIN_STACK_SIZE const.
59 pub fn with_guest_stack_size(mut self, guest_stack_size: u64) -> Self {
60 if guest_stack_size > MIN_STACK_SIZE {
61 self.config.set_stack_size(guest_stack_size);
62 }
63 self
64 }
65
66 /// Set the guest heap size
67 /// This is the size of the heap that code executing in the guest can use.
68 /// If this value is too small then the guest will fail, usually with a malloc failed error
69 /// The default (and minimum) value for this is set to the value of the MIN_HEAP_SIZE const.
70 pub fn with_guest_heap_size(mut self, guest_heap_size: u64) -> Self {
71 if guest_heap_size > MIN_HEAP_SIZE {
72 self.config.set_heap_size(guest_heap_size);
73 }
74 self
75 }
76
77 /// Sets the offset from `SIGRTMIN` to determine the real-time signal used for
78 /// interrupting the VCPU thread.
79 ///
80 /// The final signal number is computed as `SIGRTMIN + offset`, and it must fall within
81 /// the valid range of real-time signals supported by the host system.
82 ///
83 /// Returns Ok(()) if the offset is valid, or an error if it exceeds the maximum real-time signal number.
84 #[cfg(target_os = "linux")]
85 pub fn set_interrupt_vcpu_sigrtmin_offset(&mut self, offset: u8) -> Result<()> {
86 self.config.set_interrupt_vcpu_sigrtmin_offset(offset)?;
87 Ok(())
88 }
89
90 /// Sets the interrupt retry delay
91 /// This controls the delay between sending signals to the VCPU thread to interrupt it.
92 #[cfg(target_os = "linux")]
93 pub fn with_interrupt_retry_delay(mut self, delay: Duration) -> Self {
94 self.config.set_interrupt_retry_delay(delay);
95 self
96 }
97
98 /// Get the current configuration
99 pub fn get_config(&self) -> &SandboxConfiguration {
100 &self.config
101 }
102
103 /// Enable or disable crashdump generation for the sandbox
104 /// When enabled, core dumps will be generated when the guest crashes
105 /// This requires the `crashdump` feature to be enabled
106 #[cfg(feature = "crashdump")]
107 pub fn with_crashdump_enabled(mut self, enabled: bool) -> Self {
108 self.config.set_guest_core_dump(enabled);
109 self
110 }
111
112 /// Enable debugging for the guest runtime
113 /// This will allow the guest runtime to be natively debugged using GDB or
114 /// other debugging tools
115 ///
116 /// # Example:
117 /// ```rust
118 /// use hyperlight_js::SandboxBuilder;
119 /// let sandbox = SandboxBuilder::new()
120 /// .with_debugging_enabled(8080) // Enable debugging on port 8080
121 /// .build()
122 /// .expect("Failed to build sandbox");
123 /// ```
124 /// # Note:
125 /// This method is only available when the `gdb` feature is enabled
126 /// and the code is compiled in debug mode.
127 #[cfg(all(feature = "gdb", debug_assertions))]
128 pub fn with_debugging_enabled(mut self, port: u16) -> Self {
129 let debug_info = hyperlight_host::sandbox::config::DebugInfo { port };
130 self.config.set_guest_debug_info(debug_info);
131 self
132 }
133
134 /// Build the ProtoJSSandbox
135 pub fn build(self) -> Result<ProtoJSSandbox> {
136 if !is_hypervisor_present() {
137 return Err(HyperlightError::NoHypervisorFound());
138 }
139 let guest_binary = GuestBinary::Buffer(super::JSRUNTIME);
140 let proto_js_sandbox =
141 ProtoJSSandbox::new(guest_binary, Some(self.config), self.host_print_fn)?;
142 Ok(proto_js_sandbox)
143 }
144}
145
146impl Default for SandboxBuilder {
147 fn default() -> Self {
148 Self::new()
149 }
150}