punchnet-macos/Tun/Punchnet/SDLConfiguration.swift
2026-01-28 19:26:14 +08:00

192 lines
6.4 KiB
Swift

//
// SDLConfiguration.swift
// sdlan
//
// Created by on 2025/7/14.
//
import Foundation
import NIOCore
//
public class SDLConfiguration {
public struct StunServer {
public let host: String
public let ports: [Int]
public init(host: String, ports: [Int]) {
self.host = host
self.ports = ports
}
}
public struct NetworkAddress {
public let networkId: UInt32
public let ip: UInt32
public let maskLen: UInt8
public let mac: Data
public let networkDomain: String
}
//
let version: UInt8
//
let installedChannel: String
let superHost: String
let superPort: Int
let stunServers: [StunServer]
let remoteDnsServer: String
let noticePort: Int
lazy var stunSocketAddress: SocketAddress = {
let stunServer = stunServers[0]
return try! SocketAddress.makeAddressResolvingHost(stunServer.host, port: stunServer.ports[0])
}()
//
lazy var stunProbeSocketAddressArray: [[SocketAddress]] = {
return stunServers.map { stunServer in
[
try! SocketAddress.makeAddressResolvingHost(stunServer.host, port: stunServer.ports[0]),
try! SocketAddress.makeAddressResolvingHost(stunServer.host, port: stunServer.ports[1])
]
}
}()
let clientId: String
let networkAddress: NetworkAddress
let hostname: String
let accessToken: String
public init(version: UInt8,
installedChannel: String,
superHost: String,
superPort: Int,
stunServers: [StunServer],
clientId: String,
networkAddress: NetworkAddress,
hostname: String,
noticePort: Int,
accessToken: String,
remoteDnsServer: String) {
self.version = version
self.installedChannel = installedChannel
self.superHost = superHost
self.superPort = superPort
self.stunServers = stunServers
self.clientId = clientId
self.networkAddress = networkAddress
self.noticePort = noticePort
self.accessToken = accessToken
self.remoteDnsServer = remoteDnsServer
self.hostname = hostname
}
// mac
public static func getMacAddress() -> Data {
let key = "gMacAddress2"
let userDefaults = UserDefaults.standard
if let mac = userDefaults.value(forKey: key) as? Data {
return mac
}
else {
let mac = generateMacAddress()
userDefaults.setValue(mac, forKey: key)
return mac
}
}
// mac
private static func generateMacAddress() -> Data {
var macAddress = [UInt8](repeating: 0, count: 6)
for i in 0..<6 {
macAddress[i] = UInt8.random(in: 0...255)
}
return Data(macAddress)
}
}
//
extension SDLConfiguration {
static func parse(options: [String: NSObject]) -> SDLConfiguration? {
guard let installed_channel = options["installed_channel"] as? String,
let superIp = options["super_ip"] as? String,
let superPort = options["super_port"] as? Int,
let stunServersStr = options["stun_servers"] as? String,
let noticePort = options["notice_port"] as? Int,
let token = options["token"] as? String,
let accessToken = options["access_token"] as? String,
let clientId = options["client_id"] as? String,
let remoteDnsServer = options["remote_dns_server"] as? String,
let hostname = options["hostname"] as? String,
let networkAddressDict = options["networkAddress"] as? [String: NSObject] else {
return nil
}
guard let stunServers = parseStunServers(stunServersStr: stunServersStr), stunServers.count >= 2 else {
NSLog("stunServers配置错误")
return nil
}
guard let networkAddress = parseNetworkAddress(networkAddressDict) else {
return nil
}
NSLog("[PacketTunnelProvider] client_id: \(clientId), token: \(token)")
return SDLConfiguration(version: 1,
installedChannel: installed_channel,
superHost: superIp,
superPort: superPort,
stunServers: stunServers,
clientId: clientId,
networkAddress: networkAddress,
hostname: hostname,
noticePort: noticePort,
accessToken: accessToken,
remoteDnsServer: remoteDnsServer)
}
private static func parseStunServers(stunServersStr: String) -> [SDLConfiguration.StunServer]? {
let stunServers = stunServersStr.split(separator: ";").compactMap { server -> SDLConfiguration.StunServer? in
let parts = server.split(separator: ":", maxSplits: 2)
guard parts.count == 2 else {
return nil
}
let ports = parts[1].split(separator: ",", maxSplits: 2)
guard ports.count == 2, let port1 = Int(String(ports[0])), let port2 = Int(String(ports[1])) else {
return nil
}
return .init(host: String(parts[0]), ports: [port1, port2])
}
return stunServers.count >= 2 ? stunServers : nil
}
private static func parseNetworkAddress(_ config: [String: NSObject]) -> SDLConfiguration.NetworkAddress? {
guard let networkId = config["network_id"] as? UInt32,
let ipStr = config["ip"] as? String,
let ip = SDLUtil.ipv4StrToInt32(ipStr),
let maskLen = config["mask_len"] as? UInt8,
let mac = config["mac"] as? Data,
let networkDomain = config["network_domain"] as? String else {
return nil
}
return .init(networkId: networkId, ip: ip, maskLen: maskLen, mac: mac, networkDomain: networkDomain)
}
}