Skip to content

Commit 0e8fea6

Browse files
authored
Initial port of MsQuic transport (#15375)
1 parent fece470 commit 0e8fea6

12 files changed

+1181
-0
lines changed

eng/ProjectReferences.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Core" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Core\src\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Core\ref\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
6161
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Kestrel\src\Microsoft.AspNetCore.Server.Kestrel.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Kestrel\ref\Microsoft.AspNetCore.Server.Kestrel.csproj" />
6262
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Libuv\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Libuv\ref\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" />
63+
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.MsQuic\src\Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.MsQuic\ref\Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic.csproj" />
6364
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Sockets\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj" RefProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Sockets\ref\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj" />
6465
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Certificate" ProjectPath="$(RepoRoot)src\Security\Authentication\Certificate\src\Microsoft.AspNetCore.Authentication.Certificate.csproj" RefProjectPath="$(RepoRoot)src\Security\Authentication\Certificate\ref\Microsoft.AspNetCore.Authentication.Certificate.csproj" />
6566
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Cookies" ProjectPath="$(RepoRoot)src\Security\Authentication\Cookies\src\Microsoft.AspNetCore.Authentication.Cookies.csproj" RefProjectPath="$(RepoRoot)src\Security\Authentication\Cookies\ref\Microsoft.AspNetCore.Authentication.Cookies.csproj" />

src/Servers/Kestrel/Kestrel.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebUti
8484
EndProject
8585
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "http2cat", "samples\http2cat\http2cat.csproj", "{3D6821F5-F242-4828-8DDE-89488E85512D}"
8686
EndProject
87+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic", "Transport.MsQuic\src\Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic.csproj", "{1BC94F37-AF61-4641-A80A-EC32A15C5344}"
88+
EndProject
8789
Global
8890
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8991
Debug|Any CPU = Debug|Any CPU
@@ -466,6 +468,18 @@ Global
466468
{3D6821F5-F242-4828-8DDE-89488E85512D}.Release|x64.Build.0 = Release|Any CPU
467469
{3D6821F5-F242-4828-8DDE-89488E85512D}.Release|x86.ActiveCfg = Release|Any CPU
468470
{3D6821F5-F242-4828-8DDE-89488E85512D}.Release|x86.Build.0 = Release|Any CPU
471+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
472+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Debug|Any CPU.Build.0 = Debug|Any CPU
473+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Debug|x64.ActiveCfg = Debug|Any CPU
474+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Debug|x64.Build.0 = Debug|Any CPU
475+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Debug|x86.ActiveCfg = Debug|Any CPU
476+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Debug|x86.Build.0 = Debug|Any CPU
477+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Release|Any CPU.ActiveCfg = Release|Any CPU
478+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Release|Any CPU.Build.0 = Release|Any CPU
479+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Release|x64.ActiveCfg = Release|Any CPU
480+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Release|x64.Build.0 = Release|Any CPU
481+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Release|x86.ActiveCfg = Release|Any CPU
482+
{1BC94F37-AF61-4641-A80A-EC32A15C5344}.Release|x86.Build.0 = Release|Any CPU
469483
EndGlobalSection
470484
GlobalSection(SolutionProperties) = preSolution
471485
HideSolutionNode = FALSE
@@ -503,6 +517,7 @@ Global
503517
{E0AD50A3-2518-4060-8BB9-5649B04B3A6D} = {F0A1281A-B512-49D2-8362-21EE32B3674F}
504518
{EE45763C-753D-4228-8E5D-A71F8BDB3D89} = {F0A1281A-B512-49D2-8362-21EE32B3674F}
505519
{3D6821F5-F242-4828-8DDE-89488E85512D} = {F826BA61-60A9-45B6-AF29-FD1A6E313EF0}
520+
{1BC94F37-AF61-4641-A80A-EC32A15C5344} = {2B456D08-F72B-4EB8-B663-B6D78FC04BF8}
506521
EndGlobalSection
507522
GlobalSection(ExtensibilityGlobals) = postSolution
508523
SolutionGuid = {48207B50-7D05-4B10-B585-890FE0F4FCE1}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## Using MsQuic on Windows
2+
3+
### Setup pre-requisites
4+
5+
1. Update machine to the latest Windows Insiders build (build number 19010 or later). This is required for TLS 1.3 support.
6+
2. Copy msquic.dll and msquic.pdb to this directory and uncomment the copy task in Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic.csproj. This will copy the msquic.dll into any built project.
7+
8+
For external contributors, msquic.dll isn't available publicly yet. See https://github.com/aspnet/Announcements/issues/393.
9+
10+
Credit to Diwakar Mantha and the Kaizala team for the MsQuic interop code.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!-- This file is automatically generated. -->
2+
<Project Sdk="Microsoft.NET.Sdk">
3+
<PropertyGroup>
4+
<TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
5+
</PropertyGroup>
6+
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
7+
<Compile Include="Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic.netcoreapp.cs" />
8+
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
9+
<Reference Include="Microsoft.AspNetCore.Connections.Abstractions" />
10+
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
11+
<Reference Include="Microsoft.Extensions.Options" />
12+
</ItemGroup>
13+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
7+
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.MsQuic.Internal
8+
{
9+
internal class MsQuicApi : IDisposable
10+
{
11+
private bool _disposed = false;
12+
13+
private IntPtr _registrationContext;
14+
15+
internal unsafe MsQuicApi()
16+
{
17+
var status = (uint)MsQuicNativeMethods.MsQuicOpen(version: 1, out var registration);
18+
MsQuicStatusException.ThrowIfFailed(status);
19+
20+
NativeRegistration = *registration;
21+
22+
RegistrationOpenDelegate =
23+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.RegistrationOpenDelegate>(
24+
NativeRegistration.RegistrationOpen);
25+
RegistrationCloseDelegate =
26+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.RegistrationCloseDelegate>(
27+
NativeRegistration.RegistrationClose);
28+
29+
SecConfigCreateDelegate =
30+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SecConfigCreateDelegate>(
31+
NativeRegistration.SecConfigCreate);
32+
SecConfigDeleteDelegate =
33+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SecConfigDeleteDelegate>(
34+
NativeRegistration.SecConfigDelete);
35+
36+
SessionOpenDelegate =
37+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SessionOpenDelegate>(
38+
NativeRegistration.SessionOpen);
39+
SessionCloseDelegate =
40+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SessionCloseDelegate>(
41+
NativeRegistration.SessionClose);
42+
SessionShutdownDelegate =
43+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SessionShutdownDelegate>(
44+
NativeRegistration.SessionShutdown);
45+
46+
ListenerOpenDelegate =
47+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ListenerOpenDelegate>(
48+
NativeRegistration.ListenerOpen);
49+
ListenerCloseDelegate =
50+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ListenerCloseDelegate>(
51+
NativeRegistration.ListenerClose);
52+
ListenerStartDelegate =
53+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ListenerStartDelegate>(
54+
NativeRegistration.ListenerStart);
55+
ListenerStopDelegate =
56+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ListenerStopDelegate>(
57+
NativeRegistration.ListenerStop);
58+
59+
ConnectionOpenDelegate =
60+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ConnectionOpenDelegate>(
61+
NativeRegistration.ConnectionOpen);
62+
ConnectionCloseDelegate =
63+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ConnectionCloseDelegate>(
64+
NativeRegistration.ConnectionClose);
65+
ConnectionShutdownDelegate =
66+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ConnectionShutdownDelegate>(
67+
NativeRegistration.ConnectionShutdown);
68+
ConnectionStartDelegate =
69+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.ConnectionStartDelegate>(
70+
NativeRegistration.ConnectionStart);
71+
72+
StreamOpenDelegate =
73+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.StreamOpenDelegate>(
74+
NativeRegistration.StreamOpen);
75+
StreamCloseDelegate =
76+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.StreamCloseDelegate>(
77+
NativeRegistration.StreamClose);
78+
StreamStartDelegate =
79+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.StreamStartDelegate>(
80+
NativeRegistration.StreamStart);
81+
StreamShutdownDelegate =
82+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.StreamShutdownDelegate>(
83+
NativeRegistration.StreamShutdown);
84+
StreamSendDelegate =
85+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.StreamSendDelegate>(
86+
NativeRegistration.StreamSend);
87+
88+
SetContextDelegate =
89+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SetContextDelegate>(
90+
NativeRegistration.SetContext);
91+
GetContextDelegate =
92+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.GetContextDelegate>(
93+
NativeRegistration.GetContext);
94+
SetCallbackHandlerDelegate =
95+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SetCallbackHandlerDelegate>(
96+
NativeRegistration.SetCallbackHandler);
97+
98+
SetParamDelegate =
99+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.SetParamDelegate>(
100+
NativeRegistration.SetParam);
101+
GetParamDelegate =
102+
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.GetParamDelegate>(
103+
NativeRegistration.GetParam);
104+
}
105+
106+
internal MsQuicNativeMethods.NativeApi NativeRegistration { get; private set; }
107+
108+
internal MsQuicNativeMethods.RegistrationOpenDelegate RegistrationOpenDelegate { get; private set; }
109+
internal MsQuicNativeMethods.RegistrationCloseDelegate RegistrationCloseDelegate { get; private set; }
110+
111+
internal MsQuicNativeMethods.SecConfigCreateDelegate SecConfigCreateDelegate { get; private set; }
112+
internal MsQuicNativeMethods.SecConfigCreateCompleteDelegate SecConfigCreateCompleteDelegate { get; private set; }
113+
internal MsQuicNativeMethods.SecConfigDeleteDelegate SecConfigDeleteDelegate { get; private set; }
114+
115+
internal MsQuicNativeMethods.SessionOpenDelegate SessionOpenDelegate { get; private set; }
116+
internal MsQuicNativeMethods.SessionCloseDelegate SessionCloseDelegate { get; private set; }
117+
internal MsQuicNativeMethods.SessionShutdownDelegate SessionShutdownDelegate { get; private set; }
118+
119+
internal MsQuicNativeMethods.ListenerOpenDelegate ListenerOpenDelegate { get; private set; }
120+
internal MsQuicNativeMethods.ListenerCloseDelegate ListenerCloseDelegate { get; private set; }
121+
internal MsQuicNativeMethods.ListenerStartDelegate ListenerStartDelegate { get; private set; }
122+
internal MsQuicNativeMethods.ListenerStopDelegate ListenerStopDelegate { get; private set; }
123+
124+
internal MsQuicNativeMethods.ConnectionOpenDelegate ConnectionOpenDelegate { get; private set; }
125+
internal MsQuicNativeMethods.ConnectionCloseDelegate ConnectionCloseDelegate { get; private set; }
126+
internal MsQuicNativeMethods.ConnectionShutdownDelegate ConnectionShutdownDelegate { get; private set; }
127+
internal MsQuicNativeMethods.ConnectionStartDelegate ConnectionStartDelegate { get; private set; }
128+
129+
internal MsQuicNativeMethods.StreamOpenDelegate StreamOpenDelegate { get; private set; }
130+
internal MsQuicNativeMethods.StreamCloseDelegate StreamCloseDelegate { get; private set; }
131+
internal MsQuicNativeMethods.StreamStartDelegate StreamStartDelegate { get; private set; }
132+
internal MsQuicNativeMethods.StreamShutdownDelegate StreamShutdownDelegate { get; private set; }
133+
internal MsQuicNativeMethods.StreamSendDelegate StreamSendDelegate { get; private set; }
134+
internal MsQuicNativeMethods.StreamReceiveCompleteDelegate StreamReceiveComplete { get; private set; }
135+
136+
internal MsQuicNativeMethods.SetContextDelegate SetContextDelegate { get; private set; }
137+
internal MsQuicNativeMethods.GetContextDelegate GetContextDelegate { get; private set; }
138+
internal MsQuicNativeMethods.SetCallbackHandlerDelegate SetCallbackHandlerDelegate { get; private set; }
139+
140+
internal MsQuicNativeMethods.SetParamDelegate SetParamDelegate { get; private set; }
141+
internal MsQuicNativeMethods.GetParamDelegate GetParamDelegate { get; private set; }
142+
143+
internal void RegistrationOpen(byte[] name)
144+
{
145+
MsQuicStatusException.ThrowIfFailed(RegistrationOpenDelegate(name, out var ctx));
146+
_registrationContext = ctx;
147+
}
148+
149+
internal unsafe uint UnsafeSetParam(
150+
IntPtr Handle,
151+
uint Level,
152+
uint Param,
153+
MsQuicNativeMethods.QuicBuffer Buffer)
154+
{
155+
return SetParamDelegate(
156+
Handle,
157+
Level,
158+
Param,
159+
Buffer.Length,
160+
Buffer.Buffer);
161+
}
162+
163+
public void Dispose()
164+
{
165+
Dispose(disposing: true);
166+
GC.SuppressFinalize(this);
167+
}
168+
169+
~MsQuicApi()
170+
{
171+
Dispose(disposing: false);
172+
}
173+
174+
private void Dispose(bool disposing)
175+
{
176+
if (_disposed)
177+
{
178+
return;
179+
}
180+
181+
RegistrationCloseDelegate?.Invoke(_registrationContext);
182+
183+
_disposed = true;
184+
}
185+
}
186+
}

0 commit comments

Comments
 (0)