Revamp the Http2ConnectionHandler builder API

Related: #4572

Motivation:

- A user might want to extend Http2ConnectionHandler and define his/her
  own static inner Builder class that extends
  Http2ConnectionHandler.BuilderBase. This introduces potential
  confusion because there's already Http2ConnectionHandler.Builder. Your
  IDE will warn about this name duplication as well.
- BuilderBase exposes all setters with public modifier. A user's Builder
  might not want to expose them to enforce it to certain configuration.
  There's no way to hide them because it's public already and they are
  final.
- BuilderBase.build(Http2ConnectionDecoder, Http2ConnectionEncoder)
  ignores most properties exposed by BuilderBase, such as
  validateHeaders, frameLogger and encoderEnforceMaxConcurrentStreams.
  If any build() method ignores the properties exposed by the builder,
  there's something wrong.
- A user's Builder that extends BuilderBase might want to require more
  parameters in build(). There's no way to do that cleanly because
  build() is public and final already.

Modifications:

- Make BuilderBase and Builder top-level so that there's no duplicate
  name issue anymore.
  - Add AbstractHttp2ConnectionHandlerBuilder
  - Add Http2ConnectionHandlerBuilder
  - Add HttpToHttp2ConnectionHandlerBuilder
- Make all builder methods in AbstractHttp2ConnectionHandlerBuilder
  protected so that a subclass can choose which methods to expose
- Provide only a single build() method
  - Add connection() and codec() so that a user can still specify
    Http2Connection or Http2Connection(En|De)coder explicitly
  - Implement proper state validation mechanism so that it is prevented
    to invoke conflicting setters

Result:

Less confusing yet flexible builder API
This commit is contained in:
Trustin Lee 2015-12-16 14:10:28 +09:00
parent 253cd694ef
commit 2202e8f967
17 changed files with 691 additions and 285 deletions

View File

