Exemple #1
0
        public async Task CloseShouldUnblockReads()
        {
            var p      = new BufferedPipe(128);
            var input  = new byte[70];
            var output = new byte[50];

            for (var i = 0; i < 70; i++)
            {
                input[i] = (byte)i;
            }
            // Start read first
            var task = p.ReadAsync(new ArraySegment <byte>(output)).AsTask();
            // Schedule close
            var writeTask = Task.Run(async() =>
            {
                await Task.Delay(10);
                await p.CloseAsync();
            });
            // And wait for read to unblock
            var res = await task;

            Assert.Equal(true, res.EndOfStream);
            Assert.Equal(0, res.BytesRead);
            // The writeTask should also finish
            await writeTask;
        }
        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();
        }
Exemple #3
0
        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 ConnectionShouldCloseAndStreamsShouldGetResetWhenExternalCloseIsRequested()
        {
            // TODO: Add a variant of this test for clients as soon as they are supported
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Close the connection
            var closeTask = res.conn.CloseNow();
            // Expect end of stream
            await outPipe.AssertStreamEnd();

            // If the connection was successfully closed close the incoming data
            // stream, since this is expected from a bidirectional stream implementation
            await inPipe.CloseAsync();

            // Close should now be completed
            await closeTask;

            // The stream should be reset
            Assert.Equal(StreamState.Reset, res.stream.State);
            // Which also means that further writes/reads should fail
            await Assert.ThrowsAsync <StreamResetException>(async() =>
            {
                await res.stream.WriteHeadersAsync(
                    TestHeaders.DefaultStatusHeaders, true);
            });

            await Assert.ThrowsAsync <StreamResetException>(async() =>
            {
                await res.stream.ReadAllToArray();
            });
        }
        public async Task ReceivingDataDirectlyAfterInformationalHeadersShouldBeAnError()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Send informational headers to the client
            var infoHeaders = new HeaderField[]
            {
                new HeaderField {
                    Name = ":status", Value = "100"
                },
                new HeaderField {
                    Name = "extension-field", Value = "bar"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders);

            var recvdHeaders = await res.stream.ReadHeadersAsync();

            Assert.True(infoHeaders.SequenceEqual(recvdHeaders));

            // Try to send data
            await inPipe.WriteData(1u, 100, null, true);

            // Expect to receive an error
            await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError);

            Assert.Equal(StreamState.Reset, res.stream.State);

            await Assert.ThrowsAsync <StreamResetException>(
                () => res.stream.ReadHeadersAsync());
        }
Exemple #6
0
        public async Task ADataFrameOnAnUnknownStreamIdShouldTriggerAStreamReset(
            bool isServer, uint streamId)
        {
            // TODO: Add test cases for clients
            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);

            // Establish a high stream ID, which means all below are invalid
            var hEncoder        = new Encoder();
            var createdStreamId = 111u;

            if (!isServer)
            {
                throw new Exception("For clients the stream must be created from connection");
            }
            await inPipe.WriteHeaders(
                hEncoder, createdStreamId, false, DefaultGetHeaders);

            await inPipe.WriteData(streamId, 0);

            await outPipe.AssertResetStreamReception(streamId, ErrorCode.StreamClosed);
        }
        public async Task ConnectionShouldCloseAndSignalDoneWhenWritingToOutputFails(bool isServer)
        {
            var inPipe          = new BufferedPipe(1024);
            var outPipe         = new BufferedPipe(1024);
            var failableOutPipe = new FailingPipe(outPipe);
            var http2Con        = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, failableOutPipe, loggerProvider);

            // Make the next write attempt fail
            failableOutPipe.FailNextWrite = true;
            // Send something which triggers a response
            await inPipe.WritePing(new byte[8], false);

            // Wait for the connection to close the outgoing part
            await outPipe.AssertStreamEnd();

            Assert.True(failableOutPipe.CloseCalled);
            // If the connection was successfully closed close the incoming data
            // stream, since this is expected from a bidirectional stream implementation
            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");
        }
Exemple #8
0
        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();
        }
Exemple #9
0
        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();
        }
Exemple #10
0
        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();
        }
