protected override async Task QuicStreamServer(QuicConnection connection) { await using QuicStream stream = connection.OpenUnidirectionalStream(); await SendData(stream); stream.Shutdown(); await stream.ShutdownWriteCompleted(); }
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); }
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)); } }
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); }
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); } }
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)); }); }
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. } }
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); } }
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); }
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(); }); }
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); } }