Skip to content

Commit e92aeff

Browse files
authored
HTTP/3: Close unsupported unidirectional stream types (#32160)
1 parent 5065fd8 commit e92aeff

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,4 +689,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
689689
<data name="Http3ErrorControlStreamClientClosedInbound" xml:space="preserve">
690690
<value>The client closed the connection control stream inbound to the server.</value>
691691
</data>
692+
<data name="Http3ControlStreamErrorUnsupportedType" xml:space="preserve">
693+
<value>Stream type {type} is unsupported.</value>
694+
</data>
692695
</root>

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

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

159159
switch (_headerType)
160160
{
161-
case -1:
162-
return;
163161
case ControlStreamTypeId:
164162
if (!_context.StreamLifetimeHandler.OnInboundControlStream(this))
165163
{
@@ -187,10 +185,14 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli
187185
await HandleEncodingDecodingTask();
188186
break;
189187
default:
190-
// TODO Close the control stream as it's unexpected.
191-
break;
188+
// https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-6.2-6
189+
throw new Http3StreamErrorException(CoreStrings.FormatHttp3ControlStreamErrorUnsupportedType(_headerType), Http3ErrorCode.StreamCreationError);
192190
}
193191
}
192+
catch (Http3StreamErrorException ex)
193+
{
194+
Abort(new ConnectionAbortedException(ex.Message), ex.ErrorCode);
195+
}
194196
catch (Http3ConnectionErrorException ex)
195197
{
196198
_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)