private Http2ClientConnectionHandler newHttp2ConnectionHandler(Channel ch) { final boolean validateHeaders = false; final Http2Connection conn = new DefaultHttp2Connection(false); conn.addListener(new Http2GoAwayListener(ch)); Http2FrameReader reader = new DefaultHttp2FrameReader(validateHeaders); Http2FrameWriter writer = new DefaultHttp2FrameWriter(); Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(conn, writer); Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(conn, encoder, reader); final Http2Settings http2Settings = http2Settings(); final Http2ResponseDecoder listener = new Http2ResponseDecoder(conn, ch, encoder); final Http2ClientConnectionHandler handler = new Http2ClientConnectionHandler(decoder, encoder, http2Settings, listener); // Setup post build options handler.gracefulShutdownTimeoutMillis(clientFactory.idleTimeoutMillis()); return handler; }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof Http2Settings) { // Expected } else { try { final String typeInfo; if (msg instanceof ByteBuf) { typeInfo = msg + " HexDump: " + ByteBufUtil.hexDump((ByteBuf) msg); } else { typeInfo = String.valueOf(msg); } throw new IllegalStateException("unexpected message type: " + typeInfo); } finally { ReferenceCountUtil.release(msg); } } }
private void handleHttp2Settings(ChannelHandlerContext ctx, Http2Settings h2settings) { if (h2settings.isEmpty()) { logger.trace("{} HTTP/2 settings: <empty>", ctx.channel()); } else { logger.debug("{} HTTP/2 settings: {}", ctx.channel(), h2settings); } if (protocol == H1) { protocol = H2; } else if (protocol == H1C) { protocol = H2C; } final Http2ConnectionHandler handler = ctx.pipeline().get(Http2ConnectionHandler.class); if (responseEncoder == null) { responseEncoder = new Http2ObjectEncoder(handler.encoder()); } else if (responseEncoder instanceof Http1ObjectEncoder) { responseEncoder.close(); responseEncoder = new Http2ObjectEncoder(handler.encoder()); } }
private Http2ConnectionHandler newHttp2ConnectionHandler(ChannelPipeline pipeline) { final Http2Connection conn = new DefaultHttp2Connection(true); conn.addListener(new Http2GoAwayListener(pipeline.channel())); Http2FrameReader reader = new DefaultHttp2FrameReader(true); Http2FrameWriter writer = new DefaultHttp2FrameWriter(); Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(conn, writer); Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(conn, encoder, reader); final Http2ConnectionHandler handler = new Http2ServerConnectionHandler(decoder, encoder, new Http2Settings()); // Setup post build options final Http2RequestDecoder listener = new Http2RequestDecoder(config, pipeline.channel(), handler.encoder()); handler.connection().addListener(listener); handler.decoder().frameListener(listener); handler.gracefulShutdownTimeoutMillis(config.idleTimeoutMillis()); return handler; }
public void updateWindow() throws Http2Exception { if (!autoTuneFlowControlOn) { return; } pingReturn++; long elapsedTime = (System.nanoTime() - lastPingTime); if (elapsedTime == 0) { elapsedTime = 1; } long bandwidth = (getDataSincePing() * TimeUnit.SECONDS.toNanos(1)) / elapsedTime; Http2LocalFlowController fc = decoder().flowController(); // Calculate new window size by doubling the observed BDP, but cap at max window int targetWindow = Math.min(getDataSincePing() * 2, MAX_WINDOW_SIZE); setPinging(false); int currentWindow = fc.initialWindowSize(connection().connectionStream()); if (targetWindow > currentWindow && bandwidth > lastBandwidth) { lastBandwidth = bandwidth; int increase = targetWindow - currentWindow; fc.incrementWindowSize(connection().connectionStream(), increase); fc.initialWindowSize(targetWindow); Http2Settings settings = new Http2Settings(); settings.initialWindowSize(targetWindow); frameWriter().writeSettings(ctx(), settings, ctx().newPromise()); } }
@Override protected void manualSetUp() throws Exception { assertNull("manualSetUp should not run more than once", handler()); initChannel(new GrpcHttp2ServerHeadersDecoder(GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE)); // replace the keepAliveManager with spyKeepAliveManager spyKeepAliveManager = mock(KeepAliveManager.class, delegatesTo(handler().getKeepAliveManagerForTest())); handler().setKeepAliveManagerForTest(spyKeepAliveManager); // Simulate receipt of the connection preface handler().handleProtocolNegotiationCompleted(Attributes.EMPTY); channelRead(Http2CodecUtil.connectionPrefaceBuf()); // Simulate receipt of initial remote settings. ByteBuf serializedSettings = serializeSettings(new Http2Settings()); channelRead(serializedSettings); }
@Override protected Http2TestHandler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { Http2TestHandler handler = new Http2TestHandler(decoder, encoder, initialSettings); frameListener(handler); return handler; }
@Override protected void channelRead0(ChannelHandlerContext ctx, Http2Settings msg) throws Exception { promise.setSuccess(); // Only care about the first settings message ctx.pipeline().remove(this); }
@Override protected HelloWorldHttp2Handler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { HelloWorldHttp2Handler handler = new HelloWorldHttp2Handler(decoder, encoder, initialSettings); frameListener(handler); return handler; }
@Override protected void messageReceived(ChannelHandlerContext ctx, Http2Settings msg) throws Exception { promise.setSuccess(); // Only care about the first settings message ctx.pipeline().remove(this); }
private Http2FrameWriter frameWriter() { // Set initial SETTINGS Http2Settings settings = new Http2Settings(); settings.pushEnabled(false); settings.maxConcurrentStreams(100); return new Http2OutboundFrameLogger(new CustomHttp2FrameWriter(settings), logger); }
/** * write customized SETTINGS */ @Override public ChannelFuture writeSettings(ChannelHandlerContext ctx, Http2Settings settings, ChannelPromise promise) { if(this.settings != null) { return super.writeSettings(ctx, this.settings, promise); } else { return super.writeSettings(ctx, settings, promise); } }
@Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof Http2Settings) { settingsPromise.setSuccess(null); return; } if (msg instanceof FullHttpResponse) { FullHttpResponse res = (FullHttpResponse) msg; Integer streamId = res.headers().getInt( HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text()); if (streamId == null) { responsePromise.tryFailure(new AssertionError("message without stream ID: " + msg)); return; } if (streamId == 1) { // Response to the upgrade request, which is OK to ignore. return; } if (streamId != 3) { responsePromise.tryFailure(new AssertionError("unexpected stream ID: " + msg)); return; } responsePromise.setSuccess(res.content().retain()); return; } throw new IllegalStateException("unexpected message type: " + msg.getClass().getName()); }
Http2ClientConnectionHandler( Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings, Http2ResponseDecoder responseDecoder) { super(decoder, encoder, initialSettings); this.responseDecoder = responseDecoder; connection().addListener(responseDecoder); decoder().frameListener(responseDecoder); }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { isReading = true; // Cleared in channelReadComplete() if (msg instanceof Http2Settings) { handleHttp2Settings(ctx, (Http2Settings) msg); } else { handleRequest(ctx, (DecodedHttpRequest) msg); } }
@Override protected HTTP2SourceHandler build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { HTTP2SourceHandler handler = new HTTP2SourceHandler(decoder, encoder, initialSettings, connectionManager, listenerConfiguration); frameListener(handler); connection(new DefaultHttp2Connection(true)); return handler; }
HTTP2SourceHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings, ConnectionManager connectionManager, ListenerConfiguration listenerConfiguration) { super(decoder, encoder, initialSettings); this.listenerConfiguration = listenerConfiguration; this.connectionManager = connectionManager; }
@Override public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) throws Http2Exception { // h2 clients need to know that server settings have been received before they can write if (!isServer) { ctx.fireUserEventTriggered(RequestBuffer.WriteReady.INSTANCE); } }
@Override protected Http2Handler build( Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { return new Http2Handler(decoder, encoder, initialSettings); }
@Override public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) { if (firstSettings) { firstSettings = false; // Delay transportReady until we see the client's HTTP handshake, for coverage with // handshakeTimeout attributes = transportListener.transportReady(negotiationAttributes); } }
public GrpcHttp2ConnectionHandler( ChannelPromise channelUnused, Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { super(decoder, encoder, initialSettings); this.channelUnused = channelUnused; }
@Override public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) { if (firstSettings) { firstSettings = false; lifecycleManager.notifyReady(); } }
AbstractNettyHandler( ChannelPromise channelUnused, Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { super(channelUnused, decoder, encoder, initialSettings); // During a graceful shutdown, wait until all streams are closed. gracefulShutdownTimeoutMillis(GRACEFUL_SHUTDOWN_NO_TIMEOUT); // Extract the connection window from the settings if it was set. this.initialConnectionWindow = initialSettings.initialWindowSize() == null ? -1 : initialSettings.initialWindowSize(); }
@Test public void transportReadyDelayedUntilConnectionPreface() throws Exception { initChannel(new GrpcHttp2ServerHeadersDecoder(GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE)); handler().handleProtocolNegotiationCompleted(Attributes.EMPTY); verify(transportListener, never()).transportReady(any(Attributes.class)); // Simulate receipt of the connection preface channelRead(Http2CodecUtil.connectionPrefaceBuf()); channelRead(serializeSettings(new Http2Settings())); verify(transportListener).transportReady(any(Attributes.class)); }
@Test public void shouldAdvertiseMaxConcurrentStreams() throws Exception { maxConcurrentStreams = 314; manualSetUp(); ArgumentCaptor<Http2Settings> captor = ArgumentCaptor.forClass(Http2Settings.class); verifyWrite().writeSettings( any(ChannelHandlerContext.class), captor.capture(), any(ChannelPromise.class)); assertEquals(maxConcurrentStreams, captor.getValue().maxConcurrentStreams().intValue()); }
@Test public void shouldAdvertiseMaxHeaderListSize() throws Exception { maxHeaderListSize = 123; manualSetUp(); ArgumentCaptor<Http2Settings> captor = ArgumentCaptor.forClass(Http2Settings.class); verifyWrite().writeSettings( any(ChannelHandlerContext.class), captor.capture(), any(ChannelPromise.class)); assertEquals(maxHeaderListSize, captor.getValue().maxHeaderListSize().intValue()); }
@Override public ApnsClientHandler build(final Http2ConnectionDecoder decoder, final Http2ConnectionEncoder encoder, final Http2Settings initialSettings) { Objects.requireNonNull(this.authority(), "Authority must be set before building a TokenAuthenticationApnsClientHandler."); Objects.requireNonNull(this.signingKey(), "Signing key must be set before building a TokenAuthenticationApnsClientHandler."); final ApnsClientHandler handler = new TokenAuthenticationApnsClientHandler(decoder, encoder, initialSettings, this.authority(), this.signingKey(), this.idlePingIntervalMillis()); this.frameListener(handler); return handler; }
private Http2TestHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { super(decoder, encoder, initialSettings); }
@Override public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) throws Http2Exception {}
HelloWorldHttp2Handler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { super(decoder, encoder, initialSettings); }
@Override public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) { }
public CustomHttp2FrameWriter(Http2Settings settings) { this.settings = settings; }
@Override public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) { ctx.fireChannelRead(settings); }
Http2ServerConnectionHandler( Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { super(decoder, encoder, initialSettings); }
/** * Creates a new instance. */ protected AbstractHttp2ConnectionHandler( Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { super(decoder, encoder, initialSettings); }