Skip to content

Commit

Permalink
[QUIC] Handle connection abort in streams (#52776)
Browse files Browse the repository at this point in the history
This leverages newly added flag to SHUTDOWN_COMPLETED event, which means that's not a user-initiated stream shutdown, but a connection abort.

Fixes #32050
  • Loading branch information
CarnaViire committed May 26, 2021
1 parent 7f090c3 commit 5fc93f4
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 66 deletions.
2 changes: 1 addition & 1 deletion src/libraries/System.Net.Quic/readme.md
@@ -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
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
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");
}
}

// 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 @@ internal void SetNegotiatedAlpn(IntPtr alpn, int alpnLength)
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

0 comments on commit 5fc93f4

Please sign in to comment.