# Real Icecast reference harness

This is bounded test tooling, not Quikcast production code. It builds upstream **2.4.4** and **2.5.0** from release archives, generates a one-second synthetic MP3 tone with external FFmpeg, and records actual source/listener/metadata interactions. No RadioPlatform credentials or production services are used.

## Reproduce

Requirements: Docker engine, Python 3.9+, curl, FFmpeg with libmp3lame. Builds need network access. Source archive hashes and the Debian base-image digest are pinned; Debian build dependencies are resolved at build time and their exact installed versions recorded in each capture. An image ID pins the actual tested build. This is reproducible protocol tooling, not a claim of bit-for-bit reproducible compilation across future apt repositories.

From the repository root:

```sh
mkdir -p tools/icecast-reference/vendor
curl -fL https://downloads.xiph.org/releases/icecast/icecast-2.4.4.tar.gz -o tools/icecast-reference/vendor/icecast-2.4.4.tar.gz
curl -fL https://downloads.xiph.org/releases/icecast/icecast-2.5.0.tar.gz -o tools/icecast-reference/vendor/icecast-2.5.0.tar.gz
curl -fL https://downloads.xiph.org/releases/igloo/libigloo-0.9.5.tar.gz -o tools/icecast-reference/vendor/libigloo-0.9.5.tar.gz
docker build --build-arg ICECAST_RELEASE=2.4.4 -t quikcast-reference:2.4.4 tools/icecast-reference
docker build --build-arg ICECAST_RELEASE=2.5.0 -t quikcast-reference:2.5.0 tools/icecast-reference
python3 tools/icecast-reference/capture.py --release 2.4.4 --output /tmp/quikcast-reference-244-new
python3 tools/icecast-reference/capture.py --release 2.5.0 --output /tmp/quikcast-reference-250-new
python3 tools/icecast-reference/capture.py --release 2.4.4 --followup --output /tmp/quikcast-reference-244-followup-new
python3 tools/icecast-reference/capture.py --release 2.5.0 --followup --output /tmp/quikcast-reference-250-followup-new
docker build -f tools/icecast-reference/Dockerfile.liquidsoap -t quikcast-reference-client:liquidsoap tools/icecast-reference
python3 tools/icecast-reference/capture.py --release 2.4.4 --liquidsoap --output /tmp/quikcast-reference-244-liquidsoap-new
python3 tools/icecast-reference/capture.py --release 2.5.0 --liquidsoap --output /tmp/quikcast-reference-250-liquidsoap-new
python3 -B -m unittest discover -s tools/icecast-reference -p 'test_*.py'
python3 tools/icecast-reference/verify.py fixtures/icecast
python3 tools/icecast-reference/build_matrix.py fixtures/icecast
```

Output directories must not already exist. Captures contain disposable credentials by design, so request bytes remain reproducible. Never point this harness at a production service. The script launches its own container and discovers its assigned loopback port; no externally supplied target is accepted.

## Isolation and bounds

Host port binding is 127.0.0.1 only; the container listens on its own network interface for Docker forwarding. It has a read-only root filesystem, dropped capabilities, no-new-privileges, 128 MiB memory and 64 PID ceilings, and a 16 MiB temporary log filesystem. Source threads stop at 60 seconds, are explicitly stopped/joined, and captures cap each request/response at 4 MiB. All socket/subprocess operations have time bounds. Cases run sequentially, with at most two source feed threads. Containers are stopped in finally; manual cleanup after killing the harness process uses the recorded container ID, never a broad Docker prune.

Retain `.request.bin`, `.response.bin`, `.events.json`, summary, timeline, source tone, logs, package versions, provenance and manifest together. Events record application send/receive order and offsets with monotonic timestamps; they are **not packet captures** and do not imply TCP packet boundaries or precise server scheduling. Raw response Date/server fields are preserved. Replays must normalize volatile fields instead of byte-matching entire headers.

`summary.json` is a convenience extraction. The binary files and event offsets are the primary evidence. ICY extraction respects the advertised interval and padded length byte; fixture verification checks extraction against the captured wire and checks non-ICY audio against the synthetic source.

Curl's trace retains its request and response dialogue. FFmpeg debug output, return code and Icecast access/error logs retain external encoder admission evidence; raw byte-level protocol coverage comes from Python's socket clients. These clients do not establish full player/encoder compatibility or production performance.

Liquidsoap is installed only in a disposable client image; the host installation is unchanged. The client shares the reference container's network namespace and has only a read-only synthetic-tone mount, a bounded tmpfs, 512 MiB memory, and 64 PID limits. Bounded readiness probes precede listener captures. Its image ID/version/package inventory and producer script are retained. Initial early-startup probe datasets are preserved separately from successful readiness-based captures. BUTT is a later manual compatibility check and is not described as passed.

## Provenance

Official release selection: https://icecast.org/download/ and https://icecast.org/news/icecast-release-2_5_0/.

`SHA256SUMS` contains the hashes measured after HTTPS download from the official Xiph release endpoint. These identify tested bytes; they are not a separately verified upstream signature. Images record the exact source/build identity and binary version. libigloo/librhash exist solely inside reference images and are not proposed Rust production dependencies.

## Milestone 4 focused reference suite

Run `capture.py --release 2.4.4 --metadata-edges --output NEW_DIRECTORY` and repeat with 2.5.0. Ten sequential queries cover song/artist/title precedence, empty song, delimiters, controls, explicit UTF-8 charset, duplicates, invalid percent/UTF-8 and 1024/4096-byte titles. Each admin read is capped at 0.4 seconds and each ICY read at 3 seconds/150,000 target bytes; the inherited 4 MiB hard capture ceiling and 60-second source lifetime remain. Logs are exported as binary because invalid UTF-8 can reach Icecast logs. See `docs/Writerside/topics/milestone-4.md` for measured differences and intentionally narrower Quikcast behavior.

## AAC and Ogg reference cases

`python3 -B tools/icecast-reference/media_capture.py --release 2.4.4 --output PATH` (or 2.5.0) captures five MIME/codec cases with source admission, plain/ICY listeners and authenticated metadata updates. It retains raw bytes, bounded event timelines, pinned Icecast image identities, actual encoder commands, external decoder logs, and a file manifest. Docker uses disposable loopback-only reference containers. Vorbis fixture encoding uses the recorded milestone-4 proof image because the host encoder lacks libvorbis; no encoder becomes a server dependency.

The `*-media-complete` suites use 1.5-second listener observation windows and resolve the empty-body observation gaps in the retained original `*-media` suites. Verify each directory with `verify.py DIRECTORY`. The missing-host-encoder attempt is preserved as an incomplete run, not evidence.
