Skip to content
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] Handle connection abort in streams #52776

Merged
merged 3 commits into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libraries/System.Net.Quic/readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# MsQuic

`System.Net.Quic` depends on [MsQuic](https://github.com/microsoft/msquic), Microsoft, cross-platform, native implementation of the [QUIC](https://datatracker.ietf.org/wg/quic/about/) protocol.
Currently, `System.Net.Quic` depends on [**msquic@2084736032ec917f1819802caa515e61a6d3dd9a**](https://github.com/microsoft/msquic/commit/2084736032ec917f1819802caa515e61a6d3dd9a) revision.
Currently, `System.Net.Quic` depends on [**msquic@26cff1a8de7890cf7ff77709ee14b51bc84e330e**](https://github.com/microsoft/msquic/commit/26cff1a8de7890cf7ff77709ee14b51bc84e330e) revision.

## Usage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,12 @@ internal struct StreamEventDataSendShutdownComplete
internal byte Graceful;
}

[StructLayout(LayoutKind.Sequential)]
internal struct StreamEventDataShutdownComplete
{
internal byte ConnectionShutdown;
}

[StructLayout(LayoutKind.Explicit)]
internal struct StreamEventDataUnion
{
Expand All @@ -563,6 +569,9 @@ internal struct StreamEventDataUnion
[FieldOffset(0)]
internal StreamEventDataSendShutdownComplete SendShutdownComplete;

[FieldOffset(0)]
internal StreamEventDataShutdownComplete ShutdownComplete;

// TODO: missing IDEAL_SEND_BUFFER_SIZE
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal sealed class MsQuicConnection : QuicConnectionProvider
private X509RevocationMode _revocationMode = X509RevocationMode.Offline;
private RemoteCertificateValidationCallback? _remoteCertificateValidationCallback;

private sealed class State
internal sealed class State
{
public SafeMsQuicConnectionHandle Handle = null!; // set inside of MsQuicConnection ctor.

Expand Down Expand Up @@ -87,6 +87,11 @@ public MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, Saf
_stateHandle.Free();
throw;
}

if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(_state, $"[Connection#{_state.GetHashCode()}] inbound connection created");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, this is a prime example where could actually log the handle to be able to easily map it to the msquic logs, see #53224:

on the .NET side I'm wondering if we should show (or log) the handle so it easier to correlate to the native logs.

But that's absolutely not the goal of this PR and you shouldn't worry about it here, just good to be aware of it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's indeed is a good example. But let's update it separately, I'd love this PR to be merged sooner to stop blocking others

}
}

// constructor for outbound connections
Expand Down Expand Up @@ -121,6 +126,11 @@ public MsQuicConnection(QuicClientConnectionOptions options)
_stateHandle.Free();
throw;
}

if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(_state, $"[Connection#{_state.GetHashCode()}] outbound connection created");
}
}

internal override IPEndPoint? LocalEndPoint => _localEndPoint;
Expand Down Expand Up @@ -188,7 +198,7 @@ private static uint HandleEventShutdownComplete(State state, ref ConnectionEvent
private static uint HandleEventNewStream(State state, ref ConnectionEvent connectionEvent)
{
var streamHandle = new SafeMsQuicStreamHandle(connectionEvent.Data.PeerStreamStarted.Stream);
var stream = new MsQuicStream(streamHandle, connectionEvent.Data.PeerStreamStarted.Flags);
var stream = new MsQuicStream(state, streamHandle, connectionEvent.Data.PeerStreamStarted.Flags);

state.AcceptQueue.Writer.TryWrite(stream);
return MsQuicStatusCodes.Success;
Expand Down Expand Up @@ -284,18 +294,18 @@ private static uint HandleEventPeerCertificateReceived(State state, ref Connecti
{
bool success = connection._remoteCertificateValidationCallback(connection, certificate, chain, sslPolicyErrors);
if (!success && NetEventSource.Log.IsEnabled())
NetEventSource.Error(state.Connection, "Remote certificate rejected by verification callback");
NetEventSource.Error(state, $"[Connection#{state.GetHashCode()}] remote certificate rejected by verification callback");
return success ? MsQuicStatusCodes.Success : MsQuicStatusCodes.HandshakeFailure;
}

if (NetEventSource.Log.IsEnabled())
NetEventSource.Info(state.Connection, $"Certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}");
NetEventSource.Info(state, $"[Connection#{state.GetHashCode()}] certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}");

return (sslPolicyErrors == SslPolicyErrors.None) ? MsQuicStatusCodes.Success : MsQuicStatusCodes.HandshakeFailure;
}
catch (Exception ex)
{
if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state.Connection, $"Certificate validation failed ${ex.Message}");
if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state, $"[Connection#{state.GetHashCode()}] certificate validation failed ${ex.Message}");
}

return MsQuicStatusCodes.InternalError;
Expand All @@ -313,11 +323,7 @@ internal override async ValueTask<QuicStreamProvider> AcceptStreamAsync(Cancella
}
catch (ChannelClosedException)
{
throw _state.AbortErrorCode switch
{
-1 => new QuicOperationAbortedException(), // Shutdown initiated by us.
long err => new QuicConnectionAbortedException(err) // Shutdown initiated by peer.
};
throw ThrowHelper.GetConnectionAbortedException(_state.AbortErrorCode);
}

return stream;
Expand All @@ -326,13 +332,13 @@ internal override async ValueTask<QuicStreamProvider> AcceptStreamAsync(Cancella
internal override QuicStreamProvider OpenUnidirectionalStream()
{
ThrowIfDisposed();
return new MsQuicStream(_state.Handle, QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL);
return new MsQuicStream(_state, QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL);
}

internal override QuicStreamProvider OpenBidirectionalStream()
{
ThrowIfDisposed();
return new MsQuicStream(_state.Handle, QUIC_STREAM_OPEN_FLAGS.NONE);
return new MsQuicStream(_state, QUIC_STREAM_OPEN_FLAGS.NONE);
}

internal override long GetRemoteAvailableUnidirectionalStreamCount()
Expand Down Expand Up @@ -430,6 +436,12 @@ private static uint NativeCallbackHandler(
ref ConnectionEvent connectionEvent)
{
var state = (State)GCHandle.FromIntPtr(context).Target!;

if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(state, $"[Connection#{state.GetHashCode()}] received event {connectionEvent.Type}");
}

try
{
switch (connectionEvent.Type)
Expand Down
Loading