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

162 lines
5.6 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
}
}
//
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 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["network_address"] 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
}
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)
}
}