예제 #1
0
        protected override async Task QuicStreamServer(QuicConnection connection)
        {
            await using QuicStream stream = connection.OpenUnidirectionalStream();
            await SendData(stream);

            stream.Shutdown();
            await stream.ShutdownWriteCompleted();
        }
예제 #2
0
파일: Echo.cs 프로젝트: rzikm/master-thesis
        public static async Task <int> RunClient(IPEndPoint serverEp, CancellationToken token)
        {
            using var client = new QuicConnection(new QuicClientConnectionOptions
            {
                RemoteEndPoint = serverEp,
                ClientAuthenticationOptions = new SslClientAuthenticationOptions
                {
                    ApplicationProtocols = new List <SslApplicationProtocol>
                    {
                        new SslApplicationProtocol("echo") // same as used for server
                    }
                }
            });

            await client.ConnectAsync(token);

            try
            {
                await using QuicStream stream = client.OpenBidirectionalStream();

                // spawn a reader task to not let server be flow-control blocked
                _ = Task.Run(async() =>
                {
                    byte[] arr = new byte[4 * 1024];
                    int read;
                    while ((read = await stream.ReadAsync(arr, token)) > 0)
                    {
                        string s = Encoding.ASCII.GetString(arr, 0, read);
                        Console.WriteLine($"Received: {s}");
                    }
                });

                string line;
                while ((line = Console.ReadLine()) != null)
                {
                    // convert into ASCII byte array before sending
                    byte[] bytes = Encoding.ASCII.GetBytes(line);
                    await stream.WriteAsync(bytes, token);

                    // flush the stream to send the data immediately
                    await stream.FlushAsync(token);
                }

                // once all stdin is written, close the stream
                stream.Shutdown();

                // wait until the server receives all data
                await stream.ShutdownWriteCompleted(token);
            }
            finally
            {
                await client.CloseAsync(0, token);
            }

            return(0);
        }
예제 #3
0
        public async Task QuicStream_ReadWrite_Random_Success(int readSize, int writeSize)
        {
            byte[] testBuffer = new byte[8192];
            new Random().NextBytes(testBuffer);


            await Task.WhenAll(DoWrite(), DoRead());

            async Task DoWrite()
            {
                using QuicConnection clientConnection = CreateQuicConnection(DefaultListener.ListenEndPoint);
                await clientConnection.ConnectAsync();

                await using QuicStream clientStream = clientConnection.OpenUnidirectionalStream();

                ReadOnlyMemory <byte> sendBuffer = testBuffer;

                while (sendBuffer.Length != 0)
                {
                    ReadOnlyMemory <byte> chunk = sendBuffer.Slice(0, Math.Min(sendBuffer.Length, writeSize));
                    await clientStream.WriteAsync(chunk);

                    sendBuffer = sendBuffer.Slice(chunk.Length);
                }

                clientStream.Shutdown();
                await clientStream.ShutdownWriteCompleted();
            }

            async Task DoRead()
            {
                using QuicConnection serverConnection = await DefaultListener.AcceptConnectionAsync();

                await using QuicStream serverStream = await serverConnection.AcceptStreamAsync();

                byte[] receiveBuffer  = new byte[testBuffer.Length];
                int    totalBytesRead = 0;

                while (totalBytesRead != receiveBuffer.Length)
                {
                    int bytesRead = await serverStream.ReadAsync(receiveBuffer.AsMemory(totalBytesRead, Math.Min(receiveBuffer.Length - totalBytesRead, readSize)));

                    if (bytesRead == 0)
                    {
                        break;
                    }

                    totalBytesRead += bytesRead;
                }

                Assert.True(receiveBuffer.AsSpan().SequenceEqual(testBuffer));
            }
        }
예제 #4
0
        private static async Task SendAndReceiveEOFAsync(QuicStream s1, QuicStream s2)
        {
            byte[] readBuffer = new byte[1];

            await s1.WriteAsync(Memory <byte> .Empty, endStream : true);

            await s1.ShutdownWriteCompleted();

            int bytesRead = await s2.ReadAsync(readBuffer);

            Assert.Equal(0, bytesRead);

            // Another read should still give EOF
            bytesRead = await s2.ReadAsync(readBuffer);

            Assert.Equal(0, bytesRead);
        }
