Browse Source

Clamp HTTP2 config values in configureGRPCServerPipeline (#2000)

Gustavo Cairo 1 year ago
parent
commit
7585a7f56d
1 changed files with 28 additions and 15 deletions
  1. 28 15
      Sources/GRPCHTTP2Core/Internal/NIOChannelPipeline+GRPC.swift

+ 28 - 15
Sources/GRPCHTTP2Core/Internal/NIOChannelPipeline+GRPC.swift

@@ -51,10 +51,13 @@ extension ChannelPipeline.SynchronousOperations {
     )
     try self.addHandler(flushNotificationHandler)
 
+    let clampedTargetWindowSize = self.clampTargetWindowSize(http2Config.targetWindowSize)
+    let clampedMaxFrameSize = self.clampMaxFrameSize(http2Config.maxFrameSize)
+
     var http2HandlerConnectionConfiguration = NIOHTTP2Handler.ConnectionConfiguration()
     var http2HandlerHTTP2Settings = HTTP2Settings([
-      HTTP2Setting(parameter: .initialWindowSize, value: http2Config.targetWindowSize),
-      HTTP2Setting(parameter: .maxFrameSize, value: http2Config.maxFrameSize),
+      HTTP2Setting(parameter: .initialWindowSize, value: clampedTargetWindowSize),
+      HTTP2Setting(parameter: .maxFrameSize, value: clampedMaxFrameSize),
       HTTP2Setting(parameter: .maxHeaderListSize, value: HPACKDecoder.defaultMaxHeaderListSize),
     ])
     if let maxConcurrentStreams = http2Config.maxConcurrentStreams {
@@ -65,7 +68,7 @@ extension ChannelPipeline.SynchronousOperations {
     http2HandlerConnectionConfiguration.initialSettings = http2HandlerHTTP2Settings
 
     var http2HandlerStreamConfiguration = NIOHTTP2Handler.StreamConfiguration()
-    http2HandlerStreamConfiguration.targetWindowSize = http2Config.targetWindowSize
+    http2HandlerStreamConfiguration.targetWindowSize = clampedTargetWindowSize
 
     let streamMultiplexer = try self.configureAsyncHTTP2Pipeline(
       mode: .server,
@@ -111,18 +114,8 @@ extension ChannelPipeline.SynchronousOperations {
     NIOAsyncChannel<ClientConnectionEvent, Void>,
     NIOHTTP2Handler.AsyncStreamMultiplexer<Void>
   ) {
-    // Window size which mustn't exceed 2^32 - 1 (RFC 9113 § 6.1.3).
-    let clampedTargetWindowSize = min(config.http2.targetWindowSize, (1 << 31) - 1)
-
-    // Max frame size must be in the range 2^14 ..< 2^24 (RFC 9113 § 6.1.3).
-    let clampedMaxFrameSize: Int
-    if config.http2.maxFrameSize >= (1 << 24) {
-      clampedMaxFrameSize = (1 << 24) - 1
-    } else if config.http2.maxFrameSize < (1 << 14) {
-      clampedMaxFrameSize = (1 << 14)
-    } else {
-      clampedMaxFrameSize = config.http2.maxFrameSize
-    }
+    let clampedTargetWindowSize = self.clampTargetWindowSize(config.http2.targetWindowSize)
+    let clampedMaxFrameSize = self.clampMaxFrameSize(config.http2.maxFrameSize)
 
     // Use NIOs defaults as a starting point.
     var http2 = NIOHTTP2Handler.Configuration()
@@ -168,3 +161,23 @@ extension ChannelPipeline.SynchronousOperations {
     return (connection, multiplexer)
   }
 }
+
+extension ChannelPipeline.SynchronousOperations {
+  /// Max frame size must be in the range `2^14 ..< 2^24` (RFC 9113 § 4.2).
+  fileprivate func clampMaxFrameSize(_ maxFrameSize: Int) -> Int {
+    let clampedMaxFrameSize: Int
+    if maxFrameSize >= (1 << 24) {
+      clampedMaxFrameSize = (1 << 24) - 1
+    } else if maxFrameSize < (1 << 14) {
+      clampedMaxFrameSize = (1 << 14)
+    } else {
+      clampedMaxFrameSize = maxFrameSize
+    }
+    return clampedMaxFrameSize
+  }
+
+  /// Window size which mustn't exceed `2^31 - 1` (RFC 9113 § 6.5.2).
+  internal func clampTargetWindowSize(_ targetWindowSize: Int) -> Int {
+    min(targetWindowSize, (1 << 31) - 1)
+  }
+}