77
88import Foundation
99import Network
10- import NetworkKit
10+
11+ #if compiler(>=6.0)
12+ public import NetworkKit
13+ #else
14+ @_exported import NetworkKit
15+ #endif
1116
1217public struct NetworkPath : Sendable {
1318 /// A status indicating whether a path can be used by connections.
@@ -53,19 +58,46 @@ public struct NetworkPath: Sendable {
5358 return interface
5459 }
5560 }
61+ }
62+
63+ public extension NetworkPath {
64+ /// Network interfaces used by this path
65+ var usedInterfaces : [ NetworkKit . Interface ] {
66+ availableInterfaces. filter { usesInterfaceType ( $0. type) }
67+ }
68+
69+ /// Physical network interfaces used by this path, excluding virtual interfaces
70+ var usedPhysicalInterfaces : [ NetworkKit . Interface ] {
71+ usedInterfaces. filter {
72+ switch $0. type {
73+ case . wifi, . cellular, . wiredEthernet: return true
74+ default : return false
75+ }
76+ }
77+ }
5678
57- public func usesInterfaceType( _ type: Interface . InterfaceType ) -> Bool {
79+ /// The primary used physical network interface, which is the first in the list of used interfaces
80+ var primaryUsedPhysicalInterface : NetworkKit . Interface ? { usedInterfaces. first }
81+
82+ /// Checks if the path uses an NWInterface with the specified type
83+ func usesInterfaceType( _ type: Interface . InterfaceType ) -> Bool {
5884 rawNWPath. usesInterfaceType ( type. nwInterfaceType)
5985 }
6086}
6187
6288public extension NetworkPath {
6389 enum Status : Sendable {
64- case unsatisfied
90+ /// The path has a usable route upon which to send and receive data
6591 case satisfied
92+
93+ /// The path does not have a usable route. This may be due to a network interface being down, or due to system policy.
94+ case unsatisfied
95+
96+ /// The path does not currently have a usable route, but a connection attempt will trigger network attachment.
6697 case requiresConnection
6798
68- init ( nwStatus: NWPath . Status ) {
99+ /// Initializes a Status from a NWPath.Status
100+ fileprivate init ( nwStatus: NWPath . Status ) {
69101 switch nwStatus {
70102 case . satisfied:
71103 self = . satisfied
@@ -80,28 +112,52 @@ public extension NetworkPath {
80112 }
81113
82114 @available ( iOS 14 . 2 , macCatalyst 14 . 2 , macOS 11 . 0 , tvOS 14 . 2 , visionOS 1 . 0 , watchOS 7 . 1 , * )
83- enum UnsatisfiedReason : Sendable {
115+ enum UnsatisfiedReason : Sendable , CustomStringConvertible {
116+ /// No reason is given
117+ case notAvailable
118+
119+ /// The user has disabled cellular
84120 case cellularDenied
121+
122+ /// The user has disabled Wi-Fi
123+ case wifiDenied
124+
125+ /// The user has disabled local network access
85126 case localNetworkDenied
86- case notAvailable
127+
128+ /// A required VPN is not active
129+ @available ( macOS 14 . 0 , iOS 17 . 0 , macCatalyst 17 . 0 , watchOS 10 . 0 , tvOS 17 . 0 , visionOS 1 . 0 , * )
87130 case vpnInactive
88- case wifiDenied
89131
90- init ( nwUnsatisfiedReason: NWPath . UnsatisfiedReason ) {
132+ /// Initializes an UnsatisfiedReason from a NWPath.UnsatisfiedReason
133+ fileprivate init ( nwUnsatisfiedReason: NWPath . UnsatisfiedReason ) {
91134 switch nwUnsatisfiedReason {
135+ case . notAvailable:
136+ self = . notAvailable
92137 case . cellularDenied:
93138 self = . cellularDenied
139+ case . wifiDenied:
140+ self = . wifiDenied
94141 case . localNetworkDenied:
95142 self = . localNetworkDenied
96- case . notAvailable:
97- self = . notAvailable
98143 case . vpnInactive:
99- self = . vpnInactive
100- case . wifiDenied :
101- self = . wifiDenied
144+ if #available ( macOS 14 . 0 , iOS 17 . 0 , macCatalyst 17 . 0 , watchOS 10 . 0 , tvOS 17 . 0 , visionOS 1 . 0 , * ) {
145+ self = . vpnInactive
146+ }
102147 @unknown default :
103148 fatalError ( " Unknown NWPath.UnsatisfiedReason value " )
104149 }
150+ self = . notAvailable
151+ }
152+
153+ public var description : String {
154+ switch self {
155+ case . cellularDenied: return " Cellular access denied "
156+ case . localNetworkDenied: return " Local network access denied "
157+ case . notAvailable: return " Network not available "
158+ case . vpnInactive: return " VPN is inactive "
159+ case . wifiDenied: return " WiFi access denied "
160+ }
105161 }
106162 }
107163}
0 commit comments