Exemple #11
0
        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();
        }
Exemple #12
0
        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();
        }
Exemple #13
0
        public void CreatingAConnectionWithInvalidUpgradeShouldThrow()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var config = new ConnectionConfigurationBuilder(true)
                         .UseStreamListener(s => false)
                         .Build();

            var builder = new ServerUpgradeRequestBuilder();

            builder.SetHeaders(DefaultGetHeaders.ToList());
            builder.SetHttp2Settings("!");
            var upgrade = builder.Build();

            Assert.False(upgrade.IsValid);

            var ex = Assert.Throws <ArgumentException>(() =>
            {
                var conn = new Connection(
                    config, inPipe, outPipe,
                    new Connection.Options
                {
                    Logger = loggerProvider.CreateLogger(""),
                    ServerUpgradeRequest = upgrade,
                });
            });

            Assert.Equal(
                "The ServerUpgradeRequest is invalid.\n" +
                "Invalid upgrade requests must be denied by the HTTP/1 handler",
                ex.Message);
        }
Exemple #14
0
        public async Task ReadsShouldUnblockWrites()
        {
            var p      = new BufferedPipe(70);
            var input  = new byte[70];
            var input2 = new byte[50];
            var output = new byte[60];

            for (var i = 0; i < 70; i++)
            {
                input[i] = (byte)i;
            }

            // Fill the complete buffer
            await p.WriteAsync(new ArraySegment <byte>(input));

            var writeMoreTask = p.WriteAsync(new ArraySegment <byte>(input2));
            // Read in the background to unblock
            var readTask = Task.Run(async() =>
            {
                await Task.Delay(10);
                return(await p.ReadAsync(new ArraySegment <byte>(output)).AsTask());
            });
            // The next line would deadlock without the reader in the background
            await writeMoreTask;
            var   res = await readTask;

            Assert.Equal(false, res.EndOfStream);
            Assert.Equal(60, res.BytesRead);
            for (var i = 0; i < 60; i++)
            {
                Assert.Equal(i, output[i]);
            }
        }
Exemple #15
0
        public async Task TrailersShouldBeCorrectlySent(bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            await r.stream.WriteAsync(new ArraySegment <byte>(new byte[0]));

            await outPipe.ReadAndDiscardData(1u, false, 0);

            // Send trailers
            await r.stream.WriteTrailersAsync(DefaultTrailingHeaders);

            // Check the received trailers
            var fh = await outPipe.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Headers, fh.Type);
            Assert.Equal(1u, fh.StreamId);
            var expectedFlags =
                HeadersFrameFlags.EndOfHeaders | HeadersFrameFlags.EndOfStream;

            Assert.Equal((byte)expectedFlags, fh.Flags);
            Assert.InRange(fh.Length, 1, 1024);
            var headerData = new byte[fh.Length];
            await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(headerData));

            Assert.Equal(EncodedDefaultTrailingHeaders, headerData);
        }
Exemple #16
0
        public async Task StreamWindowUpdatesShouldRespectBufferState()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            // Lower the initial window size so that stream window updates are
            // sent earlier than connection window updates
            var settings = Settings.Default;

            settings.InitialWindowSize = 16000;
            settings.MaxFrameSize      = 1000000;
            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe,
                localSettings : settings);

            // Write 12k of data. Buffer amount: 12k. Remaining window: 4k
            await inPipe.WriteData(1u, 12000);

            // Read 5k of data. Buffer amount: 7k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[5000]));

            // This should not trigger a window update
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // Read 5k of data. Buffer amount: 2k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[5000]));

            // Expect a window update of 10k. Remaining window: 14k
            await outPipe.AssertWindowUpdate(1u, 10000);

            // Read 2k of data - buffer is now drained
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[2000]));

            // This should not trigger a window update
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // Write 4k of data. Buffer amount: 4k. Remaining window: 10k
            await inPipe.WriteData(1u, 4000);

            // Read 4k of data. Buffer amount: 0k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[4000]));

            // This should not trigger a window update
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // Write 8k of data. Buffer amount: 8k. Remaining window: 2k
            await inPipe.WriteData(1u, 8000);

            // Read 5k of data. Buffer amount: 3k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[5000]));

            // Expect a window update of 11k. Remaining window: 13k
            await outPipe.AssertWindowUpdate(1u, 11000);
        }
