解决系统的异常退出问题

This commit is contained in:
anlicheng 2026-02-04 14:56:30 +08:00
parent 3283c2ae61
commit 8c8006bc69
8 changed files with 128 additions and 250 deletions

View File

@ -0,0 +1,37 @@
//
// ArpServer.swift
// sdlan
//
// Created by on 2025/7/14.
//
import Foundation
import Darwin
actor ArpServerActor {
private var known_macs: [UInt32:Data] = [:]
init(known_macs: [UInt32:Data]) {
self.known_macs = known_macs
}
func query(ip: UInt32) -> Data? {
return self.known_macs[ip]
}
func append(ip: UInt32, mac: Data) {
self.known_macs[ip] = mac
}
func remove(ip: UInt32) {
self.known_macs.removeValue(forKey: ip)
}
func dropMacs(macs: [Data]) {
self.known_macs = self.known_macs.filter { !macs.contains($0.value) }
}
func clear() {
self.known_macs = [:]
}
}

View File

@ -1,51 +0,0 @@
//
// ArpServer.swift
// sdlan
//
// Created by on 2025/7/14.
//
import Foundation
import Darwin
final class ArpServer {
private var known_macs: [UInt32:Data] = [:]
private var lock = os_unfair_lock()
init(known_macs: [UInt32:Data]) {
self.known_macs = known_macs
}
func query(ip: UInt32) -> Data? {
return withLock {
return self.known_macs[ip]
}
}
func append(ip: UInt32, mac: Data) {
withLock {
self.known_macs[ip] = mac
}
}
func remove(ip: UInt32) {
withLock {
_ = self.known_macs.removeValue(forKey: ip)
}
}
func clear() {
withLock {
self.known_macs = [:]
}
}
private func withLock<T>(_ body: () throws -> T) rethrows -> T {
os_unfair_lock_lock(&lock)
defer{
os_unfair_lock_unlock(&lock)
}
return try body()
}
}

View File

@ -25,6 +25,27 @@ public class SDLConfiguration {
public let maskLen: UInt8 public let maskLen: UInt8
public let mac: Data public let mac: Data
public let networkDomain: String public let networkDomain: String
// ip
var ipAddress: String {
return SDLUtil.int32ToIp(self.ip)
}
//
var maskAddress: String {
let len0 = 32 - maskLen
let num: UInt32 = (0xFFFFFFFF >> len0) << len0
return SDLUtil.int32ToIp(num)
}
//
var netAddress: String {
let len0 = 32 - maskLen
let mask: UInt32 = (0xFFFFFFFF >> len0) << len0
return SDLUtil.int32ToIp(self.ip & mask)
}
} }
// //

View File

