From a40d5771fc586e75f3534e55178398baa1db2966 Mon Sep 17 00:00:00 2001 From: agnosticdev Date: Thu, 9 Jul 2026 07:54:18 -0700 Subject: [PATCH 1/2] SwiftQUIC: Expose remote datagram frame size through connection metadata --- .../Protocols/QUICConnectionProtocol.swift | 16 ++++++++++ .../SwiftNetwork/QUIC/QUICConnection.swift | 5 ++++ .../SwiftNetworkQUICHarnessTests.swift | 30 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift b/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift index a20ff62..ea1fc65 100644 --- a/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift @@ -779,6 +779,7 @@ public struct QUICConnectionProtocol: NetworkProtocol { var getApplicationResultHandler: QUICMetadataGetApplicationResultHandler? var setLinkFlowControlledHandler: QUICMetadataBoolSetterHandler? var getResetStreamAtSupportedHandler: QUICMetadataBoolGetterHandler? + var getRemoteMaxDatagramFrameSizeHandler: QUICMetadata16GetterHandler? #if !NETWORK_NO_SWIFT_QUIC var getLocalConnectionIDsHandler: (() -> [QUICConnectionID])? #endif @@ -1093,6 +1094,15 @@ public struct QUICConnectionProtocol: NetworkProtocol { } } + public func getRemoteDatagramFrameSize() -> UInt16 { + mutex.withLock { _ in + guard let getRemoteMaxDatagramFrameSize = self.getRemoteMaxDatagramFrameSizeHandler else { + return 0 + } + return getRemoteMaxDatagramFrameSize() + } + } + #if !NETWORK_NO_SWIFT_QUIC func getLocalConnectionIDs() -> [QUICConnectionID] { mutex.withLock { _ in @@ -1154,6 +1164,12 @@ public struct QUICConnectionProtocol: NetworkProtocol { } } + func getRemoteMaxDatagramFrameSize(handler: @escaping QUICMetadata16GetterHandler) { + mutex.withLock { _ in + self.getRemoteMaxDatagramFrameSizeHandler = handler + } + } + #if !NETWORK_NO_SWIFT_QUIC func getLocalConnectionIDs(handler: @escaping () -> [QUICConnectionID]) { mutex.withLock { _ in diff --git a/Sources/SwiftNetwork/QUIC/QUICConnection.swift b/Sources/SwiftNetwork/QUIC/QUICConnection.swift index f4956d6..7155dcd 100644 --- a/Sources/SwiftNetwork/QUIC/QUICConnection.swift +++ b/Sources/SwiftNetwork/QUIC/QUICConnection.swift @@ -735,6 +735,10 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, let keepaliveSeconds = self.keepaliveDuration.seconds return UInt16(keepaliveSeconds) } + self.connectionMetadata.getRemoteMaxDatagramFrameSize { + let datagramFrameSize = self.remoteMaxDatagramFrameSize + return UInt16(truncatingIfNeeded: datagramFrameSize) + } self.connectionMetadata.getLocalConnectionIDs { self.localCIDs.managedConnectionIDs.map { $0.connectionID } @@ -754,6 +758,7 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, self.connectionMetadata.getRemoteMaxStreamsBidirectionalHandler = nil self.connectionMetadata.getRemoteMaxStreamsUnidirectionalHandler = nil self.connectionMetadata.getLocalConnectionIDsHandler = nil + self.connectionMetadata.getRemoteMaxDatagramFrameSizeHandler = nil #endif } diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift index e2f6e94..f4b3fec 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift @@ -653,6 +653,36 @@ final class SwiftNetworkQUICHarnessTests: NetTestCase { QUICTestHarness().runQUICTest(datagram: true, blockSize: 1000, blockCount: 10) } + func testQUICDatagramRemoteMaxDatagramFrameSize() { + QUICTestHarness().runQUICTest( + datagram: true, + blockSize: 1000, + blockCount: 1, + afterData: { harness in + let expectation = XCTestExpectation(description: "Wait for remote datagram frame size to be fetched") + harness.context.async { + let clientMetadata: ProtocolMetadata? = harness.state?.clientHarness.getMetadata() + XCTAssertNotNil(clientMetadata) + if let clientMetadata { + let clientRemoteSize = clientMetadata.connectionMetadata?.getRemoteDatagramFrameSize() + XCTAssertNotNil(clientRemoteSize) + XCTAssertEqual(clientRemoteSize, 65535) + } + let serverMetadata: ProtocolMetadata? = harness.state?.serverHarness.getMetadata() + XCTAssertNotNil(serverMetadata) + if let serverMetadata { + let serverRemoteSize = serverMetadata.connectionMetadata?.getRemoteDatagramFrameSize() + XCTAssertNotNil(serverRemoteSize) + XCTAssertEqual(serverRemoteSize, 65535) + } + expectation.fulfill() + } + let waitResult = XCTWaiter.wait(for: [expectation], timeout: 2.0) + XCTAssertEqual(waitResult, .completed, "Remote datagram frame size fetch should complete") + } + ) + } + // MARK: Unidirectional tests func testQUICHelloWorldUnidirectional() { From 72a6981f274e69863ad98b8cb43f99e52dc1b7bf Mon Sep 17 00:00:00 2001 From: agnosticdev Date: Thu, 9 Jul 2026 08:24:49 -0700 Subject: [PATCH 2/2] Review freedback --- .../Protocols/QUICConnectionProtocol.swift | 17 +---------------- Sources/SwiftNetwork/QUIC/QUICConnection.swift | 7 ++----- .../SwiftNetworkQUICHarnessTests.swift | 4 ++-- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift b/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift index ea1fc65..23f84b8 100644 --- a/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift @@ -753,6 +753,7 @@ public struct QUICConnectionProtocol: NetworkProtocol { public var applicationErrorReason: String? public var activeConnectionIDLimit: Int = 0 + public var remoteMaxDatagramFrameSize: UInt16 = 0 #if NETWORK_PRIVATE var privateStorage = QUICConnectionMetadataPrivateStorage() #endif @@ -779,7 +780,6 @@ public struct QUICConnectionProtocol: NetworkProtocol { var getApplicationResultHandler: QUICMetadataGetApplicationResultHandler? var setLinkFlowControlledHandler: QUICMetadataBoolSetterHandler? var getResetStreamAtSupportedHandler: QUICMetadataBoolGetterHandler? - var getRemoteMaxDatagramFrameSizeHandler: QUICMetadata16GetterHandler? #if !NETWORK_NO_SWIFT_QUIC var getLocalConnectionIDsHandler: (() -> [QUICConnectionID])? #endif @@ -1094,15 +1094,6 @@ public struct QUICConnectionProtocol: NetworkProtocol { } } - public func getRemoteDatagramFrameSize() -> UInt16 { - mutex.withLock { _ in - guard let getRemoteMaxDatagramFrameSize = self.getRemoteMaxDatagramFrameSizeHandler else { - return 0 - } - return getRemoteMaxDatagramFrameSize() - } - } - #if !NETWORK_NO_SWIFT_QUIC func getLocalConnectionIDs() -> [QUICConnectionID] { mutex.withLock { _ in @@ -1164,12 +1155,6 @@ public struct QUICConnectionProtocol: NetworkProtocol { } } - func getRemoteMaxDatagramFrameSize(handler: @escaping QUICMetadata16GetterHandler) { - mutex.withLock { _ in - self.getRemoteMaxDatagramFrameSizeHandler = handler - } - } - #if !NETWORK_NO_SWIFT_QUIC func getLocalConnectionIDs(handler: @escaping () -> [QUICConnectionID]) { mutex.withLock { _ in diff --git a/Sources/SwiftNetwork/QUIC/QUICConnection.swift b/Sources/SwiftNetwork/QUIC/QUICConnection.swift index 7155dcd..e12d024 100644 --- a/Sources/SwiftNetwork/QUIC/QUICConnection.swift +++ b/Sources/SwiftNetwork/QUIC/QUICConnection.swift @@ -735,10 +735,6 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, let keepaliveSeconds = self.keepaliveDuration.seconds return UInt16(keepaliveSeconds) } - self.connectionMetadata.getRemoteMaxDatagramFrameSize { - let datagramFrameSize = self.remoteMaxDatagramFrameSize - return UInt16(truncatingIfNeeded: datagramFrameSize) - } self.connectionMetadata.getLocalConnectionIDs { self.localCIDs.managedConnectionIDs.map { $0.connectionID } @@ -758,7 +754,6 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, self.connectionMetadata.getRemoteMaxStreamsBidirectionalHandler = nil self.connectionMetadata.getRemoteMaxStreamsUnidirectionalHandler = nil self.connectionMetadata.getLocalConnectionIDsHandler = nil - self.connectionMetadata.getRemoteMaxDatagramFrameSizeHandler = nil #endif } @@ -4251,6 +4246,7 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, } guard let remoteTPMaxDatagramFrameSize else { self.remoteMaxDatagramFrameSize = 0 + self.connectionMetadata.remoteMaxDatagramFrameSize = 0 return } if remoteTPMaxDatagramFrameSize > TransportParameters.maxDatagramFrameSize { @@ -4258,6 +4254,7 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, } else { self.remoteMaxDatagramFrameSize = remoteTPMaxDatagramFrameSize } + self.connectionMetadata.remoteMaxDatagramFrameSize = UInt16(truncatingIfNeeded: remoteMaxDatagramFrameSize) } private func discardKeys(keyState: PacketKeyState, discardRecoveryState: Bool = true) { diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift index f4b3fec..6b470b3 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift @@ -664,14 +664,14 @@ final class SwiftNetworkQUICHarnessTests: NetTestCase { let clientMetadata: ProtocolMetadata? = harness.state?.clientHarness.getMetadata() XCTAssertNotNil(clientMetadata) if let clientMetadata { - let clientRemoteSize = clientMetadata.connectionMetadata?.getRemoteDatagramFrameSize() + let clientRemoteSize = clientMetadata.connectionMetadata?.remoteMaxDatagramFrameSize XCTAssertNotNil(clientRemoteSize) XCTAssertEqual(clientRemoteSize, 65535) } let serverMetadata: ProtocolMetadata? = harness.state?.serverHarness.getMetadata() XCTAssertNotNil(serverMetadata) if let serverMetadata { - let serverRemoteSize = serverMetadata.connectionMetadata?.getRemoteDatagramFrameSize() + let serverRemoteSize = serverMetadata.connectionMetadata?.remoteMaxDatagramFrameSize XCTAssertNotNil(serverRemoteSize) XCTAssertEqual(serverRemoteSize, 65535) }