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

[H/3] Fix code passed into QuicConnection.CloseAsync and QuicStream.Abort #55282

Merged
merged 11 commits into from
May 3, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ public override void Abort(ConnectionAbortedException abortReason)
}

var resolvedErrorCode = _error ?? 0;
// Allowed error codes are up to 62 bits non-negative integer values: https://www.rfc-editor.org/rfc/rfc9000.html#integer-encoding
if (resolvedErrorCode < 0 || resolvedErrorCode > ((1L << 62) - 1))
{
resolvedErrorCode = _context.Options.DefaultCloseErrorCode;
amcasey marked this conversation as resolved.
Show resolved Hide resolved
}
_abortReason = ExceptionDispatchInfo.Capture(abortReason);
QuicLog.ConnectionAbort(_log, this, resolvedErrorCode, abortReason.Message);
_closeTask = _connection.CloseAsync(errorCode: resolvedErrorCode).AsTask();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,11 @@ public override void Abort(ConnectionAbortedException abortReason)
}

var resolvedErrorCode = _error ?? 0;
// Allowed error codes are up to 62 bits non-negative integer values: https://www.rfc-editor.org/rfc/rfc9000.html#integer-encoding
if (resolvedErrorCode < 0 || resolvedErrorCode > ((1L << 62) - 1))
{
resolvedErrorCode = _context.Options.DefaultStreamErrorCode;
amcasey marked this conversation as resolved.
Show resolved Hide resolved
}
QuicLog.StreamAbort(_log, this, resolvedErrorCode, abortReason.Message);

if (stream.CanRead)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,63 @@ public async Task GET_ClientDisconnected_ConnectionAbortRaised()
}
}

[ConditionalFact]
[MsQuicSupported]
public async Task GET_ClientIdlesOut_ConnectionAbortRaised()
amcasey marked this conversation as resolved.
Show resolved Hide resolved
{
// Arrange
var connectionClosedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
var connectionStartedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = CreateHostBuilder(
context =>
{
return Task.CompletedTask;
},
configureKestrel: kestrel =>
{
kestrel.Listen(IPAddress.Parse("127.0.0.1"), 0, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http3;
listenOptions.UseHttps(TestResources.GetTestCertificate());

IMultiplexedConnectionBuilder multiplexedConnectionBuilder = listenOptions;
multiplexedConnectionBuilder.Use(next =>
{
return context =>
{
connectionStartedTcs.SetResult();
context.ConnectionClosed.Register(() => connectionClosedTcs.SetResult());
return next(context);
};
});
});
});

using (var host = builder.Build())
{
await host.StartAsync();

var client = HttpHelpers.CreateClient(idleTimeout: TimeSpan.FromSeconds(1));
amcasey marked this conversation as resolved.
Show resolved Hide resolved
var port = host.GetPort();

// Act
var request1 = new HttpRequestMessage(HttpMethod.Get, $"https://127.0.0.1:{port}/");
request1.Version = HttpVersion.Version30;
request1.VersionPolicy = HttpVersionPolicy.RequestVersionExact;

var response1 = await client.SendAsync(request1, CancellationToken.None);
response1.EnsureSuccessStatusCode();

await connectionStartedTcs.Task.DefaultTimeout();
// Do not dispose the client, wait for it to idle out.

Logger.LogInformation("Waiting for server to receive connection close.");
await connectionClosedTcs.Task.DefaultTimeout();

await host.StopAsync();
}
}

[ConditionalFact]
[MsQuicSupported]
public async Task ConnectionLifetimeNotificationFeature_RequestClose_ConnectionEnds()
Expand Down