From d70f7b16293a1fe1f73d3c634fea8412ee0cc8e1 Mon Sep 17 00:00:00 2001 From: Cole Moore Date: Tue, 6 Oct 2026 08:02:28 +0800 Subject: [PATCH 1/3] Add Android Bionic support so SwiftNetwork builds on the Android SDK. --- Package.swift | 8 ++++---- .../SwiftNetwork/Connection/Connection.swift | 5 ++++- .../SwiftNetwork/Context/NetworkContext.swift | 5 ++++- .../Endpoint/AddressEndpoint.swift | 5 ++++- .../Endpoint/NetlinkAddress.swift | 6 +++++- .../EndpointFlow/EndpointFlow.swift | 5 ++++- .../EndpointFlow/EndpointFlowExtension.swift | 5 ++++- .../EndpointFlow/EndpointFlowProtocols.swift | 5 ++++- .../EndpointFlow/WriteRequest.swift | 5 ++++- .../SwiftNetwork/Parameters/Parameters.swift | 5 ++++- .../Parameters/PathParameters.swift | 5 ++++- Sources/SwiftNetwork/Path/Interface.swift | 5 ++++- .../SwiftNetwork/Path/PathProperties.swift | 5 ++++- .../Protocols/BaseProtocolLinkages.swift | 5 ++++- .../Protocols/BottomProtocol.swift | 5 ++++- .../Protocols/BridgeProtocol.swift | 5 ++++- Sources/SwiftNetwork/Protocols/Checksum.swift | 5 ++++- .../Protocols/CustomIPProtocol.swift | 5 ++++- .../Protocols/CustomLinkProtocol.swift | 5 ++++- .../Protocols/DemuxProtocol.swift | 5 ++++- .../Protocols/ExternalProtocolLinkages.swift | 5 ++++- Sources/SwiftNetwork/Protocols/Frame.swift | 5 ++++- .../SwiftNetwork/Protocols/IPProtocol.swift | 5 ++++- .../Protocols/ManyToManyProtocol.swift | 5 ++++- .../Protocols/OneToOneProtocol.swift | 5 ++++- .../Protocols/ProtocolEventManager.swift | 5 ++++- .../Protocols/ProtocolInstance.swift | 9 ++++++--- .../Protocols/ProtocolLinkage.swift | 5 ++++- .../Protocols/ProtocolStack.swift | 5 ++++- .../Protocols/ProtocolStreamHandlers.swift | 5 ++++- .../Protocols/QUICConnectionProtocol.swift | 11 +++++++---- .../Protocols/QUICStreamProtocol.swift | 5 ++++- .../Protocols/SocketProtocol.swift | 5 ++++- .../Protocols/SwiftTLSProtocol.swift | 7 +++++-- .../SwiftNetwork/Protocols/TCPProtocol.swift | 5 ++++- .../SwiftNetwork/Protocols/TopProtocol.swift | 5 ++++- .../SwiftNetwork/Protocols/UDPProtocol.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Ack.swift | 5 ++++- .../SwiftNetwork/QUIC/CongestionControl.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Crypto.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Cubic.swift | 5 ++++- Sources/SwiftNetwork/QUIC/ECN.swift | 5 ++++- Sources/SwiftNetwork/QUIC/FlowControl.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Ledbat.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Logger+QUIC.swift | 5 ++++- Sources/SwiftNetwork/QUIC/PMTUD.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Pacer.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Packet.swift | 5 ++++- Sources/SwiftNetwork/QUIC/PacketBuilder.swift | 5 ++++- Sources/SwiftNetwork/QUIC/PacketFormats.swift | 5 ++++- .../SwiftNetwork/QUIC/PacketNumberSpace.swift | 5 ++++- Sources/SwiftNetwork/QUIC/PacketParser.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Prague.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Protector.swift | 5 ++++- Sources/SwiftNetwork/QUIC/QLog.swift | 5 ++++- .../SwiftNetwork/QUIC/QUICConnection.swift | 5 ++++- .../SwiftNetwork/QUIC/QUICConnectionID.swift | 5 ++++- .../SwiftNetwork/QUIC/QUICDatagramFlow.swift | 5 ++++- Sources/SwiftNetwork/QUIC/QUICError.swift | 7 +++++-- Sources/SwiftNetwork/QUIC/QUICFrame.swift | 5 ++++- Sources/SwiftNetwork/QUIC/QUICPath.swift | 5 ++++- Sources/SwiftNetwork/QUIC/QUICStream.swift | 5 ++++- Sources/SwiftNetwork/QUIC/QUICStreamID.swift | 5 ++++- .../SwiftNetwork/QUIC/QUICStreamState.swift | 5 ++++- .../SwiftNetwork/QUIC/QUICStreamZombies.swift | 5 ++++- Sources/SwiftNetwork/QUIC/QUICUtilities.swift | 7 +++++-- Sources/SwiftNetwork/QUIC/RTT.swift | 5 ++++- .../SwiftNetwork/QUIC/ReassemblyQueue.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Recovery.swift | 5 ++++- Sources/SwiftNetwork/QUIC/SendItems.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Shorthand.swift | 5 ++++- .../QUIC/StatelessResetToken.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Statistics.swift | 5 ++++- .../SwiftNetwork/QUIC/StreamSendBuffer.swift | 5 ++++- Sources/SwiftNetwork/QUIC/Timer.swift | 5 ++++- .../QUIC/TransportParameters.swift | 5 ++++- .../System/Darwin/DarwinResources.swift | 2 +- .../System/Linux/LinuxInterface.swift | 6 ++++-- .../System/Linux/LinuxResources.swift | 6 ++++-- .../System/Linux/LinuxRoute.swift | 8 +++++--- .../SwiftNetwork/System/NetworkError.swift | 5 ++++- Sources/SwiftNetwork/System/System.swift | 11 +++++++---- .../System/SystemAddressFamily.swift | 12 +++++++----- Sources/SwiftNetwork/System/SystemCalls.swift | 19 ++++++++++++++++--- .../SwiftNetwork/System/SystemInterface.swift | 10 ++++++---- .../SwiftNetwork/System/SystemSocket.swift | 13 +++++++++++-- Sources/SwiftNetwork/System/SystemUUID.swift | 5 ++++- Sources/SwiftNetwork/Utilities/Logging.swift | 7 +++++-- .../SwiftNetwork/Utilities/UInt64+VLE.swift | 5 ++++- .../BenchmarkUtility.swift | 7 +++++-- .../SwiftNetworkLinuxShim.c | 10 ++++++++++ .../include/SwiftNetworkLinuxShim.h | 5 +++-- .../HarnessProtocols.swift | 5 ++++- .../TestMultiplexingProtocol.swift | 5 ++++- .../TestProtocolLinkages.swift | 4 +++- Sources/Tools/IPUDPTransfer/main.swift | 5 ++++- Sources/Tools/QUICHandshake/main.swift | 5 ++++- Sources/Tools/QUICStreamLoad/main.swift | 5 ++++- Sources/Tools/QUICTransfer/main.swift | 5 ++++- Sources/Tools/SocketTransfer/main.swift | 5 ++++- Tests/SwiftNetworkTests/QUICTestHarness.swift | 5 ++++- .../SwiftNetworkTests/SocketTestHarness.swift | 4 +++- .../SwiftNetworkAddressTests.swift | 3 +++ .../SwiftNetworkDemuxTests.swift | 5 ++++- .../SwiftNetworkInterfaceTests.swift | 4 +++- .../SwiftNetworkQUICCIDTests.swift | 5 ++++- .../SwiftNetworkQUICECNTests.swift | 5 ++++- .../SwiftNetworkQUICEarlyDataTests.swift | 5 ++++- .../SwiftNetworkQUICHarnessTests.swift | 5 ++++- .../SwiftNetworkQUICIdleTests.swift | 5 ++++- .../SwiftNetworkQUICKeepaliveTests.swift | 5 ++++- .../SwiftNetworkQUICPacer.swift | 5 ++++- .../SwiftNetworkQUICPacketParsingTests.swift | 5 ++++- .../SwiftNetworkQUICQlogTests.swift | 5 ++++- .../SwiftNetworkQUICRetryTokenTests.swift | 5 ++++- .../SwiftNetworkQUICShortLHPacketTests.swift | 5 ++++- .../SwiftNetworkQUICSpinBitTests.swift | 5 ++++- .../SwiftNetworkQUICStackTests.swift | 5 ++++- .../SwiftNetworkQUICStatisticsTests.swift | 5 ++++- ...SwiftNetworkQUICUngracefulCloseTests.swift | 5 ++++- .../SwiftNetworkQUICVersionNegotiation.swift | 5 ++++- .../SwiftNetworkSafeAccessTests.swift | 4 ++++ .../SwiftNetworkSocketTests.swift | 6 ++++-- .../SwiftNetworkSwiftTLSRecordTests.swift | 5 ++++- .../SwiftNetworkUUIDTests.swift | 5 ++++- Tests/SwiftNetworkTests/TestLogger.swift | 7 +++++-- 126 files changed, 542 insertions(+), 156 deletions(-) diff --git a/Package.swift b/Package.swift index 3bfe1b30..621ccf18 100644 --- a/Package.swift +++ b/Package.swift @@ -113,8 +113,8 @@ let package = Package( .target( name: "SwiftNetwork", dependencies: [ - .product(name: "Logging", package: "swift-log", condition: .when(platforms: [.linux])), - .target(name: "SwiftNetworkLinuxShim", condition: .when(platforms: [.linux])), + .product(name: "Logging", package: "swift-log", condition: .when(platforms: [.linux, .android])), + .target(name: "SwiftNetworkLinuxShim", condition: .when(platforms: [.linux, .android])), .product(name: "DequeModule", package: "swift-collections"), .product(name: "BasicContainers", package: "swift-collections"), .product(name: "Crypto", package: "swift-crypto"), @@ -138,7 +138,7 @@ let package = Package( name: "SwiftNetworkTestHarness", dependencies: [ "SwiftNetwork", - .product(name: "Logging", package: "swift-log", condition: .when(platforms: [.linux])), + .product(name: "Logging", package: "swift-log", condition: .when(platforms: [.linux, .android])), .product(name: "DequeModule", package: "swift-collections"), .product(name: "BasicContainers", package: "swift-collections"), ], @@ -151,7 +151,7 @@ let package = Package( "SwiftNetworkTestHarness", .product(name: "SwiftTLS", package: "swift-tls"), .product(name: "Crypto", package: "swift-crypto"), - .product(name: "Logging", package: "swift-log", condition: .when(platforms: [.linux])), + .product(name: "Logging", package: "swift-log", condition: .when(platforms: [.linux, .android])), ], swiftSettings: availabilityMacros + settings ), diff --git a/Sources/SwiftNetwork/Connection/Connection.swift b/Sources/SwiftNetwork/Connection/Connection.swift index 9b711f4b..be22c472 100644 --- a/Sources/SwiftNetwork/Connection/Connection.swift +++ b/Sources/SwiftNetwork/Connection/Connection.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Context/NetworkContext.swift b/Sources/SwiftNetwork/Context/NetworkContext.swift index 3bf8b64c..0eaeceaa 100644 --- a/Sources/SwiftNetwork/Context/NetworkContext.swift +++ b/Sources/SwiftNetwork/Context/NetworkContext.swift @@ -16,7 +16,10 @@ import Dispatch #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Endpoint/AddressEndpoint.swift b/Sources/SwiftNetwork/Endpoint/AddressEndpoint.swift index 1ef308c9..c0bfec85 100644 --- a/Sources/SwiftNetwork/Endpoint/AddressEndpoint.swift +++ b/Sources/SwiftNetwork/Endpoint/AddressEndpoint.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Endpoint/NetlinkAddress.swift b/Sources/SwiftNetwork/Endpoint/NetlinkAddress.swift index 743dec46..6f537170 100644 --- a/Sources/SwiftNetwork/Endpoint/NetlinkAddress.swift +++ b/Sources/SwiftNetwork/Endpoint/NetlinkAddress.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +internal import SwiftNetworkLinuxShim +#elseif canImport(Glibc) import Glibc internal import Logging internal import SwiftNetworkLinuxShim diff --git a/Sources/SwiftNetwork/EndpointFlow/EndpointFlow.swift b/Sources/SwiftNetwork/EndpointFlow/EndpointFlow.swift index 7d18b344..8ef8fe5b 100644 --- a/Sources/SwiftNetwork/EndpointFlow/EndpointFlow.swift +++ b/Sources/SwiftNetwork/EndpointFlow/EndpointFlow.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/EndpointFlow/EndpointFlowExtension.swift b/Sources/SwiftNetwork/EndpointFlow/EndpointFlowExtension.swift index d80492ef..b6b848a0 100644 --- a/Sources/SwiftNetwork/EndpointFlow/EndpointFlowExtension.swift +++ b/Sources/SwiftNetwork/EndpointFlow/EndpointFlowExtension.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift b/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift index 186bd5b4..17ec6ac2 100644 --- a/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift +++ b/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/EndpointFlow/WriteRequest.swift b/Sources/SwiftNetwork/EndpointFlow/WriteRequest.swift index c128908e..8664a9ac 100644 --- a/Sources/SwiftNetwork/EndpointFlow/WriteRequest.swift +++ b/Sources/SwiftNetwork/EndpointFlow/WriteRequest.swift @@ -16,7 +16,10 @@ internal import SwiftSystem #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Parameters/Parameters.swift b/Sources/SwiftNetwork/Parameters/Parameters.swift index 564dccf7..7e4b0f2f 100644 --- a/Sources/SwiftNetwork/Parameters/Parameters.swift +++ b/Sources/SwiftNetwork/Parameters/Parameters.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Parameters/PathParameters.swift b/Sources/SwiftNetwork/Parameters/PathParameters.swift index 728322e6..09fc1ad8 100644 --- a/Sources/SwiftNetwork/Parameters/PathParameters.swift +++ b/Sources/SwiftNetwork/Parameters/PathParameters.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Path/Interface.swift b/Sources/SwiftNetwork/Path/Interface.swift index d5767fc7..b7d627d2 100644 --- a/Sources/SwiftNetwork/Path/Interface.swift +++ b/Sources/SwiftNetwork/Path/Interface.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Path/PathProperties.swift b/Sources/SwiftNetwork/Path/PathProperties.swift index 9f6eae47..3c0dd05e 100644 --- a/Sources/SwiftNetwork/Path/PathProperties.swift +++ b/Sources/SwiftNetwork/Path/PathProperties.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/BaseProtocolLinkages.swift b/Sources/SwiftNetwork/Protocols/BaseProtocolLinkages.swift index 8e328124..3471e870 100644 --- a/Sources/SwiftNetwork/Protocols/BaseProtocolLinkages.swift +++ b/Sources/SwiftNetwork/Protocols/BaseProtocolLinkages.swift @@ -20,7 +20,10 @@ // `external` case, holding a class that speaks these same concrete types -- see // `ExternalProtocolLinkages.swift`. -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/BottomProtocol.swift b/Sources/SwiftNetwork/Protocols/BottomProtocol.swift index e333ab05..8883a255 100644 --- a/Sources/SwiftNetwork/Protocols/BottomProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/BottomProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/BridgeProtocol.swift b/Sources/SwiftNetwork/Protocols/BridgeProtocol.swift index 98119e81..0fede125 100644 --- a/Sources/SwiftNetwork/Protocols/BridgeProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/BridgeProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/Checksum.swift b/Sources/SwiftNetwork/Protocols/Checksum.swift index 6ff69db6..98133cda 100644 --- a/Sources/SwiftNetwork/Protocols/Checksum.swift +++ b/Sources/SwiftNetwork/Protocols/Checksum.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/CustomIPProtocol.swift b/Sources/SwiftNetwork/Protocols/CustomIPProtocol.swift index 988c6e10..8ffb6e3a 100644 --- a/Sources/SwiftNetwork/Protocols/CustomIPProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/CustomIPProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/CustomLinkProtocol.swift b/Sources/SwiftNetwork/Protocols/CustomLinkProtocol.swift index 359f1771..c759e805 100644 --- a/Sources/SwiftNetwork/Protocols/CustomLinkProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/CustomLinkProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/DemuxProtocol.swift b/Sources/SwiftNetwork/Protocols/DemuxProtocol.swift index 03e47a92..f1ad520a 100644 --- a/Sources/SwiftNetwork/Protocols/DemuxProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/DemuxProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/ExternalProtocolLinkages.swift b/Sources/SwiftNetwork/Protocols/ExternalProtocolLinkages.swift index 84824e28..30618d41 100644 --- a/Sources/SwiftNetwork/Protocols/ExternalProtocolLinkages.swift +++ b/Sources/SwiftNetwork/Protocols/ExternalProtocolLinkages.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/Frame.swift b/Sources/SwiftNetwork/Protocols/Frame.swift index 115c368d..89ce6fc4 100644 --- a/Sources/SwiftNetwork/Protocols/Frame.swift +++ b/Sources/SwiftNetwork/Protocols/Frame.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/IPProtocol.swift b/Sources/SwiftNetwork/Protocols/IPProtocol.swift index 33499c19..b34e94f5 100644 --- a/Sources/SwiftNetwork/Protocols/IPProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/IPProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/ManyToManyProtocol.swift b/Sources/SwiftNetwork/Protocols/ManyToManyProtocol.swift index 99717834..1be6fd05 100644 --- a/Sources/SwiftNetwork/Protocols/ManyToManyProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/ManyToManyProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/OneToOneProtocol.swift b/Sources/SwiftNetwork/Protocols/OneToOneProtocol.swift index 05be2255..6f861435 100644 --- a/Sources/SwiftNetwork/Protocols/OneToOneProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/OneToOneProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/ProtocolEventManager.swift b/Sources/SwiftNetwork/Protocols/ProtocolEventManager.swift index 9af02a28..e7c11536 100644 --- a/Sources/SwiftNetwork/Protocols/ProtocolEventManager.swift +++ b/Sources/SwiftNetwork/Protocols/ProtocolEventManager.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/ProtocolInstance.swift b/Sources/SwiftNetwork/Protocols/ProtocolInstance.swift index 5436484f..ab518923 100644 --- a/Sources/SwiftNetwork/Protocols/ProtocolInstance.swift +++ b/Sources/SwiftNetwork/Protocols/ProtocolInstance.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) @@ -303,7 +306,7 @@ public struct NetworkLoggerState: ~Copyable { public func notice(_ message: @autoclosure () -> String, callingFunction: StaticString = #function) { let logPrefix = logPrefix let message = message() - #if os(Linux) + #if os(Linux) || os(Android) Logger.proto.notice("\(callingFunction) \(logPrefix) \(message)") #else Logger.proto.log("\(callingFunction) \(logPrefix) \(message)") @@ -322,7 +325,7 @@ public struct NetworkLoggerState: ~Copyable { public func notice(_ message: String, callingFunction: StaticString = #function) { let logPrefix = logPrefix - #if os(Linux) + #if os(Linux) || os(Android) Logger.proto.notice("\(callingFunction) \(logPrefix) \(message)") #else Logger.proto.log("\(callingFunction) \(logPrefix) \(message)") diff --git a/Sources/SwiftNetwork/Protocols/ProtocolLinkage.swift b/Sources/SwiftNetwork/Protocols/ProtocolLinkage.swift index 8c8d0b47..1b34f9bd 100644 --- a/Sources/SwiftNetwork/Protocols/ProtocolLinkage.swift +++ b/Sources/SwiftNetwork/Protocols/ProtocolLinkage.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/ProtocolStack.swift b/Sources/SwiftNetwork/Protocols/ProtocolStack.swift index 81d074d1..e7e6951b 100644 --- a/Sources/SwiftNetwork/Protocols/ProtocolStack.swift +++ b/Sources/SwiftNetwork/Protocols/ProtocolStack.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift b/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift index 6c7f8612..5bca4e48 100644 --- a/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift +++ b/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift b/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift index e4aa2e6c..1d491c4c 100644 --- a/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/QUICConnectionProtocol.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) @@ -142,7 +145,7 @@ public struct QUICConnectionProtocol: NetworkProtocol { public var sourceConnectionID: [UInt8]? = nil public var destinationConnectionID: [UInt8]? = nil // NOTE: sessionUpdateBlock is not supported in Embedded - #if os(Linux) + #if os(Linux) || os(Android) var sessionStateUpdateBlock: (@Sendable @convention(block) ([UInt8]?, [UInt8]?) -> Void)? #elseif !NETWORK_STANDALONE && canImport(Darwin) var sessionStateUpdateBlock: (@Sendable @convention(block) (DispatchData?, DispatchData?) -> Void)? = nil @@ -662,7 +665,7 @@ public struct QUICConnectionProtocol: NetworkProtocol { } #endif - #if os(Linux) + #if os(Linux) || os(Android) func setSessionStateUpdateBlock( _ sessionStateUpdateBlock: (@Sendable @convention(block) ([UInt8]?, [UInt8]?) -> Void)?, queue: DispatchQueue @@ -688,7 +691,7 @@ public struct QUICConnectionProtocol: NetworkProtocol { return false } // NOTE: sessionUpdateBlock is not supported in Embedded - #if os(Linux) + #if os(Linux) || os(Android) let tlsBytes = Array(tlsState[tlsState.startIndex.. UInt32 { 0 diff --git a/Sources/SwiftNetwork/System/NetworkError.swift b/Sources/SwiftNetwork/System/NetworkError.swift index e81df877..a8af8ec9 100644 --- a/Sources/SwiftNetwork/System/NetworkError.swift +++ b/Sources/SwiftNetwork/System/NetworkError.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/System/System.swift b/Sources/SwiftNetwork/System/System.swift index e1e3de93..a1b14e47 100644 --- a/Sources/SwiftNetwork/System/System.swift +++ b/Sources/SwiftNetwork/System/System.swift @@ -16,7 +16,10 @@ import Dispatch #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) @@ -48,7 +51,7 @@ internal struct System { Duration.milliseconds(1) / Duration.microseconds(1) ) /* microseconds per millisecond */ - #if os(Linux) || (NETWORK_STANDALONE && !NETWORK_DRIVERKIT) + #if os(Linux) || os(Android) || (NETWORK_STANDALONE && !NETWORK_DRIVERKIT) private static let timebaseNumerator: UInt64 = 0 private static let timebaseDenominator: UInt64 = 0 #else @@ -62,7 +65,7 @@ internal struct System { #endif static func now() -> UInt64 { - #if os(Linux) + #if os(Linux) || os(Android) return DispatchTime.now().uptimeNanoseconds / Time.NSEC_PER_USEC #elseif NETWORK_STANDALONE && !NETWORK_DRIVERKIT return 0 @@ -80,7 +83,7 @@ internal struct System { } static func nowAbsoluteNanoseconds() -> UInt64 { - #if os(Linux) + #if os(Linux) || os(Android) return DispatchTime.now().uptimeNanoseconds #elseif NETWORK_STANDALONE && !NETWORK_DRIVERKIT return 0 diff --git a/Sources/SwiftNetwork/System/SystemAddressFamily.swift b/Sources/SwiftNetwork/System/SystemAddressFamily.swift index 2ab48181..288e9784 100644 --- a/Sources/SwiftNetwork/System/SystemAddressFamily.swift +++ b/Sources/SwiftNetwork/System/SystemAddressFamily.swift @@ -12,7 +12,9 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +#elseif canImport(Glibc) import Glibc #elseif canImport(Musl) import Musl @@ -23,13 +25,13 @@ import Darwin enum AddressFamily: UInt8, Sendable { case unspecified = 0 case ipv4 = 2 - #if os(Linux) + #if os(Linux) || os(Android) case ipv6 = 10 // AF_INET6 is 10 on Linux #else case ipv6 = 30 #endif case unix = 1 - #if os(Linux) + #if os(Linux) || os(Android) case route = 16 // AF_ROUTE is 16 on Linux #else case route = 17 @@ -40,14 +42,14 @@ enum AddressFamily: UInt8, Sendable { case 0: self = .unspecified case 2: self = .ipv4 // AF_INET6 is different across platforms - #if os(Linux) + #if os(Linux) || os(Android) case 10: self = .ipv6 #else case 30: self = .ipv6 #endif case 1: self = .unix // AF_ROUTE is different across platforms - #if os(Linux) + #if os(Linux) || os(Android) case 16: self = .route #else case 17: self = .route diff --git a/Sources/SwiftNetwork/System/SystemCalls.swift b/Sources/SwiftNetwork/System/SystemCalls.swift index c3b6486f..3a22a115 100644 --- a/Sources/SwiftNetwork/System/SystemCalls.swift +++ b/Sources/SwiftNetwork/System/SystemCalls.swift @@ -12,8 +12,10 @@ // //===----------------------------------------------------------------------===// -#if os(Linux) -#if canImport(Glibc) +#if os(Linux) || os(Android) +#if canImport(Android) +import Android +#elseif canImport(Glibc) import Glibc #elseif canImport(Musl) import Musl @@ -29,8 +31,12 @@ import Darwin #if !NETWORK_STANDALONE || NETWORK_DRIVERKIT #if !NETWORK_DRIVERKIT +#if os(Android) +let sysIoctl: @convention(c) (CInt, CUnsignedLong, UnsafeMutableRawPointer) -> CInt = SwiftNetworkLinuxShim_ioctl +#else let sysIoctl: @convention(c) (CInt, CUnsignedLong, UnsafeMutableRawPointer) -> CInt = ioctl #endif +#endif let sysSocket: @convention(c) (CInt, CInt, CInt) -> CInt = socket #if !NETWORK_DRIVERKIT let sysFcntl: @Sendable @convention(c) (CInt, CInt, CInt) -> CInt = { fcntl($0, $1, $2) } @@ -42,12 +48,19 @@ let sysConnectx = connectx let sysWrite = write let sysRead = read let sysBind = bind +#if os(Android) +// Bionic marks these pointers _Nonnull. +let sysRecvMsg: @convention(c) (CInt, UnsafeMutablePointer, CInt) -> ssize_t = recvmsg +let sysSendMsg: @convention(c) (CInt, UnsafePointer, CInt) -> ssize_t = sendmsg +let sysIfNameToIndex: @convention(c) (UnsafePointer) -> CUnsignedInt = if_nametoindex +#else let sysRecvMsg: @convention(c) (CInt, UnsafeMutablePointer?, CInt) -> ssize_t = recvmsg let sysSendMsg: @convention(c) (CInt, UnsafePointer?, CInt) -> ssize_t = sendmsg let sysIfNameToIndex: @convention(c) (UnsafePointer?) -> CUnsignedInt = if_nametoindex #endif +#endif -#if os(Linux) +#if os(Linux) || os(Android) // if_indextoname is not in the Glibc Swift interface so it's bridged from c let sysIfIndexToName: @convention(c) (CInt, UnsafeMutablePointer?) -> UnsafeMutablePointer? = SwiftNetworkLinuxShim_if_indextoname diff --git a/Sources/SwiftNetwork/System/SystemInterface.swift b/Sources/SwiftNetwork/System/SystemInterface.swift index 1f5c1ac6..87fd7804 100644 --- a/Sources/SwiftNetwork/System/SystemInterface.swift +++ b/Sources/SwiftNetwork/System/SystemInterface.swift @@ -12,8 +12,10 @@ // //===----------------------------------------------------------------------===// -#if os(Linux) -#if canImport(Glibc) +#if os(Linux) || os(Android) +#if canImport(Android) +import Android +#elseif canImport(Glibc) import Glibc #elseif canImport(Musl) import Musl @@ -51,7 +53,7 @@ extension System { name: String, interfaceType: InterfaceType ) throws -> InterfaceSubtype { - #if os(Linux) + #if os(Linux) || os(Android) return SystemInterface.interfaceGetInterfaceSubType(interfaceType: interfaceType) #else return try SystemInterface.interfaceGetInterfaceSubType(socket: socket, name: name) @@ -65,7 +67,7 @@ extension System { #endif static func interfaceNameToIndex(name: String) throws -> UInt32 { - #if os(Linux) + #if os(Linux) || os(Android) return try SystemInterface.if_nametoindex(name) #elseif !NETWORK_STANDALONE || NETWORK_DRIVERKIT // Darwin just has if_nametoindex exposed diff --git a/Sources/SwiftNetwork/System/SystemSocket.swift b/Sources/SwiftNetwork/System/SystemSocket.swift index 92aa68c9..4d5d6e51 100644 --- a/Sources/SwiftNetwork/System/SystemSocket.swift +++ b/Sources/SwiftNetwork/System/SystemSocket.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) @@ -93,7 +96,7 @@ class SystemSocket { sockType: SocketType, protocolSubType: Int32 ) throws(NetworkError) -> CInt { - #if os(Linux) + #if os(Linux) || os(Android) return try System.syscall(blocking: false) { sysSocket(CInt(protocolFamily.rawValue), sockType.socketType, protocolSubType) }.result @@ -298,7 +301,11 @@ class SystemSocket { public func availableBytesToRead() -> Int { guard self.sockfd > 0 else { return 0 } var value: CInt = 0 + #if os(Android) + let result = sysIoctl(self.sockfd, CUnsignedLong(FIONREAD), &value) + #else let result = ioctl(self.sockfd, UInt(FIONREAD), &value) + #endif return result == 0 ? Int(value) : 0 } #endif @@ -443,6 +450,8 @@ extension IPAddress { sockaddr6.sin6_addr.__in6_u.__u6_addr32 = v6Address.address #elseif canImport(Musl) sockaddr6.sin6_addr.__in6_union.__s6_addr32 = v6Address.address + #elseif canImport(Android) + sockaddr6.sin6_addr.in6_u.u6_addr32 = v6Address.address #elseif canImport(Darwin) sockaddr6.sin6_len = UInt8(MemoryLayout.size) sockaddr6.sin6_addr.__u6_addr.__u6_addr32 = v6Address.address diff --git a/Sources/SwiftNetwork/System/SystemUUID.swift b/Sources/SwiftNetwork/System/SystemUUID.swift index df6704fd..d6f726a6 100644 --- a/Sources/SwiftNetwork/System/SystemUUID.swift +++ b/Sources/SwiftNetwork/System/SystemUUID.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetwork/Utilities/Logging.swift b/Sources/SwiftNetwork/Utilities/Logging.swift index b07f1700..b092fdd8 100644 --- a/Sources/SwiftNetwork/Utilities/Logging.swift +++ b/Sources/SwiftNetwork/Utilities/Logging.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) @@ -22,7 +25,7 @@ internal import Logging internal import os #endif -#if os(Linux) || (NETWORK_EMBEDDED && !NETWORK_DRIVERKIT) +#if os(Linux) || os(Android) || (NETWORK_EMBEDDED && !NETWORK_DRIVERKIT) extension Logger { #if DisableDebugLogging diff --git a/Sources/SwiftNetwork/Utilities/UInt64+VLE.swift b/Sources/SwiftNetwork/Utilities/UInt64+VLE.swift index a5b2a928..74d97ddd 100644 --- a/Sources/SwiftNetwork/Utilities/UInt64+VLE.swift +++ b/Sources/SwiftNetwork/Utilities/UInt64+VLE.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetworkBenchmarks/BenchmarkUtility.swift b/Sources/SwiftNetworkBenchmarks/BenchmarkUtility.swift index 6d68e6c1..23871980 100644 --- a/Sources/SwiftNetworkBenchmarks/BenchmarkUtility.swift +++ b/Sources/SwiftNetworkBenchmarks/BenchmarkUtility.swift @@ -24,7 +24,10 @@ internal import CryptoKit internal import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) @@ -312,7 +315,7 @@ public final class QUICBenchmarkUtility { @available(macOS 11, iOS 14, tvOS 14, watchOS 7, *) #endif public struct LoggingHandle: CustomStringConvertible { - #if os(Linux) || NETWORK_EMBEDDED + #if os(Linux) || os(Android) || NETWORK_EMBEDDED let logger = Logger(label: "com.apple.network.benchmarks") #else #if canImport(os) diff --git a/Sources/SwiftNetworkLinuxShim/SwiftNetworkLinuxShim.c b/Sources/SwiftNetworkLinuxShim/SwiftNetworkLinuxShim.c index a10d9f0f..6b27c352 100644 --- a/Sources/SwiftNetworkLinuxShim/SwiftNetworkLinuxShim.c +++ b/Sources/SwiftNetworkLinuxShim/SwiftNetworkLinuxShim.c @@ -20,6 +20,7 @@ #include #include +#include #include char * SwiftNetworkLinuxShim_if_indextoname(int index, char * name) @@ -40,4 +41,13 @@ uint64_t SwiftNetworkLinuxShim_getFDLimit() return 0; } +int SwiftNetworkLinuxShim_ioctl(int fd, unsigned long request, void * arg) +{ +#if defined(__ANDROID__) + return ioctl(fd, (unsigned)request, arg); +#else + return ioctl(fd, request, arg); +#endif +} + #endif diff --git a/Sources/SwiftNetworkLinuxShim/include/SwiftNetworkLinuxShim.h b/Sources/SwiftNetworkLinuxShim/include/SwiftNetworkLinuxShim.h index 97bcb28c..6ee1c668 100644 --- a/Sources/SwiftNetworkLinuxShim/include/SwiftNetworkLinuxShim.h +++ b/Sources/SwiftNetworkLinuxShim/include/SwiftNetworkLinuxShim.h @@ -26,9 +26,10 @@ #endif #include -// Not exposed in Glibc.swiftmodule -char * SwiftNetworkLinuxShim_if_indextoname(int index, char * name); +// Not exposed in Glibc.swiftmodule. Bionic's ioctl is variadic and unavailable from Swift. +char * _Nullable SwiftNetworkLinuxShim_if_indextoname(int index, char * _Nullable name); uint64_t SwiftNetworkLinuxShim_getFDLimit(); +int SwiftNetworkLinuxShim_ioctl(int fd, unsigned long request, void * _Nonnull arg); #endif // __linux__ #endif // SWIFTNETWORKLINIXSHIM diff --git a/Sources/SwiftNetworkTestHarness/HarnessProtocols.swift b/Sources/SwiftNetworkTestHarness/HarnessProtocols.swift index f644f42a..077cf911 100644 --- a/Sources/SwiftNetworkTestHarness/HarnessProtocols.swift +++ b/Sources/SwiftNetworkTestHarness/HarnessProtocols.swift @@ -17,7 +17,10 @@ import BasicContainers internal import DequeModule #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetworkTestHarness/TestMultiplexingProtocol.swift b/Sources/SwiftNetworkTestHarness/TestMultiplexingProtocol.swift index 67745db9..327ad0a8 100644 --- a/Sources/SwiftNetworkTestHarness/TestMultiplexingProtocol.swift +++ b/Sources/SwiftNetworkTestHarness/TestMultiplexingProtocol.swift @@ -20,7 +20,10 @@ @_spi(Essentials) @_spi(ProtocolProvider) import Network #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/SwiftNetworkTestHarness/TestProtocolLinkages.swift b/Sources/SwiftNetworkTestHarness/TestProtocolLinkages.swift index 5c6c97bf..52ed30a8 100644 --- a/Sources/SwiftNetworkTestHarness/TestProtocolLinkages.swift +++ b/Sources/SwiftNetworkTestHarness/TestProtocolLinkages.swift @@ -20,7 +20,9 @@ @_spi(Essentials) @_spi(ProtocolProvider) import Network #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +#elseif canImport(Glibc) import Glibc #elseif canImport(Musl) import Musl diff --git a/Sources/Tools/IPUDPTransfer/main.swift b/Sources/Tools/IPUDPTransfer/main.swift index 895aa6f7..432a47a7 100644 --- a/Sources/Tools/IPUDPTransfer/main.swift +++ b/Sources/Tools/IPUDPTransfer/main.swift @@ -19,7 +19,10 @@ @_spi(Essentials) @_spi(ProtocolProvider) import SwiftNetworkBenchmarks import Dispatch -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/Tools/QUICHandshake/main.swift b/Sources/Tools/QUICHandshake/main.swift index 0810db8f..f70f2e0c 100644 --- a/Sources/Tools/QUICHandshake/main.swift +++ b/Sources/Tools/QUICHandshake/main.swift @@ -19,7 +19,10 @@ #endif import Dispatch -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/Tools/QUICStreamLoad/main.swift b/Sources/Tools/QUICStreamLoad/main.swift index 1e65a83b..ff62cd6b 100644 --- a/Sources/Tools/QUICStreamLoad/main.swift +++ b/Sources/Tools/QUICStreamLoad/main.swift @@ -19,7 +19,10 @@ @_spi(Essentials) @_spi(ProtocolProvider) import SwiftNetworkBenchmarks import Dispatch -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/Tools/QUICTransfer/main.swift b/Sources/Tools/QUICTransfer/main.swift index 5b58155e..5fb76b12 100644 --- a/Sources/Tools/QUICTransfer/main.swift +++ b/Sources/Tools/QUICTransfer/main.swift @@ -19,7 +19,10 @@ @_spi(Essentials) @_spi(ProtocolProvider) import SwiftNetworkBenchmarks import Dispatch -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Sources/Tools/SocketTransfer/main.swift b/Sources/Tools/SocketTransfer/main.swift index 3d796143..70519339 100644 --- a/Sources/Tools/SocketTransfer/main.swift +++ b/Sources/Tools/SocketTransfer/main.swift @@ -16,7 +16,10 @@ @_spi(ProtocolProvider) import SwiftNetworkBenchmarks import Dispatch -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/QUICTestHarness.swift b/Tests/SwiftNetworkTests/QUICTestHarness.swift index ca58b88f..3da27fb5 100644 --- a/Tests/SwiftNetworkTests/QUICTestHarness.swift +++ b/Tests/SwiftNetworkTests/QUICTestHarness.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SocketTestHarness.swift b/Tests/SwiftNetworkTests/SocketTestHarness.swift index 96dc89aa..7fe20103 100644 --- a/Tests/SwiftNetworkTests/SocketTestHarness.swift +++ b/Tests/SwiftNetworkTests/SocketTestHarness.swift @@ -14,7 +14,9 @@ import XCTest -#if canImport(Glibc) +#if canImport(Android) +import Android +#elseif canImport(Glibc) import Glibc #elseif canImport(Darwin) internal import Darwin diff --git a/Tests/SwiftNetworkTests/SwiftNetworkAddressTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkAddressTests.swift index 6ea1525e..394595dc 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkAddressTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkAddressTests.swift @@ -13,6 +13,9 @@ //===----------------------------------------------------------------------===// import XCTest +#if canImport(Android) +import Android +#endif @_spi(Essentials) @_spi(ProtocolProvider) @testable import SwiftNetwork @available(Network 0.1.0, *) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkDemuxTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkDemuxTests.swift index 1c62b650..634c2f4b 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkDemuxTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkDemuxTests.swift @@ -26,7 +26,10 @@ import XCTest @_spi(TestHarness) @_spi(Essentials) @_spi(ProtocolProvider) import SwiftNetworkTestHarness #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift index 76f3c15f..4c3fec5a 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift @@ -15,7 +15,9 @@ import XCTest @_spi(Essentials) @_spi(ProtocolProvider) @testable import SwiftNetwork -#if canImport(Glibc) +#if canImport(Android) +import Android +#elseif canImport(Glibc) import Glibc #elseif canImport(Musl) import Musl diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICCIDTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICCIDTests.swift index fafabc6f..fa696984 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICCIDTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICCIDTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICECNTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICECNTests.swift index 4ad49f4f..50b21a10 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICECNTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICECNTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICEarlyDataTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICEarlyDataTests.swift index fa697410..a083a56b 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICEarlyDataTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICEarlyDataTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift index 30b565e1..57266616 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICIdleTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICIdleTests.swift index 265f274f..5dbeecdd 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICIdleTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICIdleTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICKeepaliveTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICKeepaliveTests.swift index 1a99fa3d..c7d581c3 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICKeepaliveTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICKeepaliveTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICPacer.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICPacer.swift index 2d774784..1c8968d5 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICPacer.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICPacer.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICPacketParsingTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICPacketParsingTests.swift index 6b647ee8..0cde2b2c 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICPacketParsingTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICPacketParsingTests.swift @@ -39,7 +39,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICQlogTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICQlogTests.swift index 47567ff8..a8b5be40 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICQlogTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICQlogTests.swift @@ -40,7 +40,10 @@ import Crypto import CryptoKit #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICRetryTokenTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICRetryTokenTests.swift index 187781a4..8a7ca269 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICRetryTokenTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICRetryTokenTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICShortLHPacketTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICShortLHPacketTests.swift index daef3127..e5d783c2 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICShortLHPacketTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICShortLHPacketTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICSpinBitTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICSpinBitTests.swift index 7b487d2b..659fb94c 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICSpinBitTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICSpinBitTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICStackTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICStackTests.swift index d1c08865..a61177ce 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICStackTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICStackTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICStatisticsTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICStatisticsTests.swift index 27b57d7c..53dfa365 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICStatisticsTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICStatisticsTests.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICUngracefulCloseTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICUngracefulCloseTests.swift index dbc76466..5b33b7fe 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICUngracefulCloseTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICUngracefulCloseTests.swift @@ -44,7 +44,10 @@ import Crypto import Dispatch #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkQUICVersionNegotiation.swift b/Tests/SwiftNetworkTests/SwiftNetworkQUICVersionNegotiation.swift index 5ec33ec5..0ef6fed5 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkQUICVersionNegotiation.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkQUICVersionNegotiation.swift @@ -40,7 +40,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkSafeAccessTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkSafeAccessTests.swift index dfe07aff..9d00fb07 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkSafeAccessTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkSafeAccessTests.swift @@ -14,6 +14,10 @@ import XCTest +#if canImport(Android) +import Android +#endif + @testable import SwiftNetwork #if !hasFeature(Embedded) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkSocketTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkSocketTests.swift index 948cd4d4..65fa76f6 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkSocketTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkSocketTests.swift @@ -14,7 +14,9 @@ import XCTest -#if canImport(Glibc) +#if canImport(Android) +import Android +#elseif canImport(Glibc) import Glibc #elseif canImport(Darwin) internal import Darwin @@ -725,7 +727,7 @@ final class SwiftNetworkSocketTests: NetTestCase { private static func processCPUSeconds() -> Double { var usage = rusage() - #if canImport(Darwin) + #if canImport(Darwin) || canImport(Android) getrusage(RUSAGE_SELF, &usage) #else getrusage(RUSAGE_SELF.rawValue, &usage) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkSwiftTLSRecordTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkSwiftTLSRecordTests.swift index 956e0e55..2f4c1065 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkSwiftTLSRecordTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkSwiftTLSRecordTests.swift @@ -35,7 +35,10 @@ import CryptoKit import Crypto #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(os) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkUUIDTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkUUIDTests.swift index 291b8fea..02105c4c 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkUUIDTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkUUIDTests.swift @@ -28,7 +28,10 @@ import XCTest import Foundation #endif -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import SwiftNetworkLinuxShim +#elseif canImport(Glibc) import Glibc internal import SwiftNetworkLinuxShim #elseif canImport(Musl) diff --git a/Tests/SwiftNetworkTests/TestLogger.swift b/Tests/SwiftNetworkTests/TestLogger.swift index 79466852..ed2cf74f 100644 --- a/Tests/SwiftNetworkTests/TestLogger.swift +++ b/Tests/SwiftNetworkTests/TestLogger.swift @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Android) +import Android +internal import Logging +#elseif canImport(Glibc) import Glibc internal import Logging #elseif canImport(Musl) @@ -23,7 +26,7 @@ internal import os #endif extension Logger { - #if os(Linux) || NETWORK_EMBEDDED + #if os(Linux) || os(Android) || NETWORK_EMBEDDED // Logging for Linux static let test = Logger(label: "com.apple.network.test") #else From f1cfe8a6f5f9a0e0d99b258ddfc881f74775260c Mon Sep 17 00:00:00 2001 From: Cole Moore Date: Tue, 6 Oct 2026 10:43:02 +0800 Subject: [PATCH 2/3] Read Android interface flags from the ioctl bytes so loopback detection matches the kernel, and configure QUIC keepalive on an already-held event context. --- .../Protocols/InstanceIdentifier.swift | 26 +++++++++++++++++++ .../SwiftNetwork/QUIC/QUICConnection.swift | 15 +++++++++++ .../System/Linux/LinuxInterface.swift | 18 ++++++++++--- .../SwiftNetworkInterfaceTests.swift | 10 +++---- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/Sources/SwiftNetwork/Protocols/InstanceIdentifier.swift b/Sources/SwiftNetwork/Protocols/InstanceIdentifier.swift index 97b02415..34c80d10 100644 --- a/Sources/SwiftNetwork/Protocols/InstanceIdentifier.swift +++ b/Sources/SwiftNetwork/Protocols/InstanceIdentifier.swift @@ -58,4 +58,30 @@ public struct InstanceIdentifier: Hashable { public var isNone: Bool { eventStateIndex.isNone } + + /// Enters this instance's execution state from outside the stack. + /// + /// Use this from a protocol implemented outside the framework when it holds its identifier + /// and context but no event context. The block receives the event context, which must be + /// threaded into any calls made to other protocols. If you already hold the event context, + /// call the `in:`-taking variant instead so the state isn't re-derived from the context. + public func fromExternal( + context: NetworkContext, + _ body: (inout NetworkContext.EventContext) throws(E) -> R + ) throws(E) -> R { + try fromExternal(in: &context.eventContext, body) + } + + /// Enters this instance's execution state from outside the stack. + /// + /// Use this from a protocol implemented outside the framework when it holds its identifier + /// and context but no event context. The block receives the event context, which must be + /// threaded into any calls made to other protocols. If you already hold the event context, + /// call the `in:`-taking variant instead so the state isn't re-derived from the context. + public func fromExternal( + context: NetworkContext, + _ body: (inout NetworkContext.EventContext) throws(E) -> R + ) throws(E) -> R { + try fromExternal(in: &context.eventContext, body) + } } diff --git a/Sources/SwiftNetwork/QUIC/QUICConnection.swift b/Sources/SwiftNetwork/QUIC/QUICConnection.swift index b496d695..d72e796d 100644 --- a/Sources/SwiftNetwork/QUIC/QUICConnection.swift +++ b/Sources/SwiftNetwork/QUIC/QUICConnection.swift @@ -3148,6 +3148,21 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, keepaliveSendPingFrame(timeSinceLastReceived: timeSinceLastReceived, now: now, in: &eventContext) } + /// Records the keep-alive interval and arms its timer. + /// + /// Call this with the event context already held. ``QUICConnectionMetadata/setKeepalive(keepAlive:)`` + /// enters the stack on its own and cannot be used from inside a delivery. + public func configureKeepalive( + seconds: UInt16, + in eventContext: inout NetworkContext.EventContext + ) { + if seconds == Constants.defaultKeepaliveValue { + keepaliveConfigure(duration: Constants.defaultKeepaliveDuration, in: &eventContext) + } else { + keepaliveConfigure(duration: .seconds(seconds), in: &eventContext) + } + } + func keepaliveConfigure( duration: NetworkDuration, in eventContext: inout NetworkContext.EventContext diff --git a/Sources/SwiftNetwork/System/Linux/LinuxInterface.swift b/Sources/SwiftNetwork/System/Linux/LinuxInterface.swift index 132e1602..ce8e5e7c 100644 --- a/Sources/SwiftNetwork/System/Linux/LinuxInterface.swift +++ b/Sources/SwiftNetwork/System/Linux/LinuxInterface.swift @@ -64,6 +64,18 @@ internal enum SystemInterface { }.result } + /// The flags `SIOCGIFFLAGS` wrote at the start of `ifr_ifru`. + /// + /// The kernel lays `ifr_flags` over the first bytes of that union. Reading the imported + /// `ifru_flags` member misses them where the union is not overlaid, which is what Android's + /// imported `ifreq` does, so the flags are taken from the bytes the ioctl wrote. + private static func interfaceFlags(of ifr: inout ifreq) -> UInt32 { + withUnsafeBytes(of: &ifr) { raw in + let offset = MemoryLayout.offset(of: \.ifr_ifru) ?? Int(Constants.IFNAMSIZ) + return UInt32(raw.loadUnaligned(fromByteOffset: offset, as: CUnsignedShort.self)) + } + } + /// Gets the MTU from the interface. /// /// Uses `ioctl` to fetch the value. @@ -104,7 +116,7 @@ internal enum SystemInterface { dstPtr.copyMemory(from: bytes) } try System.ioctl(fd: socket, request: CUnsignedLong(Constants.SIOCGIFFLAGS), ptr: &ifr) - if (UInt32(ifr.ifr_ifru.ifru_flags) & UInt32(comparisonFlag)) != 0 { + if (interfaceFlags(of: &ifr) & UInt32(comparisonFlag)) != 0 { return true } return false @@ -123,7 +135,7 @@ internal enum SystemInterface { dstPtr.copyMemory(from: bytes) } try System.ioctl(fd: socket, request: CUnsignedLong(Constants.SIOCGIFFLAGS), ptr: &ifr) - if (UInt32(ifr.ifr_ifru.ifru_flags) & UInt32(Constants.IFF_LOOPBACK)) != 0 { + if (interfaceFlags(of: &ifr) & UInt32(Constants.IFF_LOOPBACK)) != 0 { return true } return false @@ -181,7 +193,7 @@ internal enum SystemInterface { dstPtr.copyMemory(from: bytes) } try System.ioctl(fd: socket, request: CUnsignedLong(Constants.SIOCGIFFLAGS), ptr: &ifr) - return UInt32(ifr.ifr_ifru.ifru_flags) + return interfaceFlags(of: &ifr) } } diff --git a/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift index 4c3fec5a..9f9780dd 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkInterfaceTests.swift @@ -34,7 +34,7 @@ final class SwiftNetworkInterfaceTests: NetTestCase { func testCreateInterfaceByValidIndex() throws { var name = "lo0" var mtu = 16384 - #if os(Linux) + #if os(Linux) || os(Android) name = "lo" mtu = 65536 #endif @@ -49,7 +49,7 @@ final class SwiftNetworkInterfaceTests: NetTestCase { func testCreateInterfaceByValidIndexAndName() throws { var name = "lo0" - #if os(Linux) + #if os(Linux) || os(Android) name = "lo" #endif let interface = try Interface(index: 1, name: name) @@ -117,7 +117,7 @@ final class SwiftNetworkInterfaceTests: NetTestCase { } private static var loopbackInterfaceName: String { - #if os(Linux) + #if os(Linux) || os(Android) "lo" #else "lo0" @@ -126,7 +126,7 @@ final class SwiftNetworkInterfaceTests: NetTestCase { func testCompareTwoInterfaces() throws { var name = "lo0" - #if os(Linux) + #if os(Linux) || os(Android) name = "lo" #endif let interfaceByIndex = try Interface(index: 1) @@ -151,7 +151,7 @@ final class SwiftNetworkInterfaceTests: NetTestCase { } func testRouteGetInterfaceIndex() throws { - #if os(Linux) && !NETLINK_ENABLED + #if (os(Linux) || os(Android)) && !NETLINK_ENABLED try XCTSkipIf(true) #else // Very basic localhost test From a1bd8483b51a7529e2d19b4456202679ed745f9c Mon Sep 17 00:00:00 2001 From: Cole Moore Date: Tue, 6 Oct 2026 20:16:02 +0800 Subject: [PATCH 3/3] fix(swift-network): support Swift 6.4 lifetime and capacity APIs Tie frame spans to their owning FrameArray lifetime and replace the deprecated deque reallocation API with setCapacity. --- Package.swift | 2 +- Sources/SwiftNetwork/Protocols/FrameArray.swift | 13 ++++++++++++- Sources/SwiftNetwork/QUIC/PacketParser.swift | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 621ccf18..14c3a87d 100644 --- a/Package.swift +++ b/Package.swift @@ -105,7 +105,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"), - .package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.6.0")), + .package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.7.1")), .package(url: "https://github.com/apple/swift-crypto.git", from: "5.0.0-beta.1"), .package(url: "https://github.com/apple/swift-tls.git", .upToNextMinor(from: "0.1.2")), ], diff --git a/Sources/SwiftNetwork/Protocols/FrameArray.swift b/Sources/SwiftNetwork/Protocols/FrameArray.swift index 33764e57..fff43617 100644 --- a/Sources/SwiftNetwork/Protocols/FrameArray.swift +++ b/Sources/SwiftNetwork/Protocols/FrameArray.swift @@ -68,7 +68,7 @@ public struct FrameArray: ~Copyable { #if !NETWORK_EMBEDDED @_lifetime(borrow self) func bytes(at index: Int) -> RawSpan? { - frames[index].bytes + frames[index].bytes(borrowing: self) } #endif @@ -299,6 +299,17 @@ public struct FrameArray: ~Copyable { } } +#if !NETWORK_EMBEDDED +@available(Network 0.1.0, *) +private extension Frame { + // Only use when this frame is borrowed from `owner`. + @_lifetime(borrow owner) + func bytes(borrowing owner: borrowing FrameArray) -> RawSpan? { + _overrideLifetime(self.bytes, borrowing: owner) + } +} +#endif + @_spi(ProtocolProvider) @available(Network 0.1.0, *) extension NetworkUniqueDeque where Element: ~Copyable { diff --git a/Sources/SwiftNetwork/QUIC/PacketParser.swift b/Sources/SwiftNetwork/QUIC/PacketParser.swift index 5c2e84f1..86d1e30a 100644 --- a/Sources/SwiftNetwork/QUIC/PacketParser.swift +++ b/Sources/SwiftNetwork/QUIC/PacketParser.swift @@ -88,7 +88,7 @@ struct PacketParser: ~Copyable, PrefixedLoggable { // A packet stuffed with single byte frames can grow the deque a long way; a peer // shouldn't be able to pin that storage for the lifetime of the connection. if self.framesReceived.capacity > QUICPreferences.shared.maxReceivedFramesCapacity { - self.framesReceived.reallocate(capacity: Self.framesReceivedCapacity) + self.framesReceived.setCapacity(Self.framesReceivedCapacity) } }