HTTP/2 Data padding is not counted toward the connection flow-control window. This deadlocks connections with peers that pad.
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 67/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- kotlin
- Ambito
- networking
Direzione di ricerca
Start with Http2Reader.readData, Http2Connection.updateConnectionFlowControl, and Http2Stream.FramingSource.receive to trace how DATA frame bytes reach connection-level accounting. Add a regression test in Http2ConnectionTest that sends padded DATA frames and reads the stream-0 WINDOW_UPDATE; done when its increment accounts for the full padded payload, as RFC 9113 requires.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
Http2Reader does not count DATA frame padding toward the connection-level flow-control window. When the peer pads its DATA frames, the server's view of the connection window drains faster than the client's counter grows, the server's window reaches zero before the client reaches its next WINDOW_UPDATE threshold, and the connection deadlocks. PING/PONG keeps working, so the connection stays in the pool and every subsequent call on it times out.
Observed on 5.5.0; the code is unchanged on main.
Where
Http2Reader.readData reads the pad-length byte, computes the body length without padding, calls handler.data(..., dataLength) with the body length only, and then skips the padding:
https://github.com/lysine-dev/okhttp/blob/e9eae50d36e938603811a41f9e2ab04182bcb515/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/http2/Http2Reader.kt#L198-L202
Http2Connection.updateConnectionFlowControl is therefore only ever fed the body length, both through the stream path (Http2Stream.FramingSource.receive) and the unknown-stream path:
https://github.com/lysine-dev/okhttp/blob/e9eae50d36e938603811a41f9e2ab04182bcb515/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/http2/Http2Connection.kt#L189
https://github.com/lysine-dev/okhttp/blob/e9eae50d36e938603811a41f9e2ab04182bcb515/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/http2/Http2Stream.kt#L517
The pad-length byte and the padding bytes are consumed from the socket but never credited back to the peer.
Spec
RFC 9113 §6.1: "The entire DATA frame payload is included in flow control, including the Pad Length and Padding fields if present."
https://www.rfc-editor.org/rfc/rfc9113.html#section-6.1
Go's net/http2 fixed the same bug in 2016 and refunds padding immediately on receipt (golang/go#16556, https://go.googlesource.com/net/+/35028a49ca5a73b486af60cd20ac21cd6b67bfdb). Google's quiche fixed a padding flow-control leak that stalled Envoy connections (envoyproxy/envoy#32401, https://quiche.googlesource.com/quiche/+/9e875938052443c7f51b25012093be59e20598ac). Netty charges data.readableBytes() + padding.
How it shows up in practice
Google Front End pads every response DATA frame with a random 0–255 bytes. A production client of ours talking to an API behind GFE deadlocked every long-lived connection at the same point. Measured with a FlowControlListener on the pool:
| response body | ~250 B |
| DATA frame on the wire | ~372 B average, uniform 247–503 B (`DATA END_STREAM |
| fraction the client counts | ~0.665 |
| client window | 16 MiB advertised, WINDOW_UPDATE of 8 MiB once 8 MiB has been counted |
| server bytes sent at the freeze | 24.0 MiB (16 MiB initial + one 8 MiB grant) |
WindowCounter at the freeze |
total 15.7–16.7 MiB, acknowledged 8,388,6xx: below the threshold for the second grant |
| responses per connection before the freeze | ~67,000 |
After the freeze the only inbound frames were PINGs and the server's own WINDOW_UPDATEs for our request bytes. No HEADERS or DATA, no GOAWAY, no RST_STREAM. Http2Connection.isHealthy() kept returning true, so the connection was reused for every call until the server eventually closed it.
Failing test
The Http2Writer used by the test peer cannot write padded frames, so the test writes DATA frames by hand: a 9-byte frame header with FLAG_PADDED, one pad-length byte, the body, then the padding. Send enough frames for the padded total to exceed half the client window, then read the WINDOW_UPDATE the client sends on stream 0. Expected: the increment equals the padded bytes received. Actual on 5.5.0: the increment equals the body bytes only. (I can turn this into a test in Http2ConnectionTest if that helps.)
Workaround
Restricting the affected client to HTTP/1.1 removes the problem entirely.
- Lingua principale
- Kotlin
- Stelle
- 47.1k
- Fork
- 9.3k
- Merge medio
- 18h 18m
- PR unite (30g)
- 15
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di lysine-dev/okhttp
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
lysine-dev/okhttp#9788 ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
lysine-dev/okhttp#9761 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Remove crossinline `addInterceptor` and `addNetworkInterceptor` overloadsForse già presa @Amir-Golmoradi l’ha presa 6 giorni fa. Apertaenhancement
Difficoltà 3/5 1-2 giorni Idoneità per principianti 58/100
lysine-dev/okhttp#9779 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 55/100
lysine-dev/okhttp#9760 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Unexpected Hostname Causing Crash in AndroidForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 35/100
lysine-dev/okhttp#9758 · 4 reazioni ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di lysine-dev/okhttp
Issue simili
-
afk-ok area:data-quality importer size:S
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
enorm-labs/event-junkie#3301 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
rustyrazorblade/easy-db-lab#1017 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
openclaw/openclaw#172218 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement impact:U1 later P3 reach:R2 size:S
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100