Skip to content

Commit c41a6ab

Browse files
committed
Added support for setting the read and write buffers on each transport
1 parent c5b27b2 commit c41a6ab

File tree

10 files changed

+50
-16
lines changed

10 files changed

+50
-16
lines changed

src/Servers/Kestrel/Transport.Libuv/src/Internal/LibuvConnection.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ public LibuvConnection(UvStreamHandle socket,
3939
IPEndPoint remoteEndPoint,
4040
IPEndPoint localEndPoint,
4141
PipeOptions inputOptions = null,
42-
PipeOptions outputOptions = null)
42+
PipeOptions outputOptions = null,
43+
long? maxReadBufferSize = null,
44+
long? maxWriteBufferSize = null)
4345
{
4446
_socket = socket;
4547

@@ -50,8 +52,11 @@ public LibuvConnection(UvStreamHandle socket,
5052
Log = log;
5153
Thread = thread;
5254

53-
inputOptions ??= new PipeOptions(MemoryPool, PipeScheduler.ThreadPool, Thread, useSynchronizationContext: false);
54-
outputOptions ??= new PipeOptions(MemoryPool, Thread, PipeScheduler.ThreadPool, useSynchronizationContext: false);
55+
maxReadBufferSize ??= 0;
56+
maxWriteBufferSize ??= 0;
57+
58+
inputOptions ??= new PipeOptions(MemoryPool, PipeScheduler.ThreadPool, Thread, maxReadBufferSize.Value, maxReadBufferSize.Value / 2, useSynchronizationContext: false);
59+
outputOptions ??= new PipeOptions(MemoryPool, Thread, PipeScheduler.ThreadPool, maxWriteBufferSize.Value, maxWriteBufferSize.Value / 2, useSynchronizationContext: false);
5560

5661
var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions);
5762

src/Servers/Kestrel/Transport.Libuv/src/Internal/ListenerContext.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ protected internal void HandleConnection(UvStreamHandle socket)
8787
}
8888
}
8989

90-
var connection = new LibuvConnection(socket, TransportContext.Log, Thread, remoteEndPoint, localEndPoint, InputOptions, OutputOptions);
90+
var options = TransportContext.Options;
91+
var connection = new LibuvConnection(socket, TransportContext.Log, Thread, remoteEndPoint, localEndPoint, InputOptions, OutputOptions, options.MaxReadBufferSize, options.MaxWriteBufferSize);
9192
connection.Start();
9293

9394
bool accepted = _acceptQueue.Writer.TryWrite(connection);

src/Servers/Kestrel/Transport.Libuv/src/LibuvTransportOptions.cs

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

44
using System;
55
using System.Buffers;
6+
using System.IO.Pipelines;
67
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
78

89
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
@@ -22,6 +23,10 @@ public class LibuvTransportOptions
2223

2324
public bool NoDelay { get; set; }
2425

26+
public long? MaxReadBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
27+
28+
public long? MaxWriteBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
29+
2530
internal Func<MemoryPool<byte>> MemoryPoolFactory { get; set; } = () => KestrelMemoryPool.Create();
2631

2732
private static int ProcessorThreadCount

src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ internal sealed class SocketConnection : TransportConnection
3434
private volatile Exception _shutdownReason;
3535
private Task _task;
3636

