debug(quic): log MAX_STREAMS_UNI emission and per-25-stream count milestones

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
This commit is contained in:
Claude
2026-05-04 17:48:03 +00:00
parent 43720dd14d
commit 283e7760bd
2 changed files with 26 additions and 2 deletions
@@ -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.
@@ -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}"
}
}
}
}