Skip to content

Commit

Permalink
[QUIC] Adopted msquic generated interop (dotnet#68288)
Browse files Browse the repository at this point in the history
* MsQuicApi adjusted

* QuicParamHelper adjusted

* MsQuicConfiguration adjusted

* Added MsQuicException

* MsQuicConnection adjusted

* MsQuicListener adjusted

* MsQuicStream adjusted

* It compiles!

* Some test fixes

* Fixed stream read event handling

* Re-enabled IPv6 tests

* latest greatest

* Update src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs

* MsQuic interop enum names

* 3rd Party notice, version check

* SafeHandleType

* Replaced AlpnHelpers with MsQuicBuffers generic QUIC_BUFFER* helper

* Sealed exception class

* Feedback MsQuicBuffers

* NativeMemory use

* Newest msquic interop

* Buffers feedback

* Remove MemoryHandle pooling

* Buffers feedback

* Logging feedback
  • Loading branch information
ManickaP authored May 5, 2022
1 parent 6ca8c9b commit 992b395
Show file tree
Hide file tree
Showing 38 changed files with 3,894 additions and 2,553 deletions.
8 changes: 8 additions & 0 deletions THIRD-PARTY-NOTICES.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -1065,3 +1065,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

License notice for MsQuic
--------------------------------------

Copyright (c) Microsoft Corporation.
Licensed under the MIT License.

Available at
https://github.com/microsoft/msquic/blob/main/LICENSE
25 changes: 3 additions & 22 deletions src/libraries/System.Net.Quic/src/System.Net.Quic.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,16 @@
<Compile Include="System\Net\Quic\Implementations\Mock\*.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\*.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Internal\*.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicAlpnHelper.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicEnums.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicNativeMethods.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusHelper.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicTraceHelper.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicConfigurationHandle.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicConnectionHandle.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicListenerHandle.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicRegistrationHandle.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicStreamHandle.cs" />
<Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs">
<Link>Common\DisableRuntimeMarshalling.cs</Link>
</Compile>
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\*.cs" />
<!-- System.Net common -->
<Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs" Link="Common\DisableRuntimeMarshalling.cs" />
<Compile Include="$(CommonPath)System\Threading\Tasks\TaskToApm.cs" Link="Common\System\Threading\Tasks\TaskToApm.cs" />
<Compile Include="$(CommonPath)System\Net\ArrayBuffer.cs" Link="Common\System\Net\ArrayBuffer.cs" />
<Compile Include="$(CommonPath)System\Net\MultiArrayBuffer.cs" Link="Common\System\Net\MultiArrayBuffer.cs" />
<Compile Include="$(CommonPath)System\Net\Logging\NetEventSource.Common.cs" Link="Common\System\Net\Logging\NetEventSource.Common.cs" />
<Compile Include="$(CommonPath)System\Net\StreamBuffer.cs" Link="Common\System\Net\StreamBuffer.cs" />
<Compile Include="$(CommonPath)System\Net\SocketAddress.cs" Link="Common\System\Net\SocketAddress.cs" />
<Compile Include="$(CommonPath)System\Net\IPAddressParserStatics.cs" Link="Common\System\Net\IPAddressParserStatics.cs" />
<!-- System.Net.Internals -->
<Compile Include="$(CommonPath)System\Net\Internals\IPEndPointExtensions.cs" Link="Common\System\Net\Internals\IPEndPointExtensions.cs" />
</ItemGroup>
<!-- Unsupported platforms -->
Expand All @@ -74,7 +61,6 @@
<Compile Include="$(CommonPath)Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs" Link="Common\Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs" />
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Windows.cs" Link="Common\System\Net\Security\CertificateValidation.Windows.cs" />
<Compile Include="$(CommonPath)System\Net\SocketAddressPal.Windows.cs" Link="Common\System\Net\SocketAddressPal.Windows.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.Windows.cs" />
</ItemGroup>
<!-- Unix (OSX + Linux) specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Linux' or '$(TargetPlatformIdentifier)' == 'OSX' or '$(TargetPlatformIdentifier)' == 'FreeBSD'">
Expand Down Expand Up @@ -107,26 +93,21 @@
</ItemGroup>
<!-- Linux specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Linux'">
<Compile Include="$(CommonPath)Interop\Linux\Interop.Libraries.cs" Link="Common\Interop\Linux\Interop.Libraries.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.Linux.cs" />
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Unix.cs" Link="Common\System\Net\Security\CertificateValidation.Unix.cs" />
<Compile Include="$(CommonPath)Interop\Linux\Interop.Libraries.cs" Link="Common\Interop\Linux\Interop.Libraries.cs" />
</ItemGroup>
<!-- FreeBSD specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'FreeBSD' ">
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Unix.cs" Link="Common\System\Net\Security\CertificateValidation.Unix.cs" />
<Compile Include="$(CommonPath)Interop\FreeBSD\Interop.Libraries.cs" Link="Common\Interop\FreeBSD\Interop.Libraries.cs" />
<!-- Assume similarity with OSX for now -->
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.OSX.cs" />
</ItemGroup>
<!-- OSX specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'OSX'">
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.OSX.cs" Link="Common\System\Net\Security\CertificateValidation.OSX.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.Libraries.cs" Link="Common\Interop\OSX\Interop.Libraries.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.OSX.cs" />
</ItemGroup>

<!-- Project references -->

<ItemGroup>
<PackageReference Include="System.Net.MsQuic.Transport"
Version="$(SystemNetMsQuicTransportVersion)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net.Sockets;
using System.Runtime.InteropServices;
using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;

namespace System.Net.Quic.Implementations.MsQuic.Internal
{
internal static class MsQuicAddressHelpers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,29 @@

using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Quic;

using static Microsoft.Quic.MsQuic;

#if TARGET_WINDOWS
using Microsoft.Win32;
#endif

using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;

namespace System.Net.Quic.Implementations.MsQuic.Internal
{
internal sealed unsafe class MsQuicApi
{
private static readonly byte[] s_appName = Encoding.ASCII.GetBytes("System.Net.Quic");

private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000);

private static readonly Version MsQuicVersion = new Version(2, 0);

public SafeMsQuicRegistrationHandle Registration { get; }

public QUIC_API_TABLE* ApiTable { get; }

// This is workaround for a bug in ILTrimmer.
// Without these DynamicDependency attributes, .ctor() will be removed from the safe handles.
// Remove once fixed: https://github.com/mono/linker/issues/1660
Expand All @@ -26,89 +34,28 @@ internal sealed unsafe class MsQuicApi
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicListenerHandle))]
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicConnectionHandle))]
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicStreamHandle))]
private MsQuicApi(NativeApi* vtable)
private MsQuicApi(QUIC_API_TABLE* apiTable)
{
uint status;

SetParamDelegate =
new SetParamDelegate(new DelegateHelper(vtable->SetParam).SetParam);

GetParamDelegate =
new GetParamDelegate(new DelegateHelper(vtable->GetParam).GetParam);

SetCallbackHandlerDelegate =
new SetCallbackHandlerDelegate(new DelegateHelper(vtable->SetCallbackHandler).SetCallbackHandler);

RegistrationOpenDelegate =
new RegistrationOpenDelegate(new DelegateHelper(vtable->RegistrationOpen).RegistrationOpen);
RegistrationCloseDelegate =
Marshal.GetDelegateForFunctionPointer<RegistrationCloseDelegate>(
vtable->RegistrationClose);

ConfigurationOpenDelegate =
new ConfigurationOpenDelegate(new DelegateHelper(vtable->ConfigurationOpen).ConfigurationOpen);
ConfigurationCloseDelegate =
Marshal.GetDelegateForFunctionPointer<ConfigurationCloseDelegate>(
vtable->ConfigurationClose);
ConfigurationLoadCredentialDelegate =
new ConfigurationLoadCredentialDelegate(new DelegateHelper(vtable->ConfigurationLoadCredential).ConfigurationLoadCredential);

ListenerOpenDelegate =
new ListenerOpenDelegate(new DelegateHelper(vtable->ListenerOpen).ListenerOpen);
ListenerCloseDelegate =
Marshal.GetDelegateForFunctionPointer<ListenerCloseDelegate>(
vtable->ListenerClose);
ListenerStartDelegate =
new ListenerStartDelegate(new DelegateHelper(vtable->ListenerStart).ListenerStart);
ListenerStopDelegate =
new ListenerStopDelegate(new DelegateHelper(vtable->ListenerStop).ListenerStop);

ConnectionOpenDelegate =
new ConnectionOpenDelegate(new DelegateHelper(vtable->ConnectionOpen).ConnectionOpen);
ConnectionCloseDelegate =
Marshal.GetDelegateForFunctionPointer<ConnectionCloseDelegate>(
vtable->ConnectionClose);
ConnectionSetConfigurationDelegate =
new ConnectionSetConfigurationDelegate(new DelegateHelper(vtable->ConnectionSetConfiguration).ConnectionSetConfiguration);
ConnectionShutdownDelegate =
new ConnectionShutdownDelegate(new DelegateHelper(vtable->ConnectionShutdown).ConnectionShutdown);
ConnectionStartDelegate =
new ConnectionStartDelegate(new DelegateHelper(vtable->ConnectionStart).ConnectionStart);

StreamOpenDelegate =
new StreamOpenDelegate(new DelegateHelper(vtable->StreamOpen).StreamOpen);
StreamCloseDelegate =
Marshal.GetDelegateForFunctionPointer<StreamCloseDelegate>(
vtable->StreamClose);
StreamStartDelegate =
new StreamStartDelegate(new DelegateHelper(vtable->StreamStart).StreamStart);
StreamShutdownDelegate =
new StreamShutdownDelegate(new DelegateHelper(vtable->StreamShutdown).StreamShutdown);
StreamSendDelegate =
new StreamSendDelegate(new DelegateHelper(vtable->StreamSend).StreamSend);
StreamReceiveCompleteDelegate =
new StreamReceiveCompleteDelegate(new DelegateHelper(vtable->StreamReceiveComplete).StreamReceiveComplete);
StreamReceiveSetEnabledDelegate =
new StreamReceiveSetEnabledDelegate(new DelegateHelper(vtable->StreamReceiveSetEnabled).StreamReceiveSetEnabled);

var cfg = new RegistrationConfig
ApiTable = apiTable;

fixed (byte* pAppName = s_appName)
{
AppName = ".NET",
ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY
};
var cfg = new QUIC_REGISTRATION_CONFIG {
AppName = (sbyte*)pAppName,
ExecutionProfile = QUIC_EXECUTION_PROFILE.LOW_LATENCY
};

status = RegistrationOpenDelegate(ref cfg, out SafeMsQuicRegistrationHandle handle);
QuicExceptionHelpers.ThrowIfFailed(status, "RegistrationOpen failed.");
QUIC_HANDLE* handle;
ThrowIfFailure(ApiTable->RegistrationOpen(&cfg, &handle), "RegistrationOpen failed");

Registration = handle;
Registration = new SafeMsQuicRegistrationHandle(handle);
}
}

