Skip to content

Commit 6e69097

Browse files
authored
QPACK: Allow stream cancellation even if the dynamic table was config… (#267)
…ured with max capacity of 0 Motivation: It is fine to send stream cancellations even if the dynamic table had a capacity of 0 and so was disabled. We didn't follow the spec here and did case a NPE if we received a stream cancellation after the table was configured with capacity of 0. Modifications: - Allow stream cancellation if if the table capacity is 0 - Add unit test Result: Fixes #261 and #252
1 parent 35f5f7c commit 6e69097

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

src/main/java/io/netty/incubator/codec/http3/QpackEncoder.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,12 @@ void sectionAcknowledgment(long streamId) throws QpackException {
163163
* @param streamId which is cancelled.
164164
*/
165165
void streamCancellation(long streamId) throws QpackException {
166-
assert streamSectionTrackers != null;
166+
// If a configureDynamicTable(...) was called with a maxTableCapacity of 0 we will have not instanced
167+
// streamSectionTrackers. The remote peer might still send a stream cancellation for a stream, while it
168+
// is optional. See https://www.rfc-editor.org/rfc/rfc9204.html#section-2.2.2.2
169+
if (streamSectionTrackers == null) {
170+
return;
171+
}
167172
final Queue<Indices> tracker = streamSectionTrackers.remove(streamId);
168173
if (tracker != null) {
169174
for (;;) {

src/test/java/io/netty/incubator/codec/http3/QpackDecoderHandlerTest.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,18 @@ public void streamCancelUnknownStream() throws Exception {
240240
finishStreams();
241241
}
242242

243+
@Test
244+
public void streamCancelDynamicTableWithMaxCapacity0() throws Exception {
245+
setup(0);
246+
encodeHeaders(headers -> headers.add(fooBar.name, fooBar.value));
247+
verifyRequiredInsertCount(0);
248+
verifyKnownReceivedCount(0);
249+
// Send a stream cancellation for a dynamic table of capacity 0.
250+
// See https://www.rfc-editor.org/rfc/rfc9204.html#section-2.2.2.2
251+
sendStreamCancellation(decoderStream.streamId());
252+
finishStreams(false);
253+
}
254+
243255
@Test
244256
public void invalidIncrement() throws Exception {
245257
setup(128);
@@ -325,8 +337,12 @@ private void setup(long maxTableCapacity) throws Exception {
325337
}
326338

327339
private void finishStreams() {
340+
finishStreams(true);
341+
}
342+
343+
private void finishStreams(boolean encoderPendingMessage) {
328344
assertThat("Unexpected decoder stream message", decoderStream.finishAndReleaseAll(), is(false));
329-
assertThat("Unexpected encoder stream message", encoderStream.finishAndReleaseAll(), is(true));
345+
assertThat("Unexpected encoder stream message", encoderStream.finishAndReleaseAll(), is(encoderPendingMessage));
330346
assertThat("Unexpected parent stream message", parent.finishAndReleaseAll(), is(false));
331347
}
332348

0 commit comments

Comments
 (0)