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.buffer.ByteBuf; 19 import io.netty.util.concurrent.Future; 20 import io.netty.util.concurrent.Promise; 21 22 /** 23 * Manager for the state of an HTTP/2 connection with the remote end-point. 24 */ 25 public interface Http2Connection { 26 /** 27 * Listener for life-cycle events for streams in this connection. 28 */ 29 interface Listener { 30 /** 31 * Notifies the listener that the given stream was added to the connection. This stream may 32 * not yet be active (i.e. {@code OPEN} or {@code HALF CLOSED}). 33 * <p> 34 * If a {@link RuntimeException} is thrown it will be logged and <strong>not propagated</strong>. 35 * Throwing from this method is not supported and is considered a programming error. 36 */ 37 void onStreamAdded(Http2Stream stream); 38 39 /** 40 * Notifies the listener that the given stream was made active (i.e. {@code OPEN} or {@code HALF CLOSED}). 41 * <p> 42 * If a {@link RuntimeException} is thrown it will be logged and <strong>not propagated</strong>. 43 * Throwing from this method is not supported and is considered a programming error. 44 */ 45 void onStreamActive(Http2Stream stream); 46 47 /** 48 * Notifies the listener that the given stream has transitioned from {@code OPEN} to {@code HALF CLOSED}. 49 * This method will <strong>not</strong> be called until a state transition occurs from when 50 * {@link #onStreamActive(Http2Stream)} was called. 51 * The stream can be inspected to determine which side is {@code HALF CLOSED}. 52 * <p> 53 * If a {@link RuntimeException} is thrown it will be logged and <strong>not propagated</strong>. 54 * Throwing from this method is not supported and is considered a programming error. 55 */ 56 void onStreamHalfClosed(Http2Stream stream); 57 58 /** 59 * Notifies the listener that the given stream is now {@code CLOSED} in both directions and will no longer 60 * be accessible via {@link #forEachActiveStream(Http2StreamVisitor)}. 61 * <p> 62 * If a {@link RuntimeException} is thrown it will be logged and <strong>not propagated</strong>. 63 * Throwing from this method is not supported and is considered a programming error. 64 */ 65 void onStreamClosed(Http2Stream stream); 66 67 /** 68 * Notifies the listener that the given stream has now been removed from the connection and 69 * will no longer be returned via {@link Http2Connection#stream(int)}. The connection may 70 * maintain inactive streams for some time before removing them. 71 * <p> 72 * If a {@link RuntimeException} is thrown it will be logged and <strong>not propagated</strong>. 73 * Throwing from this method is not supported and is considered a programming error. 74 */ 75 void onStreamRemoved(Http2Stream stream); 76 77 /** 78 * Called when a {@code GOAWAY} frame was sent for the connection. 79 * <p> 80 * If a {@link RuntimeException} is thrown it will be logged and <strong>not propagated</strong>. 81 * Throwing from this method is not supported and is considered a programming error. 82 * @param lastStreamId the last known stream of the remote endpoint. 83 * @param errorCode the error code, if abnormal closure. 84 * @param debugData application-defined debug data. 85 */ 86 void onGoAwaySent(int lastStreamId, long errorCode, ByteBuf debugData); 87 88 /** 89 * Called when a {@code GOAWAY} was received from the remote endpoint. This event handler duplicates {@link 90 * Http2FrameListener#onGoAwayRead(io.netty.channel.ChannelHandlerContext, int, long, ByteBuf)} 91 * but is added here in order to simplify application logic for handling {@code GOAWAY} in a uniform way. An 92 * application should generally not handle both events, but if it does this method is called second, after 93 * notifying the {@link Http2FrameListener}. 94 * <p> 95 * If a {@link RuntimeException} is thrown it will be logged and <strong>not propagated</strong>. 96 * Throwing from this method is not supported and is considered a programming error. 97 * @param lastStreamId the last known stream of the remote endpoint. 98 * @param errorCode the error code, if abnormal closure. 99 * @param debugData application-defined debug data. 100 */ 101 void onGoAwayReceived(int lastStreamId, long errorCode, ByteBuf debugData); 102 } 103 104 /** 105 * A view of the connection from one endpoint (local or remote). 106 */ 107 interface Endpoint<F extends Http2FlowController> { 108 /** 109 * Increment and get the next generated stream id this endpoint. If negative, the stream IDs are 110 * exhausted for this endpoint an no further streams may be created. 111 */ 112 int incrementAndGetNextStreamId(); 113 114 /** 115 * Indicates whether the given streamId is from the set of IDs used by this endpoint to 116 * create new streams. 117 */ 118 boolean isValidStreamId(int streamId); 119 120 /** 121 * Indicates whether or not this endpoint may have created the given stream. This is {@code true} if 122 * {@link #isValidStreamId(int)} and {@code streamId} <= {@link #lastStreamCreated()}. 123 */ 124 boolean mayHaveCreatedStream(int streamId); 125 126 /** 127 * Indicates whether or not this endpoint created the given stream. 128 */ 129 boolean created(Http2Stream stream); 130 131 /** 132 * Indicates whether or a stream created by this endpoint can be opened without violating 133 * {@link #maxActiveStreams()}. 134 */ 135 boolean canOpenStream(); 136 137 /** 138 * Creates a stream initiated by this endpoint. This could fail for the following reasons: 139 * <ul> 140 * <li>The requested stream ID is not the next sequential ID for this endpoint.</li> 141 * <li>The stream already exists.</li> 142 * <li>{@link #canOpenStream()} is {@code false}.</li> 143 * <li>The connection is marked as going away.</li> 144 * </ul> 145 * <p> 146 * The initial state of the stream will be immediately set before notifying {@link Listener}s. The state 147 * transition is sensitive to {@code halfClosed} and is defined by {@link Http2Stream#open(boolean)}. 148 * @param streamId The ID of the stream 149 * @param halfClosed see {@link Http2Stream#open(boolean)}. 150 * @see Http2Stream#open(boolean) 151 */ 152 Http2Stream createStream(int streamId, boolean halfClosed) throws Http2Exception; 153 154 /** 155 * Creates a push stream in the reserved state for this endpoint and notifies all listeners. 156 * This could fail for the following reasons: 157 * <ul> 158 * <li>Server push is not allowed to the opposite endpoint.</li> 159 * <li>The requested stream ID is not the next sequential stream ID for this endpoint.</li> 160 * <li>The number of concurrent streams is above the allowed threshold for this endpoint.</li> 161 * <li>The connection is marked as going away.</li> 162 * <li>The parent stream ID does not exist or is not {@code OPEN} from the side sending the push 163 * promise.</li> 164 * <li>Could not set a valid priority for the new stream.</li> 165 * </ul> 166 * 167 * @param streamId the ID of the push stream 168 * @param parent the parent stream used to initiate the push stream. 169 */ 170 Http2Stream reservePushStream(int streamId, Http2Stream parent) throws Http2Exception; 171 172 /** 173 * Indicates whether or not this endpoint is the server-side of the connection. 174 */ 175 boolean isServer(); 176 177 /** 178 * This is the <a href="https://tools.ietf.org/html/rfc7540#section-6.5.2">SETTINGS_ENABLE_PUSH</a> value sent 179 * from the opposite endpoint. This method should only be called by Netty (not users) as a result of a 180 * receiving a {@code SETTINGS} frame. 181 */ 182 void allowPushTo(boolean allow); 183 184 /** 185 * This is the <a href="https://tools.ietf.org/html/rfc7540#section-6.5.2">SETTINGS_ENABLE_PUSH</a> value sent 186 * from the opposite endpoint. The initial value must be {@code true} for the client endpoint and always false 187 * for a server endpoint. 188 */ 189 boolean allowPushTo(); 190 191 /** 192 * Gets the number of active streams (i.e. {@code OPEN} or {@code HALF CLOSED}) that were created by this 193 * endpoint. 194 */ 195 int numActiveStreams(); 196 197 /** 198 * Gets the maximum number of streams (created by this endpoint) that are allowed to be active at 199 * the same time. This is the 200 * <a href="https://tools.ietf.org/html/rfc7540#section-6.5.2">SETTINGS_MAX_CONCURRENT_STREAMS</a> 201 * value sent from the opposite endpoint to restrict stream creation by this endpoint. 202 * <p> 203 * The default value returned by this method must be "unlimited". 204 */ 205 int maxActiveStreams(); 206 207 /** 208 * Sets the limit for {@code SETTINGS_MAX_CONCURRENT_STREAMS}. 209 * @param maxActiveStreams The maximum number of streams (created by this endpoint) that are allowed to be 210 * active at once. This is the 211 * <a href="https://tools.ietf.org/html/rfc7540#section-6.5.2">SETTINGS_MAX_CONCURRENT_STREAMS</a> value sent 212 * from the opposite endpoint to restrict stream creation by this endpoint. 213 */ 214 void maxActiveStreams(int maxActiveStreams); 215 216 /** 217 * Gets the ID of the stream last successfully created by this endpoint. 218 */ 219 int lastStreamCreated(); 220 221 /** 222 * If a GOAWAY was received for this endpoint, this will be the last stream ID from the 223 * GOAWAY frame. Otherwise, this will be {@code -1}. 224 */ 225 int lastStreamKnownByPeer(); 226 227 /** 228 * Gets the flow controller for this endpoint. 229 */ 230 F flowController(); 231 232 /** 233 * Sets the flow controller for this endpoint. 234 */ 235 void flowController(F flowController); 236 237 /** 238 * Gets the {@link Endpoint} opposite this one. 239 */ 240 Endpoint<? extends Http2FlowController> opposite(); 241 } 242 243 /** 244 * A key to be used for associating application-defined properties with streams within this connection. 245 */ 246 interface PropertyKey { 247 } 248 249 /** 250 * Close this connection. No more new streams can be created after this point and 251 * all streams that exists (active or otherwise) will be closed and removed. 252 * <p>Note if iterating active streams via {@link #forEachActiveStream(Http2StreamVisitor)} and an exception is 253 * thrown it is necessary to call this method again to ensure the close completes. 254 * @param promise Will be completed when all streams have been removed, and listeners have been notified. 255 * @return A future that will be completed when all streams have been removed, and listeners have been notified. 256 */ 257 Future<Void> close(Promise<Void> promise); 258 259 /** 260 * Creates a new key that is unique within this {@link Http2Connection}. 261 */ 262 PropertyKey newKey(); 263 264 /** 265 * Adds a listener of stream life-cycle events. 266 */ 267 void addListener(Listener listener); 268 269 /** 270 * Removes a listener of stream life-cycle events. If the same listener was added multiple times 271 * then only the first occurrence gets removed. 272 */ 273 void removeListener(Listener listener); 274 275 /** 276 * Gets the stream if it exists. If not, returns {@code null}. 277 */ 278 Http2Stream stream(int streamId); 279 280 /** 281 * Indicates whether or not the given stream may have existed within this connection. This is a short form 282 * for calling {@link Endpoint#mayHaveCreatedStream(int)} on both endpoints. 283 */ 284 boolean streamMayHaveExisted(int streamId); 285 286 /** 287 * Gets the stream object representing the connection, itself (i.e. stream zero). This object 288 * always exists. 289 */ 290 Http2Stream connectionStream(); 291 292 /** 293 * Gets the number of streams that are actively in use (i.e. {@code OPEN} or {@code HALF CLOSED}). 294 */ 295 int numActiveStreams(); 296 297 /** 298 * Provide a means of iterating over the collection of active streams. 299 * 300 * @param visitor The visitor which will visit each active stream. 301 * @return The stream before iteration stopped or {@code null} if iteration went past the end. 302 */ 303 Http2Stream forEachActiveStream(Http2StreamVisitor visitor) throws Http2Exception; 304 305 /** 306 * Indicates whether or not the local endpoint for this connection is the server. 307 */ 308 boolean isServer(); 309 310 /** 311 * Gets a view of this connection from the local {@link Endpoint}. 312 */ 313 Endpoint<Http2LocalFlowController> local(); 314 315 /** 316 * Gets a view of this connection from the remote {@link Endpoint}. 317 */ 318 Endpoint<Http2RemoteFlowController> remote(); 319 320 /** 321 * Indicates whether or not a {@code GOAWAY} was received from the remote endpoint. 322 */ 323 boolean goAwayReceived(); 324 325 /** 326 * Indicates that a {@code GOAWAY} was received from the remote endpoint and sets the last known stream. 327 * @param lastKnownStream The Last-Stream-ID in the 328 * <a href="https://tools.ietf.org/html/rfc7540#section-6.8">GOAWAY</a> frame. 329 * @param errorCode the Error Code in the 330 * <a href="https://tools.ietf.org/html/rfc7540#section-6.8">GOAWAY</a> frame. 331 * @param message The Additional Debug Data in the 332 * <a href="https://tools.ietf.org/html/rfc7540#section-6.8">GOAWAY</a> frame. Note that reference count ownership 333 * belongs to the caller (ownership is not transferred to this method). 334 */ 335 void goAwayReceived(int lastKnownStream, long errorCode, ByteBuf message) throws Http2Exception; 336 337 /** 338 * Indicates whether or not a {@code GOAWAY} was sent to the remote endpoint. 339 */ 340 boolean goAwaySent(); 341 342 /** 343 * Updates the local state of this {@link Http2Connection} as a result of a {@code GOAWAY} to send to the remote 344 * endpoint. 345 * @param lastKnownStream The Last-Stream-ID in the 346 * <a href="https://tools.ietf.org/html/rfc7540#section-6.8">GOAWAY</a> frame. 347 * @param errorCode the Error Code in the 348 * <a href="https://tools.ietf.org/html/rfc7540#section-6.8">GOAWAY</a> frame. 349 * <a href="https://tools.ietf.org/html/rfc7540#section-6.8">GOAWAY</a> frame. Note that reference count ownership 350 * belongs to the caller (ownership is not transferred to this method). 351 * @return {@code true} if the corresponding {@code GOAWAY} frame should be sent to the remote endpoint. 352 */ 353 boolean goAwaySent(int lastKnownStream, long errorCode, ByteBuf message) throws Http2Exception; 354 }