Search in sources :

Example 1 with Http2StreamVisitor

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

the class DefaultHttp2ConnectionTest method removeAllStreamsWhileIteratingActiveStreamsAndExceptionOccurs.

@Test
public void removeAllStreamsWhileIteratingActiveStreamsAndExceptionOccurs() throws Exception {
    final Endpoint<Http2RemoteFlowController> remote = client.remote();
    final Endpoint<Http2LocalFlowController> local = client.local();
    for (int c = 3, s = 2; c < 5000; c += 2, s += 2) {
        local.createStream(c, false);
        remote.createStream(s, false);
    }
    final Promise<Void> promise = group.next().newPromise();
    final CountDownLatch latch = new CountDownLatch(1);
    try {
        client.forEachActiveStream(new Http2StreamVisitor() {

            @Override
            public boolean visit(Http2Stream stream) throws Http2Exception {
                // This close call is basically a noop, because the following statement will throw an exception.
                client.close(promise);
                // Do an invalid operation while iterating.
                remote.createStream(3, false);
                return true;
            }
        });
    } catch (Http2Exception ignored) {
        client.close(promise).addListener(new FutureListener<Void>() {

            @Override
            public void operationComplete(Future<Void> future) throws Exception {
                assertTrue(promise.isDone());
                latch.countDown();
            }
        });
    }
    assertTrue(latch.await(5, TimeUnit.SECONDS));
}
Also used : FutureListener(io.netty.util.concurrent.FutureListener) CountDownLatch(java.util.concurrent.CountDownLatch) Endpoint(io.netty.handler.codec.http2.Http2Connection.Endpoint) Future(io.netty.util.concurrent.Future) Test(org.junit.jupiter.api.Test)

Example 2 with Http2StreamVisitor

use of io.netty.handler.codec.http2.Http2StreamVisitor in project grpc-java by grpc.

the class NettyClientHandler method forcefulClose.

private void forcefulClose(final ChannelHandlerContext ctx, final ForcefulCloseCommand msg, ChannelPromise promise) throws Exception {
    connection().forEachActiveStream(new Http2StreamVisitor() {

        @Override
        public boolean visit(Http2Stream stream) throws Http2Exception {
            NettyClientStream.TransportState clientStream = clientStream(stream);
            Tag tag = clientStream != null ? clientStream.tag() : PerfMark.createTag();
            PerfMark.startTask("NettyClientHandler.forcefulClose", tag);
            PerfMark.linkIn(msg.getLink());
            try {
                if (clientStream != null) {
                    clientStream.transportReportStatus(msg.getStatus(), true, new Metadata());
                    resetStream(ctx, stream.id(), Http2Error.CANCEL.code(), ctx.newPromise());
                }
                stream.close();
                return true;
            } finally {
                PerfMark.stopTask("NettyClientHandler.forcefulClose", tag);
            }
        }
    });
    close(ctx, promise);
}
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) Tag(io.perfmark.Tag)

Example 3 with Http2StreamVisitor

use of io.netty.handler.codec.http2.Http2StreamVisitor in project grpc-java by grpc.

the class NettyClientHandler method goingAway.

/**
 * Handler for a GOAWAY being received. Fails any streams created after the
 * last known stream. May only be called during a read.
 */
