From b09e8526f5bbf2abc289be91fc6c4a11743ca43c Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Mon, 11 Sep 2023 17:30:53 +0200 Subject: [PATCH 1/2] Convert ManagedQuicStream to current API shape. --- .../Managed/ManagedQuicStream.cs | 185 +++++++++++------- 1 file changed, 109 insertions(+), 76 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs index 0f60f8407ca775..e30a3ec9775855 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs @@ -6,6 +6,7 @@ using System.Buffers; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Net.Quic.Implementations.Managed.Internal; using System.Net.Quic.Implementations.Managed.Internal.Streams; using System.Threading; @@ -13,7 +14,7 @@ namespace System.Net.Quic.Implementations.Managed { - public sealed class ManagedQuicStream + public sealed class ManagedQuicStream : Stream { /// /// Node to the linked list of all flushable streams. Should be accessed only by the class. @@ -62,7 +63,7 @@ internal ManagedQuicStream(long streamId, ReceiveStream? receiveStream, SendStre Debug.Assert(receiveStream != null || sendStream != null); Debug.Assert(StreamHelpers.IsBidirectional(streamId) == (receiveStream != null && sendStream != null)); - StreamId = streamId; + Id = streamId; ReceiveStream = receiveStream; SendStream = sendStream; _connection = connection; @@ -71,33 +72,60 @@ internal ManagedQuicStream(long streamId, ReceiveStream? receiveStream, SendStre _updateQueueListNode = new LinkedListNode(this); } - private async ValueTask WriteAsyncInternal(ReadOnlyMemory buffer, bool endStream, - CancellationToken cancellationToken) + #region Public API + public override bool CanRead => ReceiveStream != null; + public override bool CanWrite => SendStream != null; + public override bool CanSeek => false; + public override bool CanTimeout => false; + + public long Id { get; } + + public override long Length => throw new NotSupportedException(); + public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } + + public Task ReadClosed => throw new NotImplementedException(); + public override int ReadTimeout { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } + public Task WriteClosed => throw new NotImplementedException(); + public override int WriteTimeout { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } + + public void Abort(QuicAbortDirection abortDirection, long errorCode) { - await SendStream!.EnqueueAsync(buffer, cancellationToken).ConfigureAwait(false); + ThrowIfDisposed(); - if (endStream) + if ((abortDirection & QuicAbortDirection.Read) != 0) { - SendStream.MarkEndOfData(); - await SendStream.FlushChunkAsync(cancellationToken).ConfigureAwait(false); + AbortRead(errorCode); } - if (SendStream.WrittenBytes - buffer.Length < SendStream.MaxData) + if ((abortDirection & QuicAbortDirection.Write) != 0) { - _connection.OnStreamDataWritten(this); + AbortWrite(errorCode); } } - internal void NotifyShutdownWriteCompleted() + public void CompleteWrites() { - _shutdownCompleted.TryComplete(); + ThrowIfDisposed(); + ThrowIfConnectionError(); + + if (CanWrite) + { + SendStream!.MarkEndOfData(); + SendStream!.FlushChunk(); + _connection.OnStreamDataWritten(this); + } } - #region Public API - internal override long StreamId { get; } - internal override bool CanRead => ReceiveStream != null; + public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); + public override void SetLength(long value) => throw new NotSupportedException(); - internal override int Read(Span buffer) + public override int Read(byte[] buffer, int offset, int count) + { + ValidateBufferArguments(buffer, offset, count); + return Read(buffer.AsSpan(offset, count)); + } + + public override int Read(Span buffer) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -112,7 +140,7 @@ internal override int Read(Span buffer) return result; } - internal override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -127,7 +155,7 @@ internal override async ValueTask ReadAsync(Memory buffer, Cancellati return result; } - internal override void AbortRead(long errorCode) + internal void AbortRead(long errorCode) { ThrowIfDisposed(); ThrowIfNotReadable(); @@ -138,7 +166,7 @@ internal override void AbortRead(long errorCode) _connection.OnStreamStateUpdated(this); } - internal override void AbortWrite(long errorCode) + internal void AbortWrite(long errorCode) { ThrowIfDisposed(); ThrowIfNotWritable(); @@ -149,18 +177,15 @@ internal override void AbortWrite(long errorCode) _connection.OnStreamStateUpdated(this); } - internal override bool CanWrite => SendStream != null; - - internal override bool CanTimeout => throw new NotImplementedException(); - - internal override bool ReadsCompleted => throw new NotImplementedException(); - - internal override int ReadTimeout { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - internal override int WriteTimeout { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override void Write(byte[] buffer, int offset, int count) + { + ValidateBufferArguments(buffer, offset, count); + Write(buffer.AsSpan(offset, count)); + } - internal override void Write(ReadOnlySpan buffer) => Write(buffer, false); + public override void Write(ReadOnlySpan buffer) => Write(buffer, false); - internal void Write(ReadOnlySpan buffer, bool endStream) + public void Write(ReadOnlySpan buffer, bool endStream) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -179,12 +204,12 @@ internal void Write(ReadOnlySpan buffer, bool endStream) } } - internal override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { return WriteAsync(buffer, false, cancellationToken); } - internal override async ValueTask WriteAsync(ReadOnlyMemory buffer, bool endStream, CancellationToken cancellationToken = default) + public async ValueTask WriteAsync(ReadOnlyMemory buffer, bool endStream, CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -195,7 +220,7 @@ internal override async ValueTask WriteAsync(ReadOnlyMemory buffer, bool e await FlushAsync(cancellationToken).ConfigureAwait(false); } - internal override async ValueTask WriteAsync(ReadOnlySequence buffers, CancellationToken cancellationToken = default) + public async ValueTask WriteAsync(ReadOnlySequence buffers, CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -209,7 +234,7 @@ internal override async ValueTask WriteAsync(ReadOnlySequence buffers, Can await FlushAsync(cancellationToken).ConfigureAwait(false); } - internal override async ValueTask WriteAsync(ReadOnlySequence buffers, bool endStream, CancellationToken cancellationToken = default) + public async ValueTask WriteAsync(ReadOnlySequence buffers, bool endStream, CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -223,12 +248,12 @@ internal override async ValueTask WriteAsync(ReadOnlySequence buffers, boo await FlushAsync(cancellationToken).ConfigureAwait(false); } - internal override ValueTask WriteAsync(ReadOnlyMemory> buffers, CancellationToken cancellationToken = default) + public ValueTask WriteAsync(ReadOnlyMemory> buffers, CancellationToken cancellationToken = default) { return WriteAsync(buffers, false, cancellationToken); } - internal override async ValueTask WriteAsync(ReadOnlyMemory> buffers, bool endStream, CancellationToken cancellationToken = default) + public async ValueTask WriteAsync(ReadOnlyMemory> buffers, bool endStream, CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -242,7 +267,7 @@ internal override async ValueTask WriteAsync(ReadOnlyMemory await FlushAsync(cancellationToken).ConfigureAwait(false); } - internal override async ValueTask ShutdownCompleted(CancellationToken cancellationToken = default) + public async ValueTask ShutdownCompleted(CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -260,8 +285,7 @@ internal override async ValueTask ShutdownCompleted(CancellationToken cancellati await _shutdownCompleted.GetTask().ConfigureAwait(false); } - // TODO: - internal override ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default) + internal ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -280,40 +304,7 @@ internal async ValueTask WaitForStartAsync(CancellationToken cancellationToken) await _started.GetTask().ConfigureAwait(false); } - internal void NotifyStarted() - { - _started.TryComplete(); - } - - internal void OnFatalException(Exception exception) - { - ReceiveStream?.OnFatalException(exception); - SendStream?.OnFatalException(exception); - } - - internal void OnConnectionClosed(QuicException exception) - { - // closing connection (CONNECTION_CLOSE frame) causes all streams to become closed - NotifyShutdownWriteCompleted(); - - _started.TryCompleteException(exception); - OnFatalException(exception); - } - - internal override void Shutdown() - { - ThrowIfDisposed(); - ThrowIfConnectionError(); - - if (CanWrite) - { - SendStream!.MarkEndOfData(); - SendStream!.FlushChunk(); - _connection.OnStreamDataWritten(this); - } - } - - internal override void Flush() + public override void Flush() { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -323,7 +314,7 @@ internal override void Flush() _connection.OnStreamDataWritten(this); } - internal override async Task FlushAsync(CancellationToken cancellationToken) + public override async Task FlushAsync(CancellationToken cancellationToken) { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -333,9 +324,9 @@ internal override async Task FlushAsync(CancellationToken cancellationToken) _connection.OnStreamDataWritten(this); } - public override void Dispose() + protected override void Dispose(bool disposing) { - if (_disposed) + if (_disposed || !disposing) { return; } @@ -382,6 +373,48 @@ public override async ValueTask DisposeAsync() #endregion + private async ValueTask WriteAsyncInternal(ReadOnlyMemory buffer, bool endStream, + CancellationToken cancellationToken) + { + await SendStream!.EnqueueAsync(buffer, cancellationToken).ConfigureAwait(false); + + if (endStream) + { + SendStream.MarkEndOfData(); + await SendStream.FlushChunkAsync(cancellationToken).ConfigureAwait(false); + } + + if (SendStream.WrittenBytes - buffer.Length < SendStream.MaxData) + { + _connection.OnStreamDataWritten(this); + } + } + + internal void NotifyShutdownWriteCompleted() + { + _shutdownCompleted.TryComplete(); + } + + internal void NotifyStarted() + { + _started.TryComplete(); + } + + internal void OnFatalException(Exception exception) + { + ReceiveStream?.OnFatalException(exception); + SendStream?.OnFatalException(exception); + } + + internal void OnConnectionClosed(QuicException exception) + { + // closing connection (CONNECTION_CLOSE frame) causes all streams to become closed + NotifyShutdownWriteCompleted(); + + _started.TryCompleteException(exception); + OnFatalException(exception); + } + private void ThrowIfDisposed() { if (_disposed) @@ -411,7 +444,7 @@ private void ThrowIfNotReadable() // ReceiveStream not null is implied by CanRead if (ReceiveStream!.Error != null) { - throw new QuicStreamAbortedException("Reading was aborted on the stream", ReceiveStream.Error.Value); + throw new QuicException(QuicError.StreamAborted, ReceiveStream.Error.Value, "Reading was aborted on the stream"); } } From b4760fbd4e0ba2dc2337e481d7c4d87fb000317f Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Mon, 11 Sep 2023 17:52:11 +0200 Subject: [PATCH 2/2] More error fixes --- .../Managed/Internal/Streams/ReceiveStream.cs | 4 +- .../Managed/Internal/Streams/SendStream.cs | 2 +- .../Managed/Internal/TransportParameters.cs | 2 +- .../Managed/ManagedQuicConnection.Frames.cs | 58 +++++++++---------- .../Managed/ManagedQuicConnection.Packets.cs | 8 +-- .../Managed/ManagedQuicConnection.cs | 12 ++-- .../Managed/ManagedQuicStream.cs | 5 +- .../{QuicError.cs => QuicTransportError.cs} | 4 +- 8 files changed, 46 insertions(+), 49 deletions(-) rename src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/{QuicError.cs => QuicTransportError.cs} (93%) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/ReceiveStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/ReceiveStream.cs index 5653b0219fdf3a..1f239d6db4c9d1 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/ReceiveStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/ReceiveStream.cs @@ -483,8 +483,8 @@ internal void DropAllBufferedData() private void SetStreamAborted(long errorCode, bool byUs) { _deliverableChannel.Writer.TryComplete(byUs - ? new QuicOperationAbortedException() - : new QuicStreamAbortedException(errorCode)); + ? new QuicException(QuicError.OperationAborted, null, "Stream aborted by us.") + : new QuicException(QuicError.StreamAborted, errorCode)); } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/SendStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/SendStream.cs index a18c50eccf5b04..0f9fbba513f4a5 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/SendStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/Streams/SendStream.cs @@ -164,7 +164,7 @@ internal void RequestAbort(long errorCode, bool byUs) StreamState = SendStreamState.WantReset; } - _writesCompleted.TryCompleteException(new QuicOperationAbortedException("Write was aborted.")); + _writesCompleted.TryCompleteException(new QuicException(QuicError.OperationAborted, null, "Write was aborted.")); _toSendChannel.Writer.TryComplete(); if (_toBeQueuedChunk.Buffer != null) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/TransportParameters.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/TransportParameters.cs index b28a6d45fe36b2..f4ae0c86da1a20 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/TransportParameters.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/Internal/TransportParameters.cs @@ -49,7 +49,7 @@ private static TransportParameters Create(long maxBidiStreams, long maxUniStream internal static TransportParameters FromConnectionOptions(QuicConnectionOptions options) { - return Create(options.MaxBidirectionalStreams, options.MaxUnidirectionalStreams, options.IdleTimeout); + return Create(options.MaxInboundBidirectionalStreams, options.MaxInboundUnidirectionalStreams, options.IdleTimeout); } /// diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Frames.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Frames.cs index 9f21d094ff75d8..dc87bed6618d04 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Frames.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Frames.cs @@ -100,7 +100,7 @@ private ProcessPacketResult ProcessFrames(QuicReader reader, PacketType packetTy if (!IsFrameAllowed(frameType, packetType)) { - return CloseConnection(TransportErrorCode.ProtocolViolation, QuicError.FrameNotAllowed, frameType); + return CloseConnection(TransportErrorCode.ProtocolViolation, QuicTransportError.FrameNotAllowed, frameType); } ackEliciting |= IsAckEliciting(frameType); @@ -140,7 +140,7 @@ _ when (frameType & FrameType.StreamMask) == frameType => ProcessStreamFrame(rea continue; case ProcessPacketResult.Error when _outboundError == null: return CloseConnection(TransportErrorCode.FrameEncodingError, - QuicError.UnableToDeserialize, frameType); + QuicTransportError.UnableToDeserialize, frameType); } return result; @@ -231,7 +231,7 @@ private ProcessPacketResult ProcessAckFrame(QuicReader reader, PacketType packet if (frame.LargestAcknowledged >= pnSpace.NextPacketNumber || // acking future packet frame.LargestAcknowledged < frame.FirstAckRange) // acking negative PN - return CloseConnection(TransportErrorCode.ProtocolViolation, QuicError.InvalidAckRange, FrameType.Ack); + return CloseConnection(TransportErrorCode.ProtocolViolation, QuicTransportError.InvalidAckRange, FrameType.Ack); Span ranges = frame.AckRangeCount < 16 ? stackalloc RangeSet.Range[(int)frame.AckRangeCount + 1] @@ -240,7 +240,7 @@ private ProcessPacketResult ProcessAckFrame(QuicReader reader, PacketType packet if (!frame.TryDecodeAckRanges(ranges)) { return CloseConnection(TransportErrorCode.FrameEncodingError, - QuicError.InvalidAckRange, frame.HasEcnCounts ? FrameType.AckWithEcn : FrameType.Ack); + QuicTransportError.InvalidAckRange, frame.HasEcnCounts ? FrameType.AckWithEcn : FrameType.Ack); } var space = GetPacketSpace(packetType); @@ -267,12 +267,12 @@ private ProcessPacketResult ProcessResetStreamFrame(QuicReader reader) if (!StreamHelpers.CanRead(IsServer, frame.StreamId)) return CloseConnection(TransportErrorCode.StreamStateError, - QuicError.StreamNotReadable, + QuicTransportError.StreamNotReadable, FrameType.ResetStream); if (!TryGetOrCreateStream(frame.StreamId, out var stream)) return CloseConnection(TransportErrorCode.StreamLimitError, - QuicError.StreamsLimitViolated, + QuicTransportError.StreamsLimitViolated, FrameType.ResetStream); // TODO-RZ: Return control flow budget @@ -294,7 +294,7 @@ private ProcessPacketResult ProcessStopSendingFrame(QuicReader reader) if (!StreamHelpers.CanWrite(IsServer, frame.StreamId)) return CloseConnection(TransportErrorCode.StreamStateError, - QuicError.StreamNotWritable, + QuicTransportError.StreamNotWritable, FrameType.StopSending); var stream = _streams.TryGetStream(frame.StreamId); @@ -304,12 +304,12 @@ private ProcessPacketResult ProcessStopSendingFrame(QuicReader reader) // Streams are Created by sending a STREAM frame, if we didn't send anything, report error !(stream?.SendStream?.UnsentOffset > 0)) return CloseConnection(TransportErrorCode.StreamStateError, - QuicError.StreamNotCreated, + QuicTransportError.StreamNotCreated, FrameType.StopSending); if (stream == null && !TryGetOrCreateStream(frame.StreamId, out stream)) return CloseConnection(TransportErrorCode.StreamLimitError, - QuicError.StreamsLimitViolated, + QuicTransportError.StreamsLimitViolated, FrameType.StopSending); Debug.Assert(stream!.CanWrite); @@ -377,11 +377,11 @@ private ProcessPacketResult ProcessMaxStreamDataFrame(QuicReader reader) if (!StreamHelpers.CanWrite(IsServer, frame.StreamId)) return CloseConnection(TransportErrorCode.StreamStateError, - QuicError.NotInRecvState, FrameType.MaxStreamData); + QuicTransportError.NotInRecvState, FrameType.MaxStreamData); if (!TryGetOrCreateStream(frame.StreamId, out var stream)) return CloseConnection(TransportErrorCode.StreamLimitError, - QuicError.StreamsLimitViolated, FrameType.MaxStreamData); + QuicTransportError.StreamsLimitViolated, FrameType.MaxStreamData); Debug.Assert(stream!.CanWrite); @@ -460,7 +460,7 @@ private ProcessPacketResult ProcessStreamDataBlockedFrame(QuicReader reader) if (!TryGetOrCreateStream(frame.StreamId, out _)) return CloseConnection(TransportErrorCode.StreamLimitError, - QuicError.StreamsLimitViolated, + QuicTransportError.StreamsLimitViolated, FrameType.StreamDataBlocked); // TODO-RZ: Implement STREAM_DATA_BLOCKED @@ -492,7 +492,7 @@ private ProcessPacketResult ProcessNewConnectionIdFrame(QuicReader reader) if (DestinationConnectionId!.Data.Length == 0) { return CloseConnection(TransportErrorCode.ProtocolViolation, - QuicError.NewConnectionIdFrameWhenZeroLengthCIDUsed, FrameType.NewConnectionId); + QuicTransportError.NewConnectionIdFrameWhenZeroLengthCIDUsed, FrameType.NewConnectionId); } // RFC: If an endpoint receives a NEW_CONNECTION_ID frame that repeats a @@ -507,7 +507,7 @@ private ProcessPacketResult ProcessNewConnectionIdFrame(QuicReader reader) existingCid != null && existingCid.StatelessResetToken != frame.StatelessResetToken) { return CloseConnection(TransportErrorCode.ProtocolViolation, - QuicError.InconsistentNewConnectionIdFrame, FrameType.NewConnectionId); + QuicTransportError.InconsistentNewConnectionIdFrame, FrameType.NewConnectionId); } if (existingCid == null) @@ -614,12 +614,12 @@ private ProcessPacketResult ProcessStreamFrame(QuicReader reader) if (!StreamHelpers.CanRead(IsServer, frame.StreamId)) return CloseConnection(TransportErrorCode.StreamStateError, - QuicError.StreamNotWritable, + QuicTransportError.StreamNotWritable, frameType); if (!TryGetOrCreateStream(frame.StreamId, out var stream)) return CloseConnection(TransportErrorCode.StreamLimitError, - QuicError.StreamsLimitViolated, + QuicTransportError.StreamsLimitViolated, frameType); Debug.Assert(stream!.CanRead); @@ -633,14 +633,14 @@ private ProcessPacketResult ProcessStreamFrame(QuicReader reader) ReceivedData += writtenOffset - buffer.Size; if (ReceivedData > _sendLimits.MaxData) { - return CloseConnection(TransportErrorCode.FlowControlError, QuicError.MaxDataViolated, frameType); + return CloseConnection(TransportErrorCode.FlowControlError, QuicTransportError.MaxDataViolated, frameType); } } // check stream-level flow control if (writtenOffset > buffer.MaxData) { - return CloseConnection(TransportErrorCode.FlowControlError, QuicError.StreamMaxDataViolated, frameType); + return CloseConnection(TransportErrorCode.FlowControlError, QuicTransportError.StreamMaxDataViolated, frameType); } if (frame.Fin) @@ -649,14 +649,14 @@ private ProcessPacketResult ProcessStreamFrame(QuicReader reader) if (buffer.FinalSizeKnown && writtenOffset != buffer.Size || writtenOffset < buffer.Size) { - return CloseConnection(TransportErrorCode.FinalSizeError, QuicError.InconsistentFinalSize, frameType); + return CloseConnection(TransportErrorCode.FinalSizeError, QuicTransportError.InconsistentFinalSize, frameType); } } // close if writing past known stream end if (buffer.FinalSizeKnown && writtenOffset > buffer.Size) { - return CloseConnection(TransportErrorCode.FinalSizeError, QuicError.WritingPastFinalSize, frameType); + return CloseConnection(TransportErrorCode.FinalSizeError, QuicTransportError.WritingPastFinalSize, frameType); } // RFC: STREAM frames received after sending STOP_SENDING are still counted @@ -697,7 +697,7 @@ private ProcessPacketResult ProcessUnknownFrame(QuicReader reader) int length = reader.BytesLeft; FrameType frameType = reader.ReadFrameType(); _trace?.OnUnknownFrame((long)frameType, length); - return CloseConnection(TransportErrorCode.FrameEncodingError, QuicError.UnknownFrameType, frameType); + return CloseConnection(TransportErrorCode.FrameEncodingError, QuicTransportError.UnknownFrameType, frameType); } private void WriteFrames(QuicWriter writer, PacketType packetType, EncryptionLevel level, QuicSocketContext.SendContext context) @@ -937,7 +937,7 @@ private bool WriteStreamMaxDataFrame(QuicWriter writer, ManagedQuicStream stream return true; } - var frame = new MaxStreamDataFrame(stream.StreamId, buffer.MaxData); + var frame = new MaxStreamDataFrame(stream.Id, buffer.MaxData); if (writer.BytesAvailable < frame.GetSerializedLength()) { return false; @@ -962,7 +962,7 @@ private bool WriteStopSendingFrame(QuicWriter writer, ManagedQuicStream stream, return true; } - var frame = new StopSendingFrame(stream.StreamId, buffer.Error.Value); + var frame = new StopSendingFrame(stream.Id, buffer.Error.Value); if (writer.BytesAvailable < frame.GetSerializedLength()) { return false; @@ -988,7 +988,7 @@ private bool WriteResetStreamFrame(QuicWriter writer, ManagedQuicStream stream, return true; } - var frame = new ResetStreamFrame(stream.StreamId, buffer.Error.Value, buffer.UnsentOffset); + var frame = new ResetStreamFrame(stream.Id, buffer.Error.Value, buffer.UnsentOffset); if (writer.BytesAvailable < frame.GetSerializedLength()) { return false; @@ -996,7 +996,7 @@ private bool WriteResetStreamFrame(QuicWriter writer, ManagedQuicStream stream, ResetStreamFrame.Write(writer, frame); _trace?.OnResetStreamFrame(frame); - context.SentPacket.StreamsReset.Add(stream.StreamId); + context.SentPacket.StreamsReset.Add(stream.Id); buffer.OnResetSent(); return true; @@ -1042,7 +1042,7 @@ private void WriteStreamFrames(QuicWriter writer, QuicSocketContext.SendContext (long offset, long count) = buffer.GetNextSendableRange(); // send only as much data as can fit into the packet - int overhead = StreamFrame.GetOverheadLength(stream.StreamId, offset, count); + int overhead = StreamFrame.GetOverheadLength(stream.Id, offset, count); count = Math.Min(count, writer.BytesAvailable - overhead); // respect connection-level control flow @@ -1054,8 +1054,8 @@ private void WriteStreamFrames(QuicWriter writer, QuicSocketContext.SendContext if (count > 0 || fin && !buffer.FinAcked) { - var payloadDestination = StreamFrame.ReservePayloadBuffer(writer, stream!.StreamId, offset, (int)count, fin); - _trace?.OnStreamFrame(new StreamFrame(stream!.StreamId, offset, fin, payloadDestination)); + var payloadDestination = StreamFrame.ReservePayloadBuffer(writer, stream.Id, offset, (int)count, fin); + _trace?.OnStreamFrame(new StreamFrame(stream.Id, offset, fin, payloadDestination)); // add the newly sent data to the flow control counter SentData += Math.Max(0, offset + count - buffer.UnsentOffset); @@ -1063,7 +1063,7 @@ private void WriteStreamFrames(QuicWriter writer, QuicSocketContext.SendContext // record sent data context.SentPacket.StreamFrames.Add( - new SentPacket.StreamFrameHeader(stream!.StreamId, offset, (int)count, fin)); + new SentPacket.StreamFrameHeader(stream.Id, offset, (int)count, fin)); written = true; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Packets.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Packets.cs index 0d2bdf0a365900..9dff96eb552e9a 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Packets.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.Packets.cs @@ -96,7 +96,7 @@ private ProcessPacketResult ReceiveOne(QuicReader reader, QuicSocketContext.Recv if (reader.Buffer.Length < QuicConstants.MinimumClientInitialDatagramSize) { return CloseConnection(TransportErrorCode.ProtocolViolation, - QuicError.InitialPacketTooShort); + QuicTransportError.InitialPacketTooShort); } } @@ -105,7 +105,7 @@ private ProcessPacketResult ReceiveOne(QuicReader reader, QuicSocketContext.Recv { return CloseConnection( TransportErrorCode.ProtocolViolation, - QuicError.UnexpectedToken); + QuicTransportError.UnexpectedToken); } // after client receives the first packet (which is either initial or retry), it must @@ -240,7 +240,7 @@ private ProcessPacketResult ReceiveOne(QuicReader reader, QuicSocketContext.Recv if (header.ReservedBits != 0) { return CloseConnection(TransportErrorCode.ProtocolViolation, - QuicError.InvalidReservedBits); + QuicTransportError.InvalidReservedBits); } result = ReceiveCore(reader, pnSpace, pnOffset, header.PacketNumberLength, packetType, recvSeal, @@ -333,7 +333,7 @@ private ProcessPacketResult ReceiveLongHeader(QuicReader reader, in LongPacketHe if (header.ReservedBits != 0) { return CloseConnection(TransportErrorCode.ProtocolViolation, - QuicError.InvalidReservedBits); + QuicTransportError.InvalidReservedBits); } return ReceiveCore(reader, pnSpace, pnOffset, header.PacketNumberLength, packetType, seal, diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs index be552da3b05250..badaf724f73819 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs @@ -179,12 +179,12 @@ internal QuicConnectionState ConnectionState /// /// Error received via CONNECTION_CLOSE frame to be reported to the user. /// - private QuicError? _inboundError; + private QuicTransportError? _inboundError; /// /// Error to send in next packet in a CONNECTION_CLOSE frame. /// - private QuicError? _outboundError; + private QuicTransportError? _outboundError; /// /// Version of the QUIC protocol used for this connection. @@ -593,7 +593,7 @@ internal PacketNumberSpace GetPacketNumberSpace(EncryptionLevel encryptionLevel) private ProcessPacketResult CloseConnection(TransportErrorCode errorCode, string? reason = null, FrameType frameType = FrameType.Padding) { - _outboundError ??= new QuicError(errorCode, reason, frameType); + _outboundError ??= new QuicTransportError(errorCode, reason, frameType); return ProcessPacketResult.Error; } @@ -618,7 +618,7 @@ internal ValueTask DisposeAsync(long errorCode) stream.OnConnectionClosed(MakeOperationAbortedException()); } - _outboundError = new QuicError((TransportErrorCode)errorCode, null, FrameType.Padding, false); + _outboundError = new QuicTransportError((TransportErrorCode)errorCode, null, FrameType.Padding, false); _disposed = true; Tls.Dispose(); _socketContext.WakeUp(); @@ -818,7 +818,7 @@ private void DropPacketNumberSpace(PacketSpace space, ObjectPool sen /// /// Timestamp of the current moment. /// Error which led to connection closing. - private void StartClosing(long now, QuicError error) + private void StartClosing(long now, QuicTransportError error) { Debug.Assert(_closingPeriodEndTimestamp == null); Debug.Assert(error != null); @@ -896,7 +896,7 @@ private QuicException MakeOperationAbortedException() : new QuicOperationAbortedException(); // initiated by us } - private static QuicException MakeConnectionAbortedException(QuicError error) + private static QuicException MakeConnectionAbortedException(QuicTransportError error) { return new QuicException(QuicError.ConnectionAborted, (long)error.ErrorCode, error.ReasonPhrase); } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs index e30a3ec9775855..49bde63a07866e 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs @@ -417,10 +417,7 @@ internal void OnConnectionClosed(QuicException exception) private void ThrowIfDisposed() { - if (_disposed) - { - throw new ObjectDisposedException(nameof(ManagedQuicStream)); - } + ObjectDisposedException.ThrowIf(_disposed, typeof(ManagedQuicStream)); } private void ThrowIfNotWritable() diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/QuicError.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/QuicTransportError.cs similarity index 93% rename from src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/QuicError.cs rename to src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/QuicTransportError.cs index 102ead0dedba5f..0ffc14768ff9dd 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/QuicError.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/QuicTransportError.cs @@ -10,14 +10,14 @@ namespace System.Net.Quic.Implementations.Managed { [DebuggerDisplay("[$ErrorCode] $ReasonPhrase ($FrameType)")] - internal sealed class QuicError + internal sealed class QuicTransportError { internal TransportErrorCode ErrorCode { get; } internal FrameType FrameType { get; } internal string? ReasonPhrase { get; } internal bool IsQuicError { get; } - public QuicError(TransportErrorCode errorCode, string? reasonPhrase = null, FrameType frameType = FrameType.Padding, + public QuicTransportError(TransportErrorCode errorCode, string? reasonPhrase = null, FrameType frameType = FrameType.Padding, bool isQuicError = true) { ErrorCode = errorCode;