@ -0,0 +1,394 @@
/*
* 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 static io.netty.util.internal.ObjectUtil.checkNotNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* Abstract base class which defines commonly used features required to build {@link Http2ConnectionHandler} instances.
*
* <h3>Three ways to build a {@link Http2ConnectionHandler}</h3>
* <h4>Let the builder create a {@link Http2ConnectionHandler}</h4>
* Simply call all the necessary setter methods, and then use {@link #build()} to build a new
* {@link Http2ConnectionHandler}. Setting the following properties are prohibited because they are used for
* other ways of building a {@link Http2ConnectionHandler}.
* conflicts with this option:
* <ul>
* <li>{@link #connection(Http2Connection)}</li>
* <li>{@link #codec(Http2ConnectionDecoder, Http2ConnectionEncoder)}</li>
* </ul>
*
*
* <h4>Let the builder use the {@link Http2ConnectionHandler} you specified</h4>
* Call {@link #connection(Http2Connection)} to tell the builder that you want to build the handler from the
* {@link Http2Connection} you specified. Setting the following properties are prohibited and thus will trigger
* an {@link IllegalStateException} because they conflict with this option.
* <ul>
* <li>{@link #server(boolean)}</li>
* <li>{@link #codec(Http2ConnectionDecoder, Http2ConnectionEncoder)}</li>
* </ul>
*
* <h4>Let the builder use the {@link Http2ConnectionDecoder} and {@link Http2ConnectionEncoder} you specified</h4>
* Call {@link #codec(Http2ConnectionDecoder, Http2ConnectionEncoder)} to tell the builder that you want to built the
* handler from the {@link Http2ConnectionDecoder} and {@link Http2ConnectionEncoder} you specified. Setting the
* following properties are prohibited and thus will trigger an {@link IllegalStateException} because they conflict
* with this option:
* <ul>
* <li>{@link #server(boolean)}</li>
* <li>{@link #connection(Http2Connection)}</li>
* <li>{@link #frameLogger(Http2FrameLogger)}</li>
* <li>{@link #headerSensitivityDetector(SensitivityDetector)}</li>
* <li>{@link #encoderEnforceMaxConcurrentStreams(boolean)}</li>
* </ul>
*
* <h3>Exposing necessary methods in a subclass</h3>
* {@link #build()} method and all property access methods are {@code protected}. Choose the methods to expose to the
* users of your builder implementation and make them {@code public}.
*
* @param <T> The type of handler created by this builder.
* @param <B> The concrete type of this builder.
*/
public abstract class AbstractHttp2ConnectionHandlerBuilder<T extends Http2ConnectionHandler,
B extends AbstractHttp2ConnectionHandlerBuilder<T, B>> {
private static final long DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT_MILLIS = MILLISECONDS.convert(30, SECONDS);
private static final SensitivityDetector DEFAULT_HEADER_SENSITIVITY_DETECTOR = Http2HeadersEncoder.NEVER_SENSITIVE;
// The properties that can always be set.
private boolean validateHeaders = true;
private Http2Settings initialSettings = new Http2Settings();
private Http2FrameListener frameListener;
private long gracefulShutdownTimeoutMillis = DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT_MILLIS;
// The property that will prohibit connection() and codec() if set by server(),
// because this property is used only when this builder creates a Http2Connection.
private Boolean isServer;
// The property that will prohibit server() and codec() if set by connection().
private Http2Connection connection;
// The properties that will prohibit server() and connection() if set by codec().
private Http2ConnectionDecoder decoder;
private Http2ConnectionEncoder encoder;
// The properties that are:
// * mutually exclusive against codec() and
// * OK to use with server() and connection()
private Http2FrameLogger frameLogger;
private SensitivityDetector headerSensitivityDetector;
private Boolean encoderEnforceMaxConcurrentStreams;
/**
* Returns if HTTP headers should be validated according to
* <a href="https://tools.ietf.org/html/rfc7540#section-8.1.2.6">RFC 7540, 8.1.2.6</a>.
*/
protected boolean isValidateHeaders() {
return validateHeaders;
}
/**
* Sets if HTTP headers should be validated according to
* <a href="https://tools.ietf.org/html/rfc7540#section-8.1.2.6">RFC 7540, 8.1.2.6</a>.
*/
protected B validateHeaders(boolean validateHeaders) {
this.validateHeaders = validateHeaders;
return self();
}
/**
* Sets the {@link Http2Settings} to use for the initial connection settings exchange.
*/
protected Http2Settings initialSettings() {
return initialSettings;
}
/**
* Sets the {@link Http2Settings} to use for the initial connection settings exchange.
*/
protected B initialSettings(Http2Settings settings) {
initialSettings = checkNotNull(settings, "settings");
return self();
}
/**
* Returns the listener of inbound frames.
*
* @return {@link Http2FrameListener} if set, or {@code null} if not set.
*/
protected Http2FrameListener frameListener() {
return frameListener;
}
/**
* Sets the listener of inbound frames.
* This listener will only be set if the decoder's listener is {@code null}.
*/
protected B frameListener(Http2FrameListener frameListener) {
this.frameListener = checkNotNull(frameListener, "frameListener");
return self();
}
/**
* Returns the graceful shutdown timeout of the {@link Http2Connection} in milliseconds.
*/
protected long gracefulShutdownTimeoutMillis() {
return gracefulShutdownTimeoutMillis;
}
/**
* Sets the graceful shutdown timeout of the {@link Http2Connection} in milliseconds.
*/
protected B gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
this.gracefulShutdownTimeoutMillis = gracefulShutdownTimeoutMillis;
return self();
}
/**
* Returns if {@link #build()} will to create a {@link Http2Connection} in server mode ({@code true})
* or client mode ({@code false}).
*/
protected boolean isServer() {
return isServer != null ? isServer : true;
}
/**
* Sets if {@link #build()} will to create a {@link Http2Connection} in server mode ({@code true})
* or client mode ({@code false}).
*/
protected B server(boolean isServer) {
enforceConstraint("server", "connection", connection);
enforceConstraint("server", "codec", decoder);
enforceConstraint("server", "codec", encoder);
this.isServer = isServer;
return self();
}
/**
* Returns the {@link Http2Connection} to use.
*
* @return {@link Http2Connection} if set, or {@code null} if not set.
*/
protected Http2Connection connection() {
return connection;
}
/**
* Sets the {@link Http2Connection} to use.
*/
protected B connection(Http2Connection connection) {
enforceConstraint("connection", "server", isServer);
enforceConstraint("connection", "codec", decoder);
enforceConstraint("connection", "codec", encoder);
this.connection = checkNotNull(connection, "connection");
return self();
}
/**
* Returns the {@link Http2ConnectionDecoder} to use.
*
* @return {@link Http2ConnectionDecoder} if set, or {@code null} if not set.
*/
protected Http2ConnectionDecoder decoder() {
return decoder;
}
/**
* Returns the {@link Http2ConnectionEncoder} to use.
*
* @return {@link Http2ConnectionEncoder} if set, or {@code null} if not set.
*/
protected Http2ConnectionEncoder encoder() {
return encoder;
}
/**
* Sets the {@link Http2ConnectionDecoder} and {@link Http2ConnectionEncoder} to use.
*/
protected B codec(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder) {
enforceConstraint("codec", "server", isServer);
enforceConstraint("codec", "connection", connection);
enforceConstraint("codec", "frameLogger", frameLogger);
enforceConstraint("codec", "headerSensitivityDetector", headerSensitivityDetector);
enforceConstraint("codec", "encoderEnforceMaxConcurrentStreams", encoderEnforceMaxConcurrentStreams);
checkNotNull(decoder, "decoder");
checkNotNull(encoder, "encoder");
if (decoder.connection() != encoder.connection()) {
throw new IllegalArgumentException("The specified encoder and decoder have different connections.");
}
this.decoder = decoder;
this.encoder = encoder;
return self();
}
/**
* Returns the logger that is used for the encoder and decoder.
*
* @return {@link Http2FrameLogger} if set, or {@code null} if not set.
*/
protected Http2FrameLogger frameLogger() {
return frameLogger;
}
/**
* Sets the logger that is used for the encoder and decoder.
*/
protected B frameLogger(Http2FrameLogger frameLogger) {
enforceNonCodecConstraints("frameLogger");
this.frameLogger = checkNotNull(frameLogger, "frameLogger");
return self();
}
/**
* Returns if the encoder should queue frames if the maximum number of concurrent streams
* would otherwise be exceeded.
*/
protected boolean encoderEnforceMaxConcurrentStreams() {
return encoderEnforceMaxConcurrentStreams != null ? encoderEnforceMaxConcurrentStreams : false;
}
/**
* Sets if the encoder should queue frames if the maximum number of concurrent streams
* would otherwise be exceeded.
*/
protected B encoderEnforceMaxConcurrentStreams(boolean encoderEnforceMaxConcurrentStreams) {
enforceNonCodecConstraints("encoderEnforceMaxConcurrentStreams");
this.encoderEnforceMaxConcurrentStreams = encoderEnforceMaxConcurrentStreams;
return self();
}
/**
* Returns the {@link SensitivityDetector} to use.
*/
protected SensitivityDetector headerSensitivityDetector() {
return headerSensitivityDetector != null ? headerSensitivityDetector : DEFAULT_HEADER_SENSITIVITY_DETECTOR;
}
/**
* Sets the {@link SensitivityDetector} to use.
*/
protected B headerSensitivityDetector(SensitivityDetector headerSensitivityDetector) {
enforceNonCodecConstraints("headerSensitivityDetector");
this.headerSensitivityDetector = checkNotNull(headerSensitivityDetector, "headerSensitivityDetector");
return self();
}
/**
* Create a new {@link Http2ConnectionHandler}.
*/
protected T build() {
if (encoder != null) {
assert decoder != null;
return buildFromCodec(decoder, encoder);
}
Http2Connection connection = this.connection;
if (connection == null) {
connection = new DefaultHttp2Connection(isServer());
}
return buildFromConnection(connection);
}
private T buildFromConnection(Http2Connection connection) {
Http2FrameReader reader = new DefaultHttp2FrameReader(validateHeaders);
Http2FrameWriter writer = new DefaultHttp2FrameWriter(headerSensitivityDetector());
if (frameLogger != null) {
reader = new Http2InboundFrameLogger(reader, frameLogger);
writer = new Http2OutboundFrameLogger(writer, frameLogger);
}
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, writer);
boolean encoderEnforceMaxConcurrentStreams = encoderEnforceMaxConcurrentStreams();
if (encoderEnforceMaxConcurrentStreams) {
if (connection.isServer()) {
encoder.close();
reader.close();
throw new IllegalArgumentException(
"encoderEnforceMaxConcurrentStreams: " + encoderEnforceMaxConcurrentStreams +
" not supported for server");
}
encoder = new StreamBufferingEncoder(encoder);
}
Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(connection, encoder, reader);
return buildFromCodec(decoder, encoder);
}
private T buildFromCodec(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder) {
final T handler;
try {
// Call the abstract build method
handler = build(decoder, encoder, initialSettings);
} catch (Throwable t) {
encoder.close();
decoder.close();
throw new IllegalStateException("failed to build a Http2ConnectionHandler", t);
}
// Setup post build options
handler.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis);
if (handler.decoder().frameListener() == null) {
handler.decoder().frameListener(frameListener);
}
return handler;
}
/**
* Implement this method to create a new {@link Http2ConnectionHandler} or its subtype instance.
* <p>
* The return of this method will be subject to the following:
* <ul>
* <li>{@link #frameListener(Http2FrameListener)} will be set if not already set in the decoder</li>
* <li>{@link #gracefulShutdownTimeoutMillis(long)} will always be set</li>
* </ul>
*/
protected abstract T build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) throws Exception;
/**
* Returns {@code this}.
*/
@SuppressWarnings("unchecked")
protected final B self() {
return (B) this;
}
private void enforceNonCodecConstraints(String rejectee) {
enforceConstraint(rejectee, "server/connection", decoder);
enforceConstraint(rejectee, "server/connection", encoder);
}
private static void enforceConstraint(String methodName, String rejectorName, Object value) {
if (value != null) {
throw new IllegalStateException(
methodName + "() cannot be called because " + rejectorName + "() has been called already.");
}
}
}