internal static MsQuicApi Api { get; } = null!;

internal static bool IsQuicSupported { get; }

private const int MsQuicVersion = 2;

internal static bool Tls13MayBeDisabled { get; }

static MsQuicApi()
Expand All @@ -129,21 +76,36 @@ static MsQuicApi()
}

IntPtr msQuicHandle;
if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle))
{
try
{
if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
{
NativeApi* vtable;
delegate* unmanaged[Cdecl]<uint, NativeApi**, uint> msQuicOpenVersion =
(delegate* unmanaged[Cdecl]<uint, NativeApi**, uint>)msQuicOpenVersionAddress;
uint status = msQuicOpenVersion(MsQuicVersion, &vtable);
if (MsQuicStatusHelper.SuccessfulStatusCode(status))
QUIC_API_TABLE* apiTable;
delegate* unmanaged[Cdecl]<uint, QUIC_API_TABLE**, int> msQuicOpenVersion = (delegate* unmanaged[Cdecl]<uint, QUIC_API_TABLE**, int>)msQuicOpenVersionAddress;
if (StatusSucceeded(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable)))
{
IsQuicSupported = true;
Api = new MsQuicApi(vtable);
int arraySize = 4;
uint* libVersion = stackalloc uint[arraySize];
uint size = (uint)arraySize * sizeof(uint);
if (StatusSucceeded(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion)))
{
var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]);
if (version >= MsQuicVersion)
{
Api = new MsQuicApi(apiTable);
IsQuicSupported = true;
}
else
{
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'");
}
}
}
}
}
}
Expand Down Expand Up @@ -182,38 +144,5 @@ private static bool IsTls13Disabled()
#endif
return false;
}

