Skip to content

Commit 992b395

Browse files
authored
[QUIC] Adopted msquic generated interop (#68288)
* 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
1 parent 6ca8c9b commit 992b395

38 files changed

+3894
-2553
lines changed

THIRD-PARTY-NOTICES.TXT

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,3 +1065,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
10651065
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
10661066
SOFTWARE.
10671067

1068+
License notice for MsQuic
1069+
--------------------------------------
1070+
1071+
Copyright (c) Microsoft Corporation.
1072+
Licensed under the MIT License.
1073+
1074+
Available at
1075+
https://github.com/microsoft/msquic/blob/main/LICENSE

src/libraries/System.Net.Quic/src/System.Net.Quic.csproj

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,16 @@
2929
<Compile Include="System\Net\Quic\Implementations\Mock\*.cs" />
3030
<Compile Include="System\Net\Quic\Implementations\MsQuic\*.cs" />
3131
<Compile Include="System\Net\Quic\Implementations\MsQuic\Internal\*.cs" />
32-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicAlpnHelper.cs" />
33-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicEnums.cs" />
34-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicNativeMethods.cs" />
35-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.cs" />
36-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusHelper.cs" />
37-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicTraceHelper.cs" />
38-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicConfigurationHandle.cs" />
39-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicConnectionHandle.cs" />
40-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicListenerHandle.cs" />
41-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicRegistrationHandle.cs" />
42-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicStreamHandle.cs" />
43-
<Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs">
44-
<Link>Common\DisableRuntimeMarshalling.cs</Link>
45-
</Compile>
32+
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\*.cs" />
4633
<!-- System.Net common -->
34+
<Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs" Link="Common\DisableRuntimeMarshalling.cs" />
4735
<Compile Include="$(CommonPath)System\Threading\Tasks\TaskToApm.cs" Link="Common\System\Threading\Tasks\TaskToApm.cs" />
4836
<Compile Include="$(CommonPath)System\Net\ArrayBuffer.cs" Link="Common\System\Net\ArrayBuffer.cs" />
4937
<Compile Include="$(CommonPath)System\Net\MultiArrayBuffer.cs" Link="Common\System\Net\MultiArrayBuffer.cs" />
5038
<Compile Include="$(CommonPath)System\Net\Logging\NetEventSource.Common.cs" Link="Common\System\Net\Logging\NetEventSource.Common.cs" />
5139
<Compile Include="$(CommonPath)System\Net\StreamBuffer.cs" Link="Common\System\Net\StreamBuffer.cs" />
5240
<Compile Include="$(CommonPath)System\Net\SocketAddress.cs" Link="Common\System\Net\SocketAddress.cs" />
5341
<Compile Include="$(CommonPath)System\Net\IPAddressParserStatics.cs" Link="Common\System\Net\IPAddressParserStatics.cs" />
54-
<!-- System.Net.Internals -->
5542
<Compile Include="$(CommonPath)System\Net\Internals\IPEndPointExtensions.cs" Link="Common\System\Net\Internals\IPEndPointExtensions.cs" />
5643
</ItemGroup>
5744
<!-- Unsupported platforms -->
@@ -74,7 +61,6 @@
7461
<Compile Include="$(CommonPath)Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs" Link="Common\Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs" />
7562
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Windows.cs" Link="Common\System\Net\Security\CertificateValidation.Windows.cs" />
7663
<Compile Include="$(CommonPath)System\Net\SocketAddressPal.Windows.cs" Link="Common\System\Net\SocketAddressPal.Windows.cs" />
77-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.Windows.cs" />
7864
</ItemGroup>
7965
<!-- Unix (OSX + Linux) specific files -->
8066
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Linux' or '$(TargetPlatformIdentifier)' == 'OSX' or '$(TargetPlatformIdentifier)' == 'FreeBSD'">
@@ -107,26 +93,21 @@
10793
</ItemGroup>
10894
<!-- Linux specific files -->
10995
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Linux'">
110-
<Compile Include="$(CommonPath)Interop\Linux\Interop.Libraries.cs" Link="Common\Interop\Linux\Interop.Libraries.cs" />
111-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.Linux.cs" />
11296
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Unix.cs" Link="Common\System\Net\Security\CertificateValidation.Unix.cs" />
97+
<Compile Include="$(CommonPath)Interop\Linux\Interop.Libraries.cs" Link="Common\Interop\Linux\Interop.Libraries.cs" />
11398
</ItemGroup>
11499
<!-- FreeBSD specific files -->
115100
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'FreeBSD' ">
116101
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Unix.cs" Link="Common\System\Net\Security\CertificateValidation.Unix.cs" />
117102
<Compile Include="$(CommonPath)Interop\FreeBSD\Interop.Libraries.cs" Link="Common\Interop\FreeBSD\Interop.Libraries.cs" />
118-
<!-- Assume similarity with OSX for now -->
119-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.OSX.cs" />
120103
</ItemGroup>
121104
<!-- OSX specific files -->
122105
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'OSX'">
123106
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.OSX.cs" Link="Common\System\Net\Security\CertificateValidation.OSX.cs" />
124107
<Compile Include="$(CommonPath)Interop\OSX\Interop.Libraries.cs" Link="Common\Interop\OSX\Interop.Libraries.cs" />
125-
<Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.OSX.cs" />
126108
</ItemGroup>
127109

128110
<!-- Project references -->
129-
130111
<ItemGroup>
131112
<PackageReference Include="System.Net.MsQuic.Transport"
132113
Version="$(SystemNetMsQuicTransportVersion)"

src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicAddressHelpers.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Net.Sockets;
5-
using System.Runtime.InteropServices;
6-
using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
7-
84
namespace System.Net.Quic.Implementations.MsQuic.Internal
95
{
106
internal static class MsQuicAddressHelpers

src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs

Lines changed: 45 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,29 @@
33

44
using System.Diagnostics.CodeAnalysis;
55
using System.Runtime.InteropServices;
6+
using System.Text;
7+
using Microsoft.Quic;
8+
9+
using static Microsoft.Quic.MsQuic;
610

711
#if TARGET_WINDOWS
812
using Microsoft.Win32;
913
#endif
1014

11-
using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
12-
1315
namespace System.Net.Quic.Implementations.MsQuic.Internal
1416
{
1517
internal sealed unsafe class MsQuicApi
1618
{
19+
private static readonly byte[] s_appName = Encoding.ASCII.GetBytes("System.Net.Quic");
20+
1721
private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000);
1822

23+
private static readonly Version MsQuicVersion = new Version(2, 0);
24+
1925
public SafeMsQuicRegistrationHandle Registration { get; }
2026

27+
public QUIC_API_TABLE* ApiTable { get; }
28+
2129
// This is workaround for a bug in ILTrimmer.
2230
// Without these DynamicDependency attributes, .ctor() will be removed from the safe handles.
2331
// Remove once fixed: https://github.com/mono/linker/issues/1660
@@ -26,89 +34,28 @@ internal sealed unsafe class MsQuicApi
2634
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicListenerHandle))]
2735
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicConnectionHandle))]
2836
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicStreamHandle))]
29-
private MsQuicApi(NativeApi* vtable)
37+
private MsQuicApi(QUIC_API_TABLE* apiTable)
3038
{
31-
uint status;
32-
33-
SetParamDelegate =
34-
new SetParamDelegate(new DelegateHelper(vtable->SetParam).SetParam);
35-
36-
GetParamDelegate =
37-
new GetParamDelegate(new DelegateHelper(vtable->GetParam).GetParam);
38-
39-
SetCallbackHandlerDelegate =
40-
new SetCallbackHandlerDelegate(new DelegateHelper(vtable->SetCallbackHandler).SetCallbackHandler);
41-
42-
RegistrationOpenDelegate =
43-
new RegistrationOpenDelegate(new DelegateHelper(vtable->RegistrationOpen).RegistrationOpen);
44-
RegistrationCloseDelegate =
45-
Marshal.GetDelegateForFunctionPointer<RegistrationCloseDelegate>(
46-
vtable->RegistrationClose);
47-
48-
ConfigurationOpenDelegate =
49-
new ConfigurationOpenDelegate(new DelegateHelper(vtable->ConfigurationOpen).ConfigurationOpen);
50-
ConfigurationCloseDelegate =
51-
Marshal.GetDelegateForFunctionPointer<ConfigurationCloseDelegate>(
52-
vtable->ConfigurationClose);
53-
ConfigurationLoadCredentialDelegate =
54-
new ConfigurationLoadCredentialDelegate(new DelegateHelper(vtable->ConfigurationLoadCredential).ConfigurationLoadCredential);
55-
56-
ListenerOpenDelegate =
57-
new ListenerOpenDelegate(new DelegateHelper(vtable->ListenerOpen).ListenerOpen);
58-
ListenerCloseDelegate =
59-
Marshal.GetDelegateForFunctionPointer<ListenerCloseDelegate>(
60-
vtable->ListenerClose);
61-
ListenerStartDelegate =
62-
new ListenerStartDelegate(new DelegateHelper(vtable->ListenerStart).ListenerStart);
63-
ListenerStopDelegate =
64-
new ListenerStopDelegate(new DelegateHelper(vtable->ListenerStop).ListenerStop);
65-
66-
ConnectionOpenDelegate =
67-
new ConnectionOpenDelegate(new DelegateHelper(vtable->ConnectionOpen).ConnectionOpen);
68-
ConnectionCloseDelegate =
69-
Marshal.GetDelegateForFunctionPointer<ConnectionCloseDelegate>(
70-
vtable->ConnectionClose);
71-
ConnectionSetConfigurationDelegate =
72-
new ConnectionSetConfigurationDelegate(new DelegateHelper(vtable->ConnectionSetConfiguration).ConnectionSetConfiguration);
73-
ConnectionShutdownDelegate =
74-
new ConnectionShutdownDelegate(new DelegateHelper(vtable->ConnectionShutdown).ConnectionShutdown);
75-
ConnectionStartDelegate =
76-
new ConnectionStartDelegate(new DelegateHelper(vtable->ConnectionStart).ConnectionStart);
77-
78-
StreamOpenDelegate =
79-
new StreamOpenDelegate(new DelegateHelper(vtable->StreamOpen).StreamOpen);
80-
StreamCloseDelegate =
81-
Marshal.GetDelegateForFunctionPointer<StreamCloseDelegate>(
82-
vtable->StreamClose);
83-
StreamStartDelegate =
84-
new StreamStartDelegate(new DelegateHelper(vtable->StreamStart).StreamStart);
85-
StreamShutdownDelegate =
86-
new StreamShutdownDelegate(new DelegateHelper(vtable->StreamShutdown).StreamShutdown);
87-
StreamSendDelegate =
88-
new StreamSendDelegate(new DelegateHelper(vtable->StreamSend).StreamSend);
89-
StreamReceiveCompleteDelegate =
90-
new StreamReceiveCompleteDelegate(new DelegateHelper(vtable->StreamReceiveComplete).StreamReceiveComplete);
91-
StreamReceiveSetEnabledDelegate =
92-
new StreamReceiveSetEnabledDelegate(new DelegateHelper(vtable->StreamReceiveSetEnabled).StreamReceiveSetEnabled);
93-
94-
var cfg = new RegistrationConfig
39+
ApiTable = apiTable;
40+
41+
fixed (byte* pAppName = s_appName)
9542
{
96-
AppName = ".NET",
97-
ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY
98-
};
43+
var cfg = new QUIC_REGISTRATION_CONFIG {
44+
AppName = (sbyte*)pAppName,
45+
ExecutionProfile = QUIC_EXECUTION_PROFILE.LOW_LATENCY
46+
};
9947

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

103-
Registration = handle;
51+
Registration = new SafeMsQuicRegistrationHandle(handle);
52+
}
10453
}
10554

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

