Search in sources :

Example 6 with Http2Stream

use of org.glassfish.grizzly.http2.Http2Stream in project grpc-java by grpc.

the class NettyClientHandler method createStream.

/**
   * Attempts to create a new stream from the given command. If there are too many active streams,
   * the creation request is queued.
   */
private void createStream(CreateStreamCommand command, final ChannelPromise promise) throws Exception {
    if (lifecycleManager.getShutdownThrowable() != null) {
        // The connection is going away, just terminate the stream now.
        promise.setFailure(lifecycleManager.getShutdownThrowable());
        return;
    }
    // Get the stream ID for the new stream.
    final int streamId;
    try {
        streamId = incrementAndGetNextStreamId();
    } catch (StatusException e) {
        // Stream IDs have been exhausted for this connection. Fail the promise immediately.
        promise.setFailure(e);
        // Initiate a graceful shutdown if we haven't already.
        if (!connection().goAwaySent()) {
            logger.fine("Stream IDs have been exhausted for this connection. " + "Initiating graceful shutdown of the connection.");
            lifecycleManager.notifyShutdown(e.getStatus());
            close(ctx(), ctx().newPromise());
        }
        return;
    }
    final NettyClientStream.TransportState stream = command.stream();
    final Http2Headers headers = command.headers();
    stream.setId(streamId);
    // Create an intermediate promise so that we can intercept the failure reported back to the
    // application.
    ChannelPromise tempPromise = ctx().newPromise();
    encoder().writeHeaders(ctx(), streamId, headers, 0, false, tempPromise).addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            if (future.isSuccess()) {
                // The http2Stream will be null in case a stream buffered in the encoder
                // was canceled via RST_STREAM.
                Http2Stream http2Stream = connection().stream(streamId);
                if (http2Stream != null) {
                    stream.getStatsTraceContext().clientHeadersSent();
                    http2Stream.setProperty(streamKey, stream);
                    // Attach the client stream to the HTTP/2 stream object as user data.
                    stream.setHttp2Stream(http2Stream);
                }
                // Otherwise, the stream has been cancelled and Netty is sending a
                // RST_STREAM frame which causes it to purge pending writes from the
                // flow-controller and delete the http2Stream. The stream listener has already
                // been notified of cancellation so there is nothing to do.
                // Just forward on the success status to the original promise.
                promise.setSuccess();
            } else {
                final Throwable cause = future.cause();
                if (cause instanceof StreamBufferingEncoder.Http2GoAwayException) {
                    StreamBufferingEncoder.Http2GoAwayException e = (StreamBufferingEncoder.Http2GoAwayException) cause;
                    lifecycleManager.notifyShutdown(statusFromGoAway(e.errorCode(), e.debugData()));
                    promise.setFailure(lifecycleManager.getShutdownThrowable());
                } else {
                    promise.setFailure(cause);
                }
            }
        }
    });
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) StreamBufferingEncoder(io.netty.handler.codec.http2.StreamBufferingEncoder) ChannelPromise(io.netty.channel.ChannelPromise) ChannelFutureListener(io.netty.channel.ChannelFutureListener) Http2Exception(io.netty.handler.codec.http2.Http2Exception) StatusException(io.grpc.StatusException) ClosedChannelException(java.nio.channels.ClosedChannelException) StatusException(io.grpc.StatusException) Http2Headers(io.netty.handler.codec.http2.Http2Headers) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Example 7 with Http2Stream

use of org.glassfish.grizzly.http2.Http2Stream in project grpc-java by grpc.

the class NettyClientHandler method channelInactive.

/**
   * Handler for the Channel shutting down.
   */
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    try {
        logger.fine("Network channel is closed");
        lifecycleManager.notifyShutdown(Status.UNAVAILABLE.withDescription("Network closed for unknown reason"));
        cancelPing(lifecycleManager.getShutdownThrowable());
        // Report status to the application layer for any open streams
        connection().forEachActiveStream(new Http2StreamVisitor() {

            @Override
            public boolean visit(Http2Stream stream) throws Http2Exception {
                NettyClientStream.TransportState clientStream = clientStream(stream);
                if (clientStream != null) {
                    clientStream.transportReportStatus(lifecycleManager.getShutdownStatus(), false, new Metadata());
                }
                return true;
            }
        });
    } finally {
        // Close any open streams
        super.channelInactive(ctx);
        if (keepAliveManager != null) {
            keepAliveManager.onTransportShutdown();
        }
    }
}
Also used : Http2Exception(io.netty.handler.codec.http2.Http2Exception) Http2StreamVisitor(io.netty.handler.codec.http2.Http2StreamVisitor) Metadata(io.grpc.Metadata) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Example 8 with Http2Stream

use of org.glassfish.grizzly.http2.Http2Stream in project grpc-java by grpc.

the class NettyHandlerTestBase method windowShouldNotExceedMaxWindowSize.

