mirror of
https://github.com/nestriness/nestri.git
synced 2026-09-19 09:15:19 +03:00
The component nescapture, neswire and nescope all talk to, and the only thing in the guest that speaks to the client. It muxes their frames into one iroh QUIC endpoint and fans input back. Renamed from nestri-guest-hub, which named a location rather than a job. Four files came across unchanged -- session.rs, ipc_listener.rs, ticket.rs, screenshot.rs. Between them they mention Steam zero times, and they import only nesprotocol's open modules; the control feature carrying LaunchIntent and SteamIdentity is used exclusively by the three files that are staying closed. The two clusters shared a main.rs and nothing else, so there was no untangling to do -- only a cut. main.rs loses --proton, --steamclient-so, --root and the game uid/gid, and no longer ends by handing the process to a controller. It runs until it is stopped. Deciding when the box is finished belongs to nesinit. The ticket used to leave via that controller, so it needed a new way out: neshub now serves it on a socket and nesinit dials for it. Listening rather than dialling matches every other socket here and means no startup ordering to get wrong. Three tests, where there were none -- the ticket crosses a process boundary as text now, so a round trip that drops a field would otherwise be found by whoever cannot connect.
51 lines
2.1 KiB
Markdown
51 lines
2.1 KiB
Markdown
## neshub
|
|
|
|
One connection out of the box.
|
|
|
|
Everything inside the guest that produces or consumes a stream talks to neshub
|
|
over a Unix socket. neshub muxes it all into a single [iroh](https://www.iroh.computer)
|
|
QUIC endpoint and fans client input back the other way. A client dials that
|
|
endpoint with a *ticket* and gets video, audio, cursor and stats on it.
|
|
|
|
### The sockets
|
|
|
|
| socket | default | direction | carries |
|
|
| --- | --- | --- | --- |
|
|
| `--video-ipc` | `/tmp/nestri-video.sock` | nescapture → neshub | encoded video frames |
|
|
| `--audio-ipc` | `/tmp/nestri-audio.sock` | neswire → neshub | Opus packets |
|
|
| `--input-ipc` | `/tmp/nestri-input.sock` | neshub ↔ nescope | input out, cursor and stats back |
|
|
| `--stats-ipc` | `/tmp/nestri-stats.sock` | nescapture → neshub | encoder stats |
|
|
| `--screenshot-ipc` | `/tmp/nestri-screenshot.sock` | neshub → nescope | a picture of the screen, on request |
|
|
| `--ticket-ipc` | `/tmp/nestri-ticket.sock` | neshub → nesinit | the ticket, once |
|
|
| — | `/tmp/nescapture-cmd.sock` | neshub → nescapture | IDR requests, encode settings |
|
|
|
|
neshub is the listener on every one of them and the other side dials in. That
|
|
is deliberate: it removes the startup ordering problem entirely, since a
|
|
producer that is not running yet simply has not connected yet.
|
|
|
|
### The ticket
|
|
|
|
```
|
|
nestri:<base64 of {endpoint_addr, stream_name}>
|
|
```
|
|
|
|
Generated once per boot, when the endpoint binds. It is served on a socket
|
|
rather than printed because stdout here is a log file inside a virtual machine
|
|
and the person who needs it is outside one — `nesinit` reads it and carries it
|
|
to the host.
|
|
|
|
### What it does not do
|
|
|
|
neshub does not start the payload, know its name, or decide when the box is
|
|
finished — `nesinit` owns all three, and shuts the VM down around this process.
|
|
The same neshub binary serves a game, a desktop, or anything else that draws to
|
|
`nescope`, because it never learns which one it is looking at.
|
|
|
|
### Running it
|
|
|
|
```bash
|
|
cargo run --bin neshub # every socket at its default
|
|
cargo run --bin neshub -- --relay none # direct connections only
|
|
RUST_LOG=neshub=debug cargo run --bin neshub
|
|
```
|