Cleaning up the initialization of Http2ConnectionHandler
Motivation: It currently takes a builder for the encoder and decoder, which makes it difficult to decorate them. Modifications: Removed the builders from the interfaces entirely. Left the builder for the decoder impl but removed it from the encoder since it's constructor only takes 2 parameters. Also added decorator base classes for the encoder and decoder and made the CompressorHttp2ConnectionEncoder extend the decorator. Result: Fixes #3530
This commit is contained in:
parent
cb63e34bda
commit
6fbca14f8a
@ -34,10 +34,10 @@ import io.netty.handler.codec.compression.ZlibCodecFactory;
|
||||
import io.netty.handler.codec.compression.ZlibWrapper;
|
||||
|
||||
/**
|
||||
* A HTTP2 encoder that will compress data frames according to the {@code content-encoding} header for each stream.
|
||||
* The compression provided by this class will be applied to the data for the entire stream.
|
||||
* A decorating HTTP2 encoder that will compress data frames according to the {@code content-encoding} header for each
|
||||
* stream. The compression provided by this class will be applied to the data for the entire stream.
|
||||
*/
|
||||
public class CompressorHttp2ConnectionEncoder extends DefaultHttp2ConnectionEncoder {
|
||||
public class CompressorHttp2ConnectionEncoder extends DecoratingHttp2ConnectionEncoder {
|
||||
private static final Http2ConnectionAdapter CLEAN_UP_LISTENER = new Http2ConnectionAdapter() {
|
||||
@Override
|
||||
public void streamRemoved(Http2Stream stream) {
|
||||
@ -48,53 +48,33 @@ public class CompressorHttp2ConnectionEncoder extends DefaultHttp2ConnectionEnco
|
||||
}
|
||||
};
|
||||
|
||||
public static final int DEFAULT_COMPRESSION_LEVEL = 6;
|
||||
public static final int DEFAULT_WINDOW_BITS = 15;
|
||||
public static final int DEFAULT_MEM_LEVEL = 8;
|
||||
|
||||
private final int compressionLevel;
|
||||
private final int windowBits;
|
||||
private final int memLevel;
|
||||
|
||||
/**
|
||||
* Builder for new instances of {@link CompressorHttp2ConnectionEncoder}
|
||||
*/
|
||||
public static class Builder extends DefaultHttp2ConnectionEncoder.Builder {
|
||||
protected int compressionLevel = 6;
|
||||
protected int windowBits = 15;
|
||||
protected int memLevel = 8;
|
||||
|
||||
public Builder compressionLevel(int compressionLevel) {
|
||||
this.compressionLevel = compressionLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder windowBits(int windowBits) {
|
||||
this.windowBits = windowBits;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder memLevel(int memLevel) {
|
||||
this.memLevel = memLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompressorHttp2ConnectionEncoder build() {
|
||||
return new CompressorHttp2ConnectionEncoder(this);
|
||||
}
|
||||
public CompressorHttp2ConnectionEncoder(Http2ConnectionEncoder delegate) {
|
||||
this(delegate, DEFAULT_COMPRESSION_LEVEL, DEFAULT_WINDOW_BITS, DEFAULT_MEM_LEVEL);
|
||||
}
|
||||
|
||||
protected CompressorHttp2ConnectionEncoder(Builder builder) {
|
||||
super(builder);
|
||||
if (builder.compressionLevel < 0 || builder.compressionLevel > 9) {
|
||||
throw new IllegalArgumentException("compressionLevel: " + builder.compressionLevel + " (expected: 0-9)");
|
||||
public CompressorHttp2ConnectionEncoder(Http2ConnectionEncoder delegate, int compressionLevel, int windowBits,
|
||||
int memLevel) {
|
||||
super(delegate);
|
||||
if (compressionLevel < 0 || compressionLevel > 9) {
|
||||
throw new IllegalArgumentException("compressionLevel: " + compressionLevel + " (expected: 0-9)");
|
||||
}
|
||||
if (builder.windowBits < 9 || builder.windowBits > 15) {
|
||||
throw new IllegalArgumentException("windowBits: " + builder.windowBits + " (expected: 9-15)");
|
||||
if (windowBits < 9 || windowBits > 15) {
|
||||
throw new IllegalArgumentException("windowBits: " + windowBits + " (expected: 9-15)");
|
||||
}
|
||||
if (builder.memLevel < 1 || builder.memLevel > 9) {
|
||||
throw new IllegalArgumentException("memLevel: " + builder.memLevel + " (expected: 1-9)");
|
||||
if (memLevel < 1 || memLevel > 9) {
|
||||
throw new IllegalArgumentException("memLevel: " + memLevel + " (expected: 1-9)");
|
||||
}
|
||||
compressionLevel = builder.compressionLevel;
|
||||
windowBits = builder.windowBits;
|
||||
memLevel = builder.memLevel;
|
||||
this.compressionLevel = compressionLevel;
|
||||
this.windowBits = windowBits;
|
||||
this.memLevel = memLevel;
|
||||
|
||||
connection().addListener(CLEAN_UP_LISTENER);
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Decorator around another {@link Http2ConnectionDecoder} instance.
|
||||
*/
|
||||
public class DecoratingHttp2ConnectionDecoder implements Http2ConnectionDecoder {
|
||||
private final Http2ConnectionDecoder delegate;
|
||||
|
||||
public DecoratingHttp2ConnectionDecoder(Http2ConnectionDecoder delegate) {
|
||||
this.delegate = checkNotNull(delegate, "delegate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lifecycleManager(Http2LifecycleManager lifecycleManager) {
|
||||
delegate.lifecycleManager(lifecycleManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2Connection connection() {
|
||||
return delegate.connection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2LocalFlowController flowController() {
|
||||
return delegate.flowController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2FrameListener listener() {
|
||||
return delegate.listener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decodeFrame(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Http2Exception {
|
||||
delegate.decodeFrame(ctx, in, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2Settings localSettings() {
|
||||
return delegate.localSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void localSettings(Http2Settings settings) throws Http2Exception {
|
||||
delegate.localSettings(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prefaceReceived() {
|
||||
return delegate.prefaceReceived();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
delegate.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
/**
|
||||
* A decorator around another {@link Http2ConnectionEncoder} instance.
|
||||
*/
|
||||
public class DecoratingHttp2ConnectionEncoder extends DecoratingHttp2FrameWriter implements Http2ConnectionEncoder {
|
||||
private final Http2ConnectionEncoder delegate;
|
||||
|
||||
public DecoratingHttp2ConnectionEncoder(Http2ConnectionEncoder delegate) {
|
||||
super(delegate);
|
||||
this.delegate = checkNotNull(delegate, "delegate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lifecycleManager(Http2LifecycleManager lifecycleManager) {
|
||||
delegate.lifecycleManager(lifecycleManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2Connection connection() {
|
||||
return delegate.connection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2RemoteFlowController flowController() {
|
||||
return delegate.flowController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2FrameWriter frameWriter() {
|
||||
return delegate.frameWriter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2Settings pollSentSettings() {
|
||||
return delegate.pollSentSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteSettings(Http2Settings settings) throws Http2Exception {
|
||||
delegate.remoteSettings(settings);
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
|
||||
/**
|
||||
* Decorator around another {@link Http2FrameWriter} instance.
|
||||
*/
|
||||
public class DecoratingHttp2FrameWriter implements Http2FrameWriter {
|
||||
private final Http2FrameWriter delegate;
|
||||
|
||||
public DecoratingHttp2FrameWriter(Http2FrameWriter delegate) {
|
||||
this.delegate = checkNotNull(delegate, "delegate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeData(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding,
|
||||
boolean endStream, ChannelPromise promise) {
|
||||
return delegate.writeData(ctx, streamId, data, padding, endStream, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeHeaders(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding,
|
||||
boolean endStream, ChannelPromise promise) {
|
||||
return delegate.writeHeaders(ctx, streamId, headers, padding, endStream, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeHeaders(ChannelHandlerContext ctx, int streamId, Http2Headers headers,
|
||||
int streamDependency, short weight, boolean exclusive, int padding,
|
||||
boolean endStream, ChannelPromise promise) {
|
||||
return delegate
|
||||
.writeHeaders(ctx, streamId, headers, streamDependency, weight, exclusive, padding, endStream, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writePriority(ChannelHandlerContext ctx, int streamId, int streamDependency, short weight,
|
||||
boolean exclusive, ChannelPromise promise) {
|
||||
return delegate.writePriority(ctx, streamId, streamDependency, weight, exclusive, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeRstStream(ChannelHandlerContext ctx, int streamId, long errorCode,
|
||||
ChannelPromise promise) {
|
||||
return delegate.writeRstStream(ctx, streamId, errorCode, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeSettings(ChannelHandlerContext ctx, Http2Settings settings, ChannelPromise promise) {
|
||||
return delegate.writeSettings(ctx, settings, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeSettingsAck(ChannelHandlerContext ctx, ChannelPromise promise) {
|
||||
return delegate.writeSettingsAck(ctx, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writePing(ChannelHandlerContext ctx, boolean ack, ByteBuf data, ChannelPromise promise) {
|
||||
return delegate.writePing(ctx, ack, data, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writePushPromise(ChannelHandlerContext ctx, int streamId, int promisedStreamId,
|
||||
Http2Headers headers, int padding, ChannelPromise promise) {
|
||||
return delegate.writePushPromise(ctx, streamId, promisedStreamId, headers, padding, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeGoAway(ChannelHandlerContext ctx, int lastStreamId, long errorCode, ByteBuf debugData,
|
||||
ChannelPromise promise) {
|
||||
return delegate.writeGoAway(ctx, lastStreamId, errorCode, debugData, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeWindowUpdate(ChannelHandlerContext ctx, int streamId, int windowSizeIncrement,
|
||||
ChannelPromise promise) {
|
||||
return delegate.writeWindowUpdate(ctx, streamId, windowSizeIncrement, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeFrame(ChannelHandlerContext ctx, byte frameType, int streamId, Http2Flags flags,
|
||||
ByteBuf payload, ChannelPromise promise) {
|
||||
return delegate.writeFrame(ctx, frameType, streamId, flags, payload, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration configuration() {
|
||||
return delegate.configuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
delegate.close();
|
||||
}
|
||||
}
|
@ -40,87 +40,40 @@ import java.util.List;
|
||||
public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
|
||||
private Http2FrameListener internalFrameListener = new PrefaceFrameListener();
|
||||
private final Http2Connection connection;
|
||||
private final Http2LifecycleManager lifecycleManager;
|
||||
private Http2LifecycleManager lifecycleManager;
|
||||
private final Http2ConnectionEncoder encoder;
|
||||
private final Http2FrameReader frameReader;
|
||||
private final Http2FrameListener listener;
|
||||
private final Http2PromisedRequestVerifier requestVerifier;
|
||||
|
||||
/**
|
||||
* Builder for instances of {@link DefaultHttp2ConnectionDecoder}.
|
||||
*/
|
||||
public static class Builder implements Http2ConnectionDecoder.Builder {
|
||||
private Http2Connection connection;
|
||||
private Http2LifecycleManager lifecycleManager;
|
||||
private Http2ConnectionEncoder encoder;
|
||||
private Http2FrameReader frameReader;
|
||||
private Http2FrameListener listener;
|
||||
private Http2PromisedRequestVerifier requestVerifier = ALWAYS_VERIFY;
|
||||
|
||||
@Override
|
||||
public Builder connection(Http2Connection connection) {
|
||||
this.connection = connection;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder lifecycleManager(Http2LifecycleManager lifecycleManager) {
|
||||
this.lifecycleManager = lifecycleManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2LifecycleManager lifecycleManager() {
|
||||
return lifecycleManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder frameReader(Http2FrameReader frameReader) {
|
||||
this.frameReader = frameReader;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder listener(Http2FrameListener listener) {
|
||||
this.listener = listener;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder encoder(Http2ConnectionEncoder encoder) {
|
||||
this.encoder = encoder;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2ConnectionDecoder.Builder requestVerifier(Http2PromisedRequestVerifier requestVerifier) {
|
||||
this.requestVerifier = requestVerifier;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2ConnectionDecoder build() {
|
||||
return new DefaultHttp2ConnectionDecoder(this);
|
||||
}
|
||||
public DefaultHttp2ConnectionDecoder(Http2Connection connection,
|
||||
Http2ConnectionEncoder encoder,
|
||||
Http2FrameReader frameReader,
|
||||
Http2FrameListener listener) {
|
||||
this(connection, encoder, frameReader, listener, ALWAYS_VERIFY);
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
protected DefaultHttp2ConnectionDecoder(Builder builder) {
|
||||
connection = checkNotNull(builder.connection, "connection");
|
||||
frameReader = checkNotNull(builder.frameReader, "frameReader");
|
||||
lifecycleManager = checkNotNull(builder.lifecycleManager, "lifecycleManager");
|
||||
encoder = checkNotNull(builder.encoder, "encoder");
|
||||
listener = checkNotNull(builder.listener, "listener");
|
||||
requestVerifier = checkNotNull(builder.requestVerifier, "requestVerifier");
|
||||
public DefaultHttp2ConnectionDecoder(Http2Connection connection,
|
||||
Http2ConnectionEncoder encoder,
|
||||
Http2FrameReader frameReader,
|
||||
Http2FrameListener listener,
|
||||
Http2PromisedRequestVerifier requestVerifier) {
|
||||
this.connection = checkNotNull(connection, "connection");
|
||||
this.frameReader = checkNotNull(frameReader, "frameReader");
|
||||
this.encoder = checkNotNull(encoder, "encoder");
|
||||
this.listener = checkNotNull(listener, "listener");
|
||||
this.requestVerifier = checkNotNull(requestVerifier, "requestVerifier");
|
||||
if (connection.local().flowController() == null) {
|
||||
connection.local().flowController(
|
||||
new DefaultHttp2LocalFlowController(connection, encoder.frameWriter()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lifecycleManager(Http2LifecycleManager lifecycleManager) {
|
||||
this.lifecycleManager = checkNotNull(lifecycleManager, "lifecycleManager");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2Connection connection() {
|
||||
return connection;
|
||||
|
@ -35,63 +35,24 @@ import java.util.ArrayDeque;
|
||||
public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder {
|
||||
private final Http2FrameWriter frameWriter;
|
||||
private final Http2Connection connection;
|
||||
private final Http2LifecycleManager lifecycleManager;
|
||||
private Http2LifecycleManager lifecycleManager;
|
||||
// We prefer ArrayDeque to LinkedList because later will produce more GC.
|
||||
// This initial capacity is plenty for SETTINGS traffic.
|
||||
private final ArrayDeque<Http2Settings> outstandingLocalSettingsQueue = new ArrayDeque<Http2Settings>(4);
|
||||
|
||||
/**
|
||||
* Builder for new instances of {@link DefaultHttp2ConnectionEncoder}.
|
||||
*/
|
||||
public static class Builder implements Http2ConnectionEncoder.Builder {
|
||||
protected Http2FrameWriter frameWriter;
|
||||
protected Http2Connection connection;
|
||||
protected Http2LifecycleManager lifecycleManager;
|
||||
|
||||
@Override
|
||||
public Builder connection(
|
||||
Http2Connection connection) {
|
||||
this.connection = connection;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder lifecycleManager(
|
||||
Http2LifecycleManager lifecycleManager) {
|
||||
this.lifecycleManager = lifecycleManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2LifecycleManager lifecycleManager() {
|
||||
return lifecycleManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder frameWriter(Http2FrameWriter frameWriter) {
|
||||
this.frameWriter = frameWriter;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2ConnectionEncoder build() {
|
||||
return new DefaultHttp2ConnectionEncoder(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
protected DefaultHttp2ConnectionEncoder(Builder builder) {
|
||||
connection = checkNotNull(builder.connection, "connection");
|
||||
frameWriter = checkNotNull(builder.frameWriter, "frameWriter");
|
||||
lifecycleManager = checkNotNull(builder.lifecycleManager, "lifecycleManager");
|
||||
public DefaultHttp2ConnectionEncoder(Http2Connection connection, Http2FrameWriter frameWriter) {
|
||||
this.connection = checkNotNull(connection, "connection");
|
||||
this.frameWriter = checkNotNull(frameWriter, "frameWriter");
|
||||
if (connection.remote().flowController() == null) {
|
||||
connection.remote().flowController(new DefaultHttp2RemoteFlowController(connection));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lifecycleManager(Http2LifecycleManager lifecycleManager) {
|
||||
this.lifecycleManager = checkNotNull(lifecycleManager, "lifecycleManager");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Http2FrameWriter frameWriter() {
|
||||
return frameWriter;
|
||||
|
@ -29,49 +29,9 @@ import java.util.List;
|
||||
public interface Http2ConnectionDecoder extends Closeable {
|
||||
|
||||
/**
|
||||
* Builder for new instances of {@link Http2ConnectionDecoder}.
|
||||
* Sets the lifecycle manager. Must be called as part of initialization before the decoder is used.
|
||||
*/
|
||||
interface Builder {
|
||||
/**
|
||||
* Sets the {@link Http2Connection} to be used when building the decoder.
|
||||
*/
|
||||
Builder connection(Http2Connection connection);
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2LifecycleManager} to be used when building the decoder.
|
||||
*/
|
||||
Builder lifecycleManager(Http2LifecycleManager lifecycleManager);
|
||||
|
||||
/**
|
||||
* Gets the {@link Http2LifecycleManager} to be used when building the decoder.
|
||||
*/
|
||||
Http2LifecycleManager lifecycleManager();
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2FrameReader} to be used when building the decoder.
|
||||
*/
|
||||
Builder frameReader(Http2FrameReader frameReader);
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2FrameListener} to be used when building the decoder.
|
||||
*/
|
||||
Builder listener(Http2FrameListener listener);
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2ConnectionEncoder} used when building the decoder.
|
||||
*/
|
||||
Builder encoder(Http2ConnectionEncoder encoder);
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2PromisedRequestVerifier} used when building the decoder.
|
||||
*/
|
||||
Builder requestVerifier(Http2PromisedRequestVerifier requestVerifier);
|
||||
|
||||
/**
|
||||
* Creates a new decoder instance.
|
||||
*/
|
||||
Http2ConnectionDecoder build();
|
||||
}
|
||||
void lifecycleManager(Http2LifecycleManager lifecycleManager);
|
||||
|
||||
/**
|
||||
* Provides direct access to the underlying connection.
|
||||
|
@ -26,35 +26,9 @@ import io.netty.channel.ChannelPromise;
|
||||
public interface Http2ConnectionEncoder extends Http2FrameWriter {
|
||||
|
||||
/**
|
||||
* Builder for new instances of {@link Http2ConnectionEncoder}.
|
||||
* Sets the lifecycle manager. Must be called as part of initialization before the encoder is used.
|
||||
*/
|
||||
interface Builder {
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2Connection} to be used when building the encoder.
|
||||
*/
|
||||
Builder connection(Http2Connection connection);
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2LifecycleManager} to be used when building the encoder.
|
||||
*/
|
||||
Builder lifecycleManager(Http2LifecycleManager lifecycleManager);
|
||||
|
||||
/**
|
||||
* Gets the {@link Http2LifecycleManager} to be used when building the encoder.
|
||||
*/
|
||||
Http2LifecycleManager lifecycleManager();
|
||||
|
||||
/**
|
||||
* Sets the {@link Http2FrameWriter} to be used when building the encoder.
|
||||
*/
|
||||
Builder frameWriter(Http2FrameWriter frameWriter);
|
||||
|
||||
/**
|
||||
* Creates a new encoder instance.
|
||||
*/
|
||||
Http2ConnectionEncoder build();
|
||||
}
|
||||
void lifecycleManager(Http2LifecycleManager lifecycleManager);
|
||||
|
||||
/**
|
||||
* Provides direct access to the underlying connection.
|
||||
|
@ -63,38 +63,19 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
|
||||
}
|
||||
|
||||
public Http2ConnectionHandler(Http2Connection connection, Http2FrameReader frameReader,
|
||||
Http2FrameWriter frameWriter, Http2FrameListener listener) {
|
||||
this(DefaultHttp2ConnectionDecoder.newBuilder().connection(connection)
|
||||
.frameReader(frameReader).listener(listener),
|
||||
DefaultHttp2ConnectionEncoder.newBuilder().connection(connection)
|
||||
.frameWriter(frameWriter));
|
||||
Http2FrameWriter frameWriter, Http2FrameListener listener) {
|
||||
encoder = new DefaultHttp2ConnectionEncoder(connection, frameWriter);
|
||||
decoder = new DefaultHttp2ConnectionDecoder(connection, encoder, frameReader, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for pre-configured encoder and decoder builders. Just sets the {@code this} as the
|
||||
* Constructor for pre-configured encoder and decoder. Just sets the {@code this} as the
|
||||
* {@link Http2LifecycleManager} and builds them.
|
||||
*/
|
||||
public Http2ConnectionHandler(Http2ConnectionDecoder.Builder decoderBuilder,
|
||||
Http2ConnectionEncoder.Builder encoderBuilder) {
|
||||
checkNotNull(decoderBuilder, "decoderBuilder");
|
||||
checkNotNull(encoderBuilder, "encoderBuilder");
|
||||
|
||||
if (encoderBuilder.lifecycleManager() != decoderBuilder.lifecycleManager()) {
|
||||
throw new IllegalArgumentException("Encoder and Decoder must share a lifecycle manager");
|
||||
} else if (encoderBuilder.lifecycleManager() == null) {
|
||||
encoderBuilder.lifecycleManager(this);
|
||||
decoderBuilder.lifecycleManager(this);
|
||||
}
|
||||
|
||||
// Build the encoder.
|
||||
encoder = checkNotNull(encoderBuilder.build(), "encoder");
|
||||
|
||||
// Build the decoder.
|
||||
decoderBuilder.encoder(encoder);
|
||||
decoder = checkNotNull(decoderBuilder.build(), "decoder");
|
||||
|
||||
// Verify that the encoder and decoder use the same connection.
|
||||
checkNotNull(encoder.connection(), "encoder.connection");
|
||||
public Http2ConnectionHandler(Http2ConnectionDecoder decoder,
|
||||
Http2ConnectionEncoder encoder) {
|
||||
this.decoder = checkNotNull(decoder, "decoder");
|
||||
this.encoder = checkNotNull(encoder, "encoder");
|
||||
if (encoder.connection() != decoder.connection()) {
|
||||
throw new IllegalArgumentException("Encoder and Decoder do not share the same connection object");
|
||||
}
|
||||
@ -304,6 +285,9 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||
// Initialize the encoder and decoder.
|
||||
encoder.lifecycleManager(this);
|
||||
decoder.lifecycleManager(this);
|
||||
byteDecoder = new PrefaceDecoder(ctx);
|
||||
}
|
||||
|
||||
|
@ -40,9 +40,9 @@ public class HttpToHttp2ConnectionHandler extends Http2ConnectionHandler {
|
||||
super(connection, frameReader, frameWriter, listener);
|
||||
}
|
||||
|
||||
public HttpToHttp2ConnectionHandler(Http2ConnectionDecoder.Builder decoderBuilder,
|
||||
Http2ConnectionEncoder.Builder encoderBuilder) {
|
||||
super(decoderBuilder, encoderBuilder);
|
||||
public HttpToHttp2ConnectionHandler(Http2ConnectionDecoder decoder,
|
||||
Http2ConnectionEncoder encoder) {
|
||||
super(decoder, encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,7 +216,7 @@ public class DataCompressionHttp2Test {
|
||||
});
|
||||
awaitServer();
|
||||
assertEquals(0, serverConnection.local().flowController().unconsumedBytes(stream));
|
||||
assertEquals(new StringBuilder(text1).append(text2).toString(),
|
||||
assertEquals(text1 + text2,
|
||||
serverOut.toString(CharsetUtil.UTF_8.name()));
|
||||
} finally {
|
||||
data1.release();
|
||||
@ -296,16 +296,13 @@ public class DataCompressionHttp2Test {
|
||||
@Override
|
||||
protected void initChannel(Channel ch) throws Exception {
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
Http2FrameWriter writer = new DefaultHttp2FrameWriter();
|
||||
Http2ConnectionHandler connectionHandler =
|
||||
new Http2ConnectionHandler(new DefaultHttp2ConnectionDecoder.Builder()
|
||||
.connection(serverConnection)
|
||||
.frameReader(new DefaultHttp2FrameReader())
|
||||
.listener(
|
||||
new DelegatingDecompressorFrameListener(serverConnection,
|
||||
serverListener)),
|
||||
new CompressorHttp2ConnectionEncoder.Builder().connection(
|
||||
serverConnection).frameWriter(writer));
|
||||
Http2ConnectionEncoder encoder = new CompressorHttp2ConnectionEncoder(
|
||||
new DefaultHttp2ConnectionEncoder(serverConnection, new DefaultHttp2FrameWriter()));
|
||||
Http2ConnectionDecoder decoder =
|
||||
new DefaultHttp2ConnectionDecoder(serverConnection, encoder, new DefaultHttp2FrameReader(),
|
||||
new DelegatingDecompressorFrameListener(serverConnection,
|
||||
serverListener));
|
||||
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(decoder, encoder);
|
||||
p.addLast(connectionHandler);
|
||||
serverChannelLatch.countDown();
|
||||
}
|
||||
@ -319,17 +316,14 @@ public class DataCompressionHttp2Test {
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
FrameCountDown clientFrameCountDown = new FrameCountDown(clientListener,
|
||||
clientSettingsAckLatch, clientLatch);
|
||||
Http2FrameWriter writer = new DefaultHttp2FrameWriter();
|
||||
Http2ConnectionHandler connectionHandler =
|
||||
new Http2ConnectionHandler(new DefaultHttp2ConnectionDecoder.Builder()
|
||||
.connection(clientConnection)
|
||||
.frameReader(new DefaultHttp2FrameReader())
|
||||
.listener(
|
||||
new DelegatingDecompressorFrameListener(clientConnection,
|
||||
clientFrameCountDown)),
|
||||
new CompressorHttp2ConnectionEncoder.Builder().connection(
|
||||
clientConnection).frameWriter(writer));
|
||||
clientEncoder = connectionHandler.encoder();
|
||||
clientEncoder = new CompressorHttp2ConnectionEncoder(
|
||||
new DefaultHttp2ConnectionEncoder(clientConnection, new DefaultHttp2FrameWriter()));
|
||||
Http2ConnectionDecoder decoder =
|
||||
new DefaultHttp2ConnectionDecoder(clientConnection, clientEncoder,
|
||||
new DefaultHttp2FrameReader(),
|
||||
new DelegatingDecompressorFrameListener(clientConnection,
|
||||
clientFrameCountDown));
|
||||
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(decoder, clientEncoder);
|
||||
p.addLast(connectionHandler);
|
||||
}
|
||||
});
|
||||
|
@ -139,9 +139,8 @@ public class DefaultHttp2ConnectionDecoderTest {
|
||||
when(ctx.newPromise()).thenReturn(promise);
|
||||
when(ctx.write(any())).thenReturn(future);
|
||||
|
||||
decoder = DefaultHttp2ConnectionDecoder.newBuilder().connection(connection)
|
||||
.frameReader(reader).encoder(encoder)
|
||||
.listener(listener).lifecycleManager(lifecycleManager).build();
|
||||
decoder = new DefaultHttp2ConnectionDecoder(connection, encoder, reader, listener);
|
||||
decoder.lifecycleManager(lifecycleManager);
|
||||
|
||||
// Simulate receiving the initial settings from the remote endpoint.
|
||||
decode().onSettingsRead(ctx, new Http2Settings());
|
||||
|
@ -195,8 +195,8 @@ public class DefaultHttp2ConnectionEncoderTest {
|
||||
when(ctx.newPromise()).thenReturn(promise);
|
||||
when(ctx.write(any())).thenReturn(future);
|
||||
|
||||
encoder = DefaultHttp2ConnectionEncoder.newBuilder().connection(connection)
|
||||
.frameWriter(writer).lifecycleManager(lifecycleManager).build();
|
||||
encoder = new DefaultHttp2ConnectionEncoder(connection, writer);
|
||||
encoder.lifecycleManager(lifecycleManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -89,12 +89,6 @@ public class Http2ConnectionHandlerTest {
|
||||
@Mock
|
||||
private Http2Stream stream;
|
||||
|
||||
@Mock
|
||||
private Http2ConnectionDecoder.Builder decoderBuilder;
|
||||
|
||||
@Mock
|
||||
private Http2ConnectionEncoder.Builder encoderBuilder;
|
||||
|
||||
@Mock
|
||||
private Http2ConnectionDecoder decoder;
|
||||
|
||||
@ -110,8 +104,6 @@ public class Http2ConnectionHandlerTest {
|
||||
|
||||
promise = new DefaultChannelPromise(channel);
|
||||
|
||||
when(encoderBuilder.build()).thenReturn(encoder);
|
||||
when(decoderBuilder.build()).thenReturn(decoder);
|
||||
when(encoder.connection()).thenReturn(connection);
|
||||
when(decoder.connection()).thenReturn(connection);
|
||||
when(encoder.frameWriter()).thenReturn(frameWriter);
|
||||
@ -132,7 +124,7 @@ public class Http2ConnectionHandlerTest {
|
||||
}
|
||||
|
||||
private Http2ConnectionHandler newHandler() throws Exception {
|
||||
Http2ConnectionHandler handler = new Http2ConnectionHandler(decoderBuilder, encoderBuilder);
|
||||
Http2ConnectionHandler handler = new Http2ConnectionHandler(decoder, encoder);
|
||||
handler.handlerAdded(ctx);
|
||||
return handler;
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
|
||||
import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
|
||||
import io.netty.handler.codec.http2.DefaultHttp2Headers;
|
||||
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.Http2FrameAdapter;
|
||||
import io.netty.handler.codec.http2.Http2FrameWriter;
|
||||
@ -264,11 +266,11 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
|
||||
connection.local().flowController(localFlowController);
|
||||
}
|
||||
environment.writer(new DefaultHttp2FrameWriter());
|
||||
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(
|
||||
new DefaultHttp2ConnectionDecoder.Builder().connection(connection)
|
||||
.frameReader(new DefaultHttp2FrameReader()).listener(new Http2FrameAdapter()),
|
||||
new DefaultHttp2ConnectionEncoder.Builder().connection(connection).frameWriter(
|
||||
environment.writer()));
|
||||
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, environment.writer());
|
||||
Http2ConnectionDecoder decoder =
|
||||
new DefaultHttp2ConnectionDecoder(connection, encoder, new DefaultHttp2FrameReader(),
|
||||
new Http2FrameAdapter());
|
||||
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(decoder, encoder);
|
||||
p.addLast(connectionHandler);
|
||||
environment.context(p.lastContext());
|
||||
}
|
||||
@ -283,10 +285,11 @@ public class Http2FrameWriterBenchmark extends AbstractSharedExecutorMicrobenchm
|
||||
private static Environment boostrapEmbeddedEnv(final ByteBufAllocator alloc) {
|
||||
final EmbeddedEnvironment env = new EmbeddedEnvironment(new DefaultHttp2FrameWriter());
|
||||
final Http2Connection connection = new DefaultHttp2Connection(false);
|
||||
final Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(
|
||||
new DefaultHttp2ConnectionDecoder.Builder().connection(connection)
|
||||
.frameReader(new DefaultHttp2FrameReader()).listener(new Http2FrameAdapter()),
|
||||
new DefaultHttp2ConnectionEncoder.Builder().connection(connection).frameWriter(env.writer()));
|
||||
Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, env.writer());
|
||||
Http2ConnectionDecoder decoder =
|
||||
new DefaultHttp2ConnectionDecoder(connection, encoder, new DefaultHttp2FrameReader(),
|
||||
new Http2FrameAdapter());
|
||||
Http2ConnectionHandler connectionHandler = new Http2ConnectionHandler(decoder, encoder);
|
||||
env.context(new EmbeddedChannelWriteReleaseHandlerContext(alloc, connectionHandler) {
|
||||
@Override
|
||||
protected void handleException(Throwable t) {
|
||||
|
Loading…
Reference in New Issue
Block a user