private Http2ClientConnectionHandler newHttp2ConnectionHandler(Channel ch) { final boolean validateHeaders = false; final Http2Connection conn = new DefaultHttp2Connection(false); final Http2FrameReader reader = new DefaultHttp2FrameReader(validateHeaders); final Http2FrameWriter writer = new DefaultHttp2FrameWriter(); final Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(conn, writer); final Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(conn, encoder, reader); return new Http2ClientConnectionHandler(decoder, encoder, http2Settings(), ch, clientFactory); }
@Override public void remoteSettings(Http2Settings settings) throws Http2Exception { Boolean pushEnabled = settings.pushEnabled(); Http2FrameWriter.Configuration config = configuration(); Http2HeadersEncoder.Configuration outboundHeaderConfig = config.headersConfiguration(); Http2FrameSizePolicy outboundFrameSizePolicy = config.frameSizePolicy(); flowController().initialWindowSize(initialWindowSize);
@Override public final Http2RemoteFlowController flowController() { return connection().remote().flowController(); }
@Override public ChannelFuture writeData(final ChannelHandlerContext ctx, final int streamId, ByteBuf data, int padding, final boolean endOfStream, ChannelPromise promise) { final Http2Stream stream; try { stream = requireStream(streamId); // Verify that the stream is in the appropriate state for sending DATA frames. switch (stream.state()) { case OPEN: case HALF_CLOSED_REMOTE: // Allowed sending DATA frames in these states. break; default: throw new IllegalStateException("Stream " + stream.id() + " in unexpected state " + stream.state()); } } catch (Throwable e) { data.release(); return promise.setFailure(e); } // Hand control of the frame to the flow controller. flowController().addFlowControlled(stream, new FlowControlledData(stream, data, padding, endOfStream, promise)); return promise; }
Http2Stream stream = requireStream(streamId); notifyLifecycleManagerOnError(future, ctx);
Http2RemoteFlowController flowController = flowController(); if (!endOfStream || !flowController.hasFlowControlled(stream)) { boolean isInformational = validateHeadersSentState(stream, headers, connection.isServer(), endOfStream); if (endOfStream) { final Http2Stream finalStream = stream; notifyLifecycleManagerOnError(future, ctx);
@Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endStream, ChannelPromise promise) { return writeHeaders(ctx, streamId, headers, 0, DEFAULT_PRIORITY_WEIGHT, false, padding, endStream, promise); }
@Override public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { error(flowController().channelHandlerContext(), future.cause()); } } }
@Override public void write(ChannelHandlerContext ctx, int allowedBytes) { int queuedData = queue.readableBytes(); if (!endOfStream) { if (queuedData == 0) { // There's no need to write any data frames because there are only empty data frames in the queue // and it is not end of stream yet. Just complete their promises by getting the buffer corresponding // to 0 bytes and writing it to the channel (to preserve notification order). ChannelPromise writePromise = ctx.newPromise().addListener(this); ctx.write(queue.remove(0, writePromise), writePromise); return; } if (allowedBytes == 0) { return; } } // Determine how much data to write. int writableData = min(queuedData, allowedBytes); ChannelPromise writePromise = ctx.newPromise().addListener(this); ByteBuf toWrite = queue.remove(writableData, writePromise); dataSize = queue.readableBytes(); // Determine how much padding to write. int writablePadding = min(allowedBytes - writableData, padding); padding -= writablePadding; // Write the frame(s). frameWriter().writeData(ctx, stream.id(), toWrite, writablePadding, endOfStream && size() == 0, writePromise); }
Http2RemoteFlowController flowController = flowController(); if (!endOfStream || !flowController.hasFlowControlled(stream)) { boolean isInformational = validateHeadersSentState(stream, headers, connection.isServer(), endOfStream); if (endOfStream) { final Http2Stream finalStream = stream; notifyLifecycleManagerOnError(future, ctx);
@Override public ChannelFuture writeData(final ChannelHandlerContext ctx, final int streamId, ByteBuf data, int padding, final boolean endOfStream, ChannelPromise promise) { final Http2Stream stream; try { stream = requireStream(streamId); // Verify that the stream is in the appropriate state for sending DATA frames. switch (stream.state()) { case OPEN: case HALF_CLOSED_REMOTE: // Allowed sending DATA frames in these states. break; default: throw new IllegalStateException("Stream " + stream.id() + " in unexpected state " + stream.state()); } } catch (Throwable e) { data.release(); return promise.setFailure(e); } // Hand control of the frame to the flow controller. flowController().addFlowControlled(stream, new FlowControlledData(stream, data, padding, endOfStream, promise)); return promise; }
Http2Stream stream = requireStream(streamId); notifyLifecycleManagerOnError(future, ctx);
@Override public ChannelFuture writeHeaders(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endStream, ChannelPromise promise) { return writeHeaders(ctx, streamId, headers, 0, DEFAULT_PRIORITY_WEIGHT, false, padding, endStream, promise); }
@Override public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { error(flowController().channelHandlerContext(), future.cause()); } } }
@Override public void write(ChannelHandlerContext ctx, int allowedBytes) { int queuedData = queue.readableBytes(); if (!endOfStream) { if (queuedData == 0) { // There's no need to write any data frames because there are only empty data frames in the queue // and it is not end of stream yet. Just complete their promises by getting the buffer corresponding // to 0 bytes and writing it to the channel (to preserve notification order). ChannelPromise writePromise = ctx.newPromise().addListener(this); ctx.write(queue.remove(0, writePromise), writePromise); return; } if (allowedBytes == 0) { return; } } // Determine how much data to write. int writableData = min(queuedData, allowedBytes); ChannelPromise writePromise = ctx.newPromise().addListener(this); ByteBuf toWrite = queue.remove(writableData, writePromise); dataSize = queue.readableBytes(); // Determine how much padding to write. int writablePadding = min(allowedBytes - writableData, padding); padding -= writablePadding; // Write the frame(s). frameWriter().writeData(ctx, stream.id(), toWrite, writablePadding, endOfStream && size() == 0, writePromise); }
private Http2ConnectionHandler newHttp2ConnectionHandler(ChannelPipeline pipeline) { final Http2Connection conn = new DefaultHttp2Connection(true); final Http2FrameReader reader = new DefaultHttp2FrameReader(true); final Http2FrameWriter writer = new DefaultHttp2FrameWriter(); final Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(conn, writer); final Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(conn, encoder, reader); return new Http2ServerConnectionHandler( decoder, encoder, http2Settings(), pipeline.channel(), config, gracefulShutdownSupport); }
Http2RemoteFlowController flowController = flowController(); if (!endOfStream || !flowController.hasFlowControlled(stream)) { boolean isInformational = validateHeadersSentState(stream, headers, connection.isServer(), endOfStream); notifyLifecycleManagerOnError(future, ctx);
@Override public ChannelFuture writeData(final ChannelHandlerContext ctx, final int streamId, ByteBuf data, int padding, final boolean endOfStream, ChannelPromise promise) { final Http2Stream stream; try { stream = requireStream(streamId); // Verify that the stream is in the appropriate state for sending DATA frames. switch (stream.state()) { case OPEN: case HALF_CLOSED_REMOTE: // Allowed sending DATA frames in these states. break; default: throw new IllegalStateException("Stream " + stream.id() + " in unexpected state " + stream.state()); } } catch (Throwable e) { data.release(); return promise.setFailure(e); } // Hand control of the frame to the flow controller. flowController().addFlowControlled(stream, new FlowControlledData(stream, data, padding, endOfStream, promise)); return promise; }
Http2Stream stream = requireStream(streamId); notifyLifecycleManagerOnError(future, ctx);
@Override public void remoteSettings(Http2Settings settings) throws Http2Exception { Boolean pushEnabled = settings.pushEnabled(); Http2FrameWriter.Configuration config = configuration(); Http2HeadersEncoder.Configuration outboundHeaderConfig = config.headersConfiguration(); Http2FrameSizePolicy outboundFrameSizePolicy = config.frameSizePolicy(); flowController().initialWindowSize(initialWindowSize);