From 283e7760bdb8fe72f52b59907344acbbaf820a59 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 4 May 2026 17:48:03 +0000 Subject: [PATCH] debug(quic): log MAX_STREAMS_UNI emission and per-25-stream count milestones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Listener cliff at uni stream #124 with the publisher continuing to push for ~55 s past that point — the prior MAX_STREAMS_UNI extension fix is either firing too late or not firing at all on the live device. The trace can't tell us which because the bump itself is silent. - QuicConnectionWriter: log every MAX_STREAMS_UNI / MAX_STREAMS_BIDI emission with old→new cap and the current peerInitiated count, so we can see whether the writer is bumping the cap at all and how far behind reception it falls. - QuicConnection: log peerInitiatedUniCount every 25 streams along with the currently advertised cap and headroom. Cheap and lets us correlate "stream count growth" against "cap bumps" without printing per-stream noise. Tag is `NestQuic` so listeners can scope `adb logcat -s NestRx:D NestTx:D NestQuic:D` to capture the full picture. https://claude.ai/code/session_01PYYez8a6sjiakyjAxsfCEQ --- .../quic/connection/QuicConnection.kt | 17 +++++++++++++++-- .../quic/connection/QuicConnectionWriter.kt | 11 +++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnection.kt b/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnection.kt index 041974e02..514f0f45b 100644 --- a/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnection.kt +++ b/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnection.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.quic.connection +import com.vitorpamplona.quartz.utils.Log import com.vitorpamplona.quic.crypto.AesEcbHeaderProtection import com.vitorpamplona.quic.crypto.InitialSecrets import com.vitorpamplona.quic.crypto.PlatformAesOneBlock @@ -635,8 +636,20 @@ class QuicConnection( // [config.initialMaxStreams*] is the lifetime maximum the peer // can open and any longer broadcast silently truncates. when (kind) { - StreamId.Kind.SERVER_UNI, StreamId.Kind.CLIENT_UNI -> peerInitiatedUniCount += 1 - StreamId.Kind.SERVER_BIDI, StreamId.Kind.CLIENT_BIDI -> peerInitiatedBidiCount += 1 + StreamId.Kind.SERVER_UNI, StreamId.Kind.CLIENT_UNI -> { + peerInitiatedUniCount += 1 + if (peerInitiatedUniCount % 25L == 0L) { + Log.d("NestQuic") { + "peerInitiatedUniCount=$peerInitiatedUniCount " + + "advertisedMaxStreamsUni=$advertisedMaxStreamsUni " + + "(headroom=${advertisedMaxStreamsUni - peerInitiatedUniCount})" + } + } + } + + StreamId.Kind.SERVER_BIDI, StreamId.Kind.CLIENT_BIDI -> { + peerInitiatedBidiCount += 1 + } } // Wake any awaitIncomingPeerStream caller. trySend on a CONFLATED // channel can never fail in steady state. diff --git a/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnectionWriter.kt b/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnectionWriter.kt index 565d7f53b..a005a8557 100644 --- a/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnectionWriter.kt +++ b/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/QuicConnectionWriter.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.quic.connection +import com.vitorpamplona.quartz.utils.Log import com.vitorpamplona.quic.frame.ConnectionCloseFrame import com.vitorpamplona.quic.frame.CryptoFrame import com.vitorpamplona.quic.frame.DatagramFrame @@ -395,15 +396,25 @@ private fun appendFlowControlUpdates( if (conn.peerInitiatedUniCount + cfg.initialMaxStreamsUni / 2 >= conn.advertisedMaxStreamsUni) { val newCap = conn.peerInitiatedUniCount + cfg.initialMaxStreamsUni if (newCap > conn.advertisedMaxStreamsUni) { + val oldCap = conn.advertisedMaxStreamsUni conn.advertisedMaxStreamsUni = newCap frames += MaxStreamsFrame(bidi = false, maxStreams = newCap) + Log.d("NestQuic") { + "MAX_STREAMS_UNI emit oldCap=$oldCap → newCap=$newCap " + + "peerInitiatedUniCount=${conn.peerInitiatedUniCount}" + } } } if (conn.peerInitiatedBidiCount + cfg.initialMaxStreamsBidi / 2 >= conn.advertisedMaxStreamsBidi) { val newCap = conn.peerInitiatedBidiCount + cfg.initialMaxStreamsBidi if (newCap > conn.advertisedMaxStreamsBidi) { + val oldCap = conn.advertisedMaxStreamsBidi conn.advertisedMaxStreamsBidi = newCap frames += MaxStreamsFrame(bidi = true, maxStreams = newCap) + Log.d("NestQuic") { + "MAX_STREAMS_BIDI emit oldCap=$oldCap → newCap=$newCap " + + "peerInitiatedBidiCount=${conn.peerInitiatedBidiCount}" + } } } }