Skip to content

Commit 97577a4

Browse files
committed
Apply ConnectionLimitMiddleware to HTTP/3 connections
1 parent 1a821c6 commit 97577a4

File tree

4 files changed

+33
-13
lines changed

4 files changed

+33
-13
lines changed

src/Servers/Kestrel/Core/src/KestrelServer.cs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ async Task OnBind(ListenOptions options)
162162
options.UseHttp3Server(ServiceContext, application, options.Protocols);
163163
var multiplexedConnectionDelegate = ((IMultiplexedConnectionBuilder)options).Build();
164164

165+
// Add the connection limit middleware
166+
multiplexedConnectionDelegate = EnforceConnectionLimit(multiplexedConnectionDelegate, Options.Limits.MaxConcurrentConnections, Trace);
167+
165168
options.EndPoint = await _transportManager.BindAsync(options.EndPoint, multiplexedConnectionDelegate, options.EndpointConfig).ConfigureAwait(false);
166169
}
167170

@@ -180,10 +183,7 @@ async Task OnBind(ListenOptions options)
180183
var connectionDelegate = options.Build();
181184

182185
// Add the connection limit middleware
183-
if (Options.Limits.MaxConcurrentConnections.HasValue)
184-
{
185-
connectionDelegate = new ConnectionLimitMiddleware(connectionDelegate, Options.Limits.MaxConcurrentConnections.Value, Trace).OnConnectionAsync;
186-
}
186+
connectionDelegate = EnforceConnectionLimit(connectionDelegate, Options.Limits.MaxConcurrentConnections, Trace);
187187

188188
options.EndPoint = await _transportManager.BindAsync(options.EndPoint, connectionDelegate, options.EndpointConfig).ConfigureAwait(false);
189189
}
@@ -359,5 +359,25 @@ private void ValidateOptions()
359359
CoreStrings.FormatMaxRequestBufferSmallerThanRequestHeaderBuffer(Options.Limits.MaxRequestBufferSize.Value, Options.Limits.MaxRequestHeadersTotalSize));
360360
}
361361
}
362+
363+
private static ConnectionDelegate EnforceConnectionLimit(ConnectionDelegate innerDelegate, long? connectionLimit, IKestrelTrace trace)
364+
{
365+
if (!connectionLimit.HasValue)
366+
{
367+
return innerDelegate;
368+
}
369+
370+
return new ConnectionLimitMiddleware<ConnectionContext>(c => innerDelegate(c), connectionLimit.Value, trace).OnConnectionAsync;
371+
}
372+
373+
private static MultiplexedConnectionDelegate EnforceConnectionLimit(MultiplexedConnectionDelegate innerDelegate, long? connectionLimit, IKestrelTrace trace)
374+
{
375+
if (!connectionLimit.HasValue)
376+
{
377+
return innerDelegate;
378+
}
379+
380+
return new ConnectionLimitMiddleware<MultiplexedConnectionContext>(c => innerDelegate(c), connectionLimit.Value, trace).OnConnectionAsync;
381+
}
362382
}
363383
}

src/Servers/Kestrel/Core/src/Middleware/ConnectionLimitMiddleware.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Threading.Tasks;
56
using Microsoft.AspNetCore.Connections;
67
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
78
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
89

910
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
1011
{
11-
internal class ConnectionLimitMiddleware
12+
internal class ConnectionLimitMiddleware<T> where T : BaseConnectionContext
1213
{
13-
private readonly ConnectionDelegate _next;
14+
private readonly Func<T, Task> _next;
1415
private readonly ResourceCounter _concurrentConnectionCounter;
1516
private readonly IKestrelTrace _trace;
1617

17-
public ConnectionLimitMiddleware(ConnectionDelegate next, long connectionLimit, IKestrelTrace trace)
18+
public ConnectionLimitMiddleware(Func<T, Task> next, long connectionLimit, IKestrelTrace trace)
1819
: this(next, ResourceCounter.Quota(connectionLimit), trace)
1920
{
2021
}
2122

2223
// For Testing
23-
internal ConnectionLimitMiddleware(ConnectionDelegate next, ResourceCounter concurrentConnectionCounter, IKestrelTrace trace)
24+
internal ConnectionLimitMiddleware(Func<T, Task> next, ResourceCounter concurrentConnectionCounter, IKestrelTrace trace)
2425
{
2526
_next = next;
2627
_concurrentConnectionCounter = concurrentConnectionCounter;
2728
_trace = trace;
2829
}
2930

30-
public async Task OnConnectionAsync(ConnectionContext connection)
31+
public async Task OnConnectionAsync(T connection)
3132
{
3233
if (!_concurrentConnectionCounter.TryLockOne())
3334
{
3435
KestrelEventSource.Log.ConnectionRejected(connection.ConnectionId);
3536
_trace.ConnectionRejected(connection.ConnectionId);
36-
connection.Transport.Input.Complete();
37-
connection.Transport.Output.Complete();
37+
await connection.DisposeAsync();
3838
return;
3939
}
4040

src/Servers/Kestrel/test/InMemory.FunctionalTests/ConnectionLimitTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Net;
66
using System.Threading;
77
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Connections;
89
using Microsoft.AspNetCore.Http;
910
using Microsoft.AspNetCore.Http.Features;
1011
using Microsoft.AspNetCore.Server.Kestrel.Core;
@@ -13,7 +14,6 @@
1314
using Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests.TestTransport;
1415
using Microsoft.AspNetCore.Server.Kestrel.Tests;
1516
using Microsoft.AspNetCore.Testing;
16-
using Microsoft.Extensions.Logging.Testing;
1717
using Xunit;
1818

1919
namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
@@ -211,7 +211,7 @@ private TestServer CreateServerWithMaxConnections(RequestDelegate app, ResourceC
211211
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
212212
listenOptions.Use(next =>
213213
{
214-
var middleware = new ConnectionLimitMiddleware(next, concurrentConnectionCounter, serviceContext.Log);
214+
var middleware = new ConnectionLimitMiddleware<ConnectionContext>(c => next(c), concurrentConnectionCounter, serviceContext.Log);
215215
return middleware.OnConnectionAsync;
216216
});
217217

0 commit comments

Comments
 (0)