Skip to content

Commit

Permalink
Reflect latest API review
Browse files Browse the repository at this point in the history
  • Loading branch information
rzikm committed Nov 15, 2023
1 parent d26aab8 commit 96dccbf
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 77 deletions.
13 changes: 9 additions & 4 deletions src/libraries/System.Net.Quic/ref/System.Net.Quic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ internal QuicConnectionOptions() { }
public long DefaultStreamErrorCode { get { throw null; } set { } }
public System.TimeSpan HandshakeTimeout { get { throw null; } set { } }
public System.TimeSpan IdleTimeout { get { throw null; } set { } }
public int InitialConnectionWindowSize { get { throw null; } set { } }
public int InitialLocallyInitiatedBidirectionalStreamReceiveWindowSize { get { throw null; } set { } }
public int InitialRemotelyInitiatedBidirectionalStreamReceiveWindowSize { get { throw null; } set { } }
public int InitialUnidirectionalStreamReceiveWindowSize { get { throw null; } set { } }
public System.Net.Quic.QuicReceiveWindowSizes InitialReceiveWindowSizes { get { throw null; } set { } }
public System.TimeSpan KeepAliveInterval { get { throw null; } set { } }
public int MaxInboundBidirectionalStreams { get { throw null; } set { } }
public int MaxInboundUnidirectionalStreams { get { throw null; } set { } }
Expand Down Expand Up @@ -91,6 +88,14 @@ public QuicListenerOptions() { }
public int ListenBacklog { get { throw null; } set { } }
public System.Net.IPEndPoint ListenEndPoint { get { throw null; } set { } }
}
public sealed partial class QuicReceiveWindowSizes
{
public QuicReceiveWindowSizes() { }
public int Connection { get { throw null; } set { } }
public int LocallyInitiatedBidirectionalStream { get { throw null; } set { } }
public int RemotelyInitiatedBidirectionalStream { get { throw null; } set { } }
public int UnidirectionalStream { get { throw null; } set { } }
}
public sealed partial class QuicServerConnectionOptions : System.Net.Quic.QuicConnectionOptions
{
public QuicServerConnectionOptions() { }
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ P:System.Net.Quic.QuicConnection.IsSupported
P:System.Net.Quic.QuicListener.IsSupported
C:System.Net.Quic.QuicListenerOptions
C:System.Net.Quic.QuicConnectionOptions
C:System.Net.Quic.QuicReceiveWindowSizes
C:System.Net.Quic.QuicClientConnectionOptions
C:System.Net.Quic.QuicServerConnectionOptions
5 changes: 4 additions & 1 deletion src/libraries/System.Net.Quic/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@
<value>Writing is not allowed on stream.</value>
</data>
<data name="net_quic_in_range" xml:space="preserve">
<value>'{0}'' should be within [0, {1}) range.</value>
<value>'{0}' should be within [0, {1}) range.</value>
</data>
<data name="net_quic_power_of_2" xml:space="preserve">
<value>'{0}' must be a power of 2.</value>
</data>
<data name="net_quic_not_null_listener" xml:space="preserve">
<value>'{0}' must be specified to start the listener.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,42 +124,29 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI
settings.IsSet.PeerBidiStreamCount = 1;
settings.PeerBidiStreamCount = (ushort)options.MaxInboundBidirectionalStreams;

if (options.IdleTimeout != TimeSpan.Zero)
if (options.IdleTimeout != Timeout.InfiniteTimeSpan)
{
settings.IsSet.IdleTimeoutMs = 1;
settings.IdleTimeoutMs = options.IdleTimeout != Timeout.InfiniteTimeSpan ? (ulong)options.IdleTimeout.TotalMilliseconds : 0;
settings.IdleTimeoutMs = (uint)options.IdleTimeout.TotalMilliseconds;
}

if (options.KeepAliveInterval != TimeSpan.Zero)
if (options.KeepAliveInterval != Timeout.InfiniteTimeSpan)
{
settings.IsSet.KeepAliveIntervalMs = 1;
settings.KeepAliveIntervalMs = (uint)options.KeepAliveInterval.TotalMilliseconds;
}

if (options.InitialConnectionWindowSize > 0)
{
settings.IsSet.ConnFlowControlWindow = 1;
settings.ConnFlowControlWindow = (uint)options.InitialConnectionWindowSize;
}
settings.IsSet.ConnFlowControlWindow = 1;
settings.ConnFlowControlWindow = (uint)options.InitialReceiveWindowSizes.Connection;

// todo: these values need all to be powers of 2
if (options.InitialLocallyInitiatedBidirectionalStreamReceiveWindowSize > 0)
{
settings.IsSet.StreamRecvWindowBidiLocalDefault = 1;
settings.StreamRecvWindowBidiLocalDefault = (uint)options.InitialLocallyInitiatedBidirectionalStreamReceiveWindowSize;
}
settings.IsSet.StreamRecvWindowBidiLocalDefault = 1;
settings.StreamRecvWindowBidiLocalDefault = (uint)options.InitialReceiveWindowSizes.LocallyInitiatedBidirectionalStream;

if (options.InitialRemotelyInitiatedBidirectionalStreamReceiveWindowSize > 0)
{
settings.IsSet.StreamRecvWindowBidiRemoteDefault = 1;
settings.StreamRecvWindowBidiRemoteDefault = (uint)options.InitialRemotelyInitiatedBidirectionalStreamReceiveWindowSize;
}
settings.IsSet.StreamRecvWindowBidiRemoteDefault = 1;
settings.StreamRecvWindowBidiRemoteDefault = (uint)options.InitialReceiveWindowSizes.RemotelyInitiatedBidirectionalStream;

if (options.InitialUnidirectionalStreamReceiveWindowSize > 0)
{
settings.IsSet.StreamRecvWindowUnidiDefault = 1;
settings.StreamRecvWindowUnidiDefault = (uint)options.InitialUnidirectionalStreamReceiveWindowSize;
}
settings.IsSet.StreamRecvWindowUnidiDefault = 1;
settings.StreamRecvWindowUnidiDefault = (uint)options.InitialReceiveWindowSizes.UnidirectionalStream;

QUIC_HANDLE* handle;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,53 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net.Security;
using System.Runtime.CompilerServices;
using System.Threading;

namespace System.Net.Quic;

/// <summary>
/// Collection of receive window sizes for <see cref="QuicConnection"/> as a whole and individual <see cref="QuicStream"/> types.
/// </summary>
public sealed class QuicReceiveWindowSizes
{
/// <summary>
/// The initial flow-control window size for the connection.
/// </summary>
public int Connection { get; set; } = 16 * 1024 * 1024;

/// <summary>
/// The initial flow-control window size for locally initiated bidirectional streams.
/// </summary>
public int LocallyInitiatedBidirectionalStream { get; set; } = 64 * 1024;

/// <summary>
/// The initial flow-control window size for remotely initiated bidirectional streams.
/// </summary>
public int RemotelyInitiatedBidirectionalStream { get; set; } = 64 * 1024;

/// <summary>
/// The initial flow-control window size for (remotely initiated) unidirectional streams.
/// </summary>
public int UnidirectionalStream { get; set; } = 64 * 1024;

internal void Validate(string argumentName)
{
ValidatePowerOf2(argumentName, Connection);
ValidatePowerOf2(argumentName, LocallyInitiatedBidirectionalStream);
ValidatePowerOf2(argumentName, RemotelyInitiatedBidirectionalStream);
ValidatePowerOf2(argumentName, UnidirectionalStream);

static void ValidatePowerOf2(string argumentName, int value, [CallerArgumentExpression(nameof(value))] string? propertyName = null)
{
if (value <= 0 || ((value - 1) & value) != 0)
{
throw new ArgumentOutOfRangeException(argumentName, value, SR.Format(SR.net_quic_power_of_2, $"{nameof(QuicConnectionOptions.InitialReceiveWindowSizes)}.{propertyName}"));
}
}
}
}

/// <summary>
/// Shared options for both client (outbound) and server (inbound) <see cref="QuicConnection" />.
/// </summary>
Expand Down Expand Up @@ -54,67 +97,58 @@ internal QuicConnectionOptions()
// We can safely use this to distinguish if user provided value during validation.
public long DefaultCloseErrorCode { get; set; } = -1;

/// <summary>
/// The interval at which keep alive packets are sent on the connection.
/// Default <see cref="TimeSpan.Zero"/> means underlying implementation default interval.
/// </summary>
public TimeSpan KeepAliveInterval { get; set; } = TimeSpan.Zero;

/// <summary>
/// The initial flow-control window size for the connection.
/// Default 0 to leave the window size to the implementation.
/// </summary>
public int InitialConnectionWindowSize { get; set; } = 0;

/// <summary>
/// The initial flow-control window size for locally initiated bidirectional streams.
/// Default 0 to leave the window size to the implementation.
/// </summary>
public int InitialLocallyInitiatedBidirectionalStreamReceiveWindowSize { get; set; } = 0;
private QuicReceiveWindowSizes? _initialRecieveWindowSizes;

/// <summary>
/// The initial flow-control window size for remotely initiated bidirectional streams.
/// Default 0 to leave the window size to the implementation.
/// The initial receive window sizes for the connection and individual stream types.
/// </summary>
public int InitialRemotelyInitiatedBidirectionalStreamReceiveWindowSize { get; set; } = 0;
public QuicReceiveWindowSizes InitialReceiveWindowSizes
{
get => _initialRecieveWindowSizes ??= new QuicReceiveWindowSizes();
set => _initialRecieveWindowSizes = value;
}

/// <summary>
/// The initial flow-control window size for (remotely initiated) unidirectional streams.
/// Default 0 to leave the window size to the implementation.
/// The interval at which keep alive packets are sent on the connection.
/// </summary>
public int InitialUnidirectionalStreamReceiveWindowSize { get; set; } = 0;
public TimeSpan KeepAliveInterval { get; set; } = Timeout.InfiniteTimeSpan;

/// <summary>
/// The upper bound on time when the handshake must complete. If the handshake does not
/// complete in this time, the connection is aborted.
/// </summary>
public TimeSpan HandshakeTimeout { get; set; } = TimeSpan.Zero;
public TimeSpan HandshakeTimeout { get; set; } = TimeSpan.FromSeconds(10);

/// <summary>
/// Validates the options and potentially sets platform specific defaults.
/// </summary>
/// <param name="argumentName">Name of the from the caller.</param>
internal virtual void Validate(string argumentName)
{
if (MaxInboundBidirectionalStreams < 0 || MaxInboundBidirectionalStreams > ushort.MaxValue)
{
throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.MaxInboundBidirectionalStreams), ushort.MaxValue), argumentName);
}
if (MaxInboundUnidirectionalStreams < 0 || MaxInboundUnidirectionalStreams > ushort.MaxValue)
{
throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.MaxInboundUnidirectionalStreams), ushort.MaxValue), argumentName);
}
if (IdleTimeout < TimeSpan.Zero && IdleTimeout != Timeout.InfiniteTimeSpan)
{
throw new ArgumentOutOfRangeException(nameof(QuicConnectionOptions.IdleTimeout), SR.net_quic_timeout_use_gt_zero);
}
if (DefaultStreamErrorCode < 0 || DefaultStreamErrorCode > QuicDefaults.MaxErrorCodeValue)
ValidateInRange(argumentName, MaxInboundBidirectionalStreams, ushort.MaxValue);
ValidateInRange(argumentName, MaxInboundUnidirectionalStreams, ushort.MaxValue);
ValidateTimespan(argumentName, IdleTimeout);
ValidateTimespan(argumentName, KeepAliveInterval);
ValidateInRange(argumentName, DefaultCloseErrorCode, QuicDefaults.MaxErrorCodeValue);
ValidateInRange(argumentName, DefaultStreamErrorCode, QuicDefaults.MaxErrorCodeValue);
ValidateTimespan(argumentName, HandshakeTimeout);