예제 #5
0
        public async Task BasicTest()
        {
            using QuicListener listener = CreateQuicListener();

            for (int i = 0; i < 100; i++)
            {
                Task listenTask = Task.Run(async() =>
                {
                    using QuicConnection connection = await listener.AcceptConnectionAsync();
                    await using QuicStream stream   = await connection.AcceptStreamAsync();

                    byte[] buffer = new byte[s_data.Length];
                    int bytesRead = await stream.ReadAsync(buffer);

                    Assert.Equal(s_data.Length, bytesRead);
                    Assert.True(s_data.Span.SequenceEqual(buffer));

                    await stream.WriteAsync(s_data, endStream: true);
                    await stream.ShutdownWriteCompleted();

                    await connection.CloseAsync(errorCode: 0);
                });

                Task clientTask = Task.Run(async() =>
                {
                    using QuicConnection connection = CreateQuicConnection(listener.ListenEndPoint);
                    await connection.ConnectAsync();
                    await using QuicStream stream = connection.OpenBidirectionalStream();

                    await stream.WriteAsync(s_data, endStream: true);

                    byte[] memory = new byte[12];
                    int bytesRead = await stream.ReadAsync(memory);

                    Assert.Equal(s_data.Length, bytesRead);
                    // TODO this failed once...
                    Assert.True(s_data.Span.SequenceEqual(memory));
                    await stream.ShutdownWriteCompleted();

                    await connection.CloseAsync(errorCode: 0);
                });

                await(new[] { listenTask, clientTask }).WhenAllOrAnyFailed(millisecondsTimeout: 10000);
            }
        }
예제 #6
0
        public async Task ReadWrite_Random_Success(int readSize, int writeSize)
        {
            byte[] testBuffer = new byte[8192];
            new Random().NextBytes(testBuffer);

            await RunClientServer(
                async clientConnection =>
            {
                await using QuicStream clientStream = clientConnection.OpenUnidirectionalStream();

                ReadOnlyMemory <byte> sendBuffer = testBuffer;
                while (sendBuffer.Length != 0)
                {
                    ReadOnlyMemory <byte> chunk = sendBuffer.Slice(0, Math.Min(sendBuffer.Length, writeSize));
                    await clientStream.WriteAsync(chunk);
                    sendBuffer = sendBuffer.Slice(chunk.Length);
                }

                clientStream.Shutdown();
                await clientStream.ShutdownWriteCompleted();
            },
                async serverConnection =>
            {
                await using QuicStream serverStream = await serverConnection.AcceptStreamAsync();

                byte[] receiveBuffer = new byte[testBuffer.Length];
                int totalBytesRead   = 0;

                while (totalBytesRead != receiveBuffer.Length)
                {
                    int bytesRead = await serverStream.ReadAsync(receiveBuffer.AsMemory(totalBytesRead, Math.Min(receiveBuffer.Length - totalBytesRead, readSize)));

                    if (bytesRead == 0)
                    {
                        break;
                    }

                    totalBytesRead += bytesRead;
                }

                Assert.True(receiveBuffer.AsSpan().SequenceEqual(testBuffer));
            });
        }
예제 #7
0
        private async ValueTask ShutdownWrite(Exception?shutdownReason)
        {
            try
            {
                lock (_shutdownLock)
                {
                    _shutdownReason = shutdownReason ?? new ConnectionAbortedException("The Quic transport's send loop completed gracefully.");

                    _log.StreamShutdownWrite(ConnectionId, _shutdownReason);
                    _stream.Shutdown();
                }

                await _stream.ShutdownWriteCompleted();
            }
            catch (Exception ex)
            {
                _log.LogWarning(ex, "Stream failed to gracefully shutdown.");
                // Ignore any errors from Shutdown() since we're tearing down the stream anyway.
            }
        }
