1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.http2;
17
18 import io.netty5.buffer.api.Buffer;
19 import io.netty5.buffer.api.BufferClosedException;
20 import io.netty5.buffer.api.DefaultBufferAllocators;
21 import io.netty5.util.Send;
22 import io.netty5.util.internal.StringUtil;
23 import io.netty5.util.internal.UnstableApi;
24
25 import static io.netty5.handler.codec.http2.Http2CodecUtil.verifyPadding;
26 import static java.util.Objects.requireNonNull;
27
28
29
30
31 @UnstableApi
32 public final class DefaultHttp2DataFrame extends AbstractHttp2StreamFrame implements Http2DataFrame {
33 private final Buffer content;
34 private final boolean endStream;
35 private final int padding;
36 private final int initialFlowControlledBytes;
37
38
39
40
41
42
43 public DefaultHttp2DataFrame(Send<Buffer> content) {
44 this(content, false);
45 }
46
47
48
49
50
51
52 public DefaultHttp2DataFrame(boolean endStream) {
53 this(DefaultBufferAllocators.onHeapAllocator().allocate(0), endStream, 0);
54 }
55
56
57
58
59
60
61
62 public DefaultHttp2DataFrame(Send<Buffer> content, boolean endStream) {
63 this(content, endStream, 0);
64 }
65
66
67
68
69
70
71
72
73
74 public DefaultHttp2DataFrame(Send<Buffer> content, boolean endStream, int padding) {
75 this(content.receive(), endStream, padding);
76 }
77
78 private DefaultHttp2DataFrame(Buffer content, boolean endStream, int padding) {
79 this.content = requireNonNull(content, "content");
80 this.endStream = endStream;
81 verifyPadding(padding);
82 this.padding = padding;
83 if (content().readableBytes() + (long) padding > Integer.MAX_VALUE) {
84 throw new IllegalArgumentException("content + padding must be <= Integer.MAX_VALUE");
85 }
86 initialFlowControlledBytes = content().readableBytes() + padding;
87 }
88
89 @Override
90 public DefaultHttp2DataFrame stream(Http2FrameStream stream) {
91 super.stream(stream);
92 return this;
93 }
94
95 @Override
96 public String name() {
97 return "DATA";
98 }
99
100 @Override
101 public boolean isEndStream() {
102 return endStream;
103 }
104
105 @Override
106 public int padding() {
107 return padding;
108 }
109
110 @Override
111 public Buffer content() {
112 if (content.isAccessible()) {
113 return content;
114 }
115 throw new BufferClosedException();
116 }
117
118 @Override
119 public int initialFlowControlledBytes() {
120 return initialFlowControlledBytes;
121 }
122
123 @Override
124 public DefaultHttp2DataFrame copy() {
125 return new DefaultHttp2DataFrame(content.copy(), endStream, padding);
126 }
127
128 @Override
129 public String toString() {
130 return StringUtil.simpleClassName(this) + "(stream=" + stream() + ", content=" + content
131 + ", endStream=" + endStream + ", padding=" + padding + ')';
132 }
133
134 @Override
135 public Send<Http2DataFrame> send() {
136 return content.send().map(Http2DataFrame.class,
137 content -> new DefaultHttp2DataFrame(content, endStream, padding));
138 }
139
140 @Override
141 public void close() {
142 content.close();
143 }
144
145 @Override
146 public boolean isAccessible() {
147 return content.isAccessible();
148 }
149
150 @Override
151 public DefaultHttp2DataFrame touch(Object hint) {
152 content.touch(hint);
153 return this;
154 }
155
156 @Override
157 public boolean equals(Object o) {
158 if (!(o instanceof DefaultHttp2DataFrame)) {
159 return false;
160 }
161 DefaultHttp2DataFrame other = (DefaultHttp2DataFrame) o;
162 return super.equals(other) && content.equals(other.content())
163 && endStream == other.endStream && padding == other.padding;
164 }
165
166 @Override
167 public int hashCode() {
168 int hash = super.hashCode();
169 hash = hash * 31 + content.hashCode();
170 hash = hash * 31 + (endStream ? 0 : 1);
171 hash = hash * 31 + padding;
172 return hash;
173 }
174 }