33
44using System . Diagnostics . CodeAnalysis ;
55using System . Runtime . InteropServices ;
6+ using System . Text ;
7+ using Microsoft . Quic ;
8+
9+ using static Microsoft . Quic . MsQuic ;
610
711#if TARGET_WINDOWS
812using Microsoft . Win32 ;
913#endif
1014
11- using static System . Net . Quic . Implementations . MsQuic . Internal . MsQuicNativeMethods ;
12-
1315namespace 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