Skip to content

Commit b415675

Browse files
authored
Expose max reset streams HTTP2 configuration (#2226)
We have exposed the max reset stream frames config in NIO H2 (apple/swift-nio-http2#494) - we need to add configuration to expose it in gRPC v1 as well.
1 parent 3bbd57b commit b415675

7 files changed

+59
-24
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ let packageDependencies: [Package.Dependency] = [
3636
),
3737
.package(
3838
url: "https://github.com/apple/swift-nio-http2.git",
39-
from: "1.32.0"
39+
from: "1.36.0"
4040
),
4141
.package(
4242
url: "https://github.com/apple/swift-nio-transport-services.git",

Sources/GRPC/ClientConnection.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,13 @@ extension ClientConnection {
457457
}
458458
}
459459

460+
/// The HTTP/2 max number of reset streams. Defaults to 32. Must be non-negative.
461+
public var httpMaxResetStreams: Int = 32 {
462+
willSet {
463+
precondition(newValue >= 0, "httpMaxResetStreams must be non-negative")
464+
}
465+
}
466+
460467
/// A logger for background information (such as connectivity state). A separate logger for
461468
/// requests may be provided in the `CallOptions`.
462469
///
@@ -630,10 +637,12 @@ extension ChannelPipeline.SynchronousOperations {
630637
connectionIdleTimeout: TimeAmount,
631638
httpTargetWindowSize: Int,
632639
httpMaxFrameSize: Int,
640+
httpMaxResetStreams: Int,
633641
errorDelegate: ClientErrorDelegate?,
634642
logger: Logger
635643
) throws {
636-
let initialSettings = [
644+
var configuration = NIOHTTP2Handler.ConnectionConfiguration()
645+
configuration.initialSettings = [
637646
// As per the default settings for swift-nio-http2:
638647
HTTP2Setting(parameter: .maxHeaderListSize, value: HPACKDecoder.defaultMaxHeaderListSize),
639648
// We never expect (or allow) server initiated streams.
@@ -642,10 +651,11 @@ extension ChannelPipeline.SynchronousOperations {
642651
HTTP2Setting(parameter: .maxFrameSize, value: httpMaxFrameSize),
643652
HTTP2Setting(parameter: .initialWindowSize, value: httpTargetWindowSize),
644653
]
654+
configuration.maximumRecentlyResetStreams = httpMaxResetStreams
645655

646656
// We could use 'configureHTTP2Pipeline' here, but we need to add a few handlers between the
647657
// two HTTP/2 handlers so we'll do it manually instead.
648-
try self.addHandler(NIOHTTP2Handler(mode: .client, initialSettings: initialSettings))
658+
try self.addHandler(NIOHTTP2Handler(mode: .client, connectionConfiguration: configuration))
649659

650660
let h2Multiplexer = HTTP2StreamMultiplexer(
651661
mode: .client,

Sources/GRPC/ConnectionManagerChannelProvider.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ internal struct DefaultChannelProvider: ConnectionManagerChannelProvider {
7070
internal var httpTargetWindowSize: Int
7171
@usableFromInline
7272
internal var httpMaxFrameSize: Int
73+
@usableFromInline
74+
internal var httpMaxResetStreams: Int
7375

7476
@usableFromInline
7577
internal var errorDelegate: Optional<ClientErrorDelegate>
@@ -102,6 +104,7 @@ internal struct DefaultChannelProvider: ConnectionManagerChannelProvider {
102104
tlsConfiguration: GRPCTLSConfiguration?,
103105
httpTargetWindowSize: Int,
104106
httpMaxFrameSize: Int,
107+
httpMaxResetStreams: Int,
105108
errorDelegate: ClientErrorDelegate?,
106109
debugChannelInitializer: ((Channel) -> EventLoopFuture<Void>)?,
107110
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
@@ -114,6 +117,7 @@ internal struct DefaultChannelProvider: ConnectionManagerChannelProvider {
114117
tlsConfiguration: tlsConfiguration,
115118
httpTargetWindowSize: httpTargetWindowSize,
116119
httpMaxFrameSize: httpMaxFrameSize,
120+
httpMaxResetStreams: httpMaxResetStreams,
117121
errorDelegate: errorDelegate,
118122
debugChannelInitializer: debugChannelInitializer
119123
)
@@ -131,6 +135,7 @@ internal struct DefaultChannelProvider: ConnectionManagerChannelProvider {
131135
tlsConfiguration: GRPCTLSConfiguration?,
132136
httpTargetWindowSize: Int,
133137
httpMaxFrameSize: Int,
138+
httpMaxResetStreams: Int,
134139
errorDelegate: ClientErrorDelegate?,
135140
debugChannelInitializer: ((Channel) -> EventLoopFuture<Void>)?
136141
) {
@@ -143,6 +148,7 @@ internal struct DefaultChannelProvider: ConnectionManagerChannelProvider {
143148

144149
self.httpTargetWindowSize = httpTargetWindowSize
145150
self.httpMaxFrameSize = httpMaxFrameSize
151+
self.httpMaxResetStreams = httpMaxResetStreams
146152

147153
self.errorDelegate = errorDelegate
148154
self.debugChannelInitializer = debugChannelInitializer
@@ -180,6 +186,7 @@ internal struct DefaultChannelProvider: ConnectionManagerChannelProvider {
180186
tlsConfiguration: configuration.tlsConfiguration,
181187
httpTargetWindowSize: configuration.httpTargetWindowSize,
182188
httpMaxFrameSize: configuration.httpMaxFrameSize,
189+
httpMaxResetStreams: configuration.httpMaxResetStreams,
183190
errorDelegate: configuration.errorDelegate,
184191
debugChannelInitializer: configuration.debugChannelInitializer
185192
)
@@ -259,6 +266,7 @@ internal struct DefaultChannelProvider: ConnectionManagerChannelProvider {
259266
connectionIdleTimeout: self.connectionIdleTimeout,
260267
httpTargetWindowSize: self.httpTargetWindowSize,
261268
httpMaxFrameSize: self.httpMaxFrameSize,
269+
httpMaxResetStreams: self.httpMaxResetStreams,
262270
errorDelegate: self.errorDelegate,
263271
logger: logger
264272
)

Sources/GRPC/ConnectionPool/GRPCChannelPool.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,13 @@ extension GRPCChannelPool.Configuration {
261261
self.maxFrameSize = self.maxFrameSize.clamped(to: Self.allowedMaxFrameSizes)
262262
}
263263
}
264+
265+
/// The HTTP/2 max number of reset streams. Defaults to 32. Must be non-negative.
266+
public var maxResetStreams: Int = 32 {
267+
willSet {
268+
precondition(newValue >= 0, "maxResetStreams must be non-negative")
269+
}
270+
}
264271
}
265272
}
266273

Sources/GRPC/ConnectionPool/PooledChannel.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ internal final class PooledChannel: GRPCChannel {
9090
tlsConfiguration: configuration.transportSecurity.tlsConfiguration,
9191
httpTargetWindowSize: configuration.http2.targetWindowSize,
9292
httpMaxFrameSize: configuration.http2.maxFrameSize,
93+
httpMaxResetStreams: configuration.http2.maxResetStreams,
9394
errorDelegate: configuration.errorDelegate,
9495
debugChannelInitializer: configuration.debugChannelInitializer,
9596
nwParametersConfigurator: configuration.transportServices.nwParametersConfigurator
@@ -103,6 +104,7 @@ internal final class PooledChannel: GRPCChannel {
103104
tlsConfiguration: configuration.transportSecurity.tlsConfiguration,
104105
httpTargetWindowSize: configuration.http2.targetWindowSize,
105106
httpMaxFrameSize: configuration.http2.maxFrameSize,
107+
httpMaxResetStreams: configuration.http2.maxResetStreams,
106108
errorDelegate: configuration.errorDelegate,
107109
debugChannelInitializer: configuration.debugChannelInitializer
108110
)
@@ -116,6 +118,7 @@ internal final class PooledChannel: GRPCChannel {
116118
tlsConfiguration: configuration.transportSecurity.tlsConfiguration,
117119
httpTargetWindowSize: configuration.http2.targetWindowSize,
118120
httpMaxFrameSize: configuration.http2.maxFrameSize,
121+
httpMaxResetStreams: configuration.http2.maxResetStreams,
119122
errorDelegate: configuration.errorDelegate,
120123
debugChannelInitializer: configuration.debugChannelInitializer
121124
)

Sources/GRPC/GRPCServerPipelineConfigurator.swift

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -79,27 +79,27 @@ final class GRPCServerPipelineConfigurator: ChannelInboundHandler, RemovableChan
7979

8080
/// Makes an HTTP/2 handler.
8181
private func makeHTTP2Handler() -> NIOHTTP2Handler {
82-
return .init(
83-
mode: .server,
84-
initialSettings: [
85-
HTTP2Setting(
86-
parameter: .maxConcurrentStreams,
87-
value: self.configuration.httpMaxConcurrentStreams
88-
),
89-
HTTP2Setting(
90-
parameter: .maxHeaderListSize,
91-
value: HPACKDecoder.defaultMaxHeaderListSize
92-
),
93-
HTTP2Setting(
94-
parameter: .maxFrameSize,
95-
value: self.configuration.httpMaxFrameSize
96-
),
97-
HTTP2Setting(
98-
parameter: .initialWindowSize,
99-
value: self.configuration.httpTargetWindowSize
100-
),
101-
]
102-
)
82+
var configuration = NIOHTTP2Handler.ConnectionConfiguration()
83+
configuration.initialSettings = [
84+
HTTP2Setting(
85+
parameter: .maxConcurrentStreams,
86+
value: self.configuration.httpMaxConcurrentStreams
87+
),
88+
HTTP2Setting(
89+
parameter: .maxHeaderListSize,
90+
value: HPACKDecoder.defaultMaxHeaderListSize
91+
),
92+
HTTP2Setting(
93+
parameter: .maxFrameSize,
94+
value: self.configuration.httpMaxFrameSize
95+
),
96+
HTTP2Setting(
97+
parameter: .initialWindowSize,
98+
value: self.configuration.httpTargetWindowSize
99+
),
100+
]
101+
configuration.maximumRecentlyResetStreams = self.configuration.httpMaxResetStreams
102+
return NIOHTTP2Handler(mode: .server, connectionConfiguration: configuration)
103103
}
104104

105105
/// Makes an HTTP/2 multiplexer suitable handling gRPC requests.

Sources/GRPC/Server.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,13 @@ extension Server {
379379
}
380380
}
381381

382+
/// The HTTP/2 max number of reset streams. Defaults to 32. Must be non-negative.
383+
public var httpMaxResetStreams: Int = 32 {
384+
willSet {
385+
precondition(newValue >= 0, "httpMaxResetStreams must be non-negative")
386+
}
387+
}
388+
382389
/// The root server logger. Accepted connections will branch from this logger and RPCs on
383390
/// each connection will use a logger branched from the connections logger. This logger is made
384391
/// available to service providers via `context`. Defaults to a no-op logger.

0 commit comments

Comments
 (0)