private void goingAway(long errorCode, byte[] debugData) {
    Status finalStatus = statusFromH2Error(Status.Code.UNAVAILABLE, "GOAWAY shut down transport", errorCode, debugData);
    lifecycleManager.notifyGracefulShutdown(finalStatus);
    abruptGoAwayStatus = statusFromH2Error(Status.Code.UNAVAILABLE, "Abrupt GOAWAY closed unsent stream", errorCode, debugData);
    // While this _should_ be UNAVAILABLE, Netty uses the wrong stream id in the GOAWAY when it
    // fails streams due to HPACK failures (e.g., header list too large). To be more conservative,
    // we assume any sent streams may be related to the GOAWAY. This should rarely impact users
    // since the main time servers should use abrupt GOAWAYs is if there is a protocol error, and if
    // there wasn't a protocol error the error code was probably NO_ERROR which is mapped to
    // UNAVAILABLE. https://github.com/netty/netty/issues/10670
    final Status abruptGoAwayStatusConservative = statusFromH2Error(null, "Abrupt GOAWAY closed sent stream", errorCode, debugData);
    final boolean mayBeHittingNettyBug = errorCode != Http2Error.NO_ERROR.code();
    // Try to allocate as many in-flight streams as possible, to reduce race window of
    // https://github.com/grpc/grpc-java/issues/2562 . To be of any help, the server has to
    // gracefully shut down the connection with two GOAWAYs. gRPC servers generally send a PING
    // after the first GOAWAY, so they can very precisely detect when the GOAWAY has been
    // processed and thus this processing must be in-line before processing additional reads.
    // This can cause reentrancy, but should be minor since it is normal to handle writes in
    // response to a read. Also, the call stack is rather shallow at this point
    clientWriteQueue.drainNow();
    if (lifecycleManager.notifyShutdown(finalStatus)) {
        // This is for the only RPCs that are actually covered by the GOAWAY error code. All other
        // RPCs were not observed by the remote and so should be UNAVAILABLE.
        channelInactiveReason = statusFromH2Error(null, "Connection closed after GOAWAY", errorCode, debugData);
    }
    final int lastKnownStream = connection().local().lastStreamKnownByPeer();
    try {
        connection().forEachActiveStream(new Http2StreamVisitor() {

            @Override
            public boolean visit(Http2Stream stream) throws Http2Exception {
                if (stream.id() > lastKnownStream) {
                    NettyClientStream.TransportState clientStream = clientStream(stream);
                    if (clientStream != null) {
                        // RpcProgress _should_ be REFUSED, but are being conservative. See comment for
                        // abruptGoAwayStatusConservative. This does reduce our ability to perform transparent
                        // retries, but only if something else caused a connection failure.
                        RpcProgress progress = mayBeHittingNettyBug ? RpcProgress.PROCESSED : RpcProgress.REFUSED;
                        clientStream.transportReportStatus(abruptGoAwayStatusConservative, progress, false, new Metadata());
                    }
                    stream.close();
                }
                return true;
            }
        });
    } catch (Http2Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : Status(io.grpc.Status) Http2Exception(io.netty.handler.codec.http2.Http2Exception) Http2StreamVisitor(io.netty.handler.codec.http2.Http2StreamVisitor) Metadata(io.grpc.Metadata) RpcProgress(io.grpc.internal.ClientStreamListener.RpcProgress) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Example 4 with Http2StreamVisitor

use of io.netty.handler.codec.http2.Http2StreamVisitor 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");
        Status status = Status.UNAVAILABLE.withDescription("Network closed for unknown reason");
        lifecycleManager.notifyShutdown(status);
        final Status streamStatus;
        if (channelInactiveReason != null) {
            streamStatus = channelInactiveReason;
        } else {
            streamStatus = lifecycleManager.getShutdownStatus();
        }
        try {
            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(streamStatus, false, new Metadata());
                    }
                    return true;
                }
            });
        } finally {
            lifecycleManager.notifyTerminated(status);
        }
    } finally {
        // Close any open streams
        super.channelInactive(ctx);
        if (keepAliveManager != null) {
            keepAliveManager.onTransportTermination();
        }
    }
}
Also used : Status(io.grpc.Status) 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 5 with Http2StreamVisitor

use of io.netty.handler.codec.http2.Http2StreamVisitor in project grpc-java by grpc.

the class NettyServerHandler method channelInactive.

/**
 * Handler for the Channel shutting down.
 */
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    try {
        if (keepAliveManager != null) {
            keepAliveManager.onTransportTermination();
        }
        if (maxConnectionIdleManager != null) {
            maxConnectionIdleManager.onTransportTermination();
        }
        if (maxConnectionAgeMonitor != null) {
            maxConnectionAgeMonitor.cancel(false);
        }
        final Status status = Status.UNAVAILABLE.withDescription("connection terminated for unknown reason");
        // Any streams that are still active must be closed
        connection().forEachActiveStream(new Http2StreamVisitor() {

            @Override
            public boolean visit(Http2Stream stream) throws Http2Exception {
                NettyServerStream.TransportState serverStream = serverStream(stream);
                if (serverStream != null) {
                    serverStream.transportReportStatus(status);
                }
                return true;
            }
        });
    } finally {
        super.channelInactive(ctx);
    }
}
Also used : Status(io.grpc.Status) InternalStatus(io.grpc.InternalStatus) Http2Exception(io.netty.handler.codec.http2.Http2Exception) Http2StreamVisitor(io.netty.handler.codec.http2.Http2StreamVisitor) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Aggregations

Http2Exception (io.netty.handler.codec.http2.Http2Exception)6 Http2Stream (io.netty.handler.codec.http2.Http2Stream)6 Http2StreamVisitor (io.netty.handler.codec.http2.Http2StreamVisitor)6 Metadata (io.grpc.Metadata)4 Status (io.grpc.Status)4 Endpoint (io.netty.handler.codec.http2.Http2Connection.Endpoint)2 Future (io.netty.util.concurrent.Future)2 FutureListener (io.netty.util.concurrent.FutureListener)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 Test (org.junit.jupiter.api.Test)2 InternalStatus (io.grpc.InternalStatus)1 RpcProgress (io.grpc.internal.ClientStreamListener.RpcProgress)1 Tag (io.perfmark.Tag)1