Forward a local port to a sandbox via SSH. Background mode keeps the spawned `ssh -N` child alive and records that PID for later management via [`stop_forward`] or [`list_forwards`].
(
server: &str,
name: &str,
spec: &ForwardSpec,
background: bool,
tls: &TlsOptions,
)
| 326 | /// Background mode keeps the spawned `ssh -N` child alive and records that PID |
| 327 | /// for later management via [`stop_forward`] or [`list_forwards`]. |
| 328 | pub async fn sandbox_forward( |
| 329 | server: &str, |
| 330 | name: &str, |
| 331 | spec: &ForwardSpec, |
| 332 | background: bool, |
| 333 | tls: &TlsOptions, |
| 334 | ) -> Result<()> { |
| 335 | openshell_core::forward::check_port_available(spec)?; |
| 336 | |
| 337 | let session = ssh_session_config(server, name, tls).await?; |
| 338 | |
| 339 | let mut command = TokioCommand::from(ssh_base_command(&session.proxy_command)); |
| 340 | command |
| 341 | .arg("-N") |
| 342 | .arg("-o") |
| 343 | .arg("ExitOnForwardFailure=yes") |
| 344 | .arg("-L") |
| 345 | .arg(spec.ssh_forward_arg()); |
| 346 | |
| 347 | command.arg("sandbox"); |
| 348 | |
| 349 | if background { |
| 350 | command |
| 351 | .kill_on_drop(false) |
| 352 | .stdin(Stdio::null()) |
| 353 | .stdout(Stdio::inherit()) |
| 354 | .stderr(Stdio::inherit()); |
| 355 | } else { |
| 356 | command |
| 357 | .stdin(Stdio::inherit()) |
| 358 | .stdout(Stdio::inherit()) |
| 359 | .stderr(Stdio::inherit()); |
| 360 | } |
| 361 | |
| 362 | let port = spec.port; |
| 363 | |
| 364 | if background { |
| 365 | let mut child = command.spawn().into_diagnostic()?; |
| 366 | let pid = child.id().ok_or_else(|| { |
| 367 | miette::miette!("ssh process did not expose a PID for background tracking") |
| 368 | })?; |
| 369 | |
| 370 | if let Err(err) = wait_for_forward_start(&mut child, spec) |
| 371 | .await |
| 372 | .wrap_err("ssh process started but local forward listener was not reachable") |
| 373 | { |
| 374 | terminate_owned_forward_child(&mut child); |
| 375 | return Err(err); |
| 376 | } |
| 377 | |
| 378 | track_background_forward_or_cleanup( |
| 379 | name, |
| 380 | port, |
| 381 | pid, |
| 382 | &session.sandbox_id, |
| 383 | &spec.bind_addr, |
| 384 | || terminate_owned_forward_child(&mut child), |
| 385 | )?; |