View Javadoc
1   /*
2    * Copyright 2016 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.codec.http2;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.buffer.ByteBufUtil;
20  import io.netty.buffer.Unpooled;
21  import io.netty.util.internal.StringUtil;
22  import io.netty.util.internal.UnstableApi;
23  
24  import static io.netty.handler.codec.http2.Http2CodecUtil.verifyPadding;
25  import static io.netty.util.internal.ObjectUtil.checkNotNull;
26  
27  /**
28   * The default {@link Http2DataFrame} implementation.
29   */
30  @UnstableApi
31  public final class DefaultHttp2DataFrame extends AbstractHttp2StreamFrame implements Http2DataFrame {
32      private final ByteBuf content;
33      private final boolean endStream;
34      private final int padding;
35      private final int initialFlowControlledBytes;
36  
37      /**
38       * Equivalent to {@code new DefaultHttp2DataFrame(content, false)}.
39       *
40       * @param content non-{@code null} payload
41       */
42      public DefaultHttp2DataFrame(ByteBuf content) {
43          this(content, false);
44      }
45  
46      /**
47       * Equivalent to {@code new DefaultHttp2DataFrame(Unpooled.EMPTY_BUFFER, endStream)}.
48       *
49       * @param endStream whether this data should terminate the stream
50       */
51      public DefaultHttp2DataFrame(boolean endStream) {
52          this(Unpooled.EMPTY_BUFFER, endStream);
53      }
54  
55      /**
56       * Equivalent to {@code new DefaultHttp2DataFrame(content, endStream, 0)}.
57       *
58       * @param content non-{@code null} payload
59       * @param endStream whether this data should terminate the stream
60       */
61      public DefaultHttp2DataFrame(ByteBuf content, boolean endStream) {
62          this(content, endStream, 0);
63      }
64  
65      /**
66       * Construct a new data message.
67       *
68       * @param content non-{@code null} payload
69       * @param endStream whether this data should terminate the stream
70       * @param padding additional bytes that should be added to obscure the true content size. Must be between 0 and
71       *                256 (inclusive).
72       */
73      public DefaultHttp2DataFrame(ByteBuf content, boolean endStream, int padding) {
74          this.content = checkNotNull(content, "content");
75          this.endStream = endStream;
76          verifyPadding(padding);
77          this.padding = padding;
78          if (content().readableBytes() + (long) padding > Integer.MAX_VALUE) {
79              throw new IllegalArgumentException("content + padding must be <= Integer.MAX_VALUE");
80          }
81          initialFlowControlledBytes = content().readableBytes() + padding;
82      }
83  
84      @Override
85      public DefaultHttp2DataFrame stream(Http2FrameStream stream) {
86          super.stream(stream);
87          return this;
88      }
89  
90      @Override
91      public String name() {
92          return "DATA";
93      }
94  
95      @Override
96      public boolean isEndStream() {
97          return endStream;
98      }
99  
100     @Override
101     public int padding() {
102         return padding;
103     }
104 
105     @Override
106     public ByteBuf content() {
107         return ByteBufUtil.ensureAccessible(content);
108     }
109 
110     @Override
111     public int initialFlowControlledBytes() {
112         return initialFlowControlledBytes;
113     }
114 
115     @Override
116     public DefaultHttp2DataFrame copy() {
117         return replace(content().copy());
118     }
119 
120     @Override
121     public DefaultHttp2DataFrame duplicate() {
122         return replace(content().duplicate());
123     }
124 
125     @Override
126     public DefaultHttp2DataFrame retainedDuplicate() {
127         return replace(content().retainedDuplicate());
128     }
129 
130     @Override
131     public DefaultHttp2DataFrame replace(ByteBuf content) {
132         return new DefaultHttp2DataFrame(content, endStream, padding);
133     }
134 
135     @Override
136     public int refCnt() {
137         return content.refCnt();
138     }
139 
140     @Override
141     public boolean release() {
142         return content.release();
143     }
144 
145     @Override
146     public boolean release(int decrement) {
147         return content.release(decrement);
148     }
149 
150     @Override
151     public DefaultHttp2DataFrame retain() {
152         content.retain();
153         return this;
154     }
155 
156     @Override
157     public DefaultHttp2DataFrame retain(int increment) {
158         content.retain(increment);
159         return this;
160     }
161 
162     @Override
163     public String toString() {
164         return StringUtil.simpleClassName(this) + "(stream=" + stream() + ", content=" + content
165                + ", endStream=" + endStream + ", padding=" + padding + ')';
166     }
167 
168     @Override
169     public DefaultHttp2DataFrame touch() {
170         content.touch();
171         return this;
172     }
173 
174     @Override
175     public DefaultHttp2DataFrame touch(Object hint) {
176         content.touch(hint);
177         return this;
178     }
179 
180     @Override
181     public boolean equals(Object o) {
182         if (!(o instanceof DefaultHttp2DataFrame)) {
183             return false;
184         }
185         DefaultHttp2DataFrame other = (DefaultHttp2DataFrame) o;
186         return super.equals(other) && content.equals(other.content())
187             && endStream == other.endStream && padding == other.padding;
188     }
189 
190     @Override
191     public int hashCode() {
192         int hash = super.hashCode();
193         hash = hash * 31 + content.hashCode();
194         hash = hash * 31 + (endStream ? 0 : 1);
195         hash = hash * 31 + padding;
196         return hash;
197     }
198 }