Exemple #17
0
        public async Task OutgoingDataShouldRespectMaxFrameSize(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            var dataSize  = Settings.Default.MaxFrameSize + 10;
            var writeTask = Task.Run(async() =>
            {
                var data = new byte[dataSize];
                await r.stream.WriteAsync(new ArraySegment <byte>(data), true);
            });

            // Expect to receive the data in fragments
            await outPipe.ReadAndDiscardData(1u, false, (int)Settings.Default.MaxFrameSize);

            await outPipe.ReadAndDiscardData(1u, true, 10);

            var doneTask = await Task.WhenAny(writeTask, Task.Delay(250));

            Assert.True(writeTask == doneTask, "Expected write task to finish");
        }
Exemple #18
0
        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 SendingInvalidTrailersShouldTriggerAStreamReset()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var headers = new HeaderField[]
            {
                new HeaderField {
                    Name = ":method", Value = "GET"
                },
                new HeaderField {
                    Name = ":scheme", Value = "http"
                },
                new HeaderField {
                    Name = ":path", Value = "/"
                },
            };
            var trailers = new HeaderField[]
            {
                new HeaderField {
                    Name = ":method", Value = "GET"
                },
            };

            Func <IStream, bool> listener = (s) => true;
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, listener);

            var hEncoder = new Encoder();
            await inPipe.WriteHeaders(hEncoder, 1, false, headers);

            await inPipe.WriteHeaders(hEncoder, 1, true, trailers);

            await outPipe.AssertResetStreamReception(1, ErrorCode.ProtocolError);
        }
Exemple #20
0
        public async Task PingAsyncShouldSendPingAndWaitForAssociatedAck()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider);

            // Request ping
            var pingTask = http2Con.PingAsync();
            // Expect ping emission
            var fh = await outPipe.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Ping, fh.Type);
            Assert.Equal(8, fh.Length);
            Assert.Equal(0, fh.Flags);
            Assert.Equal(0u, fh.StreamId);
            var pingData = new ArraySegment <byte>(new byte[8]);
            await outPipe.ReadAllWithTimeout(pingData);

            // Respond with pong
            fh.Flags = (byte)PingFrameFlags.Ack;
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(pingData);

            // Await ping task to finish
            Assert.True(
                pingTask == await Task.WhenAny(pingTask, Task.Delay(200)),
                "Expected pingTask to finish");
        }
        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");
        }
Exemple #22
0
        public async Task ConnectionShouldRespondToPingWithPong(bool isServer)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            var pingData = new byte[8];

            for (var i = 0; i < pingData.Length; i++)
            {
                pingData[i] = (byte)i;
            }
            await inPipe.WritePing(pingData, false);

            var res = await outPipe.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Ping, res.Type);
            Assert.Equal(0u, res.StreamId);
            Assert.Equal(8, res.Length);
            Assert.Equal((byte)PingFrameFlags.Ack, res.Flags);
            var pongData = new byte[8];
            await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(pongData));

            for (var i = 0; i < pingData.Length; i++)
            {
                Assert.Equal((byte)i, pongData[i]);
            }
        }
        public async Task ConnectionShouldCloseAndSignalDoneWhenReadingFromInputFails(bool isServer)
        {
            var inPipe         = new BufferedPipe(1024);
            var outPipe        = new BufferedPipe(1024);
            var failableInPipe = new FailingPipe(inPipe);
            var http2Con       = await ConnectionUtils.BuildEstablishedConnection(
                isServer, failableInPipe, outPipe, loggerProvider);

            // Make the next write attempt fail
            failableInPipe.FailNextRead = true;
            // Send something which triggers no response but will start a new read call
            await inPipe.WriteWindowUpdate(0, 128);

            // Wait for the connection to close the outgoing part
            await outPipe.AssertStreamEnd();

            // If the connection was successfully closed close the incoming data
            // stream, since this is expected from a bidirectional stream implementation
            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");
        }
