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 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 ShouldErrorIfPrefaceWasNotReceivedUntilTimeout() { var timeout = 50; var pipe = new BufferedPipe(50); await Assert.ThrowsAsync <TimeoutException>( () => ClientPreface.ReadAsync(pipe, timeout).AsTask()); }
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 ShouldReadThePrefaceFromStream() { var buffer = new BufferReadStream(50, 50); Array.Copy(ClientPreface.Bytes, buffer.Buffer, ClientPreface.Length); buffer.Written = ClientPreface.Length; await ClientPreface.ReadAsync(buffer); }
public async Task ShouldErrorIfStreamEnds() { var buffer = new BufferReadStream(50, 50); Array.Copy(ClientPreface.Bytes, buffer.Buffer, ClientPreface.Length); buffer.Written = ClientPreface.Length - 1; // Miss one byte await Assert.ThrowsAsync <EndOfStreamException>( () => ClientPreface.ReadAsync(buffer).AsTask()); }
public async Task ShouldNotErrorIfPrefaceWasReceivedWithinTimeout() { var timeout = 200; var pipe = new BufferedPipe(50); var _ = Task.Run(async() => { await pipe.WriteAsync(new ArraySegment <byte>(ClientPreface.Bytes)); }); await ClientPreface.ReadAsync(pipe, timeout); }
public async Task ShouldWriteThePrefaceToStream() { var buffer = new BufferWriteStream(50); await ClientPreface.WriteAsync(buffer); Assert.Equal(ClientPreface.Length, buffer.Written); var pf = Encoding.ASCII.GetString(buffer.Buffer, 0, ClientPreface.Length); Assert.Equal(ClientPreface.String, pf); }
public async Task ShouldErrorIfStreamDoesNotContainPreface() { var buffer = new BufferReadStream(50, 50); Array.Copy(ClientPreface.Bytes, buffer.Buffer, ClientPreface.Length); buffer.Buffer[22] = (byte)'l'; buffer.Written = ClientPreface.Length; var ex = await Assert.ThrowsAsync <Exception>( () => ClientPreface.ReadAsync(buffer).AsTask()); Assert.Equal("Invalid prefix received", ex.Message); }
public async Task ShouldErrorIfStreamWasClosedWithinTimeout() { var timeout = 200; var pipe = new BufferedPipe(50); var _ = Task.Run(async() => { await Task.Delay(10); await pipe.CloseAsync(); }); var ex = await Assert.ThrowsAsync <AggregateException>( () => ClientPreface.ReadAsync(pipe, timeout).AsTask()); Assert.IsType <EndOfStreamException>(ex.InnerException); }
public async Task ConnectionShouldAcknowledgeValidSettings() { 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); await outPipe.ReadAndDiscardSettings(); await outPipe.AssertSettingsAck(); }
public async Task ConnectionShouldAcceptSettingsAckAndNotGoAway() { 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 await inPipe.WriteSettingsAck(); // And expect that no GoAway follows - which means a timeout happens on read await outPipe.AssertReadTimeout(); }
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 static async Task PerformHandshakes( this Connection connection, IBufferedPipe inputStream, IBufferedPipe outputStream, Settings?remoteSettings = null) { if (connection.IsServer) { await ClientPreface.WriteAsync(inputStream); } var rsettings = remoteSettings ?? Settings.Default; await inputStream.WriteSettings(rsettings); if (!connection.IsServer) { await outputStream.ReadAndDiscardPreface(); } await outputStream.ReadAndDiscardSettings(); await outputStream.AssertSettingsAck(); await inputStream.WriteSettingsAck(); }
public async Task ConnectionShouldIgnoreAndAcknowledgeUnknownSettings() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, Settings.Default, inPipe, outPipe); await ClientPreface.WriteAsync(inPipe); await outPipe.ReadAndDiscardSettings(); var settings = Settings.Default; // Create a buffer for normal settings plus 3 unknown ones var settingsBuffer = new byte[settings.RequiredSize + 18]; settings.EncodeInto(new ArraySegment <byte>( settingsBuffer, 0, settings.RequiredSize)); // Use some unknown settings IDs settingsBuffer[settings.RequiredSize] = 0; settingsBuffer[settings.RequiredSize + 1] = 10; settingsBuffer[settings.RequiredSize + 6] = 10; settingsBuffer[settings.RequiredSize + 7] = 20; settingsBuffer[settings.RequiredSize + 12] = 0xFF; settingsBuffer[settings.RequiredSize + 13] = 0xFF; var settingsHeader = new FrameHeader { Type = FrameType.Settings, StreamId = 0, Flags = 0, Length = settingsBuffer.Length, }; await inPipe.WriteFrameHeader(settingsHeader); await inPipe.WriteAsync(new ArraySegment <byte>(settingsBuffer)); // Check if the connection ACKs these settings await outPipe.AssertSettingsAck(); }