Search in sources :

Example 31 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method listenerIsNotifiedOfGoawayBeforeStreamsAreRemovedFromTheConnection.

@Test
public void listenerIsNotifiedOfGoawayBeforeStreamsAreRemovedFromTheConnection() throws Exception {
    bootstrapEnv(1, 1, 2, 1, 1);
    // We want both sides to do graceful shutdown during the test.
    setClientGracefulShutdownTime(10000);
    setServerGracefulShutdownTime(10000);
    final AtomicReference<Http2Stream.State> clientStream3State = new AtomicReference<Http2Stream.State>();
    final CountDownLatch clientGoAwayLatch = new CountDownLatch(1);
    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
            clientStream3State.set(http2Client.connection().stream(3).state());
            clientGoAwayLatch.countDown();
            return null;
        }
    }).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
    // Create a single stream by sending a HEADERS frame to the server.
    final Http2Headers headers = dummyHeaders();
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Client.encoder().writeHeaders(ctx(), 1, headers, 0, (short) 16, false, 0, false, newPromise());
            http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, newPromise());
            http2Client.flush(ctx());
        }
    });
    assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    // Server has received the headers, so the stream is open
    assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    runInChannel(serverChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Server.encoder().writeGoAway(serverCtx(), 1, NO_ERROR.code(), EMPTY_BUFFER, serverNewPromise());
            http2Server.flush(serverCtx());
        }
    });
    // wait for the client to receive the GO_AWAY.
    assertTrue(clientGoAwayLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    verify(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), eq(1), eq(NO_ERROR.code()), any(ByteBuf.class));
    assertEquals(Http2Stream.State.OPEN, clientStream3State.get());
    // Make sure that stream 3 has been closed which is true if it's gone.
    final CountDownLatch probeStreamCount = new CountDownLatch(1);
    final AtomicBoolean stream3Exists = new AtomicBoolean();
    final AtomicInteger streamCount = new AtomicInteger();
    runInChannel(this.clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            stream3Exists.set(http2Client.connection().stream(3) != null);
            streamCount.set(http2Client.connection().numActiveStreams());
            probeStreamCount.countDown();
        }
    });
    // The stream should be closed right after
    assertTrue(probeStreamCount.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    assertEquals(1, streamCount.get());
    assertFalse(stream3Exists.get());
    // Wait for the server to receive a GO_AWAY, but this is expected to timeout!
    assertFalse(goAwayLatch.await(1, SECONDS));
    verify(serverListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
    // Shutdown shouldn't wait for the server to close streams
    setClientGracefulShutdownTime(0);
    setServerGracefulShutdownTime(0);
}
Also used : Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) AtomicReference(java.util.concurrent.atomic.AtomicReference) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBuf(io.netty.buffer.ByteBuf) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.junit.jupiter.api.Test)

Example 32 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method flowControlProperlyChunksLargeMessage.

@Test
public void flowControlProperlyChunksLargeMessage() throws Exception {
    final Http2Headers headers = dummyHeaders();
    // Create a large message to send.
    // 10MB
    final int length = 10485760;
    // Create a buffer filled with random bytes.
    final ByteBuf data = randomBytes(length);
    final ByteArrayOutputStream out = new ByteArrayOutputStream(length);
    doAnswer(new Answer<Integer>() {

        @Override
        public Integer answer(InvocationOnMock in) throws Throwable {
            ByteBuf buf = (ByteBuf) in.getArguments()[2];
            int padding = (Integer) in.getArguments()[3];
            int processedBytes = buf.readableBytes() + padding;
            buf.readBytes(out, buf.readableBytes());
            return processedBytes;
        }
    }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), eq(3), any(ByteBuf.class), eq(0), anyBoolean());
    try {
        // Initialize the data latch based on the number of bytes expected.
        bootstrapEnv(length, 1, 2, 1);
        // Create the stream and send all of the data at once.
        runInChannel(clientChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, newPromise());
                http2Client.encoder().writeData(ctx(), 3, data.retainedDuplicate(), 0, false, newPromise());
                // Write trailers.
                http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, true, newPromise());
                http2Client.flush(ctx());
            }
        });
        // Wait for the trailers to be received.
        assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
        assertTrue(trailersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
        // Verify that headers and trailers were received.
        verify(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(false));
        verify(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(true));
        // Verify we received all the bytes.
        assertEquals(0, dataLatch.getCount());
        out.flush();
        byte[] received = out.toByteArray();
        assertArrayEquals(data.array(), received);
    } finally {
        // Don't wait for server to close streams
        setClientGracefulShutdownTime(0);
        data.release();
        out.close();
    }
}
Also used : Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteBuf(io.netty.buffer.ByteBuf) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.junit.jupiter.api.Test)

