Skip to content

Commit 36598cd

Browse files
committed
More abort connection stuff
1 parent b38e627 commit 36598cd

File tree

8 files changed

+59
-33
lines changed

8 files changed

+59
-33
lines changed

src/Servers/Kestrel/Core/src/CoreStrings.resx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,6 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
675675
<value>The client sent a {frameType} frame to a control stream before the SETTINGS frame.</value>
676676
</data>
677677
<data name="Http3ErrorControlStreamReservedSetting" xml:space="preserve">
678-
<value>The client sent a reserved setting {identifier}.</value>
678+
<value>The client sent a reserved setting identifier: {identifier}</value>
679679
</data>
680-
</root>
680+
</root>

src/Servers/Kestrel/Core/src/Internal/Http3/Http3Connection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ internal long HighestStreamId
7878
public Http3ControlStream? ControlStream { get; set; }
7979
public Http3ControlStream? EncoderStream { get; set; }
8080
public Http3ControlStream? DecoderStream { get; set; }
81+
public string ConnectionId => _context.ConnectionId;
8182

8283
public async Task ProcessStreamsAsync<TContext>(IHttpApplication<TContext> httpApplication) where TContext : notnull
8384
{
@@ -354,7 +355,7 @@ internal async Task InnerProcessStreamsAsync<TContext>(IHttpApplication<TContext
354355

355356
foreach (var stream in _streams.Values)
356357
{
357-
stream.Abort(connectionError);
358+
stream.Abort(connectionError, (Http3ErrorCode)_errorCodeFeature.Error);
358359
}
359360

360361
while (_activeRequestCount > 0)

src/Servers/Kestrel/Core/src/Internal/Http3/Http3ConnectionErrorException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3
99
internal class Http3ConnectionErrorException : Exception
1010
{
1111
public Http3ConnectionErrorException(string message, Http3ErrorCode errorCode)
12-
: base($"HTTP/3 stream error ({errorCode}): {message}")
12+
: base($"HTTP/3 connection error ({errorCode}): {message}")
1313
{
1414
ErrorCode = errorCode;
1515
}

src/Servers/Kestrel/Core/src/Internal/Http3/Http3ControlStream.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ internal abstract class Http3ControlStream : IThreadPoolWorkItem
2828
private readonly Http3StreamContext _context;
2929
private readonly Http3PeerSettings _serverPeerSettings;
3030
private readonly IStreamIdFeature _streamIdFeature;
31+
private readonly IProtocolErrorCodeFeature _protocolErrorCodeFeature;
3132
private readonly Http3RawFrame _incomingFrame = new Http3RawFrame();
3233
private volatile int _isClosed;
3334
private int _gracefulCloseInitiator;
@@ -41,6 +42,7 @@ public Http3ControlStream(Http3Connection http3Connection, Http3StreamContext co
4142
_context = context;
4243
_serverPeerSettings = context.ServerSettings;
4344
_streamIdFeature = context.ConnectionFeatures.Get<IStreamIdFeature>()!;
45+
_protocolErrorCodeFeature = context.ConnectionFeatures.Get<IProtocolErrorCodeFeature>()!;
4446

4547
_frameWriter = new Http3FrameWriter(
4648
context.Transport.Output,
@@ -217,6 +219,9 @@ private async Task HandleControlStream()
217219
}
218220
catch (Http3ConnectionErrorException ex)
219221
{
222+
_protocolErrorCodeFeature.Error = (long)ex.ErrorCode;
223+
224+
Log.Http3ConnectionError(_http3Connection.ConnectionId, ex);
220225
_http3Connection.Abort(new ConnectionAbortedException(ex.Message, ex), ex.ErrorCode);
221226
}
222227
finally

src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,13 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli
389389
}
390390
catch (Http3ConnectionErrorException ex)
391391
{
392-
// TODO: Abort overall connection
393392
error = ex;
394-
Abort(new ConnectionAbortedException(ex.Message, ex), ex.ErrorCode);
393+
_errorCodeFeature.Error = (long)ex.ErrorCode;
394+
395+
Log.Http3ConnectionError(_http3Connection.ConnectionId, ex);
396+
_http3Connection.Abort(new ConnectionAbortedException(ex.Message, ex), ex.ErrorCode);
397+
398+
// TODO: HTTP/3 stream will be aborted by connection. Check this is correct.
395399
}
396400
catch (Exception ex)
397401
{

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http3/Http3ConnectionTests.cs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Globalization;
67
using System.Net.Http;
78
using System.Text;
89
using System.Threading.Tasks;
@@ -15,22 +16,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
1516
{
1617
public class Http3ConnectionTests : Http3TestBase
1718
{
18-
[Fact]
19-
public async Task GoAwayReceived()
20-
{
21-
await InitializeConnectionAsync(_echoApplication);
22-
23-
var outboundcontrolStream = await CreateControlStream();
24-
var inboundControlStream = await GetInboundControlStream();
25-
26-
Connection.Abort(new ConnectionAbortedException(), Http3ErrorCode.NoError);
27-
await _closedStateReached.Task.DefaultTimeout();
28-
await WaitForConnectionErrorAsync(
29-
ignoreNonGoAwayFrames: true,
30-
expectedLastStreamId: 0,
31-
expectedErrorCode: Http3ErrorCode.NoError);
32-
}
33-
3419
[Fact]
3520
public async Task CreateRequestStream_RequestCompleted_Disposed()
3621
{
@@ -83,23 +68,29 @@ public async Task GracefulServerShutdownSendsGoawayClosesConnection()
8368
Assert.Null(await MultiplexedConnectionContext.AcceptAsync().DefaultTimeout());
8469
}
8570

86-
[Fact]
87-
public async Task SETTINGS_ReservedSettingSent_ConnectionError()
71+
[Theory]
72+
[InlineData(0x0)]
73+
[InlineData(0x2)]
74+
[InlineData(0x3)]
75+
[InlineData(0x4)]
76+
[InlineData(0x5)]
77+
public async Task SETTINGS_ReservedSettingSent_ConnectionError(long settingIdentifier)
8878
{
8979
await InitializeConnectionAsync(_echoApplication);
9080

9181
var outboundcontrolStream = await CreateControlStream();
9282
await outboundcontrolStream.SendSettingsAsync(new List<Http3PeerSetting>
9383
{
94-
new Http3PeerSetting(0x0, 0) // reserved value
84+
new Http3PeerSetting((Internal.Http3.Http3SettingType) settingIdentifier, 0) // reserved value
9585
});
9686

9787
await GetInboundControlStream();
9888

99-
await WaitForConnectionErrorAsync(
89+
await WaitForConnectionErrorAsync<Http3ConnectionErrorException>(
10090
ignoreNonGoAwayFrames: true,
10191
expectedLastStreamId: 0,
102-
expectedErrorCode: Http3ErrorCode.SettingsError);
92+
expectedErrorCode: Http3ErrorCode.SettingsError,
93+
expectedErrorMessage: $"HTTP/3 connection error (SettingsError): The client sent a reserved setting identifier: 0x{settingIdentifier.ToString("X", CultureInfo.InvariantCulture)}");
10394
}
10495
}
10596
}

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http3/Http3StreamTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,12 @@ public async Task UnexpectedRequestFrame(string frameType)
17551755
await requestStream.WaitForStreamErrorAsync(
17561756
Http3ErrorCode.UnexpectedFrame,
17571757
expectedErrorMessage: CoreStrings.FormatHttp3ErrorUnsupportedFrameOnRequestStream(frame.FormattedType));
1758+
1759+
await WaitForConnectionErrorAsync<Http3ConnectionErrorException>(
1760+
ignoreNonGoAwayFrames: true,
1761+
expectedLastStreamId: 0,
1762+
expectedErrorCode: Http3ErrorCode.UnexpectedFrame,
1763+
expectedErrorMessage: CoreStrings.FormatHttp3ErrorUnsupportedFrameOnRequestStream(frame.FormattedType));
17581764
}
17591765

17601766
[Theory]

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http3/Http3TestBase.cs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ internal async ValueTask<Http3ControlStream> GetInboundControlStream()
137137
return null;
138138
}
139139

140-
internal async Task WaitForConnectionErrorAsync(bool ignoreNonGoAwayFrames, long expectedLastStreamId, Http3ErrorCode expectedErrorCode)
140+
internal async Task WaitForConnectionErrorAsync<TException>(bool ignoreNonGoAwayFrames, long expectedLastStreamId, Http3ErrorCode expectedErrorCode, params string[] expectedErrorMessage)
141+
where TException : Exception
141142
{
142143
var frame = await _inboundControlStream.ReceiveFrameAsync();
143144

@@ -149,9 +150,16 @@ internal async Task WaitForConnectionErrorAsync(bool ignoreNonGoAwayFrames, long
149150
}
150151
}
151152

153+
VerifyGoAway(frame, expectedLastStreamId);
154+
152155
Assert.Equal((long)expectedErrorCode, MultiplexedConnectionContext.Error);
153156

154-
VerifyGoAway(frame, expectedLastStreamId);
157+
if (expectedErrorMessage?.Length > 0)
158+
{
159+
var message = Assert.Single(LogMessages, m => m.Exception is TException);
160+
161+
Assert.Contains(expectedErrorMessage, expected => message.Exception.Message.Contains(expected));
162+
}
155163
}
156164

157165
internal void VerifyGoAway(Http3FrameWithPayload frame, long expectedLastStreamId)
@@ -181,6 +189,8 @@ internal async ValueTask<Http3RequestStream> InitializeConnectionAndStreamsAsync
181189

182190
OutboundControlStream = await CreateControlStream();
183191

192+
await GetInboundControlStream();
193+
184194
return await CreateRequestStream();
185195
}
186196

@@ -447,12 +457,21 @@ internal async Task WaitForStreamErrorAsync(Http3ErrorCode protocolError, string
447457
_testBase.Logger.LogTrace("Input is completed");
448458

449459
Assert.True(readResult.IsCompleted);
450-
Assert.Equal((long)protocolError, Error);
451-
452-
if (expectedErrorMessage != null)
460+
//try
453461
{
454-
Assert.Contains(_testBase.LogMessages, m => m.Exception?.Message.Contains(expectedErrorMessage) ?? false);
462+
Assert.Equal(protocolError, (Http3ErrorCode)Error);
463+
464+
if (expectedErrorMessage != null)
465+
{
466+
Assert.Contains(_testBase.LogMessages, m => m.Exception?.Message.Contains(expectedErrorMessage) ?? false);
467+
}
455468
}
469+
//catch (Exception ex)
470+
//{
471+
// Debugger.Launch();
472+
// string s = ex.Message;
473+
// throw;
474+
//}
456475
}
457476
}
458477

0 commit comments

Comments
 (0)