// TODO: Consider updating all of these delegates to instead use function pointers.
internal RegistrationOpenDelegate RegistrationOpenDelegate { get; }
internal RegistrationCloseDelegate RegistrationCloseDelegate { get; }

internal ConfigurationOpenDelegate ConfigurationOpenDelegate { get; }
internal ConfigurationCloseDelegate ConfigurationCloseDelegate { get; }
internal ConfigurationLoadCredentialDelegate ConfigurationLoadCredentialDelegate { get; }

internal ListenerOpenDelegate ListenerOpenDelegate { get; }
internal ListenerCloseDelegate ListenerCloseDelegate { get; }
internal ListenerStartDelegate ListenerStartDelegate { get; }
internal ListenerStopDelegate ListenerStopDelegate { get; }

// TODO: missing SendResumptionTicket
internal ConnectionOpenDelegate ConnectionOpenDelegate { get; }
internal ConnectionCloseDelegate ConnectionCloseDelegate { get; }
internal ConnectionShutdownDelegate ConnectionShutdownDelegate { get; }
internal ConnectionStartDelegate ConnectionStartDelegate { get; }
internal ConnectionSetConfigurationDelegate ConnectionSetConfigurationDelegate { get; }

internal StreamOpenDelegate StreamOpenDelegate { get; }
internal StreamCloseDelegate StreamCloseDelegate { get; }
internal StreamStartDelegate StreamStartDelegate { get; }
internal StreamShutdownDelegate StreamShutdownDelegate { get; }
internal StreamSendDelegate StreamSendDelegate { get; }
internal StreamReceiveCompleteDelegate StreamReceiveCompleteDelegate { get; }
internal StreamReceiveSetEnabledDelegate StreamReceiveSetEnabledDelegate { get; }

internal SetCallbackHandlerDelegate SetCallbackHandlerDelegate { get; }

internal SetParamDelegate SetParamDelegate { get; }
internal GetParamDelegate GetParamDelegate { get; }
}
}
Loading

0 comments on commit 992b395

Please sign in to comment.