View File

@ -61,9 +61,9 @@ import static java.util.concurrent.TimeUnit.SECONDS;
* {@link Http2LocalFlowController}
*/
public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http2LifecycleManager,
ChannelOutboundHandler {
ChannelOutboundHandler {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Http2ConnectionHandler.class);
private static final long DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT_MILLIS = MILLISECONDS.convert(30, SECONDS);
private final Http2ConnectionDecoder decoder;
private final Http2ConnectionEncoder encoder;
@ -72,194 +72,6 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
private BaseDecoder byteDecoder;
private long gracefulShutdownTimeoutMillis;
/**
* Builder which builds {@link Http2ConnectionHandler} objects.
*/
public static final class Builder extends BuilderBase<Http2ConnectionHandler, Builder> {
@Override
public Http2ConnectionHandler build0(Http2ConnectionDecoder decoder,
Http2ConnectionEncoder encoder) {
return new Http2ConnectionHandler(decoder, encoder, initialSettings());
}
}
/**
* Base class for a {@code builder} of any subclass of {@link Http2ConnectionHandler}.
* @param <T> The type of handler created by this builder.
* @param <B> The concrete type for this builder.
*/
public abstract static class BuilderBase<T extends Http2ConnectionHandler, B extends BuilderBase<T, B>> {
private Http2Settings initialSettings = new Http2Settings();
private Http2FrameListener frameListener;
private Http2FrameLogger frameLogger;
private Http2HeadersEncoder.SensitivityDetector headersSensativityDetector =
Http2HeadersEncoder.NEVER_SENSITIVE;
private boolean validateHeaders = true;
private boolean server = true;
private boolean encoderEnforceMaxConcurrentStreams;
private long gracefulShutdownTimeoutMillis = DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT_MILLIS;
/**
* Sets the listener for inbound frames.
* This listener will only be set if the decoder's listener is {@code null}.
*/
public B frameListener(Http2FrameListener listener) {
frameListener = listener;
return thisB();
}
/**
* Determine if HTTP headers should be validated according to
* <a href="https://tools.ietf.org/html/rfc7540#section-8.1.2.6">RFC 7540, 8.1.2.6</a>.
*/
public B validateHeaders(boolean validate) {
validateHeaders = validate;
return thisB();
}
/**
* Get if HTTP headers should be validated according to
* <a href="https://tools.ietf.org/html/rfc7540#section-8.1.2.6">RFC 7540, 8.1.2.6</a>.
*/
public final boolean isValidateHeaders() {
return validateHeaders;
}
/**
* Settings to use for the initial connection settings exchange.
*/
public B initialSettings(Http2Settings settings) {
initialSettings = settings;
return thisB();
}
/**
* Get the settings to use for the initial connection settings exchange.
*/
public final Http2Settings initialSettings() {
return initialSettings;
}
/**
* Determines if {@link #build()} will to create a {@link Http2Connection} in server mode ({@code true})
* or client mode ({@code false}).
*/
public B server(boolean isServer) {
server = isServer;
return thisB();
}
/**
* Set the logger that is used for the encoder and decoder.
*/
public B frameLogger(Http2FrameLogger logger) {
frameLogger = logger;
return thisB();
}
public B gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
this.gracefulShutdownTimeoutMillis = gracefulShutdownTimeoutMillis;
return thisB();
}
/**
* Determine if the encoder should queue frames if the maximum number of concurrent streams
* would otherwise be exceeded.
*/
public B encoderEnforceMaxConcurrentStreams(boolean encoderEnforceMaxConcurrentStreams) {
this.encoderEnforceMaxConcurrentStreams = encoderEnforceMaxConcurrentStreams;
return thisB();
}
/**
* Set the {@link Http2HeadersEncoder.SensitivityDetector} that will be used.
*/
public B headersSensativityDetector(Http2HeadersEncoder.SensitivityDetector headersSensativityDetector) {
this.headersSensativityDetector = checkNotNull(headersSensativityDetector, "headersSensativityDetector");
return thisB();
}
/**
* Create a new {@link Http2Connection} and build a new instance.
*/
public final T build() {
return build(new DefaultHttp2Connection(server));
}
/**
* Build a new instance with an existing {@link Http2Connection}.
* <p>
* Methods that will be ignored due to objects already being created:
* <ul><li>{@link #server(boolean)}</li></ul>
*/
public final T build(Http2Connection connection) {
Http2FrameReader reader = new DefaultHttp2FrameReader(validateHeaders);
Http2FrameWriter writer = new DefaultHttp2FrameWriter(headersSensativityDetector);
if (frameLogger != null) {
reader = new Http2InboundFrameLogger(reader, frameLogger);
writer = new Http2OutboundFrameLogger(writer, frameLogger);
}
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, writer);
if (encoderEnforceMaxConcurrentStreams) {
if (connection.isServer()) {
encoder.close();
reader.close();
throw new IllegalArgumentException(
"encoderEnforceMaxConcurrentStreams: " + encoderEnforceMaxConcurrentStreams +
" not supported for server");
}
encoder = new StreamBufferingEncoder(encoder);
}
Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(connection, encoder, reader);
return build(decoder, encoder);
}
/**
* Build a new instance with an existing {@link Http2ConnectionDecoder} and {@link Http2ConnectionEncoder}.
* <p>
* Methods that will be ignored due to objects already being created:
* <ul>
* <li>{@link #server(boolean)}</li>
* <li>{@link #frameLogger(Http2FrameLogger)}</li>
* <li>{@link #encoderEnforceMaxConcurrentStreams(boolean)}</li>
* <li>{@link #encoderEnforceMaxConcurrentStreams(boolean)} (int)}</li>
* <li>{@link #headersSensativityDetector(Http2HeadersEncoder.SensitivityDetector)}</li>
* </ul>
*/
public final T build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder) {
final T handler;
try {
// Call the abstract build method
handler = build0(decoder, encoder);
} catch (RuntimeException e) {
encoder.close();
decoder.close();
throw e;
}
// Setup post build options
handler.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis);
if (handler.decoder().frameListener() == null) {
handler.decoder().frameListener(frameListener);
}
return handler;
}
/**
* Sub classes should override this to instantiate the concrete type.
* <p>
* The return of this method will be subject to the following:
* <ul><li>{@link #frameListener(Http2FrameListener)} will be set if not already set in the decoder</li><li>
* {@link #gracefulShutdownTimeoutMillis(long)} will be set</li></ul>
*/
protected abstract T build0(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder);
@SuppressWarnings("unchecked")
protected B thisB() {
return (B) this;
}
}
protected Http2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
this.initialSettings = checkNotNull(initialSettings, "initialSettings");

