# `Hyper.Node.FireVMM.Agent.Relay`
[🔗](https://github.com/harmont-dev/hyper/blob/main/lib/hyper/node/fire_vmm/agent/relay.ex#L1)

Per-VM gRPC relay: listens on a host Unix-domain socket and for each
inbound connection performs the Firecracker vsock CONNECT/OK handshake
via `RelayDialer`, then pipes bytes bidirectionally until either side
closes.

Process topology:
- The GenServer owns the listen socket and spawns a linked acceptor
  process via `handle_continue`. The acceptor blocks on `:socket.accept`
  without blocking the GenServer itself.
- Each accepted connection spawns an unlinked connection process that
  calls `RelayDialer.dial/3` then spawns two linked+monitored pipe workers
  (one per direction). The link ensures a connection handler death reaps
  both workers; the monitor lets the handler react to a worker's normal end
  and close both sockets cleanly. When either worker ends, the handler
  unlinks the sibling before killing it so the resulting `:killed` exit does
  not cascade back to the handler via the link.
- `terminate/2` closes the listen socket (which causes the acceptor to
  exit on its next accept call) and removes the socket file so a
  subsequent `start_link` with the same path can rebind.

# `child_spec`

```elixir
@spec child_spec(%{vm_id: term(), vsock_uds: Path.t(), listen_path: Path.t()}) ::
  Supervisor.child_spec()
```

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `listen_path`

```elixir
@spec listen_path(GenServer.server()) :: Path.t()
```

# `start_link`

```elixir
@spec start_link(%{
  :vm_id =&gt; term(),
  :vsock_uds =&gt; Path.t(),
  :listen_path =&gt; Path.t(),
  optional(:name) =&gt; GenServer.name()
}) :: GenServer.on_start()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