Exemple #24
0
        public async Task PingShouldFailWhenConnectionIsClosedAfterPingStart()
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider);

            // Request ping
            var pingTask = http2Con.PingAsync();
            // Expect ping emission
            var fh = await outPipe.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Ping, fh.Type);
            Assert.Equal(8, fh.Length);
            Assert.Equal(0, fh.Flags);
            Assert.Equal(0u, fh.StreamId);
            var pingData = new ArraySegment <byte>(new byte[8]);
            await outPipe.ReadAllWithTimeout(pingData);

            // Close the connection
            await inPipe.CloseAsync();

            await outPipe.AssertStreamEnd();

            // Await ping to finish with exception
            var timeoutTask = Task.Delay(200);

            Assert.True(
                pingTask == await Task.WhenAny(pingTask, timeoutTask),
                "Expected pingTask to finish");
            await Assert.ThrowsAsync <ConnectionClosedException>(
                async() => await pingTask);
        }
        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 ShouldErrorIfPrefaceWasNotReceivedUntilTimeout()
 {
     var timeout = 50;
     var pipe    = new BufferedPipe(50);
     await Assert.ThrowsAsync <TimeoutException>(
         () => ClientPreface.ReadAsync(pipe, timeout).AsTask());
 }
Exemple #27
0
        public async Task RemoteGoAwayReasonShouldBeGettableFromTask(
            uint lastStreamId, ErrorCode errc, string debugString)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            var debugData = Encoding.ASCII.GetBytes(debugString);
            await inPipe.WriteGoAway(lastStreamId, errc, debugData);

            var readGoAwayTask = res.conn.RemoteGoAwayReason;

            Assert.True(
                readGoAwayTask == await Task.WhenAny(readGoAwayTask, Task.Delay(200)),
                "Expected to read GoAway data");

            var reason = await readGoAwayTask;

            Assert.Equal(lastStreamId, reason.LastStreamId);
            Assert.Equal(errc, reason.ErrorCode);
            Assert.Equal(debugString,
                         Encoding.ASCII.GetString(
                             reason.DebugData.Array,
                             reason.DebugData.Offset,
                             reason.DebugData.Count));
        }
Exemple #28
0
        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 ConnectionShouldIgnorePriorityData(
            bool isServer, uint streamId,
            uint streamDependency, bool isExclusive, byte weight)
        {
            var inPipe   = new BufferedPipe(1024);
            var outPipe  = new BufferedPipe(1024);
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                isServer, inPipe, outPipe, loggerProvider);

            var prioData = new PriorityData
            {
                StreamDependency            = streamDependency,
                StreamDependencyIsExclusive = isExclusive,
                Weight = weight,
            };
            await inPipe.WritePriority(streamId, prioData);

            // Send a ping afterwards
            // If we get a response the priority frame in between was ignored
            var pingData = new byte[8];

            for (var i = 0; i < 8; i++)
            {
                pingData[i] = (byte)i;
            }
            await inPipe.WritePing(pingData, false);

            await outPipe.ReadAndDiscardPong();
        }
        public async Task ReceivingHeadersOrDataOnAClosedStreamShouldTriggerAStreamReset(
            StreamState streamState,
            bool sendHeaders, bool sendData, bool sendTrailers)
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var localCloseDone = new SemaphoreSlim(0);

            var res = await StreamCreator.CreateConnectionAndStream(
                streamState, loggerProvider, inPipe, outPipe);

            if (sendHeaders)
            {
                await inPipe.WriteHeaders(res.hEncoder, 1, false, DefaultGetHeaders);
            }
            if (sendData)
            {
                await inPipe.WriteData(1u, 0);
            }
            if (sendTrailers)
            {
                await inPipe.WriteHeaders(res.hEncoder, 1, true, DefaultGetHeaders);
            }

            await outPipe.AssertResetStreamReception(1u, ErrorCode.StreamClosed);
            var expectedState =
                streamState == StreamState.Closed
                ? StreamState.Closed
                : StreamState.Reset;
            Assert.Equal(expectedState, res.stream.State);
        }