public void FailedWhenUnknownFrameInMiddleOfHeaderBlock() { int streamId = 1; var input = Unpooled.Buffer(); try { var headers = new DefaultHttp2Headers { Authority = (AsciiString)"foo", Method = (AsciiString)"get", Path = (AsciiString)"/", Scheme = (AsciiString)"https" }; Http2Flags flags = new Http2Flags().EndOfHeaders(false).EndOfStream(true); this.WriteHeaderFrame(input, streamId, headers, flags); Http2CodecUtil.WriteFrameHeader(input, 0, (Http2FrameTypes)0xff, new Http2Flags(), streamId); Assert.Throws <Http2Exception>(() => this.frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object)); } finally { input.Release(); } }
public void ClientShouldveSentPrefaceAndSettingsFrameWhenUserEventIsTriggered() { _connection.Setup(x => x.IsServer).Returns(false); _channel.Setup(x => x.IsActive).Returns(false); _handler = NewHandler(); _channel.Setup(x => x.IsActive).Returns(true); var evt = Http2ConnectionPrefaceAndSettingsFrameWrittenEvent.Instance; AtomicBoolean verified = new AtomicBoolean(false); _ctx .Setup(x => x.FireUserEventTriggered(It.Is <object>(v => ReferenceEquals(v, evt)))) .Returns <object>(msg => { Assert.Same(msg, evt); _ctx.Verify(x => x.WriteAsync(It.Is <object>(d => Http2CodecUtil.ConnectionPrefaceBuf().Equals((IByteBuffer)d)))); _encoder.Verify( x => x.WriteSettingsAsync( It.Is <IChannelHandlerContext>(v => v == _ctx.Object), It.IsAny <Http2Settings>(), It.IsAny <IPromise>())); verified.Value = true; return(_ctx.Object); }); _handler.ChannelActive(_ctx.Object); Assert.True(verified.Value); }
public void VerifyChannelHandlerCanBeReusedInPipeline() { _connection.Setup(x => x.IsServer).Returns(true); _handler = NewHandler(); // Only read the connection preface...after preface is read internal state of Http2ConnectionHandler // is expected to change relative to the pipeline. IByteBuffer preface = Http2CodecUtil.ConnectionPrefaceBuf(); _handler.ChannelRead(_ctx.Object, preface); _decoder.Verify( x => x.DecodeFrame( It.IsAny <IChannelHandlerContext>(), It.IsAny <IByteBuffer>(), It.IsAny <List <object> >()), Times.Never()); // Now remove and add the this.handler...this is setting up the test condition. _handler.HandlerRemoved(_ctx.Object); _handler.HandlerAdded(_ctx.Object); // Now verify we can continue as normal, reading connection preface plus more. IByteBuffer prefacePlusSome = AddSettingsHeader(Unpooled.Buffer().WriteBytes(Http2CodecUtil.ConnectionPrefaceBuf())); _handler.ChannelRead(_ctx.Object, prefacePlusSome); _decoder.Verify( x => x.DecodeFrame( It.Is <IChannelHandlerContext>(v => v == _ctx.Object), It.IsAny <IByteBuffer>(), It.IsAny <List <object> >()), Times.AtLeastOnce); }
public void ServerShouldNotSendClientPrefaceStringWhenActive() { _connection.Setup(x => x.IsServer).Returns(true); _channel.Setup(x => x.IsActive).Returns(false); _handler = NewHandler(); _channel.Setup(x => x.IsActive).Returns(true); _handler.ChannelActive(_ctx.Object); _ctx.Verify(x => x.WriteAsync(It.Is <object>(d => Http2CodecUtil.ConnectionPrefaceBuf().Equals((IByteBuffer)d))), Times.Never()); }
private static void TestUpgrade(Http2ConnectionHandler handler, IChannelHandler multiplexer) { IFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.Http11, HttpMethod.Options, "*"); request.Headers.Set(HttpHeaderNames.Host, "netty.io"); request.Headers.Set(HttpHeaderNames.Connection, "Upgrade, HTTP2-Settings"); request.Headers.Set(HttpHeaderNames.Upgrade, "h2c"); request.Headers.Set((AsciiString)"HTTP2-Settings", "AAMAAABkAAQAAP__"); var parent = new Mock <IServerChannel>(); EmbeddedChannel channel = new EmbeddedChannel(parent.Object, DefaultChannelId.NewInstance(), false, true, new ChannelHandlerAdapter()); IChannelHandlerContext ctx = channel.Pipeline.FirstContext(); Http2ServerUpgradeCodec codec; if (multiplexer == null) { codec = new Http2ServerUpgradeCodec(handler); } else { codec = new Http2ServerUpgradeCodec((Http2FrameCodec)handler, multiplexer); } Assert.True(codec.PrepareUpgradeResponse(ctx, request, new DefaultHttpHeaders())); codec.UpgradeTo(ctx, request); // Flush the channel to ensure we write out all buffered data channel.Flush(); channel.WriteInbound(Http2CodecUtil.ConnectionPrefaceBuf()); Http2FrameInboundWriter writer = new Http2FrameInboundWriter(channel); writer.WriteInboundSettings(new Http2Settings()); writer.WriteInboundRstStream(Http2CodecUtil.HttpUpgradeStreamId, Http2Error.Cancel); Assert.Same(handler, channel.Pipeline.Remove <Http2ConnectionHandler>()); Assert.Null(channel.Pipeline.Get <Http2ConnectionHandler>()); Assert.True(channel.Finish()); // Check that the preface was send (a.k.a the settings frame) var settingsBuffer = channel.ReadOutbound <IByteBuffer>(); Assert.NotNull(settingsBuffer); settingsBuffer.Release(); var buf = channel.ReadOutbound <IByteBuffer>(); Assert.NotNull(buf); buf.Release(); Assert.Null(channel.ReadOutbound()); }
public override void ExceptionCaught(IChannelHandlerContext context, Exception cause) { Http2Exception e = Http2CodecUtil.GetEmbeddedHttp2Exception(cause); if (e != null) { self.clientException = e; self.clientLatch.SafeSignal(); } else { base.ExceptionCaught(context, cause); } }
public void FailedWhenWindowUpdateFrameWithZeroDelta() { var input = Unpooled.Buffer(); try { Http2CodecUtil.WriteFrameHeader(input, 4, Http2FrameTypes.WindowUpdate, new Http2Flags(), 0); input.WriteInt(0); Assert.Throws <Http2Exception>(() => frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object)); } finally { input.Release(); } }
private void WriteContinuationFrame(IByteBuffer output, int streamId, IHttp2Headers headers, Http2Flags flags) { IByteBuffer headerBlock = Unpooled.Buffer(); try { hpackEncoder.EncodeHeaders(streamId, headerBlock, headers, NeverSensitiveDetector.Instance); Http2CodecUtil.WriteFrameHeader(output, headerBlock.ReadableBytes, Http2FrameTypes.Continuation, flags, streamId); output.WriteBytes(headerBlock, headerBlock.ReadableBytes); } finally { headerBlock.Release(); } }
public void FailedWhenAckSettingsFrameWithPayload() { var input = Unpooled.Buffer(); try { Http2CodecUtil.WriteFrameHeader(input, 1, Http2FrameTypes.Settings, new Http2Flags().Ack(true), 0); input.WriteByte(1); Assert.Throws <Http2Exception>(() => frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object)); } finally { input.Release(); } }
public void ReadAckSettingsFrame() { var input = Unpooled.Buffer(); try { Http2CodecUtil.WriteFrameHeader(input, 0, Http2FrameTypes.Settings, new Http2Flags().Ack(true), 0); frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object); this.listener.Object.OnSettingsAckRead(this.ctx.Object); } finally { input.Release(); } }
public void FailedWhenSettingsFrameWithWrongPayloadLength() { var input = Unpooled.Buffer(); try { Http2CodecUtil.WriteFrameHeader(input, 8, Http2FrameTypes.Settings, new Http2Flags(), 0); input.WriteInt(Http2CodecUtil.SettingsMaxHeaderListSize); input.WriteInt(1024); Assert.Throws <Http2Exception>(() => frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object)); } finally { input.Release(); } }
[Fact]//(timeout = 5000) public async Task NewOutboundStream() { IHttp2FrameStream stream = _frameCodec.NewStream(); Assert.NotNull(stream); Assert.False(Http2CodecUtil.IsStreamIdValid(stream.Id)); var listenerExecuted = new TaskCompletionSource(); await _channel.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers(), false) { Stream = stream }); Assert.True(Http2CodecUtil.IsStreamIdValid(stream.Id)); var data = Unpooled.Buffer().WriteZero(100); await _channel.WriteAndFlushAsync(new DefaultHttp2DataFrame(data) { Stream = stream }); }
private void WriteHeaderFramePriorityPresent(IByteBuffer output, int streamId, IHttp2Headers headers, Http2Flags flags, int streamDependency, int weight) { IByteBuffer headerBlock = Unpooled.Buffer(); try { headerBlock.WriteInt(streamDependency); headerBlock.WriteByte(weight - 1); hpackEncoder.EncodeHeaders(streamId, headerBlock, headers, NeverSensitiveDetector.Instance); Http2CodecUtil.WriteFrameHeader(output, headerBlock.ReadableBytes, Http2FrameTypes.Headers, flags, streamId); output.WriteBytes(headerBlock, headerBlock.ReadableBytes); } finally { headerBlock.Release(); } }
private void SetUp(Http2FrameCodecBuilder frameCodecBuilder, Http2Settings initialRemoteSettings) { // Some tests call this method twice. Once with JUnit's @Before and once directly to pass special settings. // This call ensures that in case of two consecutive calls to setUp(), the previous channel is shutdown and // ByteBufs are released correctly. Dispose0(); _frameWriter = Http2TestUtil.MockedFrameWriter(); var builder = frameCodecBuilder.FrameWriter(_frameWriter.Object); builder.FrameLogger = new Http2FrameLogger(Common.Internal.Logging.InternalLogLevel.TRACE); builder.InitialSettings = initialRemoteSettings; _frameCodec = frameCodecBuilder.Build(); _inboundHandler = new LastInboundHandler(); _channel = new EmbeddedChannel(); _frameInboundWriter = new Http2FrameInboundWriter(_channel); //channel.Connect(new InetSocketAddress(0)); _channel.Pipeline.AddLast(_frameCodec); _channel.Pipeline.AddLast(_inboundHandler); _channel.Pipeline.FireChannelActive(); // Handshake _frameWriter.Verify( x => x.WriteSettingsAsync( It.Is <IChannelHandlerContext>(v => v == _frameCodec._ctx), It.IsAny <Http2Settings>(), It.IsAny <IPromise>())); _frameWriter.VerifyNoOtherCalls(); _channel.WriteInbound(Http2CodecUtil.ConnectionPrefaceBuf()); _frameInboundWriter.WriteInboundSettings(initialRemoteSettings); _frameWriter.Verify( x => x.WriteSettingsAckAsync( It.Is <IChannelHandlerContext>(v => v == _frameCodec._ctx), It.IsAny <IPromise>())); _frameInboundWriter.WriteInboundSettingsAck(); var settingsFrame = _inboundHandler.ReadInbound <IHttp2SettingsFrame>(); Assert.NotNull(settingsFrame); var settingsAckFrame = _inboundHandler.ReadInbound <IHttp2SettingsAckFrame>(); Assert.NotNull(settingsAckFrame); }
public void ReadSettingsFrame() { var input = Unpooled.Buffer(); try { Http2CodecUtil.WriteFrameHeader(input, 6, Http2FrameTypes.Settings, new Http2Flags(), 0); input.WriteShort(Http2CodecUtil.SettingsMaxHeaderListSize); input.WriteInt(1024); frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object); this.listener.Object.OnSettingsRead(this.ctx.Object, new Http2Settings().MaxHeaderListSize(1024)); } finally { input.Release(); } }
private void WriteHeaderFrameWithData(IByteBuffer output, int streamId, IHttp2Headers headers, IByteBuffer dataPayload) { IByteBuffer headerBlock = Unpooled.Buffer(); try { hpackEncoder.EncodeHeaders(streamId, headerBlock, headers, NeverSensitiveDetector.Instance); Http2CodecUtil.WriteFrameHeader(output, headerBlock.ReadableBytes, Http2FrameTypes.Headers, new Http2Flags().EndOfHeaders(true), streamId); output.WriteBytes(headerBlock, headerBlock.ReadableBytes); Http2CodecUtil.WriteFrameHeader(output, dataPayload.ReadableBytes, Http2FrameTypes.Data, new Http2Flags().EndOfStream(true), streamId); output.WriteBytes(dataPayload); } finally { headerBlock.Release(); } }
public void FailedWhenDataFrameNotAssociateWithStream() { var input = Unpooled.Buffer(); var payload = Unpooled.Buffer(); try { payload.WriteByte(1); Http2CodecUtil.WriteFrameHeader(input, payload.ReadableBytes, Http2FrameTypes.Data, new Http2Flags().EndOfStream(true), 0); input.WriteBytes(payload); Assert.Throws <Http2Exception>(() => frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object)); } finally { payload.Release(); input.Release(); } }
public void ReadUnknownFrame() { var input = Unpooled.Buffer(); var payload = Unpooled.Buffer(); try { payload.WriteByte(1); Http2CodecUtil.WriteFrameHeader(input, payload.ReadableBytes, (Http2FrameTypes)0xff, new Http2Flags(), 0); input.WriteBytes(payload); this.frameReader.ReadFrame(this.ctx.Object, input, this.listener.Object); this.listener.Verify(x => x.OnUnknownFrame(this.ctx.Object, (Http2FrameTypes)0xff, 0, new Http2Flags(), payload.Slice(0, 1))); } finally { payload.Release(); input.Release(); } }
public void ServerReceivingClientPrefaceStringFollowedByNonSettingsShouldHandleException() { _connection.Setup(x => x.IsServer).Returns(true); _handler = NewHandler(); // Create a connection preface followed by a bunch of zeros (i.e. not a settings frame). IByteBuffer buf = Unpooled.Buffer().WriteBytes(Http2CodecUtil.ConnectionPrefaceBuf()).WriteZero(10); _handler.ChannelRead(_ctx.Object, buf); var captor = new ArgumentCaptor <IByteBuffer>(); _frameWriter.Verify( x => x.WriteGoAwayAsync( It.Is <IChannelHandlerContext>(v => v == _ctx.Object), It.Is <int>(v => v == 0), It.Is <Http2Error>(v => v == Http2Error.ProtocolError), It.Is <IByteBuffer>(v => captor.Capture(v)), It.Is <IPromise>(v => v == _promise)), Times.AtLeastOnce); Assert.Equal(0, captor.GetValue().ReferenceCount); }
public void MultipleOutboundStreams() { IHttp2StreamChannel childChannel1 = this.NewOutboundStream(new TestChannelInitializer()); Assert.True(childChannel1.Active); Assert.False(Http2CodecUtil.IsStreamIdValid(childChannel1.Stream.Id)); IHttp2StreamChannel childChannel2 = this.NewOutboundStream(new TestChannelInitializer()); Assert.True(childChannel2.Active); Assert.False(Http2CodecUtil.IsStreamIdValid(childChannel2.Stream.Id)); IHttp2Headers headers1 = new DefaultHttp2Headers(); IHttp2Headers headers2 = new DefaultHttp2Headers(); // Test that streams can be made active (headers sent) in different order than the corresponding channels // have been created. childChannel2.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(headers2)); childChannel1.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(headers1)); IHttp2HeadersFrame headersFrame2 = serverLastInboundHandler.BlockingReadInbound <IHttp2HeadersFrame>(); Assert.NotNull(headersFrame2); Assert.Equal(3, headersFrame2.Stream.Id); IHttp2HeadersFrame headersFrame1 = serverLastInboundHandler.BlockingReadInbound <IHttp2HeadersFrame>(); Assert.NotNull(headersFrame1); Assert.Equal(5, headersFrame1.Stream.Id); Assert.Equal(3, childChannel2.Stream.Id); Assert.Equal(5, childChannel1.Stream.Id); childChannel1.CloseAsync(); childChannel2.CloseAsync(); serverLastInboundHandler.CheckException(); }
public void NewOutboundStreamsShouldBeBuffered() { var builder = Http2FrameCodecBuilder.ForServer(); builder.EncoderEnforceMaxConcurrentStreams = true; SetUp(builder, new Http2Settings().MaxConcurrentStreams(1)); var stream1 = _frameCodec.NewStream(); var stream2 = _frameCodec.NewStream(); var promise1 = _channel.NewPromise(); var promise2 = _channel.NewPromise(); _channel.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()) { Stream = stream1 }, promise1); _channel.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()) { Stream = stream2 }, promise2); Assert.True(Http2CodecUtil.IsStreamIdValid(stream1.Id)); _channel.RunPendingTasks(); Assert.True(Http2CodecUtil.IsStreamIdValid(stream2.Id)); Assert.True(promise1.IsSuccess); Assert.False(promise2.IsCompleted); // Increase concurrent streams limit to 2 _frameInboundWriter.WriteInboundSettings(new Http2Settings().MaxConcurrentStreams(2)); _channel.Flush(); Assert.True(promise2.IsSuccess); }
private static void WritePriorityFrame(IByteBuffer output, int streamId, int streamDependency, int weight) { Http2CodecUtil.WriteFrameHeader(output, 5, Http2FrameTypes.Priority, new Http2Flags(), streamId); output.WriteInt(streamDependency); output.WriteByte(weight - 1); }
public void MultipleNewOutboundStreamsShouldBeBuffered() { var builder = Http2FrameCodecBuilder.ForServer(); builder.EncoderEnforceMaxConcurrentStreams = true; // We use a limit of 1 and then increase it step by step. SetUp(builder, new Http2Settings().MaxConcurrentStreams(1)); IHttp2FrameStream stream1 = _frameCodec.NewStream(); IHttp2FrameStream stream2 = _frameCodec.NewStream(); IHttp2FrameStream stream3 = _frameCodec.NewStream(); IPromise promise1 = _channel.NewPromise(); IPromise promise2 = _channel.NewPromise(); IPromise promise3 = _channel.NewPromise(); _channel.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()) { Stream = stream1 }, promise1); _channel.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()) { Stream = stream2 }, promise2); _channel.WriteAndFlushAsync(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()) { Stream = stream3 }, promise3); Assert.True(Http2CodecUtil.IsStreamIdValid(stream1.Id)); _channel.RunPendingTasks(); Assert.True(Http2CodecUtil.IsStreamIdValid(stream2.Id)); if (promise1.IsCompleted) { Assert.True(promise1.Task.IsSuccess()); } else { try { promise1.Task.GetAwaiter().GetResult(); } catch (Exception) { Assert.False(true); } } Assert.False(promise2.IsCompleted); Assert.False(promise3.IsCompleted); // Increase concurrent streams limit to 2 _frameInboundWriter.WriteInboundSettings(new Http2Settings().MaxConcurrentStreams(2)); _channel.Flush(); // As we increased the limit to 2 we should have also succeed the second frame. if (promise2.IsCompleted) { Assert.True(promise2.Task.IsSuccess()); } else { try { promise2.Task.GetAwaiter().GetResult(); } catch (Exception) { Assert.False(true); } } Assert.False(promise3.IsCompleted); _frameInboundWriter.WriteInboundSettings(new Http2Settings().MaxConcurrentStreams(3)); _channel.Flush(); // With the max streams of 3 all streams should be succeed now. if (promise3.IsCompleted) { Assert.True(promise3.Task.IsSuccess()); } else { try { promise3.Task.GetAwaiter().GetResult(); } catch (Exception) { Assert.False(true); } } Assert.False(_channel.FinishAndReleaseAll()); }
public void ServerReceivingValidClientPrefaceStringShouldContinueReadingFrames() { _connection.Setup(x => x.IsServer).Returns(true); _handler = NewHandler(); IByteBuffer prefacePlusSome = AddSettingsHeader(Unpooled.Buffer().WriteBytes(Http2CodecUtil.ConnectionPrefaceBuf())); _handler.ChannelRead(_ctx.Object, prefacePlusSome); _decoder.Verify( x => x.DecodeFrame( It.Is <IChannelHandlerContext>(v => v == _ctx.Object), It.IsAny <IByteBuffer>(), It.IsAny <List <object> >()), Times.AtLeastOnce); }