punchnet-macos/Tun/Punchnet/SDLConfiguration.swift
2026-05-21 13:42:43 +08:00

169 lines
5.5 KiB
Swift

//
// SDLConfiguration.swift
// sdlan
//
// Created by on 2025/7/14.
//
import Foundation
import NIOCore
//
public class SDLConfiguration {
//
public struct NetworkAddress {
public let networkId: UInt32
public let ip: UInt32
public let maskLen: UInt8
public let mac: Data
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)
}
}
//
public struct ExitNode {
let exitNodeIp: UInt32
}
//
public struct ResolvedServerEndpoint: Sendable {
let host: String
let ip: String
}
//
let version: Int
let serverEndpoint: ResolvedServerEndpoint
let stunSocketAddress: SocketAddress
//
let stunProbeSocketAddressArray: [[SocketAddress]]
let clientId: String
let networkAddress: NetworkAddress
let hostname: String
let accessToken: String
let identityId: UInt32
var exitNode: ExitNode?
public init(version: Int,
serverEndpoint: ResolvedServerEndpoint,
stunServers: [String],
clientId: String,
networkAddress: NetworkAddress,
hostname: String,
accessToken: String,
identityId: UInt32,
exitNode: ExitNode?) {
self.version = version
self.serverEndpoint = serverEndpoint
let stunHosts = stunServers.isEmpty ? [serverEndpoint.ip] : stunServers
self.stunSocketAddress = Self.makeStunSocketAddress(host: stunHosts[0], port: 1365)
self.stunProbeSocketAddressArray = stunHosts.map { stunServer in
[
Self.makeStunSocketAddress(host: stunServer, port: 1365),
Self.makeStunSocketAddress(host: stunServer, port: 1366)
]
}
self.clientId = clientId
self.networkAddress = networkAddress
self.accessToken = accessToken
self.identityId = identityId
self.hostname = hostname
self.exitNode = exitNode
}
}
private extension SDLConfiguration {
static func resolveHostAddress(host: String, port: Int) -> String {
let address = try! SocketAddress.makeAddressResolvingHost(host, port: port)
return address.ipAddress!
}
static func makeStunSocketAddress(host: String, port: Int) -> SocketAddress {
return try! SocketAddress.makeAddressResolvingHost(host, port: port)
}
}
//
extension SDLConfiguration {
static func parse(options: [String: NSObject]) -> SDLConfiguration? {
guard let version = options["version"] as? Int,
let serverHost = options["server_host"] as? String,
let stunAssistHost = options["stun_assist_host"] as? String,
let accessToken = options["access_token"] as? String,
let identityId = options["identity_id"] as? UInt32,
let clientId = options["client_id"] as? String,
let hostname = options["hostname"] as? String,
let networkAddressDict = options["network_address"] as? [String: NSObject] else {
return nil
}
guard let networkAddress = parseNetworkAddress(networkAddressDict) else {
return nil
}
//
var exitNode: ExitNode? = nil
if let exitNodeIpStr = options["exit_node_ip"] as? String, let exitNodeIp = SDLUtil.ipv4StrToInt32(exitNodeIpStr) {
exitNode = .init(exitNodeIp: exitNodeIp)
}
let serverEndpoint = ResolvedServerEndpoint(
host: serverHost,
ip: Self.resolveHostAddress(host: serverHost, port: 1443)
)
return SDLConfiguration(version: version,
serverEndpoint: serverEndpoint,
stunServers: [serverHost, stunAssistHost],
clientId: clientId,
networkAddress: networkAddress,
hostname: hostname,
accessToken: accessToken,
identityId: identityId,
exitNode: exitNode)
}
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)
}
}