37-
internal SocketConnection(Socket socket, MemoryPool<byte> memoryPool, PipeScheduler scheduler, ISocketsTrace trace)
37+
internal SocketConnection(Socket socket,
38+
MemoryPool<byte> memoryPool,
39+
PipeScheduler scheduler,
40+
ISocketsTrace trace,
41+
long? maxReadBufferSize = null,
42+
long? maxWriteBufferSize = null)
3843
{
3944
Debug.Assert(socket != null);
4045
Debug.Assert(memoryPool != null);
@@ -58,8 +63,11 @@ internal SocketConnection(Socket socket, MemoryPool<byte> memoryPool, PipeSchedu
5863
_receiver = new SocketReceiver(_socket, awaiterScheduler);
5964
_sender = new SocketSender(_socket, awaiterScheduler);
6065

61-
var inputOptions = new PipeOptions(MemoryPool, PipeScheduler.ThreadPool, awaiterScheduler, useSynchronizationContext: false);
62-
var outputOptions = new PipeOptions(MemoryPool, awaiterScheduler, PipeScheduler.ThreadPool, useSynchronizationContext: false);
66+
maxReadBufferSize ??= 0;
67+
maxWriteBufferSize ??= 0;
68+
69+
var inputOptions = new PipeOptions(MemoryPool, PipeScheduler.ThreadPool, awaiterScheduler, maxReadBufferSize.Value, maxReadBufferSize.Value / 2, useSynchronizationContext: false);
70+
var outputOptions = new PipeOptions(MemoryPool, awaiterScheduler, PipeScheduler.ThreadPool, maxWriteBufferSize.Value, maxWriteBufferSize.Value / 2, useSynchronizationContext: false);
6371

6472
var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions);
6573

src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionListener.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public async ValueTask<ConnectionContext> AcceptAsync(CancellationToken cancella
100100
var acceptSocket = await _listenSocket.AcceptAsync();
101101
acceptSocket.NoDelay = _options.NoDelay;
102102

103-
var connection = new SocketConnection(acceptSocket, _memoryPool, _schedulers[_schedulerIndex], _trace);
103+
var connection = new SocketConnection(acceptSocket, _memoryPool, _schedulers[_schedulerIndex], _trace, _options.MaxReadBufferSize, _options.MaxWriteBufferSize);
104104

105105
connection.Start();
106106

src/Servers/Kestrel/Transport.Sockets/src/SocketTransportOptions.cs

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

44
using System;
55
using System.Buffers;
6+
using System.IO.Pipelines;
67
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
78

89
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
@@ -19,6 +20,10 @@ public class SocketTransportOptions
1920

2021
public bool NoDelay { get; set; }
2122

23+
public long? MaxReadBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
24+
25+
public long? MaxWriteBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
26+
2227
internal Func<MemoryPool<byte>> MemoryPoolFactory { get; set; } = () => KestrelMemoryPool.Create();
2328
}
2429
}

src/Servers/Kestrel/shared/test/TransportTestHelpers/TestServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public TestServer(RequestDelegate app, TestServiceContext context, Action<Kestre
6161
_app = app;
6262
Context = context;
6363

64-
_host = TransportSelector.GetWebHostBuilder(context.MemoryPoolFactory)
64+
_host = TransportSelector.GetWebHostBuilder(context.MemoryPoolFactory, context.ServerOptions.Limits.MaxRequestBufferSize)
6565
.UseKestrel(options =>
6666
{
6767
configureKestrel(options);

src/Servers/Kestrel/test/FunctionalTests/MaxRequestBufferSizeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ private async Task<IWebHost> StartWebHost(long? maxRequestBufferSize,
289289
TaskCompletionSource<object> clientFinishedSendingRequestBody,
290290
Func<MemoryPool<byte>> memoryPoolFactory = null)
291291
{
292-
var host = TransportSelector.GetWebHostBuilder(memoryPoolFactory)
292+
var host = TransportSelector.GetWebHostBuilder(memoryPoolFactory, maxRequestBufferSize)
293293
.ConfigureServices(AddTestLogging)
294294
.UseKestrel(options =>
295295
{
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// 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

44
using System;
@@ -9,9 +9,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
99
{
1010
public static class TransportSelector
1111
{
12-
public static IWebHostBuilder GetWebHostBuilder(Func<MemoryPool<byte>> memoryPoolFactory = null)
12+
public static IWebHostBuilder GetWebHostBuilder(Func<MemoryPool<byte>> memoryPoolFactory = null,
13+
long? maxReadBufferSize = null)
1314
{
14-
return new WebHostBuilder().UseLibuv(options => { options.MemoryPoolFactory = memoryPoolFactory ?? options.MemoryPoolFactory; });
15+
return new WebHostBuilder().UseLibuv(options =>
16+
{
17+
options.MemoryPoolFactory = memoryPoolFactory ?? options.MemoryPoolFactory;
18+
options.MaxReadBufferSize = maxReadBufferSize;
19+
});
1520
}
1621
}
1722
}
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// 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

44
using System;
@@ -9,9 +9,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
99
{
1010
public static class TransportSelector
1111
{
12-
public static IWebHostBuilder GetWebHostBuilder(Func<MemoryPool<byte>> memoryPoolFactory = null)
12+
public static IWebHostBuilder GetWebHostBuilder(Func<MemoryPool<byte>> memoryPoolFactory = null,
13+
long? maxReadBufferSize = null)
1314
{
14-
return new WebHostBuilder().UseSockets(options => { options.MemoryPoolFactory = memoryPoolFactory ?? options.MemoryPoolFactory; });
15+
return new WebHostBuilder().UseSockets(options =>
16+
{
17+
options.MemoryPoolFactory = memoryPoolFactory ?? options.MemoryPoolFactory;
18+
options.MaxReadBufferSize = maxReadBufferSize;
19+
});
1520
}
1621
}
1722
}

0 commit comments

Comments
 (0)