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 }