Retire legacy sources and verify managed iOS deployment
This commit is contained in:
+46
-166
@@ -1,182 +1,62 @@
|
||||
# VoiceCat .NET rewrite
|
||||
# VoiceCat .NET implementation
|
||||
|
||||
The .NET 10 implementation includes protocol, TLS/TOFU and media crypto, the control and
|
||||
UDP server, client state, real-time audio, a console client and the Windows application.
|
||||
The existing C++ implementation remains the conformance oracle while Apple clients move.
|
||||
This is the supported VoiceCat implementation. It contains the protocol, TLS and media
|
||||
cryptography, server, client state, codec/DSP bindings, audio engine, and headless CLI.
|
||||
|
||||
Codec/DSP wrappers now cover Opus, DRED recovery, RNNoise, and energy VAD. Build
|
||||
the desktop native library before running their tests (CMake and a C compiler required):
|
||||
## Build and test
|
||||
|
||||
Stage the small native Opus/RNNoise library, then build the managed solution:
|
||||
|
||||
```powershell
|
||||
./dotnet/build-native.ps1
|
||||
```
|
||||
|
||||
The script downloads upstream Opus 1.5.2 with a pinned SHA-256, builds DRED-enabled
|
||||
Opus and the existing vendored RNNoise model, and stages `voicecat_media` plus license
|
||||
notices under `dotnet/artifacts/native/`. It builds independently of the C++ core and
|
||||
vcpkg. On Windows, Visual Studio's C++ workload works with the default generator;
|
||||
for this repository's MinGW toolchain use:
|
||||
|
||||
```powershell
|
||||
./dotnet/build-native.ps1 -Generator Ninja -CCompiler C:/tools/msys64/ucrt64/bin/cc.exe
|
||||
```
|
||||
|
||||
Linux/macOS can run the same script with PowerShell, or use CMake directly:
|
||||
|
||||
```sh
|
||||
cmake -S dotnet/native -B dotnet/artifacts/native-build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build dotnet/artifacts/native-build --target voicecat_media --parallel 2
|
||||
cmake --install dotnet/artifacts/native-build --component DotnetMedia --prefix dotnet/artifacts/native
|
||||
```
|
||||
|
||||
MSBuild copies the staged library into managed build/publish output for the selected
|
||||
RID. Override `VoiceCatNativeRid` or `VoiceCatNativeDirectory` for explicit staging;
|
||||
`RuntimeIdentifier` takes priority over the SDK's host RID. Cross-compilation is not
|
||||
automatic. iOS static linking and audio-device shims belong to later client phases.
|
||||
Native codec/DSP tests require this library; they do not silently skip.
|
||||
|
||||
From the repository root:
|
||||
|
||||
```powershell
|
||||
dotnet restore dotnet/VoiceCat.slnx --locked-mode
|
||||
dotnet build dotnet/VoiceCat.slnx -c Release --no-restore
|
||||
dotnet test dotnet/VoiceCat.slnx -c Release --no-build
|
||||
./dotnet/check-licenses.ps1
|
||||
```
|
||||
|
||||
Run the managed console client interactively:
|
||||
The native source lives in `native/media` and `native/rnnoise`; build output is staged under
|
||||
`dotnet/artifacts/native`. The shim exposes only fixed Opus/DRED and RNNoise entry points. It
|
||||
does not contain protocol, networking, cryptography, client state, or server behavior.
|
||||
|
||||
For an explicit native build:
|
||||
|
||||
```bash
|
||||
cmake -S native/media -B dotnet/artifacts/native-build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build dotnet/artifacts/native-build --target voicecat_media --parallel 2
|
||||
cmake --install dotnet/artifacts/native-build --component DotnetMedia \
|
||||
--prefix dotnet/artifacts/native
|
||||
```
|
||||
|
||||
## Projects
|
||||
|
||||
- `VoiceCat.Protocol` — generated protobuf types and bounded control framing.
|
||||
- `VoiceCat.Crypto` — BouncyCastle TLS 1.3/exporters, TOFU, identity, AEAD, replay protection,
|
||||
and Argon2id.
|
||||
- `VoiceCat.Codec` / `VoiceCat.Dsp` — managed owners of the narrow native media ABI.
|
||||
- `VoiceCat.Audio` — jitter, loss recovery, mixing, input activation, and PCM rings.
|
||||
- `VoiceCat.Core` — managed client connection and session state.
|
||||
- `VoiceCat.Server` — TLS control, encrypted UDP relay, SQLite state, administration, and CLI.
|
||||
- `VoiceCat.Cli` — supported interactive and deterministic headless client.
|
||||
- `VoiceCat.Tests` — managed unit, integration, allocation, and end-to-end behavior tests.
|
||||
|
||||
`proto/voicecat.proto` is the only protobuf schema. Generated C# is build output.
|
||||
|
||||
## Run
|
||||
|
||||
```powershell
|
||||
dotnet run --project dotnet/src/VoiceCat.Cli -- --host 127.0.0.1 --port 8384 --nickname Alice --trust-first
|
||||
dotnet run --project dotnet/src/VoiceCat.Server -- --data-dir ./voicecat-data
|
||||
dotnet run --project dotnet/src/VoiceCat.Cli -- \
|
||||
--host 127.0.0.1 --port 8384 --nickname Alice --trust-first
|
||||
```
|
||||
|
||||
Plain input sends channel text; `/join ID` changes channel and `/quit` exits. Headless
|
||||
conformance options include `--voice`, `--send-text`, `--expect-text`, `--expect-voice`,
|
||||
`--start-delay-ms` and `--timeout-seconds`; `--help` lists the complete syntax.
|
||||
Use `--help` on either executable for current options. Server publishing is handled by
|
||||
`dotnet/publish-server.ps1` and the platform packaging files under `packaging/`.
|
||||
|
||||
Dependencies are pinned in project files and lock files. Generated protobuf is build
|
||||
output; the schema remains `core/proto/voicecat.proto`. Production dependencies are
|
||||
Google.Protobuf (BSD-3-Clause), BouncyCastle.Cryptography (MIT), and the build-only
|
||||
Grpc.Tools (Apache-2.0). No GPL/LGPL dependencies are permitted.
|
||||
## Compatibility policy
|
||||
|
||||
## C# conventions
|
||||
|
||||
Use file-scoped namespaces, standard .NET naming, immutable values where useful, and
|
||||
spans for binary data. Invalid arguments throw; invalid network packets use parsing
|
||||
results or protocol exceptions. Async APIs accept cancellation tokens.
|
||||
|
||||
Comments explain constraints that cannot be made clear in code. Avoid banners,
|
||||
implementation history, and narration. Keep durable design explanations in `docs/`.
|
||||
|
||||
## Regenerating C++ fixtures
|
||||
|
||||
The optional oracle target calls the existing C++ protobuf, header serializer, and
|
||||
libsodium media implementation. From the root, with the development dependencies:
|
||||
|
||||
```powershell
|
||||
cmake --preset dev -DVOICECAT_BUILD_DOTNET_ORACLE=ON
|
||||
cmake --build --preset dev --target voicecat-dotnet-oracle
|
||||
New-Item -ItemType Directory -Force dotnet/tests/VoiceCat.Tests/Fixtures
|
||||
./build/dev/bin/voicecat-dotnet-oracle.exe dotnet/tests/VoiceCat.Tests/Fixtures/cpp-wire.json
|
||||
git diff -- dotnet/tests/VoiceCat.Tests/Fixtures/cpp-wire.json
|
||||
```
|
||||
|
||||
On Linux/macOS, omit `.exe` and create the directory with `mkdir -p`.
|
||||
The oracle writes deterministic JSON directly, avoiding shell output encoding.
|
||||
Fixtures contain a framed ClientHello and media packets at counters 0, 1, 65535,
|
||||
and 65536. Keys contain bytes 0–31; payload bytes count upward from zero. The
|
||||
20-byte header has type 1, marker flag, codec 0, SSRC `0xcafebabe`, timestamp 960.
|
||||
Both managed crypto backends must match these bytes.
|
||||
|
||||
The DSP oracle calls the existing C++ `ApmProcessor` with 200 deterministic noise
|
||||
frames and records the final 960 samples. Regenerate its fixture with:
|
||||
|
||||
```powershell
|
||||
cmake --build --preset dev --target voicecat-dotnet-dsp-oracle
|
||||
./build/dev/bin/voicecat-dotnet-dsp-oracle.exe dotnet/tests/VoiceCat.Tests/Fixtures/cpp-noise.json
|
||||
```
|
||||
|
||||
The managed test allows a one-unit PCM difference for floating-point rounding.
|
||||
|
||||
## TLS interoperability
|
||||
|
||||
The optional TLS oracle uses the existing mbedTLS context and libsodium media crypto.
|
||||
The test authenticates an encrypted challenge in both directions, proving exporter
|
||||
compatibility without sending raw keys. It also loads the C++ server's credential files.
|
||||
|
||||
```powershell
|
||||
cmake --build --preset dev --target voicecat-dotnet-tls-oracle
|
||||
$env:VOICECAT_TLS_ORACLE = (Resolve-Path build/dev/bin/voicecat-dotnet-tls-oracle.exe).Path
|
||||
dotnet test dotnet/VoiceCat.slnx -c Release --no-restore
|
||||
```
|
||||
|
||||
On Linux/macOS, set `VOICECAT_TLS_ORACLE` to the absolute executable path without
|
||||
`.exe`. Without that variable, only this native interoperability test is skipped;
|
||||
managed TLS loopback, rejection, persistence, and wire tests still run. CI's C++
|
||||
conformance job requires the native test. See `docs/api-dotnet.md` for ownership
|
||||
and certificate acceptance requirements.
|
||||
|
||||
## Managed server checkpoint
|
||||
|
||||
Run the TLS control server on loopback (optional arguments: data directory, TCP port):
|
||||
|
||||
```powershell
|
||||
dotnet run --project dotnet/src/VoiceCat.Server -c Release -- ./voicecat-data 7443
|
||||
./build/dev/bin/vccli.exe --host 127.0.0.1 --port 7443 --nick Guest --text "hello"
|
||||
```
|
||||
|
||||
It creates or imports `server_identity.key`, `server.crt`, `server.key`, and
|
||||
`voicecat.db`. An empty channel table gets Lobby and Music Room; existing channels
|
||||
are preserved. Guests are enabled by the CLI; hosting `VoiceServer` directly can
|
||||
disable them. Existing accounts authenticate without resetting passwords. Account
|
||||
creation is currently available through `AccountStore`; bootstrap/admin CLI and
|
||||
wire administration are pending.
|
||||
|
||||
Tests cover real TLS sockets, authentication retries, snapshots, channel moves,
|
||||
text routing, sender attribution, ping, and disconnect events. Enable native checks:
|
||||
|
||||
```powershell
|
||||
cmake --build --preset dev --target voicecat-dotnet-password-oracle voicecat-dotnet-database-oracle vccli
|
||||
$env:VOICECAT_DATABASE_ORACLE = (Resolve-Path build/dev/bin/voicecat-dotnet-database-oracle.exe).Path
|
||||
$env:VOICECAT_VCCLI = (Resolve-Path build/dev/bin/vccli.exe).Path
|
||||
dotnet test dotnet/VoiceCat.slnx -c Release --no-restore
|
||||
```
|
||||
|
||||
The database oracle creates an account/channel using the shipped C++ database code;
|
||||
managed code imports and authenticates it, then C++ authenticates a managed-created
|
||||
account. CI also regenerates the libsodium password fixture. Native checks require
|
||||
the optional `VOICECAT_BUILD_DOTNET_ORACLE=ON` configure flag and a real-deps build.
|
||||
|
||||
The server also advertises UDP on the TCP port number, supports voice subscription
|
||||
and stream signaling, and reseals encoded audio for subscribers in the same channel.
|
||||
UDP binding fixes the first endpoint for the session; reconnect after endpoint changes.
|
||||
Protected joins, administration, moderation and production configuration remain
|
||||
before Phase 4 completion. The server's media-aware reaper defaults to 45 seconds
|
||||
of inactivity with a 15-second sweep. Parsed control envelopes, valid encrypted
|
||||
voice and keepalives from bound endpoints refresh activity; invalid media does not.
|
||||
`VoiceServerOptions` configures timeouts and capacity; zero idle timeout disables
|
||||
reaping. The constructor overload accepts `TimeProvider` for deterministic expiry tests.
|
||||
|
||||
Enable deterministic native voice interoperability (no audio hardware required):
|
||||
|
||||
```powershell
|
||||
cmake --build --preset dev --target voicecat-dotnet-voice-oracle
|
||||
$env:VOICECAT_VOICE_ORACLE = (Resolve-Path build/dev/bin/voicecat-dotnet-voice-oracle.exe).Path
|
||||
dotnet test dotnet/VoiceCat.slnx -c Release --no-restore
|
||||
```
|
||||
|
||||
Two existing C++ clients authenticate, join Lobby or Music Room, publish three
|
||||
concurrent streams, feed PCM, and verify decoded energy and metadata in both directions.
|
||||
The native clients use external capture/playback to avoid device dependencies in CI.
|
||||
`MediaFanoutTests` separately verifies 50-subscriber routing/resealing without managed
|
||||
allocations after warm-up and reports throughput; socket scheduling is excluded.
|
||||
The transport load test delivers all 2,500 recipient packets from a paced 50 pps sender.
|
||||
Native `vccli --test-tone-ms 4000` runs finite external capture/playback, feeds a tone,
|
||||
and fails without decoded remote audio. Tests start two CLI processes in mono/stereo
|
||||
channels and also verify channel text. Normal `--voice` now explicitly subscribes before
|
||||
announcing its microphone stream. No C ABI or wire changes were needed.
|
||||
|
||||
The managed CLI also accepts `--test-tone-seconds N` (maximum 3600) for a finite, accurately
|
||||
paced peer used during device checks. Use a channel with Opus DTX disabled, such as the seeded
|
||||
Music Room: a steady sine is intentionally classified as non-speech by DTX and becomes comfort
|
||||
noise after its hangover period in Lobby. The finite peer prints received voice energy and exits
|
||||
normally when its requested duration completes.
|
||||
The managed implementation is the source of truth. Frozen vectors under
|
||||
`tests/VoiceCat.Tests/Fixtures` protect concrete wire, Argon2id, and RNNoise behavior, but the
|
||||
repository no longer builds or tests against the retired C++ implementation. Protocol or
|
||||
persistence changes must be versioned when current supported releases need migration; they do
|
||||
not need to retain compatibility with unsupported pre-rewrite releases.
|
||||
|
||||
Reference in New Issue
Block a user