use of io.netty.handler.codec.http2.Http2Headers 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);
}
}
}
});
}
use of io.netty.handler.codec.http2.Http2Headers in project grpc-java by grpc.
the class NettyClientHandlerTest method inboundShouldForwardToStream.
@Test
public void inboundShouldForwardToStream() throws Exception {
createStream();
// Read a headers frame first.
Http2Headers headers = new DefaultHttp2Headers().status(STATUS_OK).set(CONTENT_TYPE_HEADER, CONTENT_TYPE_GRPC).set(as("magic"), as("value"));
ByteBuf headersFrame = headersFrame(3, headers);
channelRead(headersFrame);
ArgumentCaptor<Metadata> captor = ArgumentCaptor.forClass(Metadata.class);
verify(streamListener).headersRead(captor.capture());
assertEquals("value", captor.getValue().get(Metadata.Key.of("magic", Metadata.ASCII_STRING_MARSHALLER)));
streamTransportState.requestMessagesFromDeframer(1);
// Create a data frame and then trigger the handler to read it.
ByteBuf frame = grpcDataFrame(3, false, contentAsArray());
channelRead(frame);
ArgumentCaptor<InputStream> isCaptor = ArgumentCaptor.forClass(InputStream.class);
verify(streamListener).messageRead(isCaptor.capture());
assertArrayEquals(ByteBufUtil.getBytes(content()), ByteStreams.toByteArray(isCaptor.getValue()));
isCaptor.getValue().close();
}
use of io.netty.handler.codec.http2.Http2Headers in project grpc-java by grpc.
the class NettyClientStreamTest method invalidInboundContentTypeShouldCancelStream.
@Test
public void invalidInboundContentTypeShouldCancelStream() {
// Set stream id to indicate it has been created
stream().transportState().setId(STREAM_ID);
Http2Headers headers = new DefaultHttp2Headers().status(STATUS_OK).set(CONTENT_TYPE_HEADER, new AsciiString("application/bad", UTF_8));
stream().transportState().transportHeadersReceived(headers, false);
Http2Headers trailers = new DefaultHttp2Headers().set(new AsciiString("grpc-status", UTF_8), new AsciiString("0", UTF_8));
stream().transportState().transportHeadersReceived(trailers, true);
ArgumentCaptor<Status> captor = ArgumentCaptor.forClass(Status.class);
ArgumentCaptor<Metadata> metadataCaptor = ArgumentCaptor.forClass(Metadata.class);
verify(listener).closed(captor.capture(), metadataCaptor.capture());
Status status = captor.getValue();
assertEquals(Status.Code.UNKNOWN, status.getCode());
assertTrue(status.getDescription().contains("content-type"));
assertEquals("application/bad", metadataCaptor.getValue().get(Metadata.Key.of("Content-Type", Metadata.ASCII_STRING_MARSHALLER)));
}
use of io.netty.handler.codec.http2.Http2Headers in project grpc-java by grpc.
the class NettyClientStreamTest method inboundHeadersShouldCallListenerHeadersRead.
@Test
public void inboundHeadersShouldCallListenerHeadersRead() throws Exception {
stream().transportState().setId(STREAM_ID);
Http2Headers headers = grpcResponseHeaders();
stream().transportState().transportHeadersReceived(headers, false);
verify(listener).headersRead(any(Metadata.class));
}
use of io.netty.handler.codec.http2.Http2Headers in project grpc-java by grpc.
the class GrpcHttp2HeadersDecoderTest method decode_emptyHeaders.
@Test
public void decode_emptyHeaders() throws Http2Exception {
Http2HeadersDecoder decoder = new GrpcHttp2ClientHeadersDecoder(8192);
Http2HeadersEncoder encoder = new DefaultHttp2HeadersEncoder(NEVER_SENSITIVE);
ByteBuf encodedHeaders = Unpooled.buffer();
encoder.encodeHeaders(1, /* randomly chosen */
new DefaultHttp2Headers(false), encodedHeaders);
Http2Headers decodedHeaders = decoder.decodeHeaders(3, /* randomly chosen */
encodedHeaders);
assertEquals(0, decodedHeaders.size());
assertThat(decodedHeaders.toString(), containsString("[]"));
}
Aggregations