Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Sources/SwiftNetwork/Connection/Connection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1058,8 +1058,8 @@ public struct StreamBridge: StreamProtocol {
public struct CustomLink: StreamProtocol {
public typealias ContentType = Void

private var tx: ((Span<UInt8>) -> Void)? = nil
private var rx: ((@escaping (Span<UInt8>) -> Void) -> Void)? = nil
private var tx: (@Sendable (_ bytes: Span<UInt8>) -> Void)? = nil
private var rx: (@Sendable (_ inject: @escaping (_ bytes: Span<UInt8>) -> Void) -> Void)? = nil

public let belowProtocol: Void
/// Configure CustomLink for tx byte handling
Expand All @@ -1073,7 +1073,7 @@ public struct CustomLink: StreamProtocol {
///
/// - Parameter handler: A closure that will be called with a
/// span of bytes to be written to the network.
public func tx(_ handler: @escaping (Span<UInt8>) -> Void) -> Self {
public func tx(_ handler: @escaping @Sendable (_ bytes: Span<UInt8>) -> Void) -> Self {
var mutableSelf = self
mutableSelf.tx = handler
return mutableSelf
Expand All @@ -1095,7 +1095,9 @@ public struct CustomLink: StreamProtocol {
/// - Parameter handler: A closure that will be called with an
/// escaping closure that should be stored for later use when bytes
/// need to be injected into the protocol stack.
public func rx(_ handler: @escaping ((@escaping (Span<UInt8>) -> Void) -> Void)) -> Self {
public func rx(
_ handler: @escaping @Sendable (_ inject: @escaping (_ bytes: Span<UInt8>) -> Void) -> Void
) -> Self {
var mutableSelf = self
mutableSelf.rx = handler
return mutableSelf
Expand Down
10 changes: 5 additions & 5 deletions Sources/SwiftNetwork/Protocols/BridgeProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal import Synchronization

@_spi(Essentials)
@available(Network 0.1.0, *)
public struct DatagramDrops: Equatable {
public struct DatagramDrops: Equatable, Sendable {
private var dropRanges: [ClosedRange<Int>]
private var datagramCount = 0
public var blockPacketGeneration = false
Expand Down Expand Up @@ -66,8 +66,8 @@ public struct DatagramDrops: Equatable {
}
}

public typealias BridgeObserveFirstByteHandler = ((UInt8) -> Void)?
public typealias BridgeObserveFrameHandler = ((UInt8, Int) -> Void)?
public typealias BridgeObserveFirstByteHandler = (@Sendable (_ firstByte: UInt8) -> Void)?
public typealias BridgeObserveFrameHandler = (@Sendable (_ firstByte: UInt8, _ byteCount: Int) -> Void)?

@_spi(Essentials)
@available(Network 0.1.0, *)
Expand All @@ -76,7 +76,7 @@ public struct BridgeDatagramProtocol: NetworkProtocol {
public typealias Metadata = BridgeMetadata
public typealias Instance = BridgeInstance

public struct BridgeOptions: PerProtocolOptions {
public struct BridgeOptions: PerProtocolOptions, Sendable {
public var linkDelay: NetworkDuration = .zero
public var observeFirstByteHandler: BridgeObserveFirstByteHandler = nil
public var observeFrameHandler: BridgeObserveFrameHandler = nil
Expand Down Expand Up @@ -395,7 +395,7 @@ public struct BridgeStreamProtocol: NetworkProtocol {
public typealias Metadata = BridgeMetadata
public typealias Instance = BridgeInstance

public struct BridgeOptions: PerProtocolOptions {
public struct BridgeOptions: PerProtocolOptions, Sendable {
init() {}

init?(from serializedBytes: [UInt8]) {
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftNetwork/Protocols/CustomIPProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public struct CustomIPProtocol: NetworkProtocol {
public typealias Options = CustomIPOptions
public typealias Metadata = CustomIPMetadata

public struct CustomIPOptions: PerProtocolOptions {
public struct CustomIPOptions: PerProtocolOptions, Sendable {
var ipProtocolNumber: UInt8 = 0
init() {}

Expand Down
14 changes: 7 additions & 7 deletions Sources/SwiftNetwork/Protocols/CustomLinkProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ public struct CustomLinkProtocol: NetworkProtocol {
public typealias Metadata = CustomLinkMetadata
public typealias Instance = CustomLinkInstance

public struct CustomLinkOptions: PerProtocolOptions {
public var tx: ((Span<UInt8>) -> Void)? = nil
public var rx: ((@escaping (Span<UInt8>) -> Void) -> Void)? = nil
public struct CustomLinkOptions: PerProtocolOptions, Sendable {
public var tx: (@Sendable (_ bytes: Span<UInt8>) -> Void)? = nil
public var rx: (@Sendable (_ inject: @escaping (_ bytes: Span<UInt8>) -> Void) -> Void)? = nil
init() {}

init?(from serializedBytes: [UInt8]) {
Expand Down Expand Up @@ -87,8 +87,8 @@ public struct CustomLinkProtocol: NetworkProtocol {
var log = NetworkLoggerState()
public var eventManager = ProtocolEventManager()
private var incomingFrames = FrameArray()
public var tx: ((Span<UInt8>) -> Void)? = nil
public var rx: ((@escaping (Span<UInt8>) -> Void) -> Void)? = nil
public var tx: (@Sendable (Span<UInt8>) -> Void)? = nil
public var rx: (@Sendable (@escaping (Span<UInt8>) -> Void) -> Void)? = nil

public func setup(
remote: Endpoint?,
Expand Down Expand Up @@ -179,12 +179,12 @@ public struct CustomLinkProtocol: NetworkProtocol {
@_spi(Essentials)
@available(Network 0.1.0, *)
extension ProtocolOptions<CustomLinkProtocol> {
public var tx: ((Span<UInt8>) -> Void)? {
public var tx: (@Sendable (_ bytes: Span<UInt8>) -> Void)? {
get { perProtocolOptions!.tx }
set { perProtocolOptions!.tx = newValue }
}

public var rx: ((@escaping (Span<UInt8>) -> Void) -> Void)? {
public var rx: (@Sendable (_ inject: @escaping (_ bytes: Span<UInt8>) -> Void) -> Void)? {
get { perProtocolOptions!.rx }
set { perProtocolOptions!.rx = newValue }
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftNetwork/Protocols/DemuxProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public struct DemuxProtocol: NetworkProtocol {
public typealias Options = DemuxOptions
public typealias Metadata = DemuxMetadata

public struct DemuxOptions: PerProtocolOptions {
public struct DemuxOptions: PerProtocolOptions, Sendable {
var demuxPatterns = Deque<DemuxPattern>()

init() {}
Expand Down
6 changes: 3 additions & 3 deletions Sources/SwiftNetwork/Protocols/IPProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public struct IPProtocol: NetworkProtocol {
1280
}

public enum Version: UInt8 {
public enum Version: UInt8, Sendable {
/// Allows any IP version.
case any = 0
/// Uses only IP version 4 (IPv4).
Expand All @@ -78,7 +78,7 @@ public struct IPProtocol: NetworkProtocol {
case v6 = 6
}

public enum AddressPreference: UInt8 {
public enum AddressPreference: UInt8, Sendable {
case any = 0
case temporary = 1
case stable = 2
Expand Down Expand Up @@ -110,7 +110,7 @@ public struct IPProtocol: NetworkProtocol {
}
}

public struct IPOptions: PerProtocolOptions {
public struct IPOptions: PerProtocolOptions, Sendable {
var version: Version = .any
var localAddressPreference: AddressPreference = .any

Expand Down
9 changes: 8 additions & 1 deletion Sources/SwiftNetwork/Protocols/SwiftTLSProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public struct SwiftTLSProtocol: NetworkProtocol {
_tlsOptions.externalPSK = .init(externalIdentity: identity, epsk: .init(data: epsk))
}
#else
private struct SwiftTLSOptionsStorage {
private struct SwiftTLSOptionsStorage: Sendable {
var serverName: String?
var quicTransportParameters: [UInt8]?
var applicationProtocols: [String]?
Expand Down Expand Up @@ -1311,6 +1311,13 @@ public struct SwiftTLSProtocol: NetworkProtocol {

}

#if !EXPORT_SWIFTTLS
// Under `EXPORT_SWIFTTLS` the options store a `SwiftTLSOptions`, which is not `Sendable`, so the options can only be
// `Sendable` when they hold their own copy of the fields.
@available(Network 0.1.0, *)
extension SwiftTLSProtocol.SwiftTLSProtocolOptions: Sendable {}
#endif

@_spi(ProtocolProvider)
@available(Network 0.1.0, *)
extension ProtocolOptions<SwiftTLSProtocol> {
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftNetwork/Protocols/TCPProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public struct TCPProtocol: NetworkProtocol {
16
}

public struct TCPOptions: PerProtocolOptions {
public struct TCPOptions: PerProtocolOptions, Sendable {

internal var _maximumSegmentSize: UInt32 = 0
public var maximumSegmentSize: UInt32 {
Expand Down
4 changes: 3 additions & 1 deletion Tests/SwiftNetworkTests/SwiftNetworkConnectionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,9 @@ final class SwiftNetworkConnectionTests: NetTestCase {
func testNoTransportCustomLink() {
let group = DispatchGroup()
group.enter()
var injection: ((Span<UInt8>) -> Void)?
// The rx handler writes this during connection setup, before the `.ready` update leaves `group`, and the
// test reads it only after `group.wait`, so the group orders the two accesses.
nonisolated(unsafe) var injection: ((Span<UInt8>) -> Void)?
let c1 = NetworkConnection(
to: Endpoint(address: IPv4Address.loopback, port: 7778),
using: .parameters {
Expand Down
12 changes: 8 additions & 4 deletions Tests/SwiftNetworkTests/SwiftNetworkQUICHarnessTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import Synchronization
import XCTest

#if !targetEnvironment(simulator) && (os(iOS) || os(macOS) || os(Linux))
Expand Down Expand Up @@ -762,11 +763,11 @@ final class SwiftNetworkQUICHarnessTests: NetTestCase {
let clientOptions = QUICProtocol.options()
clientOptions.connectionOptions.initialPacketSize = 1400

var observedInitialPacketSizes: [Int] = []
let observedInitialPacketSizes = Mutex<[Int]>([])
let observeFrameHandler: BridgeObserveFrameHandler = { firstByte, byteCount in
// Verify initial packet
guard (firstByte & 0xF0) == 0xC0 else { return }
observedInitialPacketSizes.append(byteCount)
observedInitialPacketSizes.withLock { $0.append(byteCount) }
}

QUICTestHarness().runQUICTest(
Expand All @@ -777,8 +778,11 @@ final class SwiftNetworkQUICHarnessTests: NetTestCase {
bridgeObserveFrameHandler: observeFrameHandler
)

XCTAssertFalse(observedInitialPacketSizes.isEmpty, "Should have observed at least one Initial packet")
XCTAssertEqual(observedInitialPacketSizes.first, 1400)
XCTAssertFalse(
observedInitialPacketSizes.withLock { $0.isEmpty },
"Should have observed at least one Initial packet"
)
XCTAssertEqual(observedInitialPacketSizes.withLock { $0.first }, 1400)
}

func testQUICDatagramRemoteMaxDatagramFrameSize() {
Expand Down
9 changes: 5 additions & 4 deletions Tests/SwiftNetworkTests/SwiftNetworkQUICSpinBitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import Synchronization
import XCTest

#if !targetEnvironment(simulator) && (os(iOS) || os(macOS) || os(Linux))
Expand Down Expand Up @@ -64,10 +65,10 @@ final class SwiftNetworkQUICSpinBitTests: NetTestCase {
// it from the server.

var hasSpinBit = true
var observedSpinBitValues: Set<Bool> = []
let observedSpinBitValues = Mutex<Set<Bool>>([])
let observeFirstByteHandler: BridgeObserveFirstByteHandler = { firstByte in
guard (firstByte & 0xC0) == 0x40 else { return }
observedSpinBitValues.insert((firstByte & 0x20) != 0)
observedSpinBitValues.withLock { values -> Void in values.insert((firstByte & 0x20) != 0) }
}
QUICTestHarness().runQUICTest(
dataBlock: Array("Hello World!".utf8),
Expand Down Expand Up @@ -99,11 +100,11 @@ final class SwiftNetworkQUICSpinBitTests: NetTestCase {
harness.context.async {
defer { expectation.fulfill() }
XCTAssertFalse(
observedSpinBitValues.isEmpty,
observedSpinBitValues.withLock { $0.isEmpty },
"BridgeDatagramProtocol should have observed short-header packets with spin bit values"
)
XCTAssertTrue(
observedSpinBitValues.contains(true),
observedSpinBitValues.withLock { $0.contains(true) },
"BridgeDatagramProtocol should have observed at least one packet with spin bit set"
)
}
Expand Down
Loading