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 }