Skip to content

Commit 580cbae

Browse files
committed
HTTP/3: Close unsupported unidirectional stream types
1 parent 76d5c62 commit 580cbae

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,4 +686,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
686686
<data name="Http3ControlStreamHeaderTimeout" xml:space="preserve">
687687
<value>Reading the control stream header timed out.</value>
688688
</data>
689+
<data name="Http3ControlStreamErrorUnsupportedType" xml:space="preserve">
690+
<value>Stream type {type} is unsupported.</value>
691+
</data>
689692
</root>

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,6 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli
157157

158158
switch (_headerType)
159159
{
160-
case -1:
161-
return;
162160
case ControlStreamTypeId:
163161
if (!_context.StreamLifetimeHandler.OnInboundControlStream(this))
164162
{
@@ -186,10 +184,13 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli
186184
await HandleEncodingDecodingTask();
187185
break;
188186
default:
189-
// TODO Close the control stream as it's unexpected.
190-
break;
187+
throw new Http3StreamErrorException(CoreStrings.FormatHttp3ControlStreamErrorUnsupportedType(_headerType), Http3ErrorCode.StreamCreationError);
191188
}
192189
}
190+
catch (Http3StreamErrorException ex)
191+
{
192+
Abort(new ConnectionAbortedException(ex.Message), ex.ErrorCode);
193+
}
193194
catch (Http3ConnectionErrorException ex)
194195
{
195196
_errorCodeFeature.Error = (long)ex.ErrorCode;

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,5 +2385,39 @@ public Task HEADERS_Received_RequestLineLength_Error()
23852385

23862386
return HEADERS_Received_InvalidHeaderFields_StreamError(headers, CoreStrings.BadRequest_RequestLineTooLong, Http3ErrorCode.RequestRejected);
23872387
}
2388+
2389+
[Theory]
2390+
[InlineData(1)]
2391+
[InlineData(4)]
2392+
[InlineData(int.MaxValue)]
2393+
public async Task UnsupportedControlStreamType(int typeId)
2394+
{
2395+
await InitializeConnectionAsync(_noopApplication);
2396+
2397+
var outboundControlStream = await CreateControlStream().DefaultTimeout();
2398+
await outboundControlStream.SendSettingsAsync(new List<Http3PeerSetting>());
2399+
2400+
var inboundControlStream = await GetInboundControlStream();
2401+
await inboundControlStream.ExpectSettingsAsync();
2402+
2403+
// Create unsupported control stream
2404+
var invalidStream = await CreateControlStream(typeId).DefaultTimeout();
2405+
await invalidStream.WaitForStreamErrorAsync(
2406+
Http3ErrorCode.StreamCreationError,
2407+
CoreStrings.FormatHttp3ControlStreamErrorUnsupportedType(typeId)).DefaultTimeout();
2408+
2409+
// Connection is still alive and available for requests
2410+
var requestStream = await CreateRequestStream().DefaultTimeout();
2411+
await requestStream.SendHeadersAsync(new[]
2412+
{
2413+
new KeyValuePair<string, string>(HeaderNames.Path, "/"),
2414+
new KeyValuePair<string, string>(HeaderNames.Scheme, "http"),
2415+
new KeyValuePair<string, string>(HeaderNames.Method, "GET"),
2416+
new KeyValuePair<string, string>(HeaderNames.Authority, "localhost:80"),
2417+
}, endStream: true);
2418+
2419+
await requestStream.ExpectHeadersAsync().DefaultTimeout();
2420+
await requestStream.ExpectReceiveEndOfStream().DefaultTimeout();
2421+
}
23882422
}
23892423
}

0 commit comments

Comments
 (0)