@Test
public void windowShouldNotExceedMaxWindowSize() throws Exception {
    makeStream();
    AbstractNettyHandler handler = (AbstractNettyHandler) handler();
    handler.setAutoTuneFlowControl(true);
    Http2Stream connectionStream = connection().connectionStream();
    Http2LocalFlowController localFlowController = connection().local().flowController();
    int maxWindow = handler.flowControlPing().maxWindow();
    handler.flowControlPing().setDataSizeSincePing(maxWindow);
    int payload = handler.flowControlPing().payload();
    ByteBuf buffer = handler.ctx().alloc().buffer(8);
    buffer.writeLong(payload);
    channelRead(pingFrame(true, buffer));
    assertEquals(maxWindow, localFlowController.initialWindowSize(connectionStream));
}
Also used : Http2LocalFlowController(io.netty.handler.codec.http2.Http2LocalFlowController) Http2Stream(io.netty.handler.codec.http2.Http2Stream) ByteBuf(io.netty.buffer.ByteBuf) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) Test(org.junit.Test)

Example 9 with Http2Stream

use of org.glassfish.grizzly.http2.Http2Stream in project vert.x by eclipse.

the class Http2ServerTest method testStreamPauseResume.

private void testStreamPauseResume(Function<HttpServerRequest, ReadStream<Buffer>> streamProvider) throws Exception {
    Buffer expected = Buffer.buffer();
    String chunk = TestUtils.randomAlphaString(1000);
    AtomicBoolean done = new AtomicBoolean();
    AtomicBoolean paused = new AtomicBoolean();
    Buffer received = Buffer.buffer();
    server.requestHandler(req -> {
        ReadStream<Buffer> stream = streamProvider.apply(req);
        vertx.setPeriodic(1, timerID -> {
            if (paused.get()) {
                vertx.cancelTimer(timerID);
                done.set(true);
                vertx.setTimer(100, id -> {
                    stream.resume();
                });
            }
        });
        stream.handler(received::appendBuffer);
        stream.endHandler(v -> {
            assertEquals(expected, received);
            testComplete();
        });
        stream.pause();
    });
    startServer();
    TestClient client = new TestClient();
    ChannelFuture fut = client.connect(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, request -> {
        int id = request.nextStreamId();
        request.encoder.writeHeaders(request.context, id, POST("/form").set("content-type", "text/plain"), 0, false, request.context.newPromise());
        request.context.flush();
        Http2Stream stream = request.connection.stream(id);
        class Anonymous {

            void send() {
                boolean writable = request.encoder.flowController().isWritable(stream);
                if (writable) {
                    Buffer buf = Buffer.buffer(chunk);
                    expected.appendBuffer(buf);
                    request.encoder.writeData(request.context, id, buf.getByteBuf(), 0, false, request.context.newPromise());
                    request.context.flush();
                    request.context.executor().execute(this::send);
                } else {
                    request.encoder.writeData(request.context, id, Unpooled.EMPTY_BUFFER, 0, true, request.context.newPromise());
                    request.context.flush();
                    paused.set(true);
                }
            }
        }
        new Anonymous().send();
    });
    fut.sync();
    await();
}
Also used : Buffer(io.vertx.core.buffer.Buffer) ChannelFuture(io.netty.channel.ChannelFuture) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Example 10 with Http2Stream

use of org.glassfish.grizzly.http2.Http2Stream in project jetty.project by eclipse.

the class FlowControlStrategyTest method testWindowSizeUpdates.