_initialRecieveWindowSizes?.Validate(argumentName);

static void ValidateInRange(string argumentName, long value, long max, [CallerArgumentExpression(nameof(value))] string? propertyName = null)
{
throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.DefaultStreamErrorCode), QuicDefaults.MaxErrorCodeValue), argumentName);
if (value < 0 || value > max)
{
throw new ArgumentOutOfRangeException(argumentName, value, SR.Format(SR.net_quic_in_range, propertyName, max));
}
}
if (DefaultCloseErrorCode < 0 || DefaultCloseErrorCode > QuicDefaults.MaxErrorCodeValue)

static void ValidateTimespan(string argumentName, TimeSpan value, [CallerArgumentExpression(nameof(value))] string? propertyName = null)
{
throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.DefaultCloseErrorCode), QuicDefaults.MaxErrorCodeValue), argumentName);
if (value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan)
{
throw new ArgumentOutOfRangeException(argumentName, value, SR.Format(SR.net_quic_timeout_use_gt_zero, propertyName));
}
}
}
}
Expand Down Expand Up @@ -159,13 +193,15 @@ internal override void Validate(string argumentName)
base.Validate(argumentName);

// The content of ClientAuthenticationOptions gets validate in MsQuicConfiguration.Create.
if (ClientAuthenticationOptions is null)
{
throw new ArgumentNullException(SR.Format(SR.net_quic_not_null_open_connection, nameof(QuicClientConnectionOptions.ClientAuthenticationOptions)), argumentName);
}
if (RemoteEndPoint is null)
ValidateNotNull(argumentName, ClientAuthenticationOptions);
ValidateNotNull(argumentName, RemoteEndPoint);

