public async Task ConnectionShouldIgnoreResetsforUnknownStreams() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); Func <IStream, bool> listener = (s) => true; var conn = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider, listener); var hEncoder = new Encoder(); var streamId = 7u; await inPipe.WriteHeaders( hEncoder, streamId, false, TestHeaders.DefaultGetHeaders); await inPipe.WriteResetStream(streamId - 2, ErrorCode.RefusedStream); await inPipe.WriteResetStream(streamId - 4, ErrorCode.Cancel); // Send a ping afterwards // If we get a response the reset frame in between was ignored await inPipe.WritePing(new byte[8], false); await outPipe.ReadAndDiscardPong(); }
public async Task ResetsOnIdleStreamsShouldBeTreatedAsConnectionError( bool isServer, uint streamId) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); await inPipe.WriteResetStream(streamId, ErrorCode.RefusedStream); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); }
public async Task ConnectionShouldGoAwayOnInvalidResetStreamId( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); await inPipe.WriteResetStream(0, ErrorCode.Cancel); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task ReceivingResetShouldYieldAResetException() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var conn = await ConnectionUtils.BuildEstablishedConnection( false, inPipe, outPipe, loggerProvider); IStream stream = await conn.CreateStreamAsync(DefaultGetHeaders); await outPipe.ReadAndDiscardHeaders(1u, false); var readTask = stream.ReadWithTimeout(new ArraySegment <byte>(new byte[1])); await inPipe.WriteResetStream(1u, ErrorCode.Cancel); var ex = await Assert.ThrowsAsync <AggregateException>( () => readTask); Assert.IsType <StreamResetException>(ex.InnerException); Assert.Equal(StreamState.Reset, stream.State); }
public async Task BlockedWritesShouldUnblockOnExternalStreamReset() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); // Create a stream. It will have a flow control window of 64kb // for stream and connection var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Initiate response by sending and consuming headers await res.stream.WriteHeadersAsync( DefaultStatusHeaders, false); await outPipe.ReadAndDiscardHeaders(1u, false); // Start discarding all ougoing data -> Not needed for this test // and pipe may not be blocked var readTask = Task.Run(async() => { await outPipe.ReadAllToArrayWithTimeout(); }); // Write flow control window amount of data await res.stream.WriteWithTimeout(new ArraySegment <byte>(new byte[65535])); var resetTask = Task.Run(async() => { await Task.Delay(20); await inPipe.WriteResetStream(1u, ErrorCode.Cancel); }); // Write additional bytes. This should block and cause a streamreset // exception when the cancel arrives await Assert.ThrowsAsync <StreamResetException>(async() => { await res.stream.WriteAsync(new ArraySegment <byte>(new byte[1024])); }); }
public async Task IncomingStreamsAfterMaxConcurrentStreamsShouldBeRejected( int maxConcurrentStreams) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var acceptedStreams = new List<IStream>(); Func<IStream, bool> listener = (s) => { lock (acceptedStreams) { acceptedStreams.Add(s); } return true; }; var settings = Settings.Default; settings.MaxConcurrentStreams = (uint)maxConcurrentStreams; var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider, listener, localSettings: settings); var hEncoder = new Encoder(); // Open maxConcurrentStreams var streamId = 1u; for (var i = 0; i < maxConcurrentStreams; i++) { await inPipe.WriteHeaders(hEncoder, streamId, false, DefaultGetHeaders); streamId += 2; } // Assert no rejection and response so far await inPipe.WritePing(new byte[8], false); await outPipe.ReadAndDiscardPong(); lock (acceptedStreams) { Assert.Equal(maxConcurrentStreams, acceptedStreams.Count); } // Try to open an additional stream await inPipe.WriteHeaders(hEncoder, streamId, false, DefaultGetHeaders); // This one should be rejected await outPipe.AssertResetStreamReception(streamId, ErrorCode.RefusedStream); lock (acceptedStreams) { Assert.Equal(maxConcurrentStreams, acceptedStreams.Count); } // Once a stream is closed a new one should be acceptable await inPipe.WriteResetStream(streamId-2, ErrorCode.Cancel); streamId += 2; await inPipe.WriteHeaders(hEncoder, streamId, false, DefaultGetHeaders); // Assert no error response await inPipe.WritePing(new byte[8], false); await outPipe.ReadAndDiscardPong(); lock (acceptedStreams) { // +1 because the dead stream isn't removed Assert.Equal(maxConcurrentStreams+1, acceptedStreams.Count); // Check if the reset worked Assert.Equal( StreamState.Reset, acceptedStreams[acceptedStreams.Count-2].State); } }