-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[QUIC] API Update #49823
[QUIC] API Update #49823
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @dotnet/ncl Issue DetailsUpdated API to microsoft/msquic@cc104e8, branched in my fork: https://github.com/ManickaP/msquic/commits/mapichov/net6_2020_03_18 The change mostly taken from https://github.com/scalablecory/runtime/tree/msquic-update
|
<Content Include="libmsquic.so" Condition="Exists('libmsquic.so')"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> | ||
</Content> | ||
<Content Include="msquic.pdb" Condition="Exists('msquic.pdb')"> | ||
<Content Include="libmsquic.lttng.so" Condition="Exists('libmsquic.lttng.so')"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scalablecory could we reference the System.Net.Experimental.Quic here instead now? https://github.com/dotnet/runtimelab/tree/feature/System.Net.Experimental.MsQuic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You won't need that package for .NET 6.
src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs
Outdated
Show resolved
Hide resolved
...aries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicAlpnHelper.cs
Outdated
Show resolved
Hide resolved
@@ -299,58 +446,68 @@ internal struct ConnectionEvent | |||
IntPtr context, | |||
ref ConnectionEvent connectionEvent); | |||
|
|||
// TODO: order is Open, Close, Shutdown, Start, SetConfiguration, SendResumptionTicket |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be removed now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, that's my comment. The order (in the comment) is taken from msquic.h, we do not follow that in here. I didn't want to generate more diffs in this PR. I'll plan to do follow up that does not change the behavior at all, just shuffles things around to be more like msquic.h.
default: | ||
return MsQuicStatusCodes.InternalError; | ||
} | ||
return MsQuicStatusCodes.InternalError; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the plan for logging inside System.Net.Quic?
For example, here there should be a log message that an unknown callback was received, including the unexpected evt.Type
value. A generic InternalError
status code isn't enough to understand what went wrong.
(logging can be added in the future, not blocking for this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found this - #32072
/// Default is 100. | ||
/// </summary> | ||
// TODO consider constraining these limits to 0 to whatever the max of the QUIC library we are using. | ||
public long MaxBidirectionalStreams { get; set; } = 100; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need validation to stop invalid values (e.g. 0 or -50). Applies to all options.
Create an issue if you would prefer to do it in a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's part of this #32079:
How should we be validating these limits?
public class MsQuicTestBase | ||
{ | ||
public SslServerAuthenticationOptions GetSslServerAuthenticationOptions() | ||
{ | ||
return new SslServerAuthenticationOptions() | ||
{ | ||
ApplicationProtocols = new List<SslApplicationProtocol>() { new SslApplicationProtocol("quictest") } | ||
ApplicationProtocols = new List<SslApplicationProtocol>() { new SslApplicationProtocol("quictest") }, | ||
// TODO: use a cert. MsQuic currently only allows certs that are trusted. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the cause of this trusted limitation? Is it a requirement of QUIC, or because we haven't added configuration to ignore invalid certificates yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we may need to plumb custom validation callback to managed code. I'm not sure if that was already done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs
Outdated
Show resolved
Hide resolved
_state.Connection = this; | ||
try | ||
{ | ||
uint status = MsQuicApi.Api.ConnectionStartDelegate( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have QuicStatus enum here? While the list of errors may grow, there are really only three interesting values IMHO. We do that in some other places and it make debugging much easier as you can see the enum instead of number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have something: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/MsQuicStatusCodes.cs
The codes differ on different platforms, that's why it's separate. Could we define an enum per platform and use it? I guess we could. Is it worth it? Depends on what we decide to do about the generated interop.
Otherwise, better messages are covered by #32066.
|
||
namespace System.Net.Quic.Implementations.MsQuic.Internal | ||
{ | ||
internal enum QUIC_EXECUTION_PROFILE : uint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really NOT the style guy but in some other places we made the names C# friendly.
runtime/src/libraries/Common/src/System/Net/SecurityStatusPal.cs
Lines 25 to 30 in 79ae74f
internal enum SecurityStatusPalErrorCode | |
{ | |
NotSet = 0, | |
OK, | |
ContinueNeeded, | |
CompleteNeeded, |
and we use int unless uint is really needed (even if underlying C is uint)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I won't change the naming scheme in this PR, that's too revolutionary 😃.
We might change it in a separate one or we might go a different direction if we chose to generate the interop.
...es/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicNativeMethods.cs
Show resolved
Hide resolved
QuicBuffer[]? buffers = null; | ||
try | ||
{ | ||
MsQuicAlpnHelper.Prepare(alpnProtocols, out handles, out buffers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need safe handles here. Since this only needs preserve through the call and never be exposed outside of this function I'm wondering if there is easier way. I'm sure the handles will work but feel heavy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But is this something we can safely assume will be true even in the future? Docs don't say anything about it: https://github.com/microsoft/msquic/blob/main/docs/api/ConfigurationOpen.md
cc: @nibanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you can rely on MsQuic to copy what it needs in the function call. The memory doesn't have to exist beyond that,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately I'd love to have a configuration API -- something like SocketsHttpHandler
really doesn't need more than a single configuration, while the current code will allocate one for every new connection it opens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately I'd love to have a configuration API -- something like
SocketsHttpHandler
really doesn't need more than a single configuration, while the current code will allocate one for every new connection it opens.
Creating a configuration is a very heavy weight operation. I'd highly recommend one of the next things you do is to refactor this like @scalablecory mentions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that mean that ConfigurationLoadCredential
might be called multiple times on the same configuration with different certificate?
Or how should I go about sharing the configuration?
Am I wrong in my train of thought: instance of SocketsHttpHandler
corresponds to one connection pool which corresponds to a single QuicConnection
which holds one configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, you create one configuration for each unique security configuration. On server that usually maps 1:1 with each server certificate. On client most times there is only one, unless they're creating clients with different configurations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This is captured in #42642)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I think there is opportunity for improvements I feel there is value in getting something in and working in improvements over time. This is not cast in stone and underlying code may be fluid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
@@ -91,7 +91,9 @@ internal override bool Connected | |||
} | |||
|
|||
// TODO: Should clone the endpoint since it is mutable | |||
internal override IPEndPoint LocalEndPoint => _localEndPoint; | |||
// TODO: could this be made back to non-nullable? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we get rid of instance method ConnectAsync
and make a static ValueTask<QuicConnection> QuicConnection.ConnectAsync()
, then we can always have LocalEndPoint
be non-null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I consider the TODO as work that needs to be done/resolved. But I don't want to hold the PR on those issues. The work will be done in follow up PRs.
|
||
private readonly IntPtr _registrationContext; | ||
SetParamDelegate = | ||
Marshal.GetDelegateForFunctionPointer<SetParamDelegate>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should consider using function pointers instead of delegates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been pointed out by Stephen and is captured here:
Line 124 in 5d3884f
// TODO: Consider updating all of these delegates to instead use function pointers. |
It's on the plate.
QuicBuffer[]? buffers = null; | ||
try | ||
{ | ||
MsQuicAlpnHelper.Prepare(alpnProtocols, out handles, out buffers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately I'd love to have a configuration API -- something like SocketsHttpHandler
really doesn't need more than a single configuration, while the current code will allocate one for every new connection it opens.
private GCHandle _handle; | ||
// TODO: remove this. | ||
// This is only used for client-initiated connections, and isn't needed even then once Connect() has been called. | ||
private readonly SafeMsQuicConfigurationHandle? _configuration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is another thing that'd be removable if we switched to a static Connect
as in a former comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I consider the TODO as work that needs to be done/resolved. But I don't want to hold the PR on those issues. The work will be done in follow up PRs.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
Only waiting for the build to finish, then I'll merge. |
Updated API to microsoft/msquic@cc104e8, branched in my fork: https://github.com/ManickaP/msquic/commits/mapichov/net6_2020_03_18
The change mostly taken from https://github.com/scalablecory/runtime/tree/msquic-update. Plus: updated the msquic version to the newest main, adjusted the API, made compilable, fixed obvious test errors.
Fixes #44580, #31695
It still needs more work, but I don't want to hold msquic API update on refactorings / clean ups.