Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion src/libraries/System.Net.Quic/ref/System.Net.Quic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public sealed partial class QuicException : System.IO.IOException
{
public QuicException(System.Net.Quic.QuicError error, long? applicationErrorCode, string message) { }
public long? ApplicationErrorCode { get { throw null; } }
public long? TransportErrorCode { get { throw null; } }
public System.Net.Quic.QuicError QuicError { get { throw null; } }
public long? TransportErrorCode { get { throw null; } }
}
public sealed partial class QuicListener : System.IAsyncDisposable
{
Expand Down Expand Up @@ -136,3 +136,63 @@ public enum QuicStreamType
Bidirectional = 1,
}
}
namespace System.Net.Quic.Implementations.Managed
{
public sealed partial class ManagedQuicConnection : System.IAsyncDisposable
{
public ManagedQuicConnection(System.Net.Quic.QuicClientConnectionOptions options) { }
public System.Net.IPEndPoint LocalEndPoint { get { throw null; } }
public System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } }
public System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } }
public System.Net.EndPoint RemoteEndPoint { get { throw null; } }
public System.Threading.Tasks.ValueTask<System.Net.Quic.Implementations.Managed.ManagedQuicStream> AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
public System.Threading.Tasks.ValueTask<System.Net.Quic.Implementations.Managed.ManagedQuicStream> OpenOutboundStreamAsync(System.Net.Quic.QuicStreamType type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public sealed partial class ManagedQuicListener : System.IAsyncDisposable
{
internal ManagedQuicListener() { }
public static bool IsSupported { get { throw null; } }
public System.Net.IPEndPoint ListenEndPoint { get { throw null; } }
public System.Threading.Tasks.ValueTask<System.Net.Quic.Implementations.Managed.ManagedQuicConnection> AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
public static System.Threading.Tasks.ValueTask<System.Net.Quic.Implementations.Managed.ManagedQuicListener> ListenAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public sealed partial class ManagedQuicStream : System.IO.Stream
{
internal ManagedQuicStream() { }
public override bool CanRead { get { throw null; } }
public override bool CanSeek { get { throw null; } }
public override bool CanTimeout { get { throw null; } }
public override bool CanWrite { get { throw null; } }
public long Id { get { throw null; } }
public override long Length { get { throw null; } }
public override long Position { get { throw null; } set { } }
public System.Threading.Tasks.Task ReadClosed { get { throw null; } }
public override int ReadTimeout { get { throw null; } set { } }
public System.Threading.Tasks.Task WriteClosed { get { throw null; } }
public override int WriteTimeout { get { throw null; } set { } }
public void Abort(System.Net.Quic.QuicAbortDirection abortDirection, long errorCode) { }
public void CompleteWrites() { }
protected override void Dispose(bool disposing) { }
public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
public override void Flush() { }
public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
public override int Read(byte[] buffer, int offset, int count) { throw null; }
public override int Read(System.Span<byte> buffer) { throw null; }
public override System.Threading.Tasks.ValueTask<int> ReadAsync(System.Memory<byte> buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; }
public override void SetLength(long value) { }
public System.Threading.Tasks.ValueTask ShutdownCompleted(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public override void Write(byte[] buffer, int offset, int count) { }
public override void Write(System.ReadOnlySpan<byte> buffer) { }
public void Write(System.ReadOnlySpan<byte> buffer, bool endStream) { }
public System.Threading.Tasks.ValueTask WriteAsync(System.Buffers.ReadOnlySequence<byte> buffers, bool endStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask WriteAsync(System.Buffers.ReadOnlySequence<byte> buffers, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory<byte> buffer, bool endStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory<byte> buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory<System.ReadOnlyMemory<byte>> buffers, bool endStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory<System.ReadOnlyMemory<byte>> buffers, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal CryptoSealAesGcm(byte[] key, byte[] headerKey, TlsCipherSuite cipherSui
Debug.Assert(headerKey.Length == 16);

CipherSuite = cipherSuite;
_aesGcm = new AesGcm(key);
_aesGcm = new AesGcm(key, IntegrityTagLength);
}

internal override TlsCipherSuite CipherSuite { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ private static bool InCongestionRecovery(RecoveryController recovery, long sentT
return sentTimestamp < recovery.CongestionRecoveryStartTime;
}

#pragma warning disable IDE0060 // Remove unused parameter
private static bool InPersistentCongestion(SentPacket largestLostPacket)
#pragma warning restore IDE0060 // Remove unused parameter
{
// var pto = SmoothedRtt.Ticks + Math.Max(4 * RttVariation.Ticks, Recovery.TimerGranularity.Ticks) +
// MaxAckDelay.Ticks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ internal sealed class QuicConnectionContext
public QuicConnectionContext(QuicServerSocketContext parent, EndPoint remoteEndpoint, ReadOnlySpan<byte> odcid, TlsFactory tlsFactory)
{
_parent = parent;
Connection = new ManagedQuicConnection(parent.ListenerOptions, this, remoteEndpoint, odcid, tlsFactory);
// TODO-RZ: move processing of first packet to Listener and create connection context only after we get the QuicServerConnectionOptions.
Connection = new ManagedQuicConnection(parent.ListenerOptions.ConnectionOptionsCallback(null!, default, default).AsTask().GetAwaiter().GetResult(), this, remoteEndpoint, odcid, tlsFactory);
Connection.SetSocketContext(this);

ObjectPool<SentPacket>? sentPacketPool = new ObjectPool<SentPacket>(256);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,8 @@ private static void ReturnMemory(in StreamChunk chunk)

public void OnFatalException(Exception e)
{
if (e is QuicException qe && qe.QuicError == QuicError.ConnectionAborted && abortedException.ErrorCode == 0)
// TODO-RZ: This feels a bit fishy now, I don't remember why it was necesary.
if (e is QuicException qe && qe.QuicError == QuicError.ConnectionAborted && qe.ApplicationErrorCode == null)
{
_deliverableChannel.Writer.TryComplete(null);
}
Expand Down Expand Up @@ -484,7 +485,7 @@ private void SetStreamAborted(long errorCode, bool byUs)
{
_deliverableChannel.Writer.TryComplete(byUs
? new QuicException(QuicError.OperationAborted, null, "Stream aborted by us.")
: new QuicException(QuicError.StreamAborted, errorCode));
: new QuicException(QuicError.StreamAborted, errorCode, "Read aborted by peer."));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -538,18 +538,18 @@ internal void ThrowIfAborted()
{
if (ResetByUs)
{
throw new QuicOperationAbortedException();
throw new QuicException(QuicError.OperationAborted, null, "Operation aborted.");
}
else
{
throw new QuicStreamAbortedException("Stream aborted", Error.Value);
throw new QuicException(QuicError.StreamAborted, Error.Value, "Stream aborted");
}
}
}

#pragma warning disable CA1822 // mark as static
#pragma warning disable CA1822, IDE0060 // mark as static, remove unused parameter
public void OnFatalException(Exception exception)
#pragma warning restore CA1822 // mark as static
#pragma warning restore CA1822, IDE0060 // mark as static
{
// TODO-RZ: handle callers blocking on other async tasks
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ private void AddHandshakeData(EncryptionLevel level, ReadOnlySpan<byte> data)
_connection.AddHandshakeData(level, data);
}

private void SendTlsAlert(EncryptionLevel level, int alert)
private void SendTlsAlert(int alert)
{
_connection.SendTlsAlert(level, alert);
_connection.SendTlsAlert(alert);
}

private void SetEncryptionSecrets(EncryptionLevel level, ReadOnlySpan<byte> readSecret,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ internal sealed class OpenSslTls : ITls
Interop.OpenSslQuic.CryptoGetExNewIndex(Interop.OpenSslQuic.CRYPTO_EX_INDEX_SSL, 0, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

#if LINUX
private static readonly TlsCipherSuite[] _supportedCiphers =
{
TlsCipherSuite.TLS_AES_128_GCM_SHA256,
Expand All @@ -56,6 +57,7 @@ internal sealed class OpenSslTls : ITls
// not supported yet
// TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256
};
#endif

private static readonly IntPtr _callbacksPtr;

Expand Down Expand Up @@ -150,8 +152,10 @@ private unsafe OpenSslTls(ManagedQuicConnection connection,
Interop.OpenSslQuic.SslCtrl(_ssl, SslCtrlCommand.SetMaxProtoVersion, (long)OpenSslTlsVersion.Tls13,
IntPtr.Zero);

#if LINUX
// explicitly set allowed suites
SetCiphersuites(cipherSuitesPolicy);
#endif

// init transport parameters
byte[] buffer = new byte[1024];
Expand All @@ -161,10 +165,7 @@ private unsafe OpenSslTls(ManagedQuicConnection connection,
Interop.OpenSslQuic.SslSetQuicTransportParams(_ssl, pData, new IntPtr(written));
}

if (applicationProtocols == null)
{
throw new ArgumentNullException(nameof(SslServerAuthenticationOptions.ApplicationProtocols));
}
ArgumentNullException.ThrowIfNull(applicationProtocols, nameof(SslServerAuthenticationOptions.ApplicationProtocols));

_alpnProtocols = applicationProtocols;
SetAlpn(applicationProtocols);
Expand Down Expand Up @@ -245,6 +246,7 @@ private bool ValidateClientHostname(string hostname)
return true;
}

#if LINUX
private void SetCiphersuites(CipherSuitesPolicy? policy)
{
// if no policy supplied, use all supported ciphers
Expand Down Expand Up @@ -278,6 +280,7 @@ private void SetCiphersuites(CipherSuitesPolicy? policy)

Interop.OpenSslQuic.SslSetCiphersuites(_ssl, ciphersString);
}
#endif

private unsafe void SetAlpn(List<SslApplicationProtocol> protos)
{
Expand Down Expand Up @@ -404,7 +407,9 @@ public SslApplicationProtocol GetNegotiatedProtocol()
return default;
}

#pragma warning disable IDE0060 // Remove unused parameter
private static int TlsExtCallbackImpl(IntPtr ssl, ref int al, IntPtr arg)
#pragma warning restore IDE0060 // Remove unused parameter
{
var namePtr = Interop.OpenSslQuic.SslGetServername(ssl, 0);
var tls = GetTlsInstance(ssl);
Expand Down Expand Up @@ -447,11 +452,13 @@ private static int FlushFlightImpl(IntPtr ssl)
return 1;
}

#pragma warning disable IDE0060 // Remove unused parameter
private static int SendAlertImpl(IntPtr ssl, OpenSslEncryptionLevel level, byte alert)
#pragma warning restore IDE0060 // Remove unused parameter
{
var tls = GetTlsInstance(ssl);

tls._connection.SendTlsAlert(ToManagedEncryptionLevel(level), alert);
tls._connection.SendTlsAlert(alert);
return 1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ internal abstract ITls CreateClient(ManagedQuicConnection connection, QuicClient

internal abstract ITls CreateServer(ManagedQuicConnection connection, QuicServerConnectionOptions options,
TransportParameters localTransportParams);

internal static TlsFactory Default => MockTlsFactory.Instance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ private ProcessPacketResult ProcessConnectionClose(QuicReader reader, QuicSocket
// keep only the first error
if (_inboundError == null)
{
_inboundError = new QuicError((TransportErrorCode)frame.ErrorCode, frame.ReasonPhrase,
_inboundError = new QuicTransportError((TransportErrorCode)frame.ErrorCode, frame.ReasonPhrase,
frame.FrameType, frame.IsQuicError);

if (_closingPeriodEndTimestamp == null)
Expand All @@ -584,7 +584,7 @@ private ProcessPacketResult ProcessConnectionClose(QuicReader reader, QuicSocket
{
// From RFC: An endpoint that receives a CONNECTION_CLOSE frame MAY send a single packet containing a
// CONNECTION_CLOSE frame before entering the draining state, using NO_ERROR code if appropriate.
_outboundError = new QuicError(TransportErrorCode.NoError);
_outboundError = new QuicTransportError(TransportErrorCode.NoError);
// draining state will be entered once the error is sent.
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public sealed partial class ManagedQuicConnection

private bool _doKeyUpdate;

#pragma warning disable IDE0060 // Remove unused parameter
internal void ReceiveData(QuicReader reader, EndPoint sender, QuicSocketContext.RecvContext ctx)
#pragma warning restore IDE0060 // Remove unused parameter
{
if (_isDraining)
{
Expand Down Expand Up @@ -243,7 +245,7 @@ private ProcessPacketResult ReceiveOne(QuicReader reader, QuicSocketContext.Recv
QuicTransportError.InvalidReservedBits);
}

result = ReceiveCore(reader, pnSpace, pnOffset, header.PacketNumberLength, packetType, recvSeal,
result = ReceiveCore(reader, pnSpace, header.PacketNumberLength, packetType, recvSeal,
context);
}

Expand Down Expand Up @@ -336,11 +338,11 @@ private ProcessPacketResult ReceiveLongHeader(QuicReader reader, in LongPacketHe
QuicTransportError.InvalidReservedBits);
}

return ReceiveCore(reader, pnSpace, pnOffset, header.PacketNumberLength, packetType, seal,
return ReceiveCore(reader, pnSpace, header.PacketNumberLength, packetType, seal,
context);
}

private ProcessPacketResult ReceiveCore(QuicReader reader, PacketNumberSpace pnSpace, int pnOffset,
private ProcessPacketResult ReceiveCore(QuicReader reader, PacketNumberSpace pnSpace,
int pnLength,
PacketType packetType, CryptoSeal seal, QuicSocketContext.RecvContext context)
{
Expand Down
Loading