예제 #8
0
        public async Task MultipleReadsAndWrites()
        {
            for (int j = 0; j < 100; j++)
            {
                Task listenTask = Task.Run(async() =>
                {
                    // Connection isn't being accepted, interesting.
                    using QuicConnection connection = await DefaultListener.AcceptConnectionAsync();
                    await using QuicStream stream   = await connection.AcceptStreamAsync();
                    byte[] buffer = new byte[s_data.Length];

                    while (true)
                    {
                        int bytesRead = await stream.ReadAsync(buffer);
                        if (bytesRead == 0)
                        {
                            break;
                        }
                        Assert.Equal(s_data.Length, bytesRead);
                        Assert.True(s_data.Span.SequenceEqual(buffer));
                    }

                    for (int i = 0; i < 5; i++)
                    {
                        await stream.WriteAsync(s_data);
                    }
                    await stream.WriteAsync(Memory <byte> .Empty, endStream: true);
                    await stream.ShutdownWriteCompleted();
                    await connection.CloseAsync();
                });

                Task clientTask = Task.Run(async() =>
                {
                    using QuicConnection connection = CreateQuicConnection(DefaultListener.ListenEndPoint);
                    await connection.ConnectAsync();
                    await using QuicStream stream = connection.OpenBidirectionalStream();

                    for (int i = 0; i < 5; i++)
                    {
                        await stream.WriteAsync(s_data);
                    }

                    await stream.WriteAsync(Memory <byte> .Empty, endStream: true);

                    byte[] memory = new byte[12];
                    while (true)
                    {
                        int res = await stream.ReadAsync(memory);
                        if (res == 0)
                        {
                            break;
                        }
                        Assert.True(s_data.Span.SequenceEqual(memory));
                    }

                    await stream.ShutdownWriteCompleted();
                    await connection.CloseAsync();
                });

                await(new[] { listenTask, clientTask }).WhenAllOrAnyFailed(millisecondsTimeout: 1000000);
            }
        }
예제 #9
0
        public async Task MultipleStreamsOnSingleConnection()
        {
            Task listenTask = Task.Run(async() =>
            {
                {
                    using QuicConnection connection = await DefaultListener.AcceptConnectionAsync();
                    await using QuicStream stream   = await connection.AcceptStreamAsync();
                    await using QuicStream stream2  = await connection.AcceptStreamAsync();

                    byte[] buffer = new byte[s_data.Length];

                    while (true)
                    {
                        int bytesRead = await stream.ReadAsync(buffer);
                        if (bytesRead == 0)
                        {
                            break;
                        }
                        Assert.Equal(s_data.Length, bytesRead);
                        Assert.True(s_data.Span.SequenceEqual(buffer));
                    }

                    while (true)
                    {
                        int bytesRead = await stream2.ReadAsync(buffer);
                        if (bytesRead == 0)
                        {
                            break;
                        }
                        Assert.True(s_data.Span.SequenceEqual(buffer));
                    }

                    await stream.WriteAsync(s_data, endStream: true);
                    await stream.ShutdownWriteCompleted();

                    await stream2.WriteAsync(s_data, endStream: true);
                    await stream2.ShutdownWriteCompleted();

                    await connection.CloseAsync();
                }
            });

            Task clientTask = Task.Run(async() =>
            {
                using QuicConnection connection = CreateQuicConnection(DefaultListener.ListenEndPoint);
                await connection.ConnectAsync();
                await using QuicStream stream  = connection.OpenBidirectionalStream();
                await using QuicStream stream2 = connection.OpenBidirectionalStream();

                await stream.WriteAsync(s_data, endStream: true);
                await stream.ShutdownWriteCompleted();
                await stream2.WriteAsync(s_data, endStream: true);
                await stream2.ShutdownWriteCompleted();

                byte[] memory = new byte[12];
                while (true)
                {
                    int res = await stream.ReadAsync(memory);
                    if (res == 0)
                    {
                        break;
                    }
                    Assert.True(s_data.Span.SequenceEqual(memory));
                }

                while (true)
                {
                    int res = await stream2.ReadAsync(memory);
                    if (res == 0)
                    {
                        break;
                    }
                    Assert.True(s_data.Span.SequenceEqual(memory));
                }

                await connection.CloseAsync();
            });

            await(new[] { listenTask, clientTask }).WhenAllOrAnyFailed(millisecondsTimeout: 60000);
        }
