# Native WebRTC voice validation

The `libremetaverse-voice-webrtc` native API owns the complete WebRTC voice
path. `WebRtcVoiceSession::connect` binds a caller-selected interface, creates
an Opus send/receive m-line and ordered `SLData` channel, posts the grid's
provision body through a `VoiceSignaling` implementation, applies the SDP
answer, and drives ICE, DTLS, SRTP, RTP, and SCTP from a single async run loop.
There is no CLR, C# process, RPC bridge, proprietary SDK, or platform-specific
fallback.

The grid wire shapes match the viewer protocol:

- Initial provisioning uses `jsep.type=offer`, `channel_type=local`, and
  `voice_server_type=webrtc`, with an optional top-level `parcel_local_id`.
- ICE completion uses the singular `candidate: { completed: true }` field and
  the opaque viewer-session ID.
- Teardown sends `logout=true`, then disconnects and joins the local peer loop.

Capability URLs, SDP, channel credentials, login secrets, and viewer-session
credentials are not printed. `VoiceSecret` always formats as `<redacted>`.
Incoming SDP and `SLData` messages are bounded and validated before use.

## Deterministic validation

`webrtc-test --fake` is the CI path. `LoopbackSignaling` accepts the real offer,
creates a second native peer, and exchanges UDP ICE checks, DTLS, encrypted
Opus RTP, and SCTP `SLData` on loopback. It publishes peer audio/position and
mute/gain maps; the client replies with join, mute, clamped gain, position,
ping/pong, and leave. A generated virtual 48 kHz tone is encoded with libopus,
echoed by the remote peer, decoded into the virtual sink, and counted. Shutdown
awaits both peers and reports zero peer/audio tasks.

WAV playback accepts bounded integer or float PCM, downmixes all channels,
linearly resamples to 48 kHz mono, encodes 20 ms Opus frames, and paces them on
the same peer loop. This keeps virtual-audio tests deterministic and prevents
orphan playback tasks.

## Native prerequisites

The default virtual path requires native libopus development files at build
time. Typical packages are:

- Ubuntu/Debian: `libopus-dev` (and `pkg-config`).
- Fedora: `opus-devel`.
- Windows MSVC: `audiopus` supplies supported prebuilt Opus libraries; a custom
  libopus can be selected with `OPUS_LIB_DIR`/`LIBOPUS_LIB_DIR`.
- macOS: install `opus` with the system package manager when it is not already
  discoverable by `pkg-config`.

Real hardware is separately opt-in. Build the program with
`--features real-audio`; CPAL uses ALSA on Linux, WASAPI on Windows, and
CoreAudio on macOS. Linux builders need ALSA development headers (for example
`libasound2-dev`). List stable endpoint IDs with `webrtc-test --list-devices`,
then pass `--input-device cpal:input:...` and/or
`--output-device cpal:output:...`. Selected capture and render streams are
opened only during the session and dropped after the peer loop is joined.

## Live grid gate

Credential-only capability validation:

```sh
webrtc-test --allow-live-login --confirm-live-login LOGIN
```

The command reads `GRID_USER="First Last"`, `GRID_PASSWORD`, and
`GRID_LOGIN_URL` from the process environment or the workspace `.env`, matching
the compatibility-test convention. Positional names/password and the legacy
`GRID_FIRST_NAME`/`GRID_LAST_NAME` pair remain supported. Merely having a
credential file never permits a login: both command-line confirmations above
are still mandatory.

Creating a live voice session and sending/receiving media requires the separate
`--allow-session-audio` flag. `--bind-ip` can select the concrete interface
advertised in the host ICE candidate; otherwise the program discovers the
preferred route without sending a packet. `--wav FILE` starts looping microphone
playback. Interactive commands preserve the upstream tool's `peers`, `mute`,
`gain`, `playwav`, `stopwav`, and `quit` controls; `--commands FILE` supplies the
same commands non-interactively. Grid logout and voice teardown run even when
the validation body fails.