View File

@ -0,0 +1,88 @@
/*
* 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;
/**
* Builder which builds {@link Http2ConnectionHandler} objects.
*/
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 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 headerSensitivityDetector(SensitivityDetector headerSensitivityDetector) {
return super.headerSensitivityDetector(headerSensitivityDetector);
}
@Override
public Http2ConnectionHandler build() {
return super.build();
}
@Override
protected Http2ConnectionHandler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
return new Http2ConnectionHandler(decoder, encoder, initialSettings);
}
}

View File

@ -36,17 +36,6 @@ public class HttpToHttp2ConnectionHandler extends Http2ConnectionHandler {
private final boolean validateHeaders;
private int currentStreamId;
/**
* Builder which builds {@link HttpToHttp2ConnectionHandler} objects.
*/
public static final class Builder extends BuilderBase<HttpToHttp2ConnectionHandler, Builder> {
@Override
public HttpToHttp2ConnectionHandler build0(Http2ConnectionDecoder decoder,
Http2ConnectionEncoder encoder) {
return new HttpToHttp2ConnectionHandler(decoder, encoder, initialSettings(), isValidateHeaders());
}
}
protected HttpToHttp2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings, boolean validateHeaders) {
super(decoder, encoder, initialSettings);

View File

@ -0,0 +1,90 @@
/*
* 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;
/**
* Builder which builds {@link HttpToHttp2ConnectionHandler} objects.
*/
public final class HttpToHttp2ConnectionHandlerBuilder extends
AbstractHttp2ConnectionHandlerBuilder<HttpToHttp2ConnectionHandler, HttpToHttp2ConnectionHandlerBuilder> {
@Override
public HttpToHttp2ConnectionHandlerBuilder validateHeaders(boolean validateHeaders) {
return super.validateHeaders(validateHeaders);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder initialSettings(Http2Settings settings) {
return super.initialSettings(settings);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder frameListener(Http2FrameListener frameListener) {
return super.frameListener(frameListener);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
return super.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder server(boolean isServer) {
return super.server(isServer);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder connection(Http2Connection connection) {
return super.connection(connection);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder codec(Http2ConnectionDecoder decoder,
Http2ConnectionEncoder encoder) {
return super.codec(decoder, encoder);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder frameLogger(Http2FrameLogger frameLogger) {
return super.frameLogger(frameLogger);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder encoderEnforceMaxConcurrentStreams(
boolean encoderEnforceMaxConcurrentStreams) {
return super.encoderEnforceMaxConcurrentStreams(encoderEnforceMaxConcurrentStreams);
}
@Override
public HttpToHttp2ConnectionHandlerBuilder headerSensitivityDetector(
SensitivityDetector headerSensitivityDetector) {
return super.headerSensitivityDetector(headerSensitivityDetector);
}
@Override
public HttpToHttp2ConnectionHandler build() {
return super.build();
}
@Override
protected HttpToHttp2ConnectionHandler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
return new HttpToHttp2ConnectionHandler(decoder, encoder, initialSettings, isValidateHeaders());
}
}

View File

@ -305,9 +305,9 @@ public class DataCompressionHttp2Test {
new DefaultHttp2ConnectionEncoder(serverConnection, frameWriter));
Http2ConnectionDecoder decoder =
new DefaultHttp2ConnectionDecoder(serverConnection, encoder, new DefaultHttp2FrameReader());
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler.Builder()
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandlerBuilder()
.frameListener(new DelegatingDecompressorFrameListener(serverConnection, serverListener))
.build(decoder, encoder);
.codec(decoder, encoder).build();
p.addLast(connectionHandler);
serverChannelLatch.countDown();
}
@ -330,11 +330,11 @@ public class DataCompressionHttp2Test {
Http2ConnectionDecoder decoder =
new DefaultHttp2ConnectionDecoder(clientConnection, clientEncoder,
new DefaultHttp2FrameReader());
clientHandler = new Http2ConnectionHandler.Builder()
clientHandler = new Http2ConnectionHandlerBuilder()
.frameListener(new DelegatingDecompressorFrameListener(clientConnection, clientListener))
// By default tests don't wait for server to gracefully shutdown streams
.gracefulShutdownTimeoutMillis(0)
.build(decoder, clientEncoder);
.codec(decoder, clientEncoder).build();
p.addLast(clientHandler);
}
});

View File

@ -24,7 +24,6 @@ import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.DefaultChannelPromise;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.GenericFutureListener;
import org.junit.After;
@ -180,7 +179,7 @@ public class Http2ConnectionHandlerTest {
}
private Http2ConnectionHandler newHandler() throws Exception {
Http2ConnectionHandler handler = new Http2ConnectionHandler.Builder().build(decoder, encoder);
Http2ConnectionHandler handler = new Http2ConnectionHandlerBuilder().codec(decoder, encoder).build();
handler.handlerAdded(ctx);
return handler;
}
@ -426,11 +425,11 @@ public class Http2ConnectionHandlerTest {
verify(ctx, times(1)).flush();
}
private ByteBuf dummyData() {
return Unpooled.buffer().writeBytes("abcdefgh".getBytes(CharsetUtil.UTF_8));
private static ByteBuf dummyData() {
return Unpooled.buffer().writeBytes("abcdefgh".getBytes(UTF_8));
}
private ByteBuf addSettingsHeader(ByteBuf buf) {
private static ByteBuf addSettingsHeader(ByteBuf buf) {
buf.writeMedium(Http2CodecUtil.SETTING_ENTRY_LENGTH);
buf.writeByte(Http2FrameTypes.SETTINGS);
buf.writeByte(0);

View File

@ -482,7 +482,7 @@ public class Http2ConnectionRoundtripTest {
serverFrameCountDown =
new FrameCountDown(serverListener, serverSettingsAckLatch,
requestLatch, dataLatch, trailersLatch, goAwayLatch);
p.addLast(new Http2ConnectionHandler.Builder()
p.addLast(new Http2ConnectionHandlerBuilder()
.server(true)
.frameListener(serverFrameCountDown)
.validateHeaders(false)
@ -496,7 +496,7 @@ public class Http2ConnectionRoundtripTest {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new Http2ConnectionHandler.Builder()
p.addLast(new Http2ConnectionHandlerBuilder()
.server(false)
.frameListener(clientListener)
.validateHeaders(false)

View File

@ -508,7 +508,7 @@ public class HttpToHttp2ConnectionHandlerTest {
ChannelPipeline p = ch.pipeline();
serverFrameCountDown =
new FrameCountDown(serverListener, serverSettingsAckLatch, requestLatch, null, trailersLatch);
p.addLast(new HttpToHttp2ConnectionHandler.Builder()
p.addLast(new HttpToHttp2ConnectionHandlerBuilder()
.server(true)
.frameListener(serverFrameCountDown)
.build());
@ -521,7 +521,7 @@ public class HttpToHttp2ConnectionHandlerTest {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
HttpToHttp2ConnectionHandler handler = new HttpToHttp2ConnectionHandler.Builder()
HttpToHttp2ConnectionHandler handler = new HttpToHttp2ConnectionHandlerBuilder()
.server(false)
.frameListener(clientListener)
.gracefulShutdownTimeoutMillis(0)

View File

@ -115,8 +115,9 @@ public class StreamBufferingEncoderTest {
encoder = new StreamBufferingEncoder(defaultEncoder);
DefaultHttp2ConnectionDecoder decoder =
new DefaultHttp2ConnectionDecoder(connection, encoder, mock(Http2FrameReader.class));
Http2ConnectionHandler handler = new Http2ConnectionHandler.Builder()
.frameListener(mock(Http2FrameListener.class)).build(decoder, encoder);
Http2ConnectionHandler handler = new Http2ConnectionHandlerBuilder()
.frameListener(mock(Http2FrameListener.class))
.codec(decoder, encoder).build();
// Set LifeCycleManager on encoder and decoder
when(ctx.channel()).thenReturn(channel);

View File

@ -30,6 +30,7 @@ import io.netty.handler.codec.http2.Http2ClientUpgradeCodec;
import io.netty.handler.codec.http2.Http2Connection;
import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandler;
import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandlerBuilder;
import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapter;
import io.netty.handler.ssl.ApplicationProtocolNames;
import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
@ -57,14 +58,15 @@ public class Http2ClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) throws Exception {
final Http2Connection connection = new DefaultHttp2Connection(false);
connectionHandler = new HttpToHttp2ConnectionHandler.Builder()
connectionHandler = new HttpToHttp2ConnectionHandlerBuilder()
.frameListener(new DelegatingDecompressorFrameListener(connection,
new InboundHttp2ToHttpAdapter.Builder(connection)
.maxContentLength(maxContentLength)
.propagateSettings(true)
.build()))
.frameLogger(logger)
.build(connection);
.connection(connection)
.build();
responseHandler = new HttpResponseHandler();
settingsHandler = new Http2SettingsHandler(ch.newPromise());
if (sslCtx != null) {

View File

@ -23,10 +23,8 @@ import io.netty.handler.codec.http2.DefaultHttp2Headers;
import io.netty.handler.codec.http2.Http2ConnectionDecoder;
import io.netty.handler.codec.http2.Http2ConnectionEncoder;
import io.netty.handler.codec.http2.Http2ConnectionHandler;
import io.netty.handler.codec.http2.Http2Exception;
import io.netty.handler.codec.http2.Http2Flags;
import io.netty.handler.codec.http2.Http2FrameListener;
import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.codec.http2.Http2Headers;
import io.netty.handler.codec.http2.Http2Settings;
import io.netty.util.AsciiString;
@ -36,31 +34,16 @@ import static io.netty.buffer.Unpooled.copiedBuffer;
import static io.netty.buffer.Unpooled.unreleasableBuffer;
import static io.netty.example.http2.Http2ExampleUtil.UPGRADE_RESPONSE_HEADER;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.logging.LogLevel.INFO;
/**
* A simple handler that responds with the message "Hello World!".
*/
public final class HelloWorldHttp2Handler extends Http2ConnectionHandler implements Http2FrameListener {
private static final Http2FrameLogger logger = new Http2FrameLogger(INFO, HelloWorldHttp2Handler.class);
static final ByteBuf RESPONSE_BYTES = unreleasableBuffer(copiedBuffer("Hello World", CharsetUtil.UTF_8));
public static final class Builder extends BuilderBase<HelloWorldHttp2Handler, Builder> {
public Builder() {
frameLogger(logger);
}
@Override
public HelloWorldHttp2Handler build0(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder) {
HelloWorldHttp2Handler handler = new HelloWorldHttp2Handler(decoder, encoder, initialSettings());
frameListener(handler);
return handler;
}
}
private HelloWorldHttp2Handler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
HelloWorldHttp2Handler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
super(decoder, encoder, initialSettings);
}
@ -99,8 +82,7 @@ public final class HelloWorldHttp2Handler extends Http2ConnectionHandler impleme
}
@Override
public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream)
throws Http2Exception {
public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream) {
int processed = data.readableBytes() + padding;
if (endOfStream) {
sendResponse(ctx, streamId, data.retain());
@ -109,11 +91,11 @@ public final class HelloWorldHttp2Handler extends Http2ConnectionHandler impleme
}
@Override
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding,
boolean endOfStream) throws Http2Exception {
public void onHeadersRead(ChannelHandlerContext ctx, int streamId,
Http2Headers headers, int padding, boolean endOfStream) {
if (endOfStream) {
ByteBuf content = ctx.alloc().buffer();
content.writeBytes(HelloWorldHttp2Handler.RESPONSE_BYTES.duplicate());
content.writeBytes(RESPONSE_BYTES.duplicate());
ByteBufUtil.writeAscii(content, " - via HTTP/2");
sendResponse(ctx, streamId, content);
}
@ -121,52 +103,50 @@ public final class HelloWorldHttp2Handler extends Http2ConnectionHandler impleme
@Override
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency,
short weight, boolean exclusive, int padding, boolean endOfStream) throws Http2Exception {
short weight, boolean exclusive, int padding, boolean endOfStream) {
onHeadersRead(ctx, streamId, headers, padding, endOfStream);
}
@Override
public void onPriorityRead(ChannelHandlerContext ctx, int streamId, int streamDependency, short weight,
boolean exclusive) throws Http2Exception {
public void onPriorityRead(ChannelHandlerContext ctx, int streamId, int streamDependency,
short weight, boolean exclusive) {
}
@Override
public void onRstStreamRead(ChannelHandlerContext ctx, int streamId, long errorCode) throws Http2Exception {
public void onRstStreamRead(ChannelHandlerContext ctx, int streamId, long errorCode) {
}
@Override
public void onSettingsAckRead(ChannelHandlerContext ctx) throws Http2Exception {
public void onSettingsAckRead(ChannelHandlerContext ctx) {
}
@Override
public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) throws Http2Exception {
public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) {
}
@Override
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) {
}
@Override
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2Exception {
public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) {
}
@Override
public void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int promisedStreamId, Http2Headers headers,
int padding) throws Http2Exception {
public void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int promisedStreamId,
Http2Headers headers, int padding) {
}
@Override
public void onGoAwayRead(ChannelHandlerContext ctx, int lastStreamId, long errorCode, ByteBuf debugData)
throws Http2Exception {
public void onGoAwayRead(ChannelHandlerContext ctx, int lastStreamId, long errorCode, ByteBuf debugData) {
}
@Override
public void onWindowUpdateRead(ChannelHandlerContext ctx, int streamId, int windowSizeIncrement)
throws Http2Exception {
public void onWindowUpdateRead(ChannelHandlerContext ctx, int streamId, int windowSizeIncrement) {
}
@Override
public void onUnknownFrame(ChannelHandlerContext ctx, byte frameType, int streamId, Http2Flags flags,
ByteBuf payload) throws Http2Exception {
public void onUnknownFrame(ChannelHandlerContext ctx, byte frameType, int streamId,
Http2Flags flags, ByteBuf payload) {
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.example.http2.helloworld.server;
import io.netty.handler.codec.http2.AbstractHttp2ConnectionHandlerBuilder;
import io.netty.handler.codec.http2.Http2ConnectionDecoder;
import io.netty.handler.codec.http2.Http2ConnectionEncoder;
import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.codec.http2.Http2Settings;
import static io.netty.handler.logging.LogLevel.INFO;
public final class HelloWorldHttp2HandlerBuilder
extends AbstractHttp2ConnectionHandlerBuilder<HelloWorldHttp2Handler, HelloWorldHttp2HandlerBuilder> {
private static final Http2FrameLogger logger = new Http2FrameLogger(INFO, HelloWorldHttp2Handler.class);
public HelloWorldHttp2HandlerBuilder() {
frameLogger(logger);
}
@Override
public HelloWorldHttp2Handler build() {
return super.build();
}
@Override
protected HelloWorldHttp2Handler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
HelloWorldHttp2Handler handler = new HelloWorldHttp2Handler(decoder, encoder, initialSettings);
frameListener(handler);
return handler;
}
}

View File

@ -35,7 +35,7 @@ public class Http2OrHttpHandler extends ApplicationProtocolNegotiationHandler {
@Override
protected void configurePipeline(ChannelHandlerContext ctx, String protocol) throws Exception {
if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
ctx.pipeline().addLast(new HelloWorldHttp2Handler.Builder().build());
ctx.pipeline().addLast(new HelloWorldHttp2HandlerBuilder().build());
return;
}

View File

@ -43,7 +43,7 @@ public class Http2ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
public UpgradeCodec newUpgradeCodec(CharSequence protocol) {
if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) {
return new Http2ServerUpgradeCodec(new HelloWorldHttp2Handler.Builder().build());
return new Http2ServerUpgradeCodec(new HelloWorldHttp2HandlerBuilder().build());
} else {
return null;
}

View File

@ -20,9 +20,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandler;
import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandlerBuilder;
import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapter;
import io.netty.handler.ssl.ApplicationProtocolNames;
import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
@ -59,10 +57,12 @@ public class Http2OrHttpHandler extends ApplicationProtocolNegotiationHandler {
InboundHttp2ToHttpAdapter listener = new InboundHttp2ToHttpAdapter.Builder(connection)
.propagateSettings(true).validateHttpHeaders(false).maxContentLength(MAX_CONTENT_LENGTH).build();
ctx.pipeline().addLast(new HttpToHttp2ConnectionHandler.Builder()
.frameListener(listener)
// .frameLogger(TilesHttp2ToHttpHandler.logger)
.build(connection));
ctx.pipeline().addLast(new HttpToHttp2ConnectionHandlerBuilder()
.frameListener(listener)
// .frameLogger(TilesHttp2ToHttpHandler.logger)
.connection(connection)
.build());
ctx.pipeline().addLast(new Http2RequestHandler());
}

View File

@ -14,12 +14,6 @@
*/
package io.netty.microbench.http2;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_MAX_FRAME_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_FRAME_SIZE_UPPER_BOUND;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
@ -55,6 +49,7 @@ import io.netty.handler.codec.http2.Http2Connection;
import io.netty.handler.codec.http2.Http2ConnectionDecoder;
import io.netty.handler.codec.http2.Http2ConnectionEncoder;
import io.netty.handler.codec.http2.Http2ConnectionHandler;
import io.netty.handler.codec.http2.Http2ConnectionHandlerBuilder;
import io.netty.handler.codec.http2.Http2FrameAdapter;
import io.netty.handler.codec.http2.Http2FrameWriter;
import io.netty.handler.codec.http2.Http2Headers;
@ -64,12 +59,6 @@ import io.netty.microbench.channel.EmbeddedChannelWriteReleaseHandlerContext;
import io.netty.microbench.util.AbstractSharedExecutorMicrobenchmark;
import io.netty.util.AsciiString;
import io.netty.util.concurrent.Future;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
@ -78,6 +67,17 @@ import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_MAX_FRAME_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_FRAME_SIZE_UPPER_BOUND;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@State(Scope.Benchmark)
public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchmark {
private static final EnvironmentParameters NIO_UNPOOLED_PARAMS =
@ -263,9 +263,10 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, environment.writer());
Http2ConnectionDecoder decoder =
new DefaultHttp2ConnectionDecoder(connection, encoder, new DefaultHttp2FrameReader());
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler.Builder()
.encoderEnforceMaxConcurrentStreams(false)
.frameListener(new Http2FrameAdapter()).build(decoder, encoder);
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandlerBuilder()
.encoderEnforceMaxConcurrentStreams(false)
.frameListener(new Http2FrameAdapter())
.codec(decoder, encoder).build();
p.addLast(connectionHandler);
environment.context(p.lastContext());
// Must wait for context to be set.
@ -293,9 +294,10 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, env.writer());
Http2ConnectionDecoder decoder =
new DefaultHttp2ConnectionDecoder(connection, encoder, new DefaultHttp2FrameReader());
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler.Builder()
.encoderEnforceMaxConcurrentStreams(false)
.frameListener(new Http2FrameAdapter()).build(decoder, encoder);
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandlerBuilder()
.encoderEnforceMaxConcurrentStreams(false)
.frameListener(new Http2FrameAdapter())
.codec(decoder, encoder).build();
env.context(new EmbeddedChannelWriteReleaseHandlerContext(alloc, connectionHandler) {
@Override
protected void handleException(Throwable t) {