fix punch
This commit is contained in:
parent
ccb3a22707
commit
9d3a380063
89
Tun/Punchnet/Actors/SDLPuncherActor.swift
Normal file
89
Tun/Punchnet/Actors/SDLPuncherActor.swift
Normal file
@ -0,0 +1,89 @@
|
||||
//
|
||||
// SDLPuncherActor.swift
|
||||
// Tun
|
||||
//
|
||||
// Created by 安礼成 on 2026/1/7.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
actor SDLPuncherActor {
|
||||
// dstMac
|
||||
private var coolingDown: Set<Data> = []
|
||||
private let cooldown: Duration = .seconds(5)
|
||||
|
||||
private var superClientActor: SDLSuperClientActor?
|
||||
private var udpHoleActor: SDLUDPHoleActor?
|
||||
|
||||
// 处理holer
|
||||
private var logger: SDLLogger
|
||||
|
||||
struct RegisterRequest {
|
||||
let srcMac: Data
|
||||
let dstMac: Data
|
||||
let networkId: UInt32
|
||||
}
|
||||
|
||||
init(logger: SDLLogger) {
|
||||
self.logger = logger
|
||||
}
|
||||
|
||||
func setSuperClientActor(superClientActor: SDLSuperClientActor?) {
|
||||
self.superClientActor = superClientActor
|
||||
}
|
||||
|
||||
func setUDPHoleActor(udpHoleActor: SDLUDPHoleActor?) {
|
||||
self.udpHoleActor = udpHoleActor
|
||||
}
|
||||
|
||||
func submitRegisterRequest(request: RegisterRequest) {
|
||||
let dstMac = request.dstMac
|
||||
|
||||
guard !coolingDown.contains(dstMac) else {
|
||||
return
|
||||
}
|
||||
|
||||
// 触发一次打洞
|
||||
coolingDown.insert(dstMac)
|
||||
|
||||
Task {
|
||||
await self.tryHole(request: request)
|
||||
// 启动冷却期
|
||||
try? await Task.sleep(for: .seconds(5))
|
||||
self.endCooldown(for: dstMac)
|
||||
}
|
||||
}
|
||||
|
||||
private func endCooldown(for key: Data) {
|
||||
self.coolingDown.remove(key)
|
||||
}
|
||||
|
||||
private func tryHole(request: RegisterRequest) async {
|
||||
var queryInfo = SDLQueryInfo()
|
||||
queryInfo.dstMac = request.dstMac
|
||||
guard let message = try? await self.superClientActor?.request(type: .queryInfo, data: try queryInfo.serializedData()).get() else {
|
||||
return
|
||||
}
|
||||
|
||||
switch message.packet {
|
||||
case .empty:
|
||||
self.logger.log("[SDLContext] hole query_info get empty: \(message)", level: .debug)
|
||||
case .peerInfo(let peerInfo):
|
||||
if let remoteAddress = peerInfo.v4Info.socketAddress() {
|
||||
self.logger.log("[SDLContext] hole sock address: \(remoteAddress)", level: .debug)
|
||||
// 发送register包
|
||||
var register = SDLRegister()
|
||||
register.networkID = request.networkId
|
||||
register.srcMac = request.srcMac
|
||||
register.dstMac = request.dstMac
|
||||
|
||||
await self.udpHoleActor?.send(type: .register, data: try! register.serializedData(), remoteAddress: remoteAddress)
|
||||
} else {
|
||||
self.logger.log("[SDLContext] hole sock address is invalid: \(peerInfo.v4Info)", level: .warning)
|
||||
}
|
||||
default:
|
||||
self.logger.log("[SDLContext] hole query_info is packet: \(message)", level: .warning)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -51,6 +51,7 @@ public class SDLContext {
|
||||
var udpHoleActor: SDLUDPHoleActor?
|
||||
var superClientActor: SDLSuperClientActor?
|
||||
var providerActor: SDLTunnelProviderActor
|
||||
var puncherActor: SDLPuncherActor
|
||||
|
||||
// dns的client对象
|
||||
var dnsClient: DNSClient?
|
||||
@ -74,20 +75,9 @@ public class SDLContext {
|
||||
private var flowTracer = SDLFlowTracerActor()
|
||||
private var flowTracerCancel: AnyCancellable?
|
||||
|
||||
// 处理holer
|
||||
private var holerPublishers: [Data:PassthroughSubject<RegisterRequest, Never>] = [:]
|
||||
private var bag = Set<AnyCancellable>()
|
||||
private var locker = NSLock()
|
||||
|
||||
private let logger: SDLLogger
|
||||
private var rootTask: Task<Void, Error>?
|
||||
|
||||
struct RegisterRequest {
|
||||
let srcMac: Data
|
||||
let dstMac: Data
|
||||
let networkId: UInt32
|
||||
}
|
||||
|
||||
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher, aesCipher: AESCipher, logger: SDLLogger) {
|
||||
self.logger = logger
|
||||
|
||||
@ -103,6 +93,7 @@ public class SDLContext {
|
||||
self.sessionManager = SessionManager()
|
||||
self.arpServer = ArpServer(known_macs: [:])
|
||||
self.providerActor = SDLTunnelProviderActor(provider: provider, logger: logger)
|
||||
self.puncherActor = SDLPuncherActor(logger: logger)
|
||||
}
|
||||
|
||||
public func start() async throws {
|
||||
@ -297,6 +288,8 @@ public class SDLContext {
|
||||
private func handleSuperEvent(event: SDLSuperClientActor.SuperEvent) async throws {
|
||||
switch event {
|
||||
case .ready:
|
||||
await self.puncherActor.setSuperClientActor(superClientActor: self.superClientActor)
|
||||
|
||||
self.logger.log("[SDLContext] get registerSuper, mac address: \(SDLUtil.formatMacAddress(mac: self.devAddr.mac))", level: .debug)
|
||||
var registerSuper = SDLRegisterSuper()
|
||||
registerSuper.version = UInt32(self.config.version)
|
||||
@ -413,6 +406,7 @@ public class SDLContext {
|
||||
private func handleUDPEvent(event: SDLUDPHoleActor.UDPEvent) async throws {
|
||||
switch event {
|
||||
case .ready:
|
||||
await self.puncherActor.setUDPHoleActor(udpHoleActor: self.udpHoleActor)
|
||||
// 获取当前网络的类型
|
||||
//self.natType = await SDLNatProber.getNatType(udpHole: self.udpHole, config: self.config)
|
||||
self.logger.log("[SDLContext] nat type is: \(self.natType)", level: .debug)
|
||||
@ -602,60 +596,7 @@ public class SDLContext {
|
||||
await self.flowTracer.inc(num: data.count, type: .forward)
|
||||
|
||||
// 尝试打洞
|
||||
let registerRequest = RegisterRequest(srcMac: self.devAddr.mac, dstMac: dstMac, networkId: self.devAddr.networkID)
|
||||
self.submitRegisterRequest(request: registerRequest)
|
||||
}
|
||||
}
|
||||
|
||||
private func submitRegisterRequest(request: RegisterRequest) {
|
||||
self.locker.lock()
|
||||
defer {
|
||||
self.locker.unlock()
|
||||
}
|
||||
|
||||
let dstMac = request.dstMac
|
||||
if let publisher = self.holerPublishers[dstMac] {
|
||||
publisher.send(request)
|
||||
} else {
|
||||
let publisher = PassthroughSubject<RegisterRequest, Never>()
|
||||
publisher.throttle(for: .seconds(5), scheduler: DispatchQueue.global(), latest: true)
|
||||
.sink { request in
|
||||
Task {
|
||||
await self.tryHole(request: request)
|
||||
}
|
||||
}
|
||||
.store(in: &self.bag)
|
||||
|
||||
self.holerPublishers[dstMac] = publisher
|
||||
}
|
||||
}
|
||||
|
||||
private func tryHole(request: RegisterRequest) async {
|
||||
var queryInfo = SDLQueryInfo()
|
||||
queryInfo.dstMac = request.dstMac
|
||||
|
||||
guard let message = try? await self.superClientActor?.request(type: .queryInfo, data: try queryInfo.serializedData()).get() else {
|
||||
return
|
||||
}
|
||||
|
||||
switch message.packet {
|
||||
case .empty:
|
||||
self.logger.log("[SDLContext] hole query_info get empty: \(message)", level: .debug)
|
||||
case .peerInfo(let peerInfo):
|
||||
if let remoteAddress = peerInfo.v4Info.socketAddress() {
|
||||
self.logger.log("[SDLContext] hole sock address: \(remoteAddress)", level: .debug)
|
||||
// 发送register包
|
||||
var register = SDLRegister()
|
||||
register.networkID = request.networkId
|
||||
register.srcMac = request.srcMac
|
||||
register.dstMac = request.dstMac
|
||||
|
||||
await self.udpHoleActor?.send(type: .register, data: try! register.serializedData(), remoteAddress: remoteAddress)
|
||||
} else {
|
||||
self.logger.log("[SDLContext] hole sock address is invalid: \(peerInfo.v4Info)", level: .warning)
|
||||
}
|
||||
default:
|
||||
self.logger.log("[SDLContext] hole query_info is packet: \(message)", level: .warning)
|
||||
await self.puncherActor.submitRegisterRequest(request: .init(srcMac: self.devAddr.mac, dstMac: dstMac, networkId: self.devAddr.networkID))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user