swiftlib_sdlan/Sources/sdlan/SDLNetworkMonitor.swift
2025-07-15 00:17:20 +08:00

63 lines
1.7 KiB
Swift

//
// SDLNetworkMonitor.swift
// Tun
//
// Created by on 2024/5/16.
//
import Foundation
import Network
import Combine
//
class SDLNetworkMonitor: @unchecked Sendable {
private var monitor: NWPathMonitor
private var interfaceType: NWInterface.InterfaceType?
private let publisher = PassthroughSubject<NWInterface.InterfaceType, Never>()
private var cancel: AnyCancellable?
private let queue = DispatchQueue(label: "networkMonitorQueue")
public let eventFlow = PassthroughSubject<MonitorEvent, Never>()
enum MonitorEvent {
case changed
case unreachable
}
init() {
self.monitor = NWPathMonitor()
}
func start() {
self.monitor.pathUpdateHandler = {path in
if path.status == .satisfied {
if path.usesInterfaceType(.wifi) {
self.publisher.send(.wifi)
} else if path.usesInterfaceType(.cellular) {
self.publisher.send(.cellular)
} else if path.usesInterfaceType(.wiredEthernet) {
self.publisher.send(.wiredEthernet)
}
} else {
self.eventFlow.send(.unreachable)
self.interfaceType = nil
}
}
self.monitor.start(queue: self.queue)
self.cancel = publisher.throttle(for: 5.0, scheduler: self.queue, latest: true)
.sink { type in
if self.interfaceType != nil && self.interfaceType != type {
self.eventFlow.send(.changed)
}
self.interfaceType = type
}
}
deinit {
self.monitor.cancel()
self.cancel?.cancel()
}
}