Search in sources :

Example 1 with DefaultHttp2GoAwayFrame

use of io.netty.handler.codec.http2.DefaultHttp2GoAwayFrame in project netty by netty.

the class Http2MultiplexCodecTest method outboundStreamShouldWriteGoAwayWithoutReset.

@Test
public void outboundStreamShouldWriteGoAwayWithoutReset() {
    childChannelInitializer.handler = new ChannelInboundHandlerAdapter() {

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.writeAndFlush(new DefaultHttp2GoAwayFrame(Http2Error.NO_ERROR));
            ctx.fireChannelActive();
        }
    };
    Http2StreamChannelBootstrap b = new Http2StreamChannelBootstrap();
    b.parentChannel(parentChannel).handler(childChannelInitializer);
    Channel childChannel = b.connect().channel();
    assertTrue(childChannel.isActive());
    Http2GoAwayFrame goAwayFrame = parentChannel.readOutbound();
    assertNotNull(goAwayFrame);
    goAwayFrame.release();
    childChannel.close();
    parentChannel.runPendingTasks();
    Http2ResetFrame reset = parentChannel.readOutbound();
    assertNull(reset);
}
Also used : EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) Channel(io.netty.channel.Channel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) StreamException(io.netty.handler.codec.http2.Http2Exception.StreamException) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter) Test(org.junit.Test)

Example 2 with DefaultHttp2GoAwayFrame

use of io.netty.handler.codec.http2.DefaultHttp2GoAwayFrame in project zuul by Netflix.

the class Http2ConnectionCloseHandler method gracefullyWithDelay.

/**
 * WARNING: Found the OkHttp client gets confused by this behaviour (it ends up putting itself in a bad shutdown state
 * after receiving the first goaway frame, and then dropping any inflight responses but also timing out waiting for them).
 *
 * And worried that other http/2 stacks may be similar, so for now we should NOT use this.
 *
 * This is unfortunate, as FTL wanted this, and it is correct according to the spec.
 *
 * See this code in okhttp where it drops response header frame if state is already shutdown:
 * https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/http2/Http2Connection.java#L609
 */
private void gracefullyWithDelay(EventExecutor executor, Channel parent, ChannelPromise promise) {
    // See javadoc for explanation of why this may be disabled.
    boolean allowGracefulDelayed = ConnectionCloseChannelAttributes.allowGracefulDelayed(parent);
    if (!allowGracefulDelayed) {
        immediate(parent, promise);
        return;
    }
    if (!parent.isActive()) {
        promise.setSuccess();
        return;
    }
    // First send a 'graceful shutdown' GOAWAY frame.
    /*
        "A server that is attempting to gracefully shut down a connection SHOULD send an initial GOAWAY frame with
        the last stream identifier set to 231-1 and a NO_ERROR code. This signals to the client that a shutdown is
        imminent and that initiating further requests is prohibited."
          -- https://http2.github.io/http2-spec/#GOAWAY
         */
    DefaultHttp2GoAwayFrame goaway = new DefaultHttp2GoAwayFrame(Http2Error.NO_ERROR);
    goaway.setExtraStreamIds(Integer.MAX_VALUE);
    parent.writeAndFlush(goaway);
    LOG.debug("gracefullyWithDelay: flushed initial go_away frame. channel=" + parent.id().asShortText());
    // In N secs time, throw an error that causes the http2 codec to send another GOAWAY frame
    // (this time with accurate lastStreamId) and then close the connection.
    int gracefulCloseDelay = ConnectionCloseChannelAttributes.gracefulCloseDelay(parent);
    executor.schedule(() -> {
        // Check that the client hasn't already closed the connection (due to the earlier goaway we sent).
        if (parent.isActive()) {
            // NOTE - the netty Http2ConnectionHandler specifically does not send another goaway when we call
            // channel.close() if one has already been sent .... so when we want more than one sent, we need to do it
            // explicitly ourselves like this.
            LOG.debug("gracefullyWithDelay: firing graceful_shutdown event to make netty send a final go_away frame and then close connection. channel=" + parent.id().asShortText());
            Http2Exception h2e = new Http2Exception(Http2Error.NO_ERROR, Http2Exception.ShutdownHint.GRACEFUL_SHUTDOWN);
            parent.pipeline().fireExceptionCaught(h2e);
            parent.close().addListener(future -> {
                promise.setSuccess();
            });
        } else {
            promise.setSuccess();
        }
    }, gracefulCloseDelay, TimeUnit.SECONDS);
}
Also used : Http2Exception(io.netty.handler.codec.http2.Http2Exception) DefaultHttp2GoAwayFrame(io.netty.handler.codec.http2.DefaultHttp2GoAwayFrame)

Aggregations

Channel (io.netty.channel.Channel)1 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)1 ChannelInboundHandlerAdapter (io.netty.channel.ChannelInboundHandlerAdapter)1 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)1 DefaultHttp2GoAwayFrame (io.netty.handler.codec.http2.DefaultHttp2GoAwayFrame)1 Http2Exception (io.netty.handler.codec.http2.Http2Exception)1 StreamException (io.netty.handler.codec.http2.Http2Exception.StreamException)1 Test (org.junit.Test)1