Example 33 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method createStreamAfterReceiveGoAwayShouldNotSendGoAway.

@Test
public void createStreamAfterReceiveGoAwayShouldNotSendGoAway() throws Exception {
    bootstrapEnv(1, 1, 2, 1, 1);
    // We want both sides to do graceful shutdown during the test.
    setClientGracefulShutdownTime(10000);
    setServerGracefulShutdownTime(10000);
    final CountDownLatch clientGoAwayLatch = new CountDownLatch(1);
    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
            clientGoAwayLatch.countDown();
            return null;
        }
    }).when(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
    // Create a single stream by sending a HEADERS frame to the server.
    final Http2Headers headers = dummyHeaders();
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, newPromise());
            http2Client.flush(ctx());
        }
    });
    assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    // Server has received the headers, so the stream is open
    assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    runInChannel(serverChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Server.encoder().writeGoAway(serverCtx(), 3, NO_ERROR.code(), EMPTY_BUFFER, serverNewPromise());
            http2Server.flush(serverCtx());
        }
    });
    // wait for the client to receive the GO_AWAY.
    assertTrue(clientGoAwayLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    verify(clientListener).onGoAwayRead(any(ChannelHandlerContext.class), eq(3), eq(NO_ERROR.code()), any(ByteBuf.class));
    final AtomicReference<ChannelFuture> clientWriteAfterGoAwayFutureRef = new AtomicReference<ChannelFuture>();
    final CountDownLatch clientWriteAfterGoAwayLatch = new CountDownLatch(1);
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            ChannelFuture f = http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, (short) 16, false, 0, true, newPromise());
            clientWriteAfterGoAwayFutureRef.set(f);
            http2Client.flush(ctx());
            f.addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    clientWriteAfterGoAwayLatch.countDown();
                }
            });
        }
    });
    // Wait for the client's write operation to complete.
    assertTrue(clientWriteAfterGoAwayLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    ChannelFuture clientWriteAfterGoAwayFuture = clientWriteAfterGoAwayFutureRef.get();
    assertNotNull(clientWriteAfterGoAwayFuture);
    Throwable clientCause = clientWriteAfterGoAwayFuture.cause();
    assertThat(clientCause, is(instanceOf(Http2Exception.StreamException.class)));
    assertEquals(Http2Error.REFUSED_STREAM.code(), ((Http2Exception.StreamException) clientCause).error().code());
    // Wait for the server to receive a GO_AWAY, but this is expected to timeout!
    assertFalse(goAwayLatch.await(1, SECONDS));
    verify(serverListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
    // Shutdown shouldn't wait for the server to close streams
    setClientGracefulShutdownTime(0);
    setServerGracefulShutdownTime(0);
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBuf(io.netty.buffer.ByteBuf) ChannelFutureListener(io.netty.channel.ChannelFutureListener) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.junit.jupiter.api.Test)

Example 34 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class InboundHttp2ToHttpAdapterTest method clientRequestSingleHeaderNonAsciiShouldThrow.

@Test
public void clientRequestSingleHeaderNonAsciiShouldThrow() throws Exception {
    boostrapEnv(1, 1, 1);
    final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https")).authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource2")).add(new AsciiString("çã".getBytes(CharsetUtil.UTF_8)), new AsciiString("Ãã".getBytes(CharsetUtil.UTF_8)));
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
            clientChannel.flush();
        }
    });
    awaitResponses();
    assertTrue(isStreamError(clientException));
}
Also used : Http2CodecUtil.getEmbeddedHttp2Exception(io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception) Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) AsciiString(io.netty.util.AsciiString) Test(org.junit.jupiter.api.Test)

Example 35 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class InboundHttp2ToHttpAdapterTest method serverRequestPushPromise.

