import Foundation import Network /// Network interfaces that services can be bound to (e.g. en7 = technical network). public enum NetworkInterfaces { public struct Info: Hashable, Sendable, Identifiable { public var id: String { name } public let name: String public let kind: String } /// Currently available interfaces (wired, Wi-Fi, other), excluding loopback. public static func available() async -> [Info] { await withCheckedContinuation { continuation in let monitor = NWPathMonitor() let once = OnceFlag() monitor.pathUpdateHandler = { path in guard once.claim() else { return } monitor.cancel() continuation.resume(returning: path.availableInterfaces .filter { $0.type != .loopback } .map { Info(name: $0.name, kind: describe($0.type)) }) } monitor.start(queue: .global(qos: .utility)) } } static func interface(named name: String) async -> NWInterface? { await withCheckedContinuation { continuation in let monitor = NWPathMonitor() let once = OnceFlag() monitor.pathUpdateHandler = { path in guard once.claim() else { return } monitor.cancel() continuation.resume(returning: path.availableInterfaces.first { $0.name == name }) } monitor.start(queue: .global(qos: .utility)) } } private static func describe(_ type: NWInterface.InterfaceType) -> String { switch type { case .wiredEthernet: "Ethernet" case .wifi: "WLAN" default: "Andere" } } } final class OnceFlag: @unchecked Sendable { private let lock = NSLock() private var done = false func claim() -> Bool { lock.withLock { defer { done = true }; return !done } } }