예제 #10
0
        public async Task WriteTests(int[][] writes, WriteType writeType)
        {
            await RunClientServer(
                async clientConnection =>
            {
                await using QuicStream stream = clientConnection.OpenUnidirectionalStream();

                foreach (int[] bufferLengths in writes)
                {
                    switch (writeType)
                    {
                    case WriteType.SingleBuffer:
                        foreach (int bufferLength in bufferLengths)
                        {
                            await stream.WriteAsync(new byte[bufferLength]);
                        }
                        break;

                    case WriteType.GatheredBuffers:
                        var buffers = bufferLengths
                                      .Select(bufferLength => new ReadOnlyMemory <byte>(new byte[bufferLength]))
                                      .ToArray();
                        await stream.WriteAsync(buffers);
                        break;

                    case WriteType.GatheredSequence:
                        var firstSegment          = new BufferSegment(new byte[bufferLengths[0]]);
                        BufferSegment lastSegment = firstSegment;

                        foreach (int bufferLength in bufferLengths.Skip(1))
                        {
                            lastSegment = lastSegment.Append(new byte[bufferLength]);
                        }

                        var buffer = new ReadOnlySequence <byte>(firstSegment, 0, lastSegment, lastSegment.Memory.Length);
                        await stream.WriteAsync(buffer);
                        break;

                    default:
                        Debug.Fail("Unknown write type.");
                        break;
                    }
                }

                stream.Shutdown();
                await stream.ShutdownWriteCompleted();
            },
                async serverConnection =>
            {
                await using QuicStream stream = await serverConnection.AcceptStreamAsync();

                var buffer        = new byte[4096];
                int receivedBytes = 0, totalBytes = 0;

                while ((receivedBytes = await stream.ReadAsync(buffer)) != 0)
                {
                    totalBytes += receivedBytes;
                }

                int expectedTotalBytes = writes.SelectMany(x => x).Sum();
                Assert.Equal(expectedTotalBytes, totalBytes);

                stream.Shutdown();
                await stream.ShutdownWriteCompleted();
            });
        }
예제 #11
0
        public async Task LargeDataSentAndReceived()
        {
            byte[]    data           = Enumerable.Range(0, 64 * 1024).Select(x => (byte)x).ToArray();
            const int NumberOfWrites = 256;       // total sent = 16M

            using QuicListener listener = CreateQuicListener();

            for (int j = 0; j < 100; j++)
            {
                Task listenTask = Task.Run(async() =>
                {
                    using QuicConnection connection = await listener.AcceptConnectionAsync();
                    await using QuicStream stream   = await connection.AcceptStreamAsync();
                    byte[] buffer = new byte[data.Length];

                    for (int i = 0; i < NumberOfWrites; i++)
                    {
                        int totalBytesRead = 0;
                        while (totalBytesRead < data.Length)
                        {
                            int bytesRead = await stream.ReadAsync(buffer.AsMemory(totalBytesRead));
                            Assert.NotEqual(0, bytesRead);
                            totalBytesRead += bytesRead;
                        }

                        Assert.Equal(data.Length, totalBytesRead);
                        Assert.True(data.AsSpan().SequenceEqual(buffer));
                    }

                    for (int i = 0; i < NumberOfWrites; i++)
                    {
                        await stream.WriteAsync(data);
                    }

                    await stream.WriteAsync(Memory <byte> .Empty, endStream: true);

                    await stream.ShutdownWriteCompleted();
                    await connection.CloseAsync(errorCode: 0);
                });

                Task clientTask = Task.Run(async() =>
                {
                    using QuicConnection connection = CreateQuicConnection(listener.ListenEndPoint);
                    await connection.ConnectAsync();
                    await using QuicStream stream = connection.OpenBidirectionalStream();
                    byte[] buffer = new byte[data.Length];

                    for (int i = 0; i < NumberOfWrites; i++)
                    {
                        await stream.WriteAsync(data);
                    }

                    await stream.WriteAsync(Memory <byte> .Empty, endStream: true);

                    for (int i = 0; i < NumberOfWrites; i++)
                    {
                        int totalBytesRead = 0;
                        while (totalBytesRead < data.Length)
                        {
                            int bytesRead = await stream.ReadAsync(buffer.AsMemory(totalBytesRead));
                            Assert.NotEqual(0, bytesRead);
                            totalBytesRead += bytesRead;
                        }

                        Assert.Equal(data.Length, totalBytesRead);
                        Assert.True(data.AsSpan().SequenceEqual(buffer));
                    }

                    await stream.ShutdownWriteCompleted();
                    await connection.CloseAsync(errorCode: 0);
                });

                await(new[] { listenTask, clientTask }).WhenAllOrAnyFailed(millisecondsTimeout: 1000000);
            }
        }