1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package io.netty5.handler.codec.http2;
16
17 import io.netty5.buffer.api.Buffer;
18 import io.netty5.channel.ChannelHandlerContext;
19 import io.netty5.util.internal.ObjectUtil;
20
21
22
23
24
25 final class Http2EmptyDataFrameListener extends Http2FrameListenerDecorator {
26 private final int maxConsecutiveEmptyFrames;
27
28 private boolean violationDetected;
29 private int emptyDataFrames;
30
31 Http2EmptyDataFrameListener(Http2FrameListener listener, int maxConsecutiveEmptyFrames) {
32 super(listener);
33 this.maxConsecutiveEmptyFrames = ObjectUtil.checkPositive(
34 maxConsecutiveEmptyFrames, "maxConsecutiveEmptyFrames");
35 }
36
37 @Override
38 public int onDataRead(ChannelHandlerContext ctx, int streamId, Buffer data, int padding, boolean endOfStream)
39 throws Http2Exception {
40 if (endOfStream || data.readableBytes() > 0) {
41 emptyDataFrames = 0;
42 } else if (emptyDataFrames++ == maxConsecutiveEmptyFrames && !violationDetected) {
43 violationDetected = true;
44 throw Http2Exception.connectionError(Http2Error.ENHANCE_YOUR_CALM,
45 "Maximum number %d of empty data frames without end_of_stream flag received",
46 maxConsecutiveEmptyFrames);
47 }
48
49 return super.onDataRead(ctx, streamId, data, padding, endOfStream);
50 }
51
52 @Override
53 public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers,
54 int padding, boolean endStream) throws Http2Exception {
55 emptyDataFrames = 0;
56 super.onHeadersRead(ctx, streamId, headers, padding, endStream);
57 }
58
59 @Override
60 public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency,
61 short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception {
62 emptyDataFrames = 0;
63 super.onHeadersRead(ctx, streamId, headers, streamDependency, weight, exclusive, padding, endStream);
64 }
65 }