10857
internal static bool IsQuicSupported { get; }
10958

110-
private const int MsQuicVersion = 2;
111-
11259
internal static bool Tls13MayBeDisabled { get; }
11360

11461
static MsQuicApi()
@@ -129,21 +76,36 @@ static MsQuicApi()
12976
}
13077

13178
IntPtr msQuicHandle;
132-
if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
79+
if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
13380
NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle))
13481
{
13582
try
13683
{
13784
if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
13885
{
139-
NativeApi* vtable;
140-
delegate* unmanaged[Cdecl]<uint, NativeApi**, uint> msQuicOpenVersion =
141-
(delegate* unmanaged[Cdecl]<uint, NativeApi**, uint>)msQuicOpenVersionAddress;
142-
uint status = msQuicOpenVersion(MsQuicVersion, &vtable);
143-
if (MsQuicStatusHelper.SuccessfulStatusCode(status))
86+
QUIC_API_TABLE* apiTable;
87+
delegate* unmanaged[Cdecl]<uint, QUIC_API_TABLE**, int> msQuicOpenVersion = (delegate* unmanaged[Cdecl]<uint, QUIC_API_TABLE**, int>)msQuicOpenVersionAddress;
88+
if (StatusSucceeded(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable)))
14489
{
145-
IsQuicSupported = true;
146-
Api = new MsQuicApi(vtable);
90+
int arraySize = 4;
91+
uint* libVersion = stackalloc uint[arraySize];
92+
uint size = (uint)arraySize * sizeof(uint);
93+
if (StatusSucceeded(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion)))
94+
{
95+
var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]);
96+
if (version >= MsQuicVersion)
97+
{
98+
Api = new MsQuicApi(apiTable);
99+
IsQuicSupported = true;
100+
}
101+
else
102+
{
103+
if (NetEventSource.Log.IsEnabled())
104+
{
105+
NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'");
106+
}
107+
}
108+
}
147109
}
148110
}
149111
}
@@ -182,38 +144,5 @@ private static bool IsTls13Disabled()
182144
#endif
183145
return false;
184146
}
185-
186-
// TODO: Consider updating all of these delegates to instead use function pointers.
187-
internal RegistrationOpenDelegate RegistrationOpenDelegate { get; }
188-
internal RegistrationCloseDelegate RegistrationCloseDelegate { get; }
189-
190-
internal ConfigurationOpenDelegate ConfigurationOpenDelegate { get; }
191-
internal ConfigurationCloseDelegate ConfigurationCloseDelegate { get; }
192-
internal ConfigurationLoadCredentialDelegate ConfigurationLoadCredentialDelegate { get; }
193-
194-
internal ListenerOpenDelegate ListenerOpenDelegate { get; }
195-
internal ListenerCloseDelegate ListenerCloseDelegate { get; }
196-
internal ListenerStartDelegate ListenerStartDelegate { get; }
197-
internal ListenerStopDelegate ListenerStopDelegate { get; }
198-
199-
// TODO: missing SendResumptionTicket
200-
internal ConnectionOpenDelegate ConnectionOpenDelegate { get; }
201-
internal ConnectionCloseDelegate ConnectionCloseDelegate { get; }
202-
internal ConnectionShutdownDelegate ConnectionShutdownDelegate { get; }
203-
internal ConnectionStartDelegate ConnectionStartDelegate { get; }
204-
internal ConnectionSetConfigurationDelegate ConnectionSetConfigurationDelegate { get; }
205-
206-
internal StreamOpenDelegate StreamOpenDelegate { get; }
207-
internal StreamCloseDelegate StreamCloseDelegate { get; }
208-
internal StreamStartDelegate StreamStartDelegate { get; }
209-
internal StreamShutdownDelegate StreamShutdownDelegate { get; }
210-
internal StreamSendDelegate StreamSendDelegate { get; }
211-
internal StreamReceiveCompleteDelegate StreamReceiveCompleteDelegate { get; }
212-
internal StreamReceiveSetEnabledDelegate StreamReceiveSetEnabledDelegate { get; }
213-
214-
internal SetCallbackHandlerDelegate SetCallbackHandlerDelegate { get; }
215-
216-
internal SetParamDelegate SetParamDelegate { get; }
217-
internal GetParamDelegate GetParamDelegate { get; }
218147
}
219148
}

0 commit comments

Comments
 (0)