@ -35,7 +35,6 @@ actor SDLContextActor {
private var udpHole: SDLUDPHole? private var udpHole: SDLUDPHole?
private var udpHoleWorkers: [Task<Void, Never>]? private var udpHoleWorkers: [Task<Void, Never>]?
nonisolated let providerAdapter: SDLTunnelProviderAdapter
// dnsclient // dnsclient
private var dnsClient: SDLDNSClient? private var dnsClient: SDLDNSClient?
private var dnsWorker: Task<Void, Never>? private var dnsWorker: Task<Void, Never>?
@ -48,7 +47,7 @@ actor SDLContextActor {
private var readTask: Task<(), Never>? private var readTask: Task<(), Never>?
private var sessionManager: SessionManager private var sessionManager: SessionManager
private var arpServer: ArpServer private var arpServer: ArpServerActor
// //
private var monitor: SDLNetworkMonitor? private var monitor: SDLNetworkMonitor?
@ -63,14 +62,16 @@ actor SDLContextActor {
// //
private var loopChildWorkers: [Task<Void, Never>] = [] private var loopChildWorkers: [Task<Void, Never>] = []
private let provider: NEPacketTunnelProvider
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher, aesCipher: AESCipher) { public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher, aesCipher: AESCipher) {
self.provider = provider
self.config = config self.config = config
self.rsaCipher = rsaCipher self.rsaCipher = rsaCipher
self.aesCipher = aesCipher self.aesCipher = aesCipher
self.sessionManager = SessionManager() self.sessionManager = SessionManager()
self.arpServer = ArpServer(known_macs: [:]) self.arpServer = ArpServerActor(known_macs: [:])
self.providerAdapter = SDLTunnelProviderAdapter(provider: provider)
self.puncherActor = SDLPuncherActor(querySocketAddress: config.stunSocketAddress) self.puncherActor = SDLPuncherActor(querySocketAddress: config.stunSocketAddress)
self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray) self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray)
@ -153,7 +154,7 @@ actor SDLContextActor {
break break
} }
let nePacket = NEPacket(data: packet, protocolFamily: 2) let nePacket = NEPacket(data: packet, protocolFamily: 2)
self.providerAdapter.writePackets(packets: [nePacket]) self.provider.packetFlow.writePacketObjects([nePacket])
} }
} }
@ -188,7 +189,7 @@ actor SDLContextActor {
await self.sendStunRequest() await self.sendStunRequest()
} }
SDLLogger.shared.log("[SDLContext] pingTask cancel") SDLLogger.shared.log("[SDLContext] udp pingTask cancel")
} }
// //
@ -199,6 +200,8 @@ actor SDLContextActor {
} }
try? await self.handleData(data: data) try? await self.handleData(data: data)
} }
SDLLogger.shared.log("[SDLContext] udp dataTask cancel")
} }
// //
@ -225,6 +228,8 @@ actor SDLContextActor {
await self.handleRegisterAck(remoteAddress: remoteAddress, registerAck: registerAck) await self.handleRegisterAck(remoteAddress: remoteAddress, registerAck: registerAck)
} }
} }
SDLLogger.shared.log("[SDLContext] udp signalTask cancel")
} }
self.udpHole = udpHole self.udpHole = udpHole
@ -293,13 +298,12 @@ actor SDLContextActor {
SDLLogger.shared.log("[SDLContext] get registerSuperAck, aes_key len: \(self.aesKey!.count)", level: .info) SDLLogger.shared.log("[SDLContext] get registerSuperAck, aes_key len: \(self.aesKey!.count)", level: .info)
// tun // tun
do { do {
let ipAddress = try await self.providerAdapter.setNetworkSettings(networkAddress: self.config.networkAddress, dnsServer: SDLDNSClient.Helper.dnsServer) try await self.setNetworkSettings(networkAddress: self.config.networkAddress, dnsServer: SDLDNSClient.Helper.dnsServer)
SDLLogger.shared.log("[SDLContext] setNetworkSettings successed") SDLLogger.shared.log("[SDLContext] setNetworkSettings successed")
self.noticeClient?.send(data: NoticeMessage.ipAdress(ip: ipAddress))
self.startReader() self.startReader()
} catch let err { } catch let err {
SDLLogger.shared.log("[SDLContext] setTunnelNetworkSettings get error: \(err)", level: .error) SDLLogger.shared.log("[SDLContext] setTunnelNetworkSettings get error: \(err)", level: .error)
exit(-1) self.provider.cancelTunnelWithError(err)
} }
} }
@ -313,7 +317,10 @@ actor SDLContextActor {
case .invalidToken, .nodeDisabled: case .invalidToken, .nodeDisabled:
let alertNotice = NoticeMessage.alert(alert: errorMessage) let alertNotice = NoticeMessage.alert(alert: errorMessage)
self.noticeClient?.send(data: alertNotice) self.noticeClient?.send(data: alertNotice)
exit(-1) // 退
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
self.provider.cancelTunnelWithError(error)
case .noIpAddress, .networkFault, .internalFault: case .noIpAddress, .networkFault, .internalFault:
let alertNotice = NoticeMessage.alert(alert: errorMessage) let alertNotice = NoticeMessage.alert(alert: errorMessage)
self.noticeClient?.send(data: alertNotice) self.noticeClient?.send(data: alertNotice)
@ -322,12 +329,11 @@ actor SDLContextActor {
} }
private func handleEvent(event: SDLEvent) throws { private func handleEvent(event: SDLEvent) async throws {
switch event { switch event {
case .dropMacs(let dropMacsEvent): case .dropMacs(let dropMacsEvent):
// TODO
SDLLogger.shared.log("[SDLContext] drop macs", level: .info) SDLLogger.shared.log("[SDLContext] drop macs", level: .info)
() await self.arpServer.dropMacs(macs: dropMacsEvent.macs)
case .natChanged(let natChangedEvent): case .natChanged(let natChangedEvent):
let dstMac = natChangedEvent.mac let dstMac = natChangedEvent.mac
SDLLogger.shared.log("[SDLContext] natChangedEvent, dstMac: \(dstMac)", level: .info) SDLLogger.shared.log("[SDLContext] natChangedEvent, dstMac: \(dstMac)", level: .info)
@ -349,7 +355,10 @@ actor SDLContextActor {
case .networkShutdown(let shutdownEvent): case .networkShutdown(let shutdownEvent):
let alertNotice = NoticeMessage.alert(alert: shutdownEvent.message) let alertNotice = NoticeMessage.alert(alert: shutdownEvent.message)
self.noticeClient?.send(data: alertNotice) self.noticeClient?.send(data: alertNotice)
exit(-1)
// 退
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)
self.provider.cancelTunnelWithError(error)
} }
} }
@ -436,7 +445,7 @@ actor SDLContextActor {
await self.routeLayerPacket(dstMac: arpPacket.senderMAC, type: .arp, data: response.marshal()) await self.routeLayerPacket(dstMac: arpPacket.senderMAC, type: .arp, data: response.marshal())
case .response: case .response:
SDLLogger.shared.log("[SDLContext] get arp response packet", level: .debug) SDLLogger.shared.log("[SDLContext] get arp response packet", level: .debug)
self.arpServer.append(ip: arpPacket.senderIP, mac: arpPacket.senderMAC) await self.arpServer.append(ip: arpPacket.senderIP, mac: arpPacket.senderMAC)
} }
} else { } else {
SDLLogger.shared.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(networkAddr.ip))", level: .debug) SDLLogger.shared.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(networkAddr.ip))", level: .debug)
@ -449,7 +458,7 @@ actor SDLContextActor {
return return
} }
let packet = NEPacket(data: ipPacket.data, protocolFamily: 2) let packet = NEPacket(data: ipPacket.data, protocolFamily: 2)
self.providerAdapter.writePackets(packets: [packet]) self.provider.packetFlow.writePacketObjects([packet])
default: default:
SDLLogger.shared.log("[SDLContext] get invalid packet", level: .debug) SDLLogger.shared.log("[SDLContext] get invalid packet", level: .debug)
} }
@ -482,14 +491,15 @@ actor SDLContextActor {
return return
} }
let packets = await self.providerAdapter.readPackets() let (packets, numbers) = await self.provider.packetFlow.readPackets()
let ipPackets = packets.compactMap { IPPacket($0) } for (data, number) in zip(packets, numbers) where number == 2 {
for ipPacket in ipPackets { if let ipPacket = IPPacket(data) {
await self.dealPacket(packet: ipPacket) await self.dealPacket(packet: ipPacket)
} }
} }
} }
} }
}
// //
private func dealPacket(packet: IPPacket) async { private func dealPacket(packet: IPPacket) async {
@ -505,12 +515,12 @@ actor SDLContextActor {
// , ip // , ip
if dstIp == networkAddr.ip { if dstIp == networkAddr.ip {
let nePacket = NEPacket(data: packet.data, protocolFamily: 2) let nePacket = NEPacket(data: packet.data, protocolFamily: 2)
self.providerAdapter.writePackets(packets: [nePacket]) self.provider.packetFlow.writePacketObjects([nePacket])
return return
} }
// arpmac // arpmac
if let dstMac = self.arpServer.query(ip: dstIp) { if let dstMac = await self.arpServer.query(ip: dstIp) {
await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data) await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data)
} }
else { else {
@ -564,6 +574,43 @@ actor SDLContextActor {
} }
} }
//
private func setNetworkSettings(networkAddress: SDLConfiguration.NetworkAddress, dnsServer: String) async throws {
let routes: [NEIPv4Route] = [
NEIPv4Route(destinationAddress: networkAddress.netAddress, subnetMask: networkAddress.maskAddress),
NEIPv4Route(destinationAddress: dnsServer, subnetMask: "255.255.255.255"),
]
// Add code here to start the process of connecting the tunnel.
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "8.8.8.8")
networkSettings.mtu = 1250
// DNS
let networkDomain = networkAddress.networkDomain
let dnsSettings = NEDNSSettings(servers: [dnsServer])
dnsSettings.searchDomains = [networkDomain]
dnsSettings.matchDomains = [networkDomain]
dnsSettings.matchDomainsNoSearch = false
networkSettings.dnsSettings = dnsSettings
let ipv4Settings = NEIPv4Settings(addresses: [networkAddress.ipAddress], subnetMasks: [networkAddress.maskAddress])
//
//NEIPv4Route.default()
ipv4Settings.includedRoutes = routes
networkSettings.ipv4Settings = ipv4Settings
//
try await self.provider.setTunnelNetworkSettings(networkSettings)
}
// , 线packetFlow
func readPackets() async -> [Data] {
let (packets, numbers) = await self.provider.packetFlow.readPackets()
return zip(packets, numbers).compactMap { (data, number) in
return number == 2 ? data : nil
}
}
private func spawnLoop(_ body: @escaping () async throws -> Void) -> Task<Void, Never> { private func spawnLoop(_ body: @escaping () async throws -> Void) -> Task<Void, Never> {
return Task.detached { return Task.detached {
while !Task.isCancelled { while !Task.isCancelled {

View File

@ -1,49 +0,0 @@
//
// SDLIPAddress.swift
// Tun
//
// Created by on 2024/3/4.
//
import Foundation
struct SDLNetAddress {
let ip: UInt32
let maskLen: UInt8
// ip
var ipAddress: String {
return intToIpAddress(self.ip)
}
//
var maskAddress: String {
let len0 = 32 - maskLen
let num: UInt32 = (0xFFFFFFFF >> len0) << len0
return intToIpAddress(num)
}
//
var networkAddress: String {
let len0 = 32 - maskLen
let mask: UInt32 = (0xFFFFFFFF >> len0) << len0
return intToIpAddress(self.ip & mask)
}
init(ip: UInt32, maskLen: UInt8) {
self.ip = ip
self.maskLen = maskLen
}
private func intToIpAddress(_ num: UInt32) -> String {
let ip0 = (UInt8) (num >> 24 & 0xFF)
let ip1 = (UInt8) (num >> 16 & 0xFF)
let ip2 = (UInt8) (num >> 8 & 0xFF)
let ip3 = (UInt8) (num & 0xFF)
return "\(ip0).\(ip1).\(ip2).\(ip3)"
}
}

View File

@ -1,84 +0,0 @@
//
// SDLContext.swift
// Tun
//
// Created by on 2024/2/29.
//
import Foundation
import NetworkExtension
import NIOCore
import Combine
//
/*
1. rsa的加解密逻辑
*/
final class SDLTunnelProviderAdapter {
//
struct Route {
let dstAddress: String
let subnetMask: String
var debugInfo: String {
return "\(dstAddress):\(subnetMask)"
}
}
let provider: NEPacketTunnelProvider
public init(provider: NEPacketTunnelProvider) {
self.provider = provider
}
func writePackets(packets: [NEPacket]) {
//let packet = NEPacket(data: ipPacket.data, protocolFamily: 2)
self.provider.packetFlow.writePacketObjects(packets)
}
//
func setNetworkSettings(networkAddress: SDLConfiguration.NetworkAddress, dnsServer: String) async throws -> String {
let netAddress = SDLNetAddress(ip: networkAddress.ip, maskLen: networkAddress.maskLen)
let routes = [
Route(dstAddress: netAddress.networkAddress, subnetMask: netAddress.maskAddress),
Route(dstAddress: dnsServer, subnetMask: "255.255.255.255")
]
// Add code here to start the process of connecting the tunnel.
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "8.8.8.8")
networkSettings.mtu = 1250
// DNS
let networkDomain = networkAddress.networkDomain
let dnsSettings = NEDNSSettings(servers: [dnsServer])
dnsSettings.searchDomains = [networkDomain]
dnsSettings.matchDomains = [networkDomain]
dnsSettings.matchDomainsNoSearch = false
networkSettings.dnsSettings = dnsSettings
SDLLogger.shared.log("[SDLTunnelProviderAdapter] Tun started at network ip: \(netAddress.ipAddress), mask: \(netAddress.maskAddress)", level: .info)
let ipv4Settings = NEIPv4Settings(addresses: [netAddress.ipAddress], subnetMasks: [netAddress.maskAddress])
//
//NEIPv4Route.default()
ipv4Settings.includedRoutes = routes.map { route in
NEIPv4Route(destinationAddress: route.dstAddress, subnetMask: route.subnetMask)
}
networkSettings.ipv4Settings = ipv4Settings
//
try await self.provider.setTunnelNetworkSettings(networkSettings)
return netAddress.ipAddress
}
// , 线packetFlow
func readPackets() async -> [Data] {
let (packets, numbers) = await self.provider.packetFlow.readPackets()
return zip(packets, numbers).compactMap { (data, number) in
return number == 2 ? data : nil
}
}
}

View File

@ -11,9 +11,7 @@ import NIOCore
struct NoticeMessage { struct NoticeMessage {
enum InboundMessage { enum InboundMessage {
case none case none
case upgradeMessage(prompt: String, address: String)
case alertMessage(alert: String) case alertMessage(alert: String)
case ip(ip: String)
} }
static func decodeMessage(buffer: inout ByteBuffer) -> InboundMessage { static func decodeMessage(buffer: inout ByteBuffer) -> InboundMessage {
@ -23,23 +21,10 @@ struct NoticeMessage {
switch type { switch type {
case 0x01: case 0x01:
if let len0 = buffer.readInteger(as: UInt16.self),
let prompt = buffer.readString(length: Int(len0)),
let len1 = buffer.readInteger(as: UInt16.self),
let address = buffer.readString(length: Int(len1)) {
return .upgradeMessage(prompt: prompt, address: address)
}
case 0x02:
if let len0 = buffer.readInteger(as: UInt16.self), if let len0 = buffer.readInteger(as: UInt16.self),
let alert = buffer.readString(length: Int(len0)) { let alert = buffer.readString(length: Int(len0)) {
return .alertMessage(alert: alert) return .alertMessage(alert: alert)
} }
case 0x03:
if let len0 = buffer.readInteger(as: UInt16.self),
let ipAddress = buffer.readString(length: Int(len0)) {
return .ip(ip: ipAddress)
}
default: default:
return .none return .none
} }
@ -47,39 +32,16 @@ struct NoticeMessage {
return .none return .none
} }
static func upgrade(prompt: String, address: String) -> Data { static func alert(alert: String) -> Data {
var data = Data() var data = Data()
data.append(contentsOf: [0x01]) data.append(contentsOf: [0x01])
data.append(contentsOf: lenBytes(UInt16(prompt.count)))
data.append(prompt.data(using: .utf8)!)
data.append(contentsOf: lenBytes(UInt16(address.count)))
data.append(address.data(using: .utf8)!)
return data
}
static func alert(alert: String) -> Data {
var data = Data()
data.append(contentsOf: [0x02])
data.append(contentsOf: lenBytes(UInt16(alert.count))) data.append(contentsOf: lenBytes(UInt16(alert.count)))
data.append(alert.data(using: .utf8)!) data.append(alert.data(using: .utf8)!)
return data return data
} }
static func ipAdress(ip: String) -> Data {
var data = Data()
data.append(contentsOf: [0x03])
data.append(contentsOf: lenBytes(UInt16(ip.count)))
data.append(ip.data(using: .utf8)!)
return data
}
private static func lenBytes(_ value: UInt16) -> [UInt8] { private static func lenBytes(_ value: UInt16) -> [UInt8] {
let byte1 = UInt8((value >> 8) & 0xFF) let byte1 = UInt8((value >> 8) & 0xFF)
let bytes2 = UInt8(value & 0xFF) let bytes2 = UInt8(value & 0xFF)

View File

@ -222,8 +222,6 @@ struct IndexView: View {
} }
.alert(isPresented: $showStunAlert) { .alert(isPresented: $showStunAlert) {
switch self.message { switch self.message {
case .upgradeMessage(let prompt, _):
Alert(title: Text(prompt))
case .alertMessage(let alert): case .alertMessage(let alert):
Alert(title: Text(alert)) Alert(title: Text(alert))
default: default:
@ -250,9 +248,6 @@ struct IndexView: View {
switch message { switch message {
case .none: case .none:
() ()
case .ip(let ip):
self.showIpAdress = true
self.ipAddress = ip
default: default:
self.message = message self.message = message
self.showStunAlert = true self.showStunAlert = true