From 67af4248c97d2e1568e5c22179fa0026dbbc5219 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 3 Oct 2026 13:36:19 +0200 Subject: fix(android): the cast header is everything before the first moof The node's first chunk can be the 28-byte ftyp alone, the moov in the next; served as the header, the receiver had no moov and gave up. A receiver early for the header now waits for all of it. Co-Authored-By: Claude Opus 5.5 --- .../kotlin/org/meshbay/client/CastRelayTest.kt | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'packages/meshbay-android/app/src/test/kotlin/org/meshbay') diff --git a/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/CastRelayTest.kt b/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/CastRelayTest.kt index 1c604d0..5d3125f 100644 --- a/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/CastRelayTest.kt +++ b/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/CastRelayTest.kt @@ -106,6 +106,31 @@ class CastRelayTest { assertArrayEquals("header, then each fragment once", stream, reply.body) } + @Test fun `a header split across chunks is served whole`() { + // Measured on a fresh start: the first chunk was the 28-byte ftyp + // alone, the moov came in the next push. Served as the header, the + // receiver had no moov and gave up — the first cast failed every time. + val ftyp = box("ftyp", 20) + val moov = box("moov", 2124) + val started = relay.start(ftyp, null) + val url = started.getString("url") + // The page pushes the first chunk too, then the rest. + relay.push(ftyp); relay.push(moov); relay.push(fragment(1)); relay.push(fragment(2)) + val reply = get(url, readBytes = ftyp.size + moov.size + fragment(1).size + fragment(2).size) + assertArrayEquals(ftyp + moov + fragment(1) + fragment(2), reply.body) + } + + @Test fun `a receiver early for the header waits for all of it`() { + val ftyp = box("ftyp", 20) + val moov = box("moov", 2124) + val url = relay.start(ftyp, null).getString("url") + relay.push(ftyp) + val late = Thread { Thread.sleep(400); relay.push(moov); relay.push(fragment(1)) }.apply { start() } + val reply = get(url, readBytes = ftyp.size + moov.size + fragment(1).size) + late.join() + assertArrayEquals(ftyp + moov + fragment(1), reply.body) + } + @Test fun `the token is required and unguessable`() { val url = relay.start(null, null).getString("url") val token = url.substringAfter("t=") -- cgit v1.2.3