View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
5    * "License"); you may not use this file except in compliance with the License. You may obtain a
6    * 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 distributed under the License
11   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing permissions and limitations under
13   * the License.
14   */
15  
16  package io.netty.handler.codec.http2;
17  
18  import io.netty.util.internal.UnstableApi;
19  
20  /**
21   * Provides utility methods for accessing specific flags as defined by the HTTP/2 spec.
22   */
23  @UnstableApi
24  public final class Http2Flags {
25      public static final short END_STREAM = 0x1;
26      public static final short END_HEADERS = 0x4;
27      public static final short ACK = 0x1;
28      public static final short PADDED = 0x8;
29      public static final short PRIORITY = 0x20;
30  
31      private short value;
32  
33      public Http2Flags() {
34      }
35  
36      public Http2Flags(short value) {
37          this.value = value;
38      }
39  
40      /**
41       * Gets the underlying flags value.
42       */
43      public short value() {
44          return value;
45      }
46  
47      /**
48       * Determines whether the {@link #END_STREAM} flag is set. Only applies to DATA and HEADERS
49       * frames.
50       */
51      public boolean endOfStream() {
52          return isFlagSet(END_STREAM);
53      }
54  
55      /**
56       * Determines whether the {@link #END_HEADERS} flag is set. Only applies for HEADERS,
57       * PUSH_PROMISE, and CONTINUATION frames.
58       */
59      public boolean endOfHeaders() {
60          return isFlagSet(END_HEADERS);
61      }
62  
63      /**
64       * Determines whether the flag is set indicating the presence of the exclusive, stream
65       * dependency, and weight fields in a HEADERS frame.
66       */
67      public boolean priorityPresent() {
68          return isFlagSet(PRIORITY);
69      }
70  
71      /**
72       * Determines whether the flag is set indicating that this frame is an ACK. Only applies for
73       * SETTINGS and PING frames.
74       */
75      public boolean ack() {
76          return isFlagSet(ACK);
77      }
78  
79      /**
80       * For frames that include padding, indicates if the {@link #PADDED} field is present. Only
81       * applies to DATA, HEADERS, PUSH_PROMISE and CONTINUATION frames.
82       */
83      public boolean paddingPresent() {
84          return isFlagSet(PADDED);
85      }
86  
87      /**
88       * Gets the number of bytes expected for the priority fields of the payload. This is determined
89       * by the {@link #priorityPresent()} flag.
90       */
91      public int getNumPriorityBytes() {
92          return priorityPresent() ? 5 : 0;
93      }
94  
95      /**
96       * Gets the length in bytes of the padding presence field expected in the payload. This is
97       * determined by the {@link #paddingPresent()} flag.
98       */
99      public int getPaddingPresenceFieldLength() {
100         return paddingPresent() ? 1 : 0;
101     }
102 
103     /**
104      * Sets the {@link #END_STREAM} flag.
105      */
106     public Http2Flags endOfStream(boolean endOfStream) {
107         return setFlag(endOfStream, END_STREAM);
108     }
109 
110     /**
111      * Sets the {@link #END_HEADERS} flag.
112      */
113     public Http2Flags endOfHeaders(boolean endOfHeaders) {
114         return setFlag(endOfHeaders, END_HEADERS);
115     }
116 
117     /**
118      * Sets the {@link #PRIORITY} flag.
119      */
120     public Http2Flags priorityPresent(boolean priorityPresent) {
121         return setFlag(priorityPresent, PRIORITY);
122     }
123 
124     /**
125      * Sets the {@link #PADDED} flag.
126      */
127     public Http2Flags paddingPresent(boolean paddingPresent) {
128         return setFlag(paddingPresent, PADDED);
129     }
130 
131     /**
132      * Sets the {@link #ACK} flag.
133      */
134     public Http2Flags ack(boolean ack) {
135         return setFlag(ack, ACK);
136     }
137 
138     /**
139      * Generic method to set any flag.
140      * @param on if the flag should be enabled or disabled.
141      * @param mask the mask that identifies the bit for the flag.
142      * @return this instance.
143      */
144     public Http2Flags setFlag(boolean on, short mask) {
145         if (on) {
146             value |= mask;
147         } else {
148             value &= ~mask;
149         }
150         return this;
151     }
152 
153     /**
154      * Indicates whether or not a particular flag is set.
155      * @param mask the mask identifying the bit for the particular flag being tested
156      * @return {@code true} if the flag is set
157      */
158     public boolean isFlagSet(short mask) {
159         return (value & mask) != 0;
160     }
161 
162     @Override
163     public int hashCode() {
164         final int prime = 31;
165         int result = 1;
166         result = prime * result + value;
167         return result;
168     }
169 
170     @Override
171     public boolean equals(Object obj) {
172         if (this == obj) {
173             return true;
174         }
175         if (obj == null) {
176             return false;
177         }
178         if (getClass() != obj.getClass()) {
179             return false;
180         }
181 
182         return value == ((Http2Flags) obj).value;
183     }
184 
185     @Override
186     public String toString() {
187         StringBuilder builder = new StringBuilder();
188         builder.append("value = ").append(value).append(" (");
189         if (ack()) {
190             builder.append("ACK,");
191         }
192         if (endOfHeaders()) {
193             builder.append("END_OF_HEADERS,");
194         }
195         if (endOfStream()) {
196             builder.append("END_OF_STREAM,");
197         }
198         if (priorityPresent()) {
199             builder.append("PRIORITY_PRESENT,");
200         }
201         if (paddingPresent()) {
202             builder.append("PADDING_PRESENT,");
203         }
204         builder.append(')');
205         return builder.toString();
206     }
207 }