Motivation: Http2ConnectionHandler#close(..) always runs the GOAWAY and graceful close logic. This coupling means that a user would have to override Http2ConnectionHandler#close(..) to modify the behavior, and the Http2FrameCodec and Http2MultiplexCodec are not extendable so you cannot override at this layer. Ideally we can totally decouple the close(..) of the transport and the GOAWAY graceful closure process completely, but to preserve backwards compatibility we can add an opt-out option to decouple where the application is responsible for sending a GOAWAY with error code equal to NO_ERROR as described in https://tools.ietf.org/html/rfc7540#section-6.8 in order to initiate graceful close. Modifications: - Http2ConnectionHandler supports an additional boolean constructor argument to opt out of close(..) going through the graceful close path. - Http2FrameCodecBuilder and Http2MultiplexCodec expose gracefulShutdownTimeoutMillis but do not hook them up properly. Since these are already exposed we should hook them up and make sure the timeout is applied properly. - Http2ConnectionHandler's goAway(..) method from Http2LifecycleManager should initiate the graceful closure process after writing a GOAWAY frame if the error code is NO_ERROR. This means that writing a Http2GoAwayFrame from Http2FrameCodec will initiate graceful close. Result: Http2ConnectionHandler#close(..) can now be decoupled from the graceful close process, and immediately close the underlying transport if desired.
111 lines
3.9 KiB
Java
111 lines
3.9 KiB
Java
/*
|
|
* Copyright 2015 The Netty Project
|
|
*
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
package io.netty.handler.codec.http2;
|
|
|
|
import io.netty.handler.codec.http2.Http2HeadersEncoder.SensitivityDetector;
|
|
import io.netty.util.internal.UnstableApi;
|
|
|
|
/**
|
|
* Builder which builds {@link Http2ConnectionHandler} objects.
|
|
*/
|
|
@UnstableApi
|
|
public final class Http2ConnectionHandlerBuilder
|
|
extends AbstractHttp2ConnectionHandlerBuilder<Http2ConnectionHandler, Http2ConnectionHandlerBuilder> {
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder validateHeaders(boolean validateHeaders) {
|
|
return super.validateHeaders(validateHeaders);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder initialSettings(Http2Settings settings) {
|
|
return super.initialSettings(settings);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder frameListener(Http2FrameListener frameListener) {
|
|
return super.frameListener(frameListener);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
|
|
return super.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder server(boolean isServer) {
|
|
return super.server(isServer);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder connection(Http2Connection connection) {
|
|
return super.connection(connection);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder maxReservedStreams(int maxReservedStreams) {
|
|
return super.maxReservedStreams(maxReservedStreams);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder codec(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder) {
|
|
return super.codec(decoder, encoder);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder frameLogger(Http2FrameLogger frameLogger) {
|
|
return super.frameLogger(frameLogger);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder encoderEnforceMaxConcurrentStreams(
|
|
boolean encoderEnforceMaxConcurrentStreams) {
|
|
return super.encoderEnforceMaxConcurrentStreams(encoderEnforceMaxConcurrentStreams);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder encoderIgnoreMaxHeaderListSize(boolean encoderIgnoreMaxHeaderListSize) {
|
|
return super.encoderIgnoreMaxHeaderListSize(encoderIgnoreMaxHeaderListSize);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder headerSensitivityDetector(SensitivityDetector headerSensitivityDetector) {
|
|
return super.headerSensitivityDetector(headerSensitivityDetector);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder initialHuffmanDecodeCapacity(int initialHuffmanDecodeCapacity) {
|
|
return super.initialHuffmanDecodeCapacity(initialHuffmanDecodeCapacity);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandlerBuilder decoupleCloseAndGoAway(boolean decoupleCloseAndGoAway) {
|
|
return super.decoupleCloseAndGoAway(decoupleCloseAndGoAway);
|
|
}
|
|
|
|
@Override
|
|
public Http2ConnectionHandler build() {
|
|
return super.build();
|
|
}
|
|
|
|
@Override
|
|
protected Http2ConnectionHandler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
|
|
Http2Settings initialSettings) {
|
|
return new Http2ConnectionHandler(decoder, encoder, initialSettings, decoupleCloseAndGoAway());
|
|
}
|
|
}
|