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    *   http://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.Unpooled;
20  import io.netty.util.IllegalReferenceCountException;
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         if (content.refCnt() <= 0) {
108             throw new IllegalReferenceCountException(content.refCnt());
109         }
110         return content;
111     }
112 
113     @Override
114     public int initialFlowControlledBytes() {
115         return initialFlowControlledBytes;
116     }
117 
118     @Override
119     public DefaultHttp2DataFrame copy() {
120         return replace(content().copy());
121     }
122 
123     @Override
124     public DefaultHttp2DataFrame duplicate() {
125         return replace(content().duplicate());
126     }
127 
128     @Override
129     public DefaultHttp2DataFrame retainedDuplicate() {
130         return replace(content().retainedDuplicate());
131     }
132 
133     @Override
134     public DefaultHttp2DataFrame replace(ByteBuf content) {
135         return new DefaultHttp2DataFrame(content, endStream, padding);
136     }
137 
138     @Override
139     public int refCnt() {
140         return content.refCnt();
141     }
142 
143     @Override
144     public boolean release() {
145         return content.release();
146     }
147 
148     @Override
149     public boolean release(int decrement) {
150         return content.release(decrement);
151     }
152 
153     @Override
154     public DefaultHttp2DataFrame retain() {
155         content.retain();
156         return this;
157     }
158 
159     @Override
160     public DefaultHttp2DataFrame retain(int increment) {
161         content.retain(increment);
162         return this;
163     }
164 
165     @Override
166     public String toString() {
167         return StringUtil.simpleClassName(this) + "(stream=" + stream() + ", content=" + content
168                + ", endStream=" + endStream + ", padding=" + padding + ')';
169     }
170 
171     @Override
172     public DefaultHttp2DataFrame touch() {
173         content.touch();
174         return this;
175     }
176 
177     @Override
178     public DefaultHttp2DataFrame touch(Object hint) {
179         content.touch(hint);
180         return this;
181     }
182 
183     @Override
184     public boolean equals(Object o) {
185         if (!(o instanceof DefaultHttp2DataFrame)) {
186             return false;
187         }
188         DefaultHttp2DataFrame other = (DefaultHttp2DataFrame) o;
189         return super.equals(other) && content.equals(other.content())
190             && endStream == other.endStream && padding == other.padding;
191     }
192 
193     @Override
194     public int hashCode() {
195         int hash = super.hashCode();
196         hash = hash * 31 + content.hashCode();
197         hash = hash * 31 + (endStream ? 0 : 1);
198         hash = hash * 31 + padding;
199         return hash;
200     }
201 }