public async Task ServerShouldCloseTheConnectionIfCorrectPrefaceIsNotReceived() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, inPipe, outPipe); var b = new byte[ClientPreface.Length]; // Initialize with non-preface data for (var i = 0; i < b.Length; i++) { b[i] = 10; } await inPipe.WriteAsync(new ArraySegment <byte>(b)); // Wait for the response - a settings frame is expected first // But as there's a race condition the connection could be closed // before or after the settings frame was fully received try { await outPipe.ReadAndDiscardSettings(); var hdrBuf = new byte[FrameHeader.HeaderSize + 50]; var header = await FrameHeader.ReceiveAsync(outPipe, hdrBuf); Assert.Equal(FrameType.GoAway, header.Type); } catch (Exception e) { Assert.IsType <System.IO.EndOfStreamException>(e); } }
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 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 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 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 ServerShouldCloseTheConnectionIfNoPrefaceIsSent( int nrDummyPrefaceData) { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, inPipe, outPipe); // Write some dummy data // All this data is not long enough to be a preface, so the // preface reception should time out if (nrDummyPrefaceData != 0) { var b = new byte[nrDummyPrefaceData]; for (var i = 0; i < b.Length; i++) { b[i] = 10; } await inPipe.WriteAsync(new ArraySegment <byte>(b)); } // Settings will be sent by connection before the preface is // checked - so they must be discarded await outPipe.ReadAndDiscardSettings(); // Wait for the stream to end within 400ms. // This is longer than the timeout in the connection waiting for the // preface var buf = new byte[1]; var readTask = outPipe.ReadAsync(new ArraySegment <byte>(buf)).AsTask(); var timeoutTask = Task.Delay(400); var finishedTask = await Task.WhenAny( new Task[] { readTask, timeoutTask }); if (ReferenceEquals(finishedTask, readTask)) { var res = readTask.Result; Assert.Equal(true, res.EndOfStream); Assert.Equal(0, res.BytesRead); // Received end of stream return; } Assert.True(false, "Expected connection to close outgoing stream. " + "Got timeout"); }
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 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 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 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 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(); }