mirror of
https://github.com/nestriness/nestri.git
synced 2026-09-19 17:25:19 +03:00
feat(nesinit): carry the session's address out of the guest
Whatever serves media in a box knows how it can be reached, and the person who needs to know is not in the box. Standard output here is a log file inside a VM, so the control channel is the delivery path rather than a convenience -- which makes this init's job and not a detail of whichever component happens to bind the port. The socket it reads was already documented as being read this way; nothing read it. Polled rather than read once, because an address is not a value but the best answer so far. An endpoint discovers more ways to reach it after it binds, so the first answer is the one that works on a local network and fails from anywhere else. Only a changed answer is forwarded. It dials rather than listens, which is the opposite of the relay next door and deliberate: there the guest listens because the workload starts later, and here the server is the long-lived one. Dialling also makes a server that has not bound yet something to retry rather than something to wait for without knowing whether it is coming. The address itself is never logged. It is a capability to reach the session, and a log inside the guest is the one place it has no reason to be. A carrier that stops does not end a session: whatever was already reported is still correct, and the workload's exit still has to be.
This commit is contained in:
@@ -4,13 +4,14 @@
|
||||
// the workload the channel describes, and turn the end of either into an
|
||||
// ordered shutdown.
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
|
||||
use nesinit::payload::{self, Ports};
|
||||
use nesinit::reap::{self, Waiters};
|
||||
use nesinit::session::{self, Outcome};
|
||||
use nesinit::shutdown::{self, Machine};
|
||||
use nesinit::ticket;
|
||||
use nesinit::workload::{Process, Workload};
|
||||
use nesprotocol::lifecycle::CONTROL_PORT;
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
@@ -25,6 +26,13 @@ const GRACE: Duration = Duration::from_secs(10);
|
||||
/// deep queue holds stale copies of it rather than protecting anything.
|
||||
const RELAY_DEPTH: usize = 8;
|
||||
|
||||
/// How many addresses may be waiting to be forwarded.
|
||||
///
|
||||
/// Two, because only the newest one matters: an address is superseded by the
|
||||
/// next one rather than added to, so a deeper queue holds stale copies of it
|
||||
/// and delays the one that is current.
|
||||
const ADDRESS_DEPTH: usize = 2;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
@@ -97,8 +105,14 @@ async fn guest(waiters: &Waiters, workload: &mut Process) -> anyhow::Result<Outc
|
||||
from_workload: up_rx,
|
||||
};
|
||||
|
||||
// Started before the workload, like the relay, and for the same reason:
|
||||
// whatever serves the address may bind the moment it comes up, and nothing
|
||||
// here should be the reason a session waits to be reachable.
|
||||
let (found_tx, mut found_rx) = tokio::sync::mpsc::channel(ADDRESS_DEPTH);
|
||||
tokio::spawn(ticket::carry(PathBuf::from(ticket::SOCKET), found_tx));
|
||||
|
||||
let outcome = tokio::select! {
|
||||
outcome = session::run(channel, workload, &mut ports) => outcome?,
|
||||
outcome = session::run(channel, workload, &mut ports, &mut found_rx) => outcome?,
|
||||
signal = asked_to_stop() => {
|
||||
signal?;
|
||||
tracing::info!("asked to stop");
|
||||
|
||||
Reference in New Issue
Block a user