601 lines
23 KiB
Swift
601 lines
23 KiB
Swift
//
|
||
// SDLContext.swift
|
||
// Tun
|
||
//
|
||
// Created by 安礼成 on 2024/2/29.
|
||
//
|
||
|
||
import Foundation
|
||
import NetworkExtension
|
||
import NIOCore
|
||
|
||
// 上下文环境变量,全局共享
|
||
/*
|
||
1. 处理rsa的加解密逻辑
|
||
*/
|
||
|
||
func startMonitorTask(name: String, _ body: @escaping () async throws -> Void, retryDelay: Duration = .seconds(5)) -> Task<Void, Never> {
|
||
return Task(name: name) {
|
||
while true {
|
||
do {
|
||
try Task.checkCancellation()
|
||
try await body()
|
||
} catch is CancellationError {
|
||
SDLLogger.log("[SDLContext] worker \(name) cancelled", for: .debug)
|
||
break
|
||
} catch let err {
|
||
SDLLogger.log("[SDLContext] worker \(name) crashed: \(err.localizedDescription), will restart", for: .debug)
|
||
do {
|
||
try await Task.sleep(for: retryDelay)
|
||
} catch is CancellationError {
|
||
break
|
||
} catch {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
enum SDLContextError: Error {
|
||
case udpHoleClosed
|
||
|
||
case dnsLocalClientClosed
|
||
case dnsLocalClientCancelled
|
||
|
||
case dnsClientClosed
|
||
case dnsClientCancelled
|
||
}
|
||
|
||
actor SDLContextActor {
|
||
|
||
private var config: SDLConfiguration
|
||
// nat的网络类型
|
||
var natType: SDLNATProberActor.NatType = .blocked
|
||
|
||
// AES加密,授权通过后,对象才会被创建
|
||
private var dataCipher: CCDataCipher?
|
||
|
||
// session token
|
||
private var sessionToken: Data?
|
||
|
||
// rsa的相关配置, public_key是本地生成的
|
||
// 加密算法相关
|
||
nonisolated let rsaCipher: RSACipher
|
||
|
||
private var dnsService: DNSService?
|
||
private let superServiceProxy: SDLSuperServiceProxy
|
||
private let udpHoleServiceProxy: SDLUDPHoleServiceProxy
|
||
private let packetOutboundActor: PacketOutboundActor
|
||
private let packetInboundActor: PacketInboundActor
|
||
private let tunNetworkManager: SDLTunNetworkManager
|
||
|
||
private let publicDnsServers = ["223.5.5.5", "119.29.29.29"]
|
||
|
||
nonisolated private let puncherActor: SDLPuncherActor
|
||
// 网络探测对象
|
||
nonisolated private let proberActor: SDLNATProberActor
|
||
|
||
// 本地ipv6地址信息探测
|
||
private var ipv6AssistClient: SDLIPV6AssistClient?
|
||
|
||
private let sessionManager: SessionManager
|
||
nonisolated private let arpResolver: ArpResolver
|
||
|
||
// 内部socket通讯
|
||
// 改为基于 App Group + Darwin Notification 的通知
|
||
|
||
// 流量统计
|
||
nonisolated private let flowTracer: SDLFlowTracer
|
||
|
||
nonisolated private let provider: NEPacketTunnelProvider
|
||
|
||
// 处理权限控制
|
||
private let policyService: PolicyService
|
||
private var updatePolicyWorker: PeriodicWorker?
|
||
|
||
// stunRequest任务
|
||
private var stunRequestWorker: PeriodicWorker?
|
||
|
||
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) {
|
||
let puncherActor = SDLPuncherActor()
|
||
let proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray)
|
||
let sessionManager = SessionManager()
|
||
let arpResolver = ArpResolver()
|
||
let flowTracer = SDLFlowTracer()
|
||
let policyService = PolicyService(identityId: config.identityId)
|
||
let superServiceProxy = SDLSuperServiceProxy()
|
||
let udpHoleServiceProxy = SDLUDPHoleServiceProxy()
|
||
let tunNetworkManager = SDLTunNetworkManager(provider: provider)
|
||
let packetOutboundActor = PacketOutboundActor(
|
||
provider: provider,
|
||
config: config,
|
||
dataCipher: nil,
|
||
sessionManager: sessionManager,
|
||
arpResolver: arpResolver,
|
||
puncherActor: puncherActor,
|
||
policyService: policyService,
|
||
superServiceProxy: superServiceProxy,
|
||
udpHoleServiceProxy: udpHoleServiceProxy,
|
||
flowTracer: flowTracer
|
||
)
|
||
let packetInboundActor = PacketInboundActor(
|
||
provider: provider,
|
||
config: config,
|
||
dataCipher: nil,
|
||
policyService: policyService,
|
||
packetOutboundActor: packetOutboundActor,
|
||
arpResolver: arpResolver,
|
||
superServiceProxy: superServiceProxy,
|
||
flowTracer: flowTracer
|
||
)
|
||
|
||
self.provider = provider
|
||
self.config = config
|
||
self.rsaCipher = rsaCipher
|
||
|
||
self.puncherActor = puncherActor
|
||
self.proberActor = proberActor
|
||
|
||
self.sessionManager = sessionManager
|
||
self.arpResolver = arpResolver
|
||
self.flowTracer = flowTracer
|
||
|
||
// 权限控制
|
||
self.policyService = policyService
|
||
self.superServiceProxy = superServiceProxy
|
||
self.udpHoleServiceProxy = udpHoleServiceProxy
|
||
self.packetOutboundActor = packetOutboundActor
|
||
self.packetInboundActor = packetInboundActor
|
||
self.tunNetworkManager = tunNetworkManager
|
||
}
|
||
|
||
public func start() async {
|
||
self.prepareTunnelNotifier()
|
||
|
||
// 启动arp的定时清理任务
|
||
await self.puncherActor.start()
|
||
await self.arpResolver.start()
|
||
|
||
let dnsService = DNSService(serverAddress: self.config.serverAddress, publicDnsServers: self.publicDnsServers) { [weak self] event in
|
||
await self?.handleDNSEvent(event)
|
||
}
|
||
self.dnsService = dnsService
|
||
await self.packetOutboundActor.updateDNSService(dnsService)
|
||
await dnsService.start()
|
||
|
||
await self.udpHoleServiceProxy.bindInbound(self.packetInboundActor) { [weak self] event in
|
||
await self?.handleUDPHoleControlEvent(event)
|
||
}
|
||
|
||
let udpHoleEventHandler = await self.udpHoleServiceProxy.makeEventHandler()
|
||
let udpHoleService = SDLUDPHoleService(proberActor: self.proberActor, onEvent: udpHoleEventHandler)
|
||
await self.udpHoleServiceProxy.replace(udpHoleService)
|
||
await udpHoleService.start(includeV6: false)
|
||
|
||
let superService = SDLSuperService(serverName: self.config.serverName, serverAddress: self.config.serverAddress) { [weak self] message in
|
||
await self?.handleSuperMessage(message: message)
|
||
}
|
||
await self.superServiceProxy.replace(superService)
|
||
await superService.start()
|
||
}
|
||
|
||
// 处理context的停止问题
|
||
public func stop() async {
|
||
await self.puncherActor.stop()
|
||
await self.arpResolver.stop()
|
||
await self.sessionManager.clear()
|
||
|
||
await self.stunRequestWorker?.stop()
|
||
self.stunRequestWorker = nil
|
||
|
||
await self.updatePolicyWorker?.stop()
|
||
self.updatePolicyWorker = nil
|
||
await self.policyService.clear()
|
||
|
||
await self.packetOutboundActor.stop()
|
||
|
||
await self.udpHoleServiceProxy.stop()
|
||
|
||
let dnsService = self.dnsService
|
||
self.dnsService = nil
|
||
await self.packetOutboundActor.updateDNSService(nil)
|
||
await dnsService?.stop()
|
||
|
||
await self.superServiceProxy.stop()
|
||
|
||
self.sessionToken = nil
|
||
self.dataCipher = nil
|
||
self.natType = .blocked
|
||
await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: nil)
|
||
await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: nil)
|
||
|
||
await self.ipv6AssistClient?.stop()
|
||
self.ipv6AssistClient = nil
|
||
}
|
||
|
||
deinit {
|
||
SDLLogger.log("[SDLContext] deinit", for: .debug)
|
||
}
|
||
|
||
}
|
||
|
||
// MARK: probe网络类型
|
||
extension SDLContextActor {
|
||
|
||
private func setNatType(natType: SDLNATProberActor.NatType) {
|
||
self.natType = natType
|
||
}
|
||
}
|
||
|
||
// MARK: Notifier通知机制
|
||
extension SDLContextActor {
|
||
|
||
private func prepareTunnelNotifier() {
|
||
// 启动noticeClient
|
||
// 旧的 UDP NoticeClient 已移除,改为初始化基于 App Group 的通知通道。
|
||
SDLTunnelAppNotifier.shared.clear()
|
||
|
||
SDLLogger.log("[SDLContext] tunnelAppNotifier ready")
|
||
}
|
||
|
||
private func publishTunnelEvent(code: Int? = nil, message: String) {
|
||
SDLTunnelAppNotifier.shared.publish(code: code, message: message)
|
||
}
|
||
}
|
||
|
||
// MARK: 数据发送
|
||
extension SDLContextActor {
|
||
|
||
// 发送给super/stun节点的数据
|
||
private func sendSuperPacket(type: SDLPacketType, data: Data) async {
|
||
await self.sendPacket(type: type, data: data, remoteAddress: self.config.stunSocketAddress)
|
||
}
|
||
|
||
// 发送给peer的数据
|
||
private func sendPeerPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) async {
|
||
await self.sendPacket(type: type, data: data, remoteAddress: remoteAddress)
|
||
}
|
||
|
||
private func sendPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) async {
|
||
await self.udpHoleServiceProxy.send(type: type, data: data, remoteAddress: remoteAddress)
|
||
}
|
||
}
|
||
|
||
// MARK: 处理和Super之间的通讯
|
||
extension SDLContextActor {
|
||
|
||
private func handleSuperMessage(message: SDLQUICInboundMessage) async {
|
||
switch message {
|
||
case .welcome(let welcome):
|
||
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
|
||
|
||
await self.ipv6AssistClient?.stop()
|
||
self.ipv6AssistClient = nil
|
||
// 尝试创建v6地址的辅助探测器
|
||
if welcome.hasIpv6Assist {
|
||
self.ipv6AssistClient = SDLIPV6AssistClient(assistServerInfo: welcome.ipv6Assist)
|
||
await self.ipv6AssistClient?.start()
|
||
}
|
||
|
||
// 注册
|
||
await self.doRegisterSuper()
|
||
SDLLogger.log("[SDLContext] quic doRegisterSuper")
|
||
case .pong:
|
||
//SDLLogger.shared.log("[SDLContext] quic pong")
|
||
()
|
||
case .registerSuperAck(let registerSuperAck):
|
||
await self.handleRegisterSuperAck(registerSuperAck: registerSuperAck)
|
||
case .registerSuperNak(let registerSuperNak):
|
||
self.handleRegisterSuperNak(nakPacket: registerSuperNak)
|
||
case .peerInfo(let peerInfo):
|
||
SDLLogger.log("[SDLContext] peer message: \(peerInfo)")
|
||
let packets = await self.puncherActor.makeRegisterPackets(peerInfo: peerInfo)
|
||
for packet in packets {
|
||
await self.udpHoleServiceProxy.send(type: .register, data: packet.data, remoteAddress: packet.remoteAddress)
|
||
}
|
||
case .event(let event):
|
||
await self.handleEvent(event: event)
|
||
case .policyReponse(let policyResponse):
|
||
// 处理权限的请求问题
|
||
await self.policyService.applyPolicyResponse(policyResponse)
|
||
case .arpResponse(let arpResponse):
|
||
SDLLogger.log("[SDLContext] get arp response: \(arpResponse)")
|
||
await self.arpResolver.handleArpResponse(arpResponse: arpResponse)
|
||
}
|
||
}
|
||
|
||
private func makeSuperEventProcessor() -> SDLSuperEventProcessor {
|
||
return .init(networkAddress: self.config.networkAddress)
|
||
}
|
||
|
||
private func handleRegisterSuperAck(registerSuperAck: SDLRegisterSuperAck) async {
|
||
// 需要对数据通过rsa的私钥解码
|
||
guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else {
|
||
SDLLogger.log("[SDLContext] registerSuperAck invalid key")
|
||
let error = SDLError.invalidKey
|
||
self.provider.cancelTunnelWithError(error)
|
||
return
|
||
}
|
||
|
||
let algorithm = registerSuperAck.algorithm.lowercased()
|
||
let regionId = registerSuperAck.regionID
|
||
self.sessionToken = registerSuperAck.sessionToken
|
||
|
||
switch algorithm {
|
||
case "aes":
|
||
self.dataCipher = CCAESChiper(key: key)
|
||
case "chacha20":
|
||
self.dataCipher = CCChaCha20Cipher(regionId: regionId, keyData: key)
|
||
default:
|
||
SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)")
|
||
let error = SDLError.unsupportedAlgorithm(algorithm: algorithm)
|
||
self.provider.cancelTunnelWithError(error)
|
||
return
|
||
}
|
||
|
||
await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher)
|
||
await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher)
|
||
SDLLogger.log("[SDLContext] registerSuperAck, use algorithm \(algorithm), key len: \(key.count)")
|
||
// 服务器分配的tun网卡信息
|
||
do {
|
||
try await self.tunNetworkManager.apply(settings: .init(config: self.config), dnsServer: DNSHelper.dnsServer)
|
||
SDLLogger.log("[SDLContext] setNetworkSettings successed")
|
||
await self.packetOutboundActor.startPacketReader()
|
||
// 开启权限的定时更新
|
||
await self.whenRegistedSuper()
|
||
} catch let err {
|
||
SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)")
|
||
self.provider.cancelTunnelWithError(err)
|
||
}
|
||
}
|
||
|
||
// 注册成功super的回调函数
|
||
private func whenRegistedSuper() async {
|
||
await self.updatePolicyWorker?.stop()
|
||
let policyService = self.policyService
|
||
let superServiceProxy = self.superServiceProxy
|
||
|
||
let updatePolicyWorker = PeriodicWorker(
|
||
configuration: .init(
|
||
interval: .seconds(300),
|
||
runImmediately: false,
|
||
mode: .fixedDelay,
|
||
errorPolicy: .keepRunning(delay: .seconds(5))
|
||
),
|
||
operation: {
|
||
SDLLogger.log("[SDLContext] updatePolicyTask execute")
|
||
await policyService.updatePolicy(superServiceProxy: superServiceProxy)
|
||
},
|
||
onError: { err in
|
||
SDLLogger.log("[SDLContext] updatePolicyTask stop with err: \(err)")
|
||
}
|
||
)
|
||
self.updatePolicyWorker = updatePolicyWorker
|
||
await updatePolicyWorker.start()
|
||
|
||
// 启动stun任务
|
||
await self.startStunRequestTask()
|
||
}
|
||
|
||
private func handleRegisterSuperNak(nakPacket: SDLRegisterSuperNak) {
|
||
let errorMessage = nakPacket.errorMessage
|
||
guard let errorCode = SDLNAKErrorCode(rawValue: UInt8(nakPacket.errorCode)) else {
|
||
return
|
||
}
|
||
|
||
switch errorCode {
|
||
case .invalidToken, .nodeDisabled:
|
||
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
||
// 报告错误并退出
|
||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
|
||
self.provider.cancelTunnelWithError(error)
|
||
|
||
case .noIpAddress, .networkFault, .internalFault:
|
||
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
||
}
|
||
SDLLogger.log("[SDLContext] Get a SuperNak message exit")
|
||
}
|
||
|
||
private func handleEvent(event: SDLEvent) async {
|
||
let processor = self.makeSuperEventProcessor()
|
||
let plan = await processor.makeProcessingPlan(event: event)
|
||
if let logMessage = plan.logMessage {
|
||
SDLLogger.log(logMessage)
|
||
}
|
||
|
||
switch plan.action {
|
||
case .removeSession(let dstMac):
|
||
await self.sessionManager.removeSession(dstMac: dstMac)
|
||
case .sendRegister(let registerData, let remoteAddresses):
|
||
for remoteAddress in remoteAddresses {
|
||
await self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress)
|
||
}
|
||
case .shutdown(let message):
|
||
self.publishTunnelEvent(message: message)
|
||
|
||
// 报告错误并退出
|
||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)
|
||
self.provider.cancelTunnelWithError(error)
|
||
case .none:
|
||
()
|
||
}
|
||
}
|
||
|
||
private func doRegisterSuper() async {
|
||
// 注册
|
||
var registerSuper = SDLRegisterSuper()
|
||
registerSuper.clientID = self.config.clientId
|
||
registerSuper.networkID = self.config.networkAddress.networkId
|
||
registerSuper.mac = self.config.networkAddress.mac
|
||
registerSuper.ip = self.config.networkAddress.ip
|
||
registerSuper.maskLen = UInt32(self.config.networkAddress.maskLen)
|
||
registerSuper.hostname = self.config.hostname
|
||
registerSuper.pubKey = self.rsaCipher.pubKey
|
||
registerSuper.accessToken = self.config.accessToken
|
||
|
||
if let registerSuperData = try? registerSuper.serializedData() {
|
||
SDLLogger.log("[SDLContext] will send register super")
|
||
await self.superServiceProxy.send(type: .registerSuper, data: registerSuperData)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// MARK: DNS service events
|
||
extension SDLContextActor {
|
||
private func handleDNSEvent(_ event: DNSService.Event) async {
|
||
switch event {
|
||
case .packet(let packet):
|
||
let nePacket = NEPacket(data: packet, protocolFamily: 2)
|
||
self.provider.packetFlow.writePacketObjects([nePacket])
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: 处理从Hole收到的数据
|
||
extension SDLContextActor {
|
||
private func handleUDPHoleControlEvent(_ event: SDLUDPHoleService.Event) async {
|
||
switch event {
|
||
case .ready(let localAddress):
|
||
SDLLogger.log("[SDLContext] udpHole ready: \(localAddress)")
|
||
case .natType(let natType):
|
||
self.setNatType(natType: natType)
|
||
SDLLogger.log("[SDLContext] nat_type is: \(natType)")
|
||
case .packet(let remoteAddress, let message, let source):
|
||
await self.handleUDPHolePacket(remoteAddress: remoteAddress, message: message, source: source)
|
||
case .closed(let error):
|
||
SDLLogger.log("[SDLContext] udpHole closed: \(error)", for: .debug)
|
||
}
|
||
}
|
||
|
||
private func handleUDPHolePacket(remoteAddress: SocketAddress, message: SDLHoleMessage, source: SDLUDPHoleKind) async {
|
||
switch message.inboundMessage {
|
||
case .control(let message):
|
||
switch message {
|
||
case .stunReply(_), .stunProbeReply(_):
|
||
SDLLogger.log("[SDLContext] get a stun reply", for: .debug)
|
||
case .register(let register):
|
||
try? await self.handleRegister(remoteAddress: remoteAddress, register: register, source: source)
|
||
case .registerAck(let registerAck):
|
||
await self.handleRegisterAck(remoteAddress: remoteAddress, registerAck: registerAck, source: source)
|
||
}
|
||
case .data:
|
||
SDLLogger.log("[SDLContext] unexpected data packet in control path", for: .debug)
|
||
}
|
||
}
|
||
|
||
private func handleRegister(remoteAddress: SocketAddress, register: SDLRegister, source: SDLUDPHoleKind) async throws {
|
||
let networkAddr = config.networkAddress
|
||
SDLLogger.log("[SDLContext] register packet: \(register), network_address: \(networkAddr)")
|
||
|
||
// 判断目标地址是否是tun的网卡地址, 并且是在同一个网络下
|
||
if register.dstMac == networkAddr.mac && register.networkID == networkAddr.networkId {
|
||
// 回复ack包
|
||
var registerAck = SDLRegisterAck()
|
||
registerAck.networkID = networkAddr.networkId
|
||
registerAck.srcMac = networkAddr.mac
|
||
registerAck.dstMac = register.srcMac
|
||
|
||
await self.sendPeerPacket(type: .registerAck, data: try registerAck.serializedData(), remoteAddress: remoteAddress)
|
||
// 这里需要建立到来源的会话, 在复杂网络下,通过super-node查询到的nat地址不一定靠谱,需要通过udp包的来源地址作为nat地址
|
||
if let session = Session(dstMac: register.srcMac, natAddress: remoteAddress, addressType: source.convertAddressType()) {
|
||
await self.sessionManager.addSession(session: session)
|
||
} else {
|
||
SDLLogger.log("[SDLContext] didReadRegister get unsupported remoteAddress: \(remoteAddress)", for: .debug)
|
||
}
|
||
} else {
|
||
SDLLogger.log("[SDLContext] didReadRegister get a invalid packet, because dst_ip not matched: \(register.dstMac)")
|
||
}
|
||
}
|
||
|
||
private func handleRegisterAck(remoteAddress: SocketAddress, registerAck: SDLRegisterAck, source: SDLUDPHoleKind) async {
|
||
// 判断目标地址是否是tun的网卡地址, 并且是在同一个网络下
|
||
let networkAddr = config.networkAddress
|
||
if registerAck.dstMac == networkAddr.mac && registerAck.networkID == networkAddr.networkId {
|
||
if let session = Session(dstMac: registerAck.srcMac, natAddress: remoteAddress, addressType: source.convertAddressType()) {
|
||
await self.sessionManager.addSession(session: session)
|
||
} else {
|
||
SDLLogger.log("[SDLContext] didReadRegisterAck get unsupported remoteAddress: \(remoteAddress)", for: .debug)
|
||
}
|
||
} else {
|
||
SDLLogger.log("[SDLContext] didReadRegisterAck get a invalid packet, because dst_mac not matched: \(registerAck.dstMac)")
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// MARK: 和Stun相关的心跳机制
|
||
extension SDLContextActor {
|
||
|
||
// MARK: -- StunRequestTask
|
||
private func startStunRequestTask() async {
|
||
await self.stunRequestWorker?.stop()
|
||
|
||
let stunRequestWorker = PeriodicWorker(
|
||
configuration: .init(
|
||
interval: .seconds(8),
|
||
runImmediately: true,
|
||
mode: .fixedDelay,
|
||
errorPolicy: .keepRunning(delay: .seconds(5))
|
||
),
|
||
operation: { [weak self] in
|
||
let probeReply = try? await self?.ipv6AssistClient?.probe(requestTimeout: .seconds(3))
|
||
|
||
if let v6Info = probeReply?.v6Info, let v6Address = SDLUtil.ipv6DataToString(v6Info.v6) {
|
||
SDLLogger.log("[SDLContext] probe ipv6 address: \(v6Address)")
|
||
} else {
|
||
SDLLogger.log("[SDLContext] probe ipv6 address: empty")
|
||
}
|
||
|
||
await self?.sendStunRequest(v6Info: probeReply?.v6Info)
|
||
},
|
||
onError: { err in
|
||
SDLLogger.log("[SDLContext] udp stunRequestTask stop with err: \(err)")
|
||
}
|
||
)
|
||
self.stunRequestWorker = stunRequestWorker
|
||
await stunRequestWorker.start()
|
||
}
|
||
|
||
private func sendStunRequest(v6Info: SDLV6Info?) async {
|
||
guard let sessionToken = self.sessionToken else {
|
||
return
|
||
}
|
||
|
||
var stunRequest = SDLStunRequest()
|
||
stunRequest.clientID = self.config.clientId
|
||
stunRequest.networkID = self.config.networkAddress.networkId
|
||
stunRequest.ip = self.config.networkAddress.ip
|
||
stunRequest.mac = self.config.networkAddress.mac
|
||
stunRequest.natType = UInt32(self.natType.rawValue)
|
||
stunRequest.sessionToken = sessionToken
|
||
|
||
if let v6Info {
|
||
stunRequest.v6Info = v6Info
|
||
}
|
||
|
||
if let stunData = try? stunRequest.serializedData() {
|
||
await self.sendSuperPacket(type: .stunRequest, data: stunData)
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: NEPacketTunnelProvider相关的逻辑
|
||
extension SDLContextActor {
|
||
|
||
// 取消出口节点的时候,ip地址为: 0.0.0.0
|
||
public func updateExitNode(exitNodeIp: String) async throws {
|
||
if let ip = SDLUtil.ipv4StrToInt32(exitNodeIp), ip > 0 {
|
||
self.config.exitNode = .init(exitNodeIp: ip)
|
||
} else {
|
||
self.config.exitNode = nil
|
||
}
|
||
await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher)
|
||
await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher)
|
||
|
||
try await self.tunNetworkManager.apply(settings: .init(config: self.config), dnsServer: DNSHelper.dnsServer)
|
||
}
|
||
|
||
}
|