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

            stream.Shutdown();
            await stream.ShutdownWriteCompleted();
        }
Example #2
0
        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);
        }
Example #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));
            }
        }
Example #4
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));
            });
        }
Example #5
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.
            }
        }
Example #6
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.ShutdownCompleted();
            },
                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.ShutdownCompleted();
            });
        }