static void ValidateNotNull(string argumentName, object value, [CallerArgumentExpression(nameof(value))] string? propertyName = null)
{
throw new ArgumentNullException(SR.Format(SR.net_quic_not_null_open_connection, nameof(QuicClientConnectionOptions.RemoteEndPoint)), argumentName);
if (value is null)
{
throw new ArgumentNullException(argumentName, SR.Format(SR.net_quic_not_null_open_connection, propertyName));
}
}
}
}
Expand Down Expand Up @@ -199,9 +235,14 @@ internal override void Validate(string argumentName)
base.Validate(argumentName);

// The content of ServerAuthenticationOptions gets validate in MsQuicConfiguration.Create.
if (ServerAuthenticationOptions is null)
ValidateNotNull(argumentName, ServerAuthenticationOptions);

static void ValidateNotNull(string argumentName, object value, [CallerArgumentExpression(nameof(value))] string? propertyName = null)
{
throw new ArgumentNullException(SR.Format(SR.net_quic_not_null_accept_connection, nameof(QuicServerConnectionOptions.ServerAuthenticationOptions)), argumentName);
if (value is null)
{
throw new ArgumentNullException(argumentName, SR.Format(SR.net_quic_not_null_accept_connection, propertyName));
}
}
}
}

0 comments on commit 96dccbf

Please sign in to comment.