@Test
public void serverRequestPushPromise() throws Exception {
    boostrapEnv(1, 1, 1);
    final String text = "hello world big time data!";
    final ByteBuf content = Unpooled.copiedBuffer(text.getBytes());
    final String text2 = "hello world smaller data?";
    final ByteBuf content2 = Unpooled.copiedBuffer(text2.getBytes());
    final FullHttpMessage response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content, true);
    final FullHttpMessage response2 = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CREATED, content2, true);
    final FullHttpMessage request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/push/test", true);
    try {
        HttpHeaders httpHeaders = response.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        HttpHeaders httpHeaders2 = response2.headers();
        httpHeaders2.set(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text(), "https");
        httpHeaders2.set(HttpHeaderNames.HOST, "example.org");
        httpHeaders2.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 5);
        httpHeaders2.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_PROMISE_ID.text(), 3);
        httpHeaders2.setInt(HttpHeaderNames.CONTENT_LENGTH, text2.length());
        httpHeaders = request.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        final Http2Headers http2Headers3 = new DefaultHttp2Headers().method(new AsciiString("GET")).path(new AsciiString("/push/test"));
        runInChannel(clientChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers3, 0, true, newPromiseClient());
                clientChannel.flush();
            }
        });
        awaitRequests();
        ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
        verify(serverListener).messageReceived(requestCaptor.capture());
        capturedRequests = requestCaptor.getAllValues();
        assertEquals(request, capturedRequests.get(0));
        final Http2Headers http2Headers = new DefaultHttp2Headers().status(new AsciiString("200"));
        // The PUSH_PROMISE frame includes a header block that contains a
        // complete set of request header fields that the server attributes to
        // the request.
        // https://tools.ietf.org/html/rfc7540#section-8.2.1
        // Therefore, we should consider the case where there is no Http response status.
        final Http2Headers http2Headers2 = new DefaultHttp2Headers().scheme(new AsciiString("https")).authority(new AsciiString("example.org"));
        runInChannel(serverConnectedChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                serverHandler.encoder().writeHeaders(ctxServer(), 3, http2Headers, 0, false, newPromiseServer());
                serverHandler.encoder().writePushPromise(ctxServer(), 3, 2, http2Headers2, 0, newPromiseServer());
                serverHandler.encoder().writeData(ctxServer(), 3, content.retainedDuplicate(), 0, true, newPromiseServer());
                serverHandler.encoder().writeData(ctxServer(), 5, content2.retainedDuplicate(), 0, true, newPromiseServer());
                serverConnectedChannel.flush();
            }
        });
        awaitResponses();
        ArgumentCaptor<FullHttpMessage> responseCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
        verify(clientListener).messageReceived(responseCaptor.capture());
        capturedResponses = responseCaptor.getAllValues();
        assertEquals(response, capturedResponses.get(0));
    } finally {
        request.release();
        response.release();
        response2.release();
    }
}
Also used : DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) Http2CodecUtil.getEmbeddedHttp2Exception(io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage) AsciiString(io.netty.util.AsciiString) AsciiString(io.netty.util.AsciiString) ByteBuf(io.netty.buffer.ByteBuf) Test(org.junit.jupiter.api.Test)

Aggregations

Http2Runnable (io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable)41 Test (org.junit.jupiter.api.Test)37 ByteBuf (io.netty.buffer.ByteBuf)28 AsciiString (io.netty.util.AsciiString)20 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)18 Http2CodecUtil.getEmbeddedHttp2Exception (io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception)12 DefaultFullHttpRequest (io.netty.handler.codec.http.DefaultFullHttpRequest)11 FullHttpMessage (io.netty.handler.codec.http.FullHttpMessage)11 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)11 CountDownLatch (java.util.concurrent.CountDownLatch)11 FullHttpRequest (io.netty.handler.codec.http.FullHttpRequest)9 InvocationOnMock (org.mockito.invocation.InvocationOnMock)9 ChannelFuture (io.netty.channel.ChannelFuture)6 ChannelFutureListener (io.netty.channel.ChannelFutureListener)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)6 ExecutionException (java.util.concurrent.ExecutionException)5 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 IllegalReferenceCountException (io.netty.util.IllegalReferenceCountException)3 ChannelHandlerAdapter (io.netty.channel.ChannelHandlerAdapter)2 ChannelPromise (io.netty.channel.ChannelPromise)2