@Test
public void testWindowSizeUpdates() throws Exception {
    final CountDownLatch prefaceLatch = new CountDownLatch(1);
    final CountDownLatch stream1Latch = new CountDownLatch(1);
    final CountDownLatch stream2Latch = new CountDownLatch(1);
    final CountDownLatch settingsLatch = new CountDownLatch(1);
    start(new ServerSessionListener.Adapter() {

        @Override
        public Map<Integer, Integer> onPreface(Session session) {
            HTTP2Session serverSession = (HTTP2Session) session;
            Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, serverSession.getSendWindow());
            Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, serverSession.getRecvWindow());
            prefaceLatch.countDown();
            return null;
        }

        @Override
        public void onSettings(Session session, SettingsFrame frame) {
            for (Stream stream : session.getStreams()) {
                HTTP2Stream serverStream = (HTTP2Stream) stream;
                Assert.assertEquals(0, serverStream.getSendWindow());
                Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, serverStream.getRecvWindow());
            }
            settingsLatch.countDown();
        }

        @Override
        public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) {
            HTTP2Stream serverStream = (HTTP2Stream) stream;
            MetaData.Request request = (MetaData.Request) frame.getMetaData();
            if ("GET".equalsIgnoreCase(request.getMethod())) {
                Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, serverStream.getSendWindow());
                Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, serverStream.getRecvWindow());
                stream1Latch.countDown();
            } else {
                Assert.assertEquals(0, serverStream.getSendWindow());
                Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, serverStream.getRecvWindow());
                stream2Latch.countDown();
            }
            return null;
        }
    });
    HTTP2Session clientSession = (HTTP2Session) newClient(new Session.Listener.Adapter());
    Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientSession.getSendWindow());
    Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientSession.getRecvWindow());
    Assert.assertTrue(prefaceLatch.await(5, TimeUnit.SECONDS));
    MetaData.Request request1 = newRequest("GET", new HttpFields());
    FuturePromise<Stream> promise1 = new FuturePromise<>();
    clientSession.newStream(new HeadersFrame(request1, null, true), promise1, new Stream.Listener.Adapter());
    HTTP2Stream clientStream1 = (HTTP2Stream) promise1.get(5, TimeUnit.SECONDS);
    Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientStream1.getSendWindow());
    Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientStream1.getRecvWindow());
    Assert.assertTrue(stream1Latch.await(5, TimeUnit.SECONDS));
    // Send a SETTINGS frame that changes the window size.
    // This tells the server that its stream send window must be updated,
    // so on the client it's the receive window that must be updated.
    Map<Integer, Integer> settings = new HashMap<>();
    settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, 0);
    SettingsFrame frame = new SettingsFrame(settings, false);
    FutureCallback callback = new FutureCallback();
    clientSession.settings(frame, callback);
    callback.get(5, TimeUnit.SECONDS);
    Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientStream1.getSendWindow());
    Assert.assertEquals(0, clientStream1.getRecvWindow());
    settingsLatch.await(5, TimeUnit.SECONDS);
    // Now create a new stream, it must pick up the new value.
    MetaData.Request request2 = newRequest("POST", new HttpFields());
    FuturePromise<Stream> promise2 = new FuturePromise<>();
    clientSession.newStream(new HeadersFrame(request2, null, true), promise2, new Stream.Listener.Adapter());
    HTTP2Stream clientStream2 = (HTTP2Stream) promise2.get(5, TimeUnit.SECONDS);
    Assert.assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientStream2.getSendWindow());
    Assert.assertEquals(0, clientStream2.getRecvWindow());
    Assert.assertTrue(stream2Latch.await(5, TimeUnit.SECONDS));
}
Also used : ServerSessionListener(org.eclipse.jetty.http2.api.server.ServerSessionListener) HTTP2Stream(org.eclipse.jetty.http2.HTTP2Stream) HashMap(java.util.HashMap) FuturePromise(org.eclipse.jetty.util.FuturePromise) CountDownLatch(java.util.concurrent.CountDownLatch) HTTP2Session(org.eclipse.jetty.http2.HTTP2Session) HeadersFrame(org.eclipse.jetty.http2.frames.HeadersFrame) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SettingsFrame(org.eclipse.jetty.http2.frames.SettingsFrame) MetaData(org.eclipse.jetty.http.MetaData) HttpFields(org.eclipse.jetty.http.HttpFields) HTTP2Stream(org.eclipse.jetty.http2.HTTP2Stream) Stream(org.eclipse.jetty.http2.api.Stream) Map(java.util.Map) HashMap(java.util.HashMap) ServerSessionListener(org.eclipse.jetty.http2.api.server.ServerSessionListener) FutureCallback(org.eclipse.jetty.util.FutureCallback) HTTP2Session(org.eclipse.jetty.http2.HTTP2Session) Session(org.eclipse.jetty.http2.api.Session) ISession(org.eclipse.jetty.http2.ISession) Test(org.junit.Test)

Aggregations

Http2Stream (io.netty.handler.codec.http2.Http2Stream)21 Http2Exception (io.netty.handler.codec.http2.Http2Exception)8 Test (org.junit.Test)8 Http2StreamVisitor (io.netty.handler.codec.http2.Http2StreamVisitor)5 Metadata (io.grpc.Metadata)4 Http2LocalFlowController (io.netty.handler.codec.http2.Http2LocalFlowController)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 HttpFields (org.eclipse.jetty.http.HttpFields)4 HTTP2Session (org.eclipse.jetty.http2.HTTP2Session)4 HTTP2Stream (org.eclipse.jetty.http2.HTTP2Stream)4 Session (org.eclipse.jetty.http2.api.Session)4 Stream (org.eclipse.jetty.http2.api.Stream)4 ServerSessionListener (org.eclipse.jetty.http2.api.server.ServerSessionListener)4 HeadersFrame (org.eclipse.jetty.http2.frames.HeadersFrame)4 FuturePromise (org.eclipse.jetty.util.FuturePromise)4 Status (io.grpc.Status)2 ByteBuf (io.netty.buffer.ByteBuf)2 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)2 ChannelFuture (io.netty.channel.ChannelFuture)2 DefaultHttp2Connection (io.netty.handler.codec.http2.DefaultHttp2Connection)2