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