Skip to main content

plugin_host/
sandbox.rs

1/// Modo de sandboxing de un plugin.
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum SandboxMode {
4    /// Plugin corre en el mismo proceso que la DAW.
5    /// Máximo rendimiento, mínima latencia.
6    /// Si el plugin crashea, crashea la DAW.
7    InProcess,
8
9    /// Plugin corre en un proceso hijo separado.
10    /// Si crashea, la DAW puede recuperarse y recargar el plugin.
11    /// Comunicación via shared memory para los buffers de audio
12    /// (evita copia de datos entre procesos).
13    OutOfProcess,
14}
15
16impl Default for SandboxMode {
17    fn default() -> Self {
18        // Por defecto in-process para compatibilidad máxima
19        // El usuario puede cambiar a OutOfProcess plugins que crashean frecuentemente
20        Self::InProcess
21    }
22}
23
24/// Configuración de sandboxing por plugin.
25#[derive(Debug, Clone)]
26pub struct SandboxConfig {
27    pub mode: SandboxMode,
28    /// Timeout en ms para llamadas IPC (solo OutOfProcess)
29    pub ipc_timeout_ms: u32,
30    /// Si true, reintentar automáticamente si el proceso hijo muere
31    pub auto_restart: bool,
32    /// Máximo número de reinicios antes de desactivar el plugin
33    pub max_restarts: u32,
34}
35
36impl Default for SandboxConfig {
37    fn default() -> Self {
38        Self {
39            mode: SandboxMode::InProcess,
40            ipc_timeout_ms: 100,
41            auto_restart: true,
42            max_restarts: 3,
43        }
44    }
45}
46
47impl SandboxConfig {
48    pub fn in_process() -> Self {
49        Self { mode: SandboxMode::InProcess, ..Default::default() }
50    }
51
52    pub fn out_of_process() -> Self {
53        Self { mode: SandboxMode::OutOfProcess, ..Default::default() }
54    }
55}
56
57/// Estado del proceso sandbox (solo relevante en OutOfProcess).
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum SandboxState {
60    /// Proceso hijo corriendo normalmente
61    Running,
62    /// Proceso hijo murió — en proceso de reinicio
63    Restarting,
64    /// Demasiados crashes — plugin desactivado
65    Disabled,
66    /// No aplica (InProcess)
67    NotApplicable,
68}
69
70/// Handle al proceso sandbox de un plugin OutOfProcess.
71/// En producción wrappea un `std::process::Child`.
72pub struct SandboxProcess {
73    pub state: SandboxState,
74    pub restart_count: u32,
75    pub config: SandboxConfig,
76}
77
78impl SandboxProcess {
79    pub fn new(config: SandboxConfig) -> Self {
80        Self {
81            state: if config.mode == SandboxMode::OutOfProcess {
82                SandboxState::Running
83            } else {
84                SandboxState::NotApplicable
85            },
86            restart_count: 0,
87            config,
88        }
89    }
90
91    /// Llamar cuando el proceso hijo muere inesperadamente.
92    pub fn on_crash(&mut self) -> SandboxState {
93        self.restart_count += 1;
94        if self.config.auto_restart && self.restart_count <= self.config.max_restarts {
95            self.state = SandboxState::Restarting;
96        } else {
97            self.state = SandboxState::Disabled;
98        }
99        self.state
100    }
101
102    pub fn on_restart_success(&mut self) {
103        self.state = SandboxState::Running;
104    }
105
106    pub fn is_alive(&self) -> bool {
107        matches!(self.state, SandboxState::Running | SandboxState::NotApplicable)
108    }
109}