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