Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2014 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.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandler;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http2.Http2Exception.CompositeStreamException;
import io.netty.handler.codec.http2.Http2Exception.StreamException;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.ScheduledFuture;
import io.netty.util.internal.UnstableApi;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.net.SocketAddress;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static io.netty.buffer.ByteBufUtil.hexDump;
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
import static io.netty.handler.codec.http2.Http2CodecUtil.HTTP_UPGRADE_STREAM_ID;
import static io.netty.handler.codec.http2.Http2CodecUtil.connectionPrefaceBuf;
import static io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception;
import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR;
import static io.netty.handler.codec.http2.Http2Error.NO_ERROR;
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
import static io.netty.handler.codec.http2.Http2Exception.connectionError;
import static io.netty.handler.codec.http2.Http2Exception.isStreamError;
import static io.netty.handler.codec.http2.Http2FrameTypes.SETTINGS;
import static io.netty.handler.codec.http2.Http2Stream.State.IDLE;
import static io.netty.util.CharsetUtil.UTF_8;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static java.lang.Math.min;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
/**
* Provides the default implementation for processing inbound frame events and delegates to a
* {@link Http2FrameListener}
*
* This class will read HTTP/2 frames and delegate the events to a {@link Http2FrameListener}
*
* This interface enforces inbound flow control functionality through
* {@link Http2LocalFlowController}
*/
@UnstableApi
public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http2LifecycleManager,
ChannelOutboundHandler {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Http2ConnectionHandler.class);
private static final Http2Headers HEADERS_TOO_LARGE_HEADERS = ReadOnlyHttp2Headers.serverHeaders(false,
HttpResponseStatus.REQUEST_HEADER_FIELDS_TOO_LARGE.codeAsText());
private static final ByteBuf HTTP_1_X_BUF = Unpooled.unreleasableBuffer(
Unpooled.wrappedBuffer(new byte[] {'H', 'T', 'T', 'P', '/', '1', '.'})).asReadOnly();
private final Http2ConnectionDecoder decoder;
private final Http2ConnectionEncoder encoder;
private final Http2Settings initialSettings;
private ChannelFutureListener closeListener;
private BaseDecoder byteDecoder;
private long gracefulShutdownTimeoutMillis;
protected Http2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder,
Http2Settings initialSettings) {
this.initialSettings = checkNotNull(initialSettings, "initialSettings");
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");
}
}
Http2ConnectionHandler(boolean server, Http2FrameWriter frameWriter, Http2FrameLogger frameLogger,
Http2Settings initialSettings) {
this.initialSettings = checkNotNull(initialSettings, "initialSettings");
Http2Connection connection = new DefaultHttp2Connection(server);
Long maxHeaderListSize = initialSettings.maxHeaderListSize();
Http2FrameReader frameReader = new DefaultHttp2FrameReader(maxHeaderListSize == null ?
new DefaultHttp2HeadersDecoder(true) :
new DefaultHttp2HeadersDecoder(true, maxHeaderListSize));
if (frameLogger != null) {
frameWriter = new Http2OutboundFrameLogger(frameWriter, frameLogger);
frameReader = new Http2InboundFrameLogger(frameReader, frameLogger);
}
encoder = new DefaultHttp2ConnectionEncoder(connection, frameWriter);
decoder = new DefaultHttp2ConnectionDecoder(connection, encoder, frameReader);
}
/**
* Get the amount of time (in milliseconds) this endpoint will wait for all streams to be closed before closing
* the connection during the graceful shutdown process. Returns -1 if this connection is configured to wait
* indefinitely for all streams to close.
*/
public long gracefulShutdownTimeoutMillis() {
return gracefulShutdownTimeoutMillis;
}
/**
* Set the amount of time (in milliseconds) this endpoint will wait for all streams to be closed before closing
* the connection during the graceful shutdown process.
* @param gracefulShutdownTimeoutMillis the amount of time (in milliseconds) this endpoint will wait for all
* streams to be closed before closing the connection during the graceful shutdown process.
*/
public void gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
if (gracefulShutdownTimeoutMillis < -1) {
throw new IllegalArgumentException("gracefulShutdownTimeoutMillis: " + gracefulShutdownTimeoutMillis +
" (expected: -1 for indefinite or >= 0)");
}
this.gracefulShutdownTimeoutMillis = gracefulShutdownTimeoutMillis;
}
public Http2Connection connection() {
return encoder.connection();
}
public Http2ConnectionDecoder decoder() {
return decoder;
}
public Http2ConnectionEncoder encoder() {
return encoder;
}
private boolean prefaceSent() {
return byteDecoder != null && byteDecoder.prefaceSent();
}
/**
* Handles the client-side (cleartext) upgrade from HTTP to HTTP/2.
* Reserves local stream 1 for the HTTP/2 response.
*/
public void onHttpClientUpgrade() throws Http2Exception {
if (connection().isServer()) {
throw connectionError(PROTOCOL_ERROR, "Client-side HTTP upgrade requested for a server");
}
if (!prefaceSent()) {
// If the preface was not sent yet it most likely means the handler was not added to the pipeline before
// calling this method.
throw connectionError(INTERNAL_ERROR, "HTTP upgrade must occur after preface was sent");
}
if (decoder.prefaceReceived()) {
throw connectionError(PROTOCOL_ERROR, "HTTP upgrade must occur before HTTP/2 preface is received");
}
// Create a local stream used for the HTTP cleartext upgrade.
connection().local().createStream(HTTP_UPGRADE_STREAM_ID, true);
}
/**
* Handles the server-side (cleartext) upgrade from HTTP to HTTP/2.
* @param settings the settings for the remote endpoint.
*/
public void onHttpServerUpgrade(Http2Settings settings) throws Http2Exception {
if (!connection().isServer()) {
throw connectionError(PROTOCOL_ERROR, "Server-side HTTP upgrade requested for a client");
}
if (!prefaceSent()) {
// If the preface was not sent yet it most likely means the handler was not added to the pipeline before
// calling this method.
throw connectionError(INTERNAL_ERROR, "HTTP upgrade must occur after preface was sent");
}
if (decoder.prefaceReceived()) {
throw connectionError(PROTOCOL_ERROR, "HTTP upgrade must occur before HTTP/2 preface is received");
}
// Apply the settings but no ACK is necessary.
encoder.remoteSettings(settings);
// Create a stream in the half-closed state.
connection().remote().createStream(HTTP_UPGRADE_STREAM_ID, true);
}
@Override
public void flush(ChannelHandlerContext ctx) {
try {
// Trigger pending writes in the remote flow controller.
encoder.flowController().writePendingBytes();
ctx.flush();
} catch (Http2Exception e) {
onError(ctx, true, e);
} catch (Throwable cause) {
onError(ctx, true, connectionError(INTERNAL_ERROR, cause, "Error flushing"));
}
}
private abstract class BaseDecoder {
public abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List