public async Task ConnectionShouldGoAwayOnSettingsAckWithNonZeroLength( int frameLength) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); await inPipe.WriteSettings(Settings.Default); // Wait for remote settings await outPipe.ReadAndDiscardSettings(); // Wait for ack to our settings await outPipe.AssertSettingsAck(); var fh = new FrameHeader { Type = FrameType.Settings, Flags = (byte)SettingsFrameFlags.Ack, StreamId = 0, Length = frameLength, }; await inPipe.WriteFrameHeader(fh); // Wait for GoAway due to wrong stream ID await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task ShouldGoAwayWhenStreamWindowIsOverflowedThroughSettingsUpdate() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Let the remote increase the flow control window of the stream await inPipe.WriteWindowUpdate( 1u, (int)(int.MaxValue - Settings.Default.InitialWindowSize)); // Should be still alive await inPipe.WritePing(new byte[8], false); await outPipe.ReadAndDiscardPong(); // And now write new settings which overflow the window var newSettings = Settings.Default; newSettings.InitialWindowSize++; await inPipe.WriteSettings(newSettings); // Dead through overflow await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 1u); }
public async Task ConnectionShouldCloseAndSignalDoneInCaseOfAProtocolError(bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); // Cause a protocol error var fh = new FrameHeader { Type = FrameType.Data, StreamId = 0u, Flags = 0, Length = 0, }; await inPipe.WriteFrameHeader(fh); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); await outPipe.AssertStreamEnd(); await inPipe.CloseAsync(); // Expect the connection to close within timeout var closed = http2Con.Done; Assert.True( closed == await Task.WhenAny(closed, Task.Delay(1000)), "Expected connection to close"); }
public async Task ConnectionShouldGoAwayOnUnsolicitedSettingsAck() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); await inPipe.WriteSettings(Settings.Default); // Wait for remote settings await outPipe.ReadAndDiscardSettings(); // Wait for ack to our settings await outPipe.AssertSettingsAck(); // Acknowledge remote settings 2 times await inPipe.WriteSettingsAck(); await inPipe.WriteSettingsAck(); // Wait for GoAway due to multiple ACKs await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnInvalidWindowSizeSettingWithFlowControlError() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); var settings = Settings.Default; settings.InitialWindowSize = (uint)int.MaxValue + 1u; // Invalid var settingsData = new byte[settings.RequiredSize]; var fh = new FrameHeader { Type = FrameType.Settings, Length = settingsData.Length, Flags = 0, StreamId = 0, }; settings.EncodeInto(new ArraySegment <byte>(settingsData)); await inPipe.WriteFrameHeader(fh); await inPipe.WriteAsync(new ArraySegment <byte>(settingsData)); await outPipe.ReadAndDiscardSettings(); await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 0u); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnInvalidSettingsFrameLength() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); var settings = Settings.Default; var settingsData = new byte[settings.RequiredSize + 1]; // 1 byte extra var fh = new FrameHeader { Type = FrameType.Settings, Length = settingsData.Length, Flags = 0, StreamId = 0, }; settings.EncodeInto(new ArraySegment <byte>( settingsData, 0, settingsData.Length - 1)); await inPipe.WriteFrameHeader(fh); await inPipe.WriteAsync(new ArraySegment <byte>(settingsData)); await outPipe.ReadAndDiscardSettings(); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); await outPipe.AssertStreamEnd(); }
public async Task ClientShouldGoAwayIfFirstFrameIsNotSettings() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(false, Settings.Default, inPipe, outPipe); var fh = new FrameHeader { Type = FrameType.Headers, Length = 0, Flags = 0, StreamId = 2 }; await inPipe.WriteFrameHeader(fh); var expected = Settings.Default; expected.EnablePush = false; await outPipe.ReadAndDiscardPreface(); await outPipe.ReadAndDiscardSettings(); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnInvalidGoAwayFrameLength( bool isServer, int frameLength) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); var fh = new FrameHeader { Type = FrameType.GoAway, Flags = 0, Length = frameLength, StreamId = 0, }; await inPipe.WriteFrameHeader(fh); var expectedErr = frameLength > 65535 ? ErrorCode.FrameSizeError : ErrorCode.ProtocolError; await outPipe.AssertGoAwayReception(expectedErr, 0); await outPipe.AssertStreamEnd(); }
public async Task PaddingViolationsOnStreamsShouldLeadToGoAway( bool onKnownStream, int frameLength, byte?padData) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var r = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); var fh = new FrameHeader { Type = FrameType.Data, StreamId = onKnownStream ? 1u : 2u, Flags = (byte)DataFrameFlags.Padded, Length = frameLength, }; await inPipe.WriteFrameHeader(fh); if (frameLength > 0) { var data = new byte[frameLength]; data[0] = padData.Value; await inPipe.WriteAsync(new ArraySegment <byte>(data)); } await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1u); }
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 ADataFrameOnAnIdleStreamIdShouldTriggerAGoAway( bool isServer, uint streamId) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); Func <IStream, bool> listener = (s) => true; var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider, listener); await inPipe.WriteData(streamId, 0); await outPipe.AssertGoAwayReception(ErrorCode.StreamClosed, 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 ReceivingWindowUpdatesOnIdleStreamsShouldTriggerGoAway( uint streamId) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); await inPipe.WriteWindowUpdate(streamId, 0); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnPushPromiseWithInvalidLength( bool isServer, int?padLen) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); // This test is set up in a way where the payload length is 1 byte // too small for the transferred content var requiredLen = 4; var flags = (byte)PushPromiseFrameFlags.EndOfHeaders; if (padLen != null) { flags |= (byte)PushPromiseFrameFlags.Padded; requiredLen += 1 + padLen.Value; } var actualLen = requiredLen - 1; var fh = new FrameHeader { Type = FrameType.PushPromise, Flags = flags, Length = actualLen, StreamId = 1, }; await inPipe.WriteFrameHeader(fh); var content = new byte[actualLen]; var offset = 0; if (padLen != null) { content[offset] = (byte)padLen.Value; offset++; } // Set promised stream Id content[offset + 0] = content[offset + 1] = content[offset + 2] = 0; if (offset + 3 <= content.Length - 1) { content[offset + 3] = 1; } offset += 4; await inPipe.WriteAsync(new ArraySegment <byte>(content)); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task ShouldGoAwayWhenConnectionFlowControlWindowIsOverloaded( int amount) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider, null); await inPipe.WriteWindowUpdate(0, amount); await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 0); await outPipe.AssertStreamEnd(); }
public async Task ContinuationsWithoutHeadersShouldLeadToGoAway() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); Func <IStream, bool> listener = (s) => true; var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider, listener); var hEncoder = new Encoder(); await inPipe.WriteContinuation(hEncoder, 1u, DefaultGetHeaders, true); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task HeadersOnStreamId0ShouldTriggerAGoAway( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); Func <IStream, bool> listener = (s) => true; var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider, listener); var hEncoder = new Encoder(); await inPipe.WriteHeaders(hEncoder, 0, false, DefaultGetHeaders); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnPriorityStreamIdZero() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider); var prioData = new PriorityData { StreamDependency = 1, StreamDependencyIsExclusive = false, Weight = 0, }; await inPipe.WritePriority(0, prioData); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); await outPipe.AssertStreamEnd(); }
public async Task InCaseOfManualGoAwayAndConnectionErrorOnlyASingleGoAwayShouldBeSent() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Send the manual GoAway await res.conn.GoAwayAsync(ErrorCode.NoError, false); // Expect to read it await outPipe.AssertGoAwayReception(ErrorCode.NoError, 1u); // And force a connection error that should not yield a further GoAway await inPipe.WriteSettingsAck(); // Expect end of stream and not GoAway await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnInvalidPingFrameLength(int pingFrameLength) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider); var pingHeader = new FrameHeader { Type = FrameType.Ping, Flags = 0, Length = pingFrameLength, StreamId = 0, }; await inPipe.WriteFrameHeader(pingHeader); await outPipe.AssertGoAwayReception(ErrorCode.FrameSizeError, 0); await outPipe.AssertStreamEnd(); }
public async Task NewStreamsAfterGoAwayShouldBeRejected() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Start the GoAway process await res.conn.GoAwayAsync(ErrorCode.NoError, false); // Expect the GoAway message await outPipe.AssertGoAwayReception(ErrorCode.NoError, 1u); // Try to establish a new stream var hEncoder = new Http2.Hpack.Encoder(); await inPipe.WriteHeaders(hEncoder, 3, true, TestHeaders.DefaultGetHeaders); // Expect a stream rejection await outPipe.AssertResetStreamReception(3u, ErrorCode.RefusedStream); }
public async Task ConnectionShouldGoAwayOnPushPromiseWithInvalidStreamId( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); var fh = new FrameHeader { Type = FrameType.PushPromise, Flags = (byte)PushPromiseFrameFlags.EndOfHeaders, Length = 128, StreamId = 1, }; await inPipe.WriteFrameHeader(fh); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnInvalidResetStreamFrameLength( bool isServer, int resetFrameLength) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); var rstStreamHeader = new FrameHeader { Type = FrameType.ResetStream, Flags = 0, Length = resetFrameLength, StreamId = 1, }; await inPipe.WriteFrameHeader(rstStreamHeader); await outPipe.AssertGoAwayReception(ErrorCode.FrameSizeError, 0); await outPipe.AssertStreamEnd(); }
public async Task ReceivingWindowUpdatesWith0AmountShouldTriggerGoAwayOrReset( uint streamId) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); await inPipe.WriteWindowUpdate(streamId, 0); if (streamId == 0) { await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1); await outPipe.AssertStreamEnd(); } else { await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError); } }
public async Task ConnectionShouldGoAwayOnPushPromise( bool isServer, uint streamId, int payloadLength) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); var fh = new FrameHeader { Type = FrameType.PushPromise, Flags = 0, Length = payloadLength, StreamId = streamId, }; await inPipe.WriteFrameHeader(fh); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task ServersShouldGoAwayIfFirstFrameIsNotSettings() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); var fh = new FrameHeader { Type = FrameType.Headers, Length = 0, Flags = 0, StreamId = 2, }; await inPipe.WriteFrameHeader(fh); await outPipe.ReadAndDiscardSettings(); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnSettingsStreamIdNonZero() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); var fh = new FrameHeader { Type = FrameType.Settings, Length = Settings.Default.RequiredSize, Flags = 0, StreamId = 1, }; await inPipe.WriteFrameHeader(fh); await outPipe.ReadAndDiscardSettings(); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0u); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnInvalidSettingsMaxLengthExceeded() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); var fh = new FrameHeader { Type = FrameType.Settings, Length = (int)Settings.Default.MaxFrameSize + 1, Flags = 0, StreamId = 0, }; await inPipe.WriteFrameHeader(fh); await outPipe.ReadAndDiscardSettings(); await outPipe.AssertGoAwayReception(ErrorCode.FrameSizeError, 0u); await outPipe.AssertStreamEnd(); }
public async Task ConnectionShouldGoAwayOnInvalidGoAwayStreamId( bool isServer) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = await ConnectionUtils.BuildEstablishedConnection( isServer, inPipe, outPipe, loggerProvider); var goAwayData = new GoAwayFrameData { Reason = new GoAwayReason { LastStreamId = 0u, ErrorCode = ErrorCode.NoError, DebugData = new ArraySegment <byte>(new byte[0]), }, }; var fh = new FrameHeader { Type = FrameType.GoAway, Flags = 0, StreamId = 1, Length = goAwayData.RequiredSize, }; var dataBytes = new byte[goAwayData.RequiredSize]; goAwayData.EncodeInto(new ArraySegment <byte>(dataBytes)); await inPipe.WriteFrameHeader(fh); await inPipe.WriteAsync(new ArraySegment <byte>(dataBytes)); await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 0); await outPipe.AssertStreamEnd(); }
public async Task GoAwayShouldBeSendable(bool withConnectionClose) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, inPipe, outPipe); // Start the GoAway process in a background task. // As waiting for this will block the current task in case // of connection close var closeTask = Task.Run(() => res.conn.GoAwayAsync(ErrorCode.InternalError, withConnectionClose)); // Expect the GoAway message await outPipe.AssertGoAwayReception(ErrorCode.InternalError, 1u); if (withConnectionClose) { await outPipe.AssertStreamEnd(); await inPipe.